Autor: barti879
Redakcja: Dondu
Jakiś czas temu rozpocząłem naukę pisania programów na mikrokontrolery AVR w języku C. Przeczytałem wiele tutoriali, poradników, itp. (m.in. ze strony mikrokotrolery.blogspot.com), aż w końcu doszedłem do pisania własnych, prostych programów.
Po kilku takich „pseudoprogramach” zdecydowałem, że teraz czas napisać coś bardziej rozbudowanego, a za razem przydatnego ;-)
Już od dawna w warsztacie brakowało mi trawiarki do płytek PCB, więc dlaczego nie?
Rozpoczęły się prace, których efektem jest:
a powstała tak ...
Założenia
Przed przystąpieniem do budowy miałem kilka założeń dotyczących konstrukcji. Po pierwsze wszystko miało być wykonane własnoręcznie, w jak najprostszy sposób i technikami „warsztatowymi”. Trawiarka miała być również mało skomplikowana, ale co najważniejsze funkcjonalna.Zabieramy się do budowy
Pierwszym elementem, który powstał był oczywiście program ;) Powstawał był modułowo, tzn. najpierw napisałem fragment obsługi LCD, potem DS’a, następnie termostatu, itd… Na końcu wszystkie elementy kodu poskładałem w spójną całość. Podkreślam, że jest to mój pierwszy tak rozbudowany program. Pewnie wielu z Was napisało by go dużo lepiej, a na pewno prościej.Tak prezentuje się kod. Jest w nim dużo komentarzy, ale jako, że jestem początkujący pomagały mi one w eliminowaniu błędów (choć pewnie nie udało się wyeliminować wszystkich). Biblioteki do obsługi LCD i DS'a zapożyczyłem ze strony: radzio.dxp.pl
*/ * Sterownik_Trawiarki.cpp * ATmega 1MHz, LCD 2x16, DS18b20 * * Wykonano: 07.03.2014r. * Autor: Bartłomiej G. */ //#define F_CPU 1000000UL częstotliwość ustaw w opcjach projektu zgodnie z: //http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html //nagłówki bibliotek standardowych #include <avr/io.h> #include <avr/interrupt.h> #include <stdlib.h> #include <stdio.h> #include <util/delay.h> //pliki obsługi LCD #include "HD44780.c" #include "HD44780.h" //pliki obsługi DS'a #include "ds18b20.c" #include "ds18b20.h" //definicje przycisków #define KEY_ON_OF (1<<PC0) #define KEY_NEXT (1<<PC1) #define KEY_PLUS (1<<PC2) #define KEY_MINUS (1<<PC3) //definicje diod sygnalizujących #define LED_NAGRZEWANIE (1<<PC4) #define LED_MIESZANIE (1<<PC5) //definicje włączania grzałki i napowietrzacza #define NAGRZEWANIE (1<<PB2) #define MIESZANIE (1<<PB1) //togglowanie (zmiana stanu na przeciwny) wyjściem napowietrzacza #define MIESZANIE_TOG PORTB ^= (1<<PB1) //togglowanie (zmiana stanu na przeciwny) diodą sygnalizacyjną #define LED_MIESZANIE_TOG PORTC ^= (1<<PC5) //flagi przycisków volatile uint8_t flaga_on_of, flaga_next, flaga_plus, flaga_minus; int main(void) { //wyjścia grzałki i napowietrzacza DDRB = NAGRZEWANIE | MIESZANIE; //wyjścia diod sygnalizacyjnych DDRC = LED_NAGRZEWANIE | LED_MIESZANIE; //wejścia przycisków z podciągnieciem do Vcc PORTC = KEY_ON_OF | KEY_NEXT | KEY_PLUS | KEY_MINUS; //zmienne uint8_t licznik_czasu = 15; uint8_t licznik_menu = 0; int8_t mieszanie = 0; uint8_t stan_ster = 0; uint8_t nastawa = 40; uint8_t czas = 15; //tablice przechowujące znaki w kodzie ASCII char tablica_czasu [2]; char tablica_temp [17]; char tablica_temp_zadana [10]; double temp; //zmiennna przechowuje aktualną wartość temperatury unsigned char ds18b20_pad[9]; //tablica odczytów z DS //timer2 (8-bitowy) z preskalerem 1024 (przerwanie sprawdzające przyciski) TCCR2 |= (1<<CS20) | (1<<CS21) | (1<<CS22); TCCR2 |= (1<<WGM21); //tryb CTC TIMSK |= (1<<OCIE2); //zezwolenie na przerwania CTC OCR2 = 170; // 170 cykli = ~175ms sei(); //globalne zezwolenie na przerwania //timer1 (16-bitowy) z preskalerem 64 (licznik czasu mieszania) TCCR1B = (1<<CS10) | (1<<CS11); LCD_Initalize(); //inicjalizacja LCD //napis powitalny LCD_WriteText(" TRAWIARKA PCB"); LCD_GoTo(4, 1); LCD_WriteText("Bartek G"); _delay_ms(3000); LCD_Clear(); while(1) { //###################################### STAN STEROWNIKA ################ //zmień stan jeśli wciśnięty przycisk "on/off" if (flaga_on_of) { stan_ster++; flaga_on_of = 0; if (stan_ster >= 2) { stan_ster = 0; licznik_menu = 0; } } //###################################### MENU NASTAW ###################### if (stan_ster == 0) { TCNT1 = 0; //zerowanie timera1 licznik_czasu = 0; //zerowanie licznika czasu PORTB = 0x00; //RESET PORTB PORTC &= ~LED_NAGRZEWANIE; PORTC &= ~LED_MIESZANIE; //wyłączenie diod sygnalizacyjnych //kolejny ekran nastaw jeśli wciśnięty przycisk "next" if (flaga_next) { licznik_menu++; flaga_next = 0; if (licznik_menu >= 3) licznik_menu = 0; } switch (licznik_menu) { //############################## NASTAWA TEMPERATURY ################## case 0: //inkrementuj zmienną "nastawa" jeśli wciśnięty przycisk "plus" if (flaga_plus) { nastawa++; flaga_plus = 0; if (nastawa >=60) nastawa = 30; } //dekrementuj zmienną "nastawa" jeśli wciśnięty przycisk "minus" if (flaga_minus) { nastawa--; flaga_minus = 0; if(nastawa <= 30) nastawa = 60; } //konwersja zmiennej na łańcuch znaków dla LCD itoa(nastawa, tablica_temp_zadana, 10); LCD_Home(); LCD_WriteText(" TEMPERATURA "); LCD_GoTo(0, 1); LCD_WriteText(" - "); LCD_WriteText(tablica_temp_zadana); LCD_WriteData(0xdf); //znak stopnia LCD_WriteText("C + "); break; //################################ STAN MIESZANIA ##################### case 1: //inkrementuj zmienną "mieszanie" jeśli wciśnięty przycisk "plus" if (flaga_plus) { mieszanie++; flaga_plus = 0; if (mieszanie >= 3) mieszanie = 0; } //dekrementuj zmienną "mieszanie" jeśli wciśnięty przycisk "minus" if (flaga_minus) { mieszanie--; flaga_minus = 0; } if (mieszanie < 0) mieszanie = 2; LCD_Home(); LCD_WriteText(" MIESZANIE "); LCD_GoTo(0, 1); switch (mieszanie) { case 0: LCD_WriteText(" <AUTOMATYCZNE> "); //tryb automatyczny break; case 1: LCD_WriteText(" <CIAGLE> "); //tryb ciągły break; case 2: LCD_WriteText(" <WYLACZONE> "); //tryb wyłaczony break; } break; //################################# NASTAWA CZASU MIESZANIA ############ case 2: switch (mieszanie) { case 0: //tryb automatyczny //inkrementuj zmienną "czas" jeśli wciśnięty przycisk "plus" if(flaga_plus) { czas++; flaga_plus = 0; } //dekermentuj zmienną "czas" jeśli wciśnięty przycisk "minus" if(flaga_minus) { czas--; flaga_minus = 0; if (czas <= 0) czas = 1; } //konwersja na łańcuch znaków dla LCD itoa(czas, tablica_czasu, 10); LCD_Home(); LCD_WriteText(" CZAS MIESZANIA "); LCD_GoTo(0, 1); LCD_WriteText(" - "); LCD_WriteText(tablica_czasu); LCD_WriteText("s + "); break; case 1: licznik_menu = 0; break; case 2: licznik_menu = 0; break; } break; } } /////////////////////////////////// TRYB PRACY ////////////////////// else { //################################## TERMOMETR ###################### if(ds18b20_ConvertT()) //polecenie pomiaru { _delay_ms(1); ds18b20_Read(ds18b20_pad); // odczyt z czujnika oraz zapis w tablicy //składa dwa bity pomiary w całość temp = ((ds18b20_pad[1] << 8) + ds18b20_pad[0]) / 16.0 ; //konwersja na kod ASCII i zapis w tablicy "tablica_temp" sprintf(tablica_temp, "%4.1f\xdf""C", temp); } //################################## WYŚWIETLACZ ################# LCD_Home(); LCD_WriteText(" "); LCD_WriteText(tablica_temp); LCD_WriteText(" "); LCD_WriteData(0x2D); LCD_WriteData(0x3E ); //strzałka -> LCD_WriteText(" "); LCD_WriteText(tablica_temp_zadana); LCD_WriteData(0xdf); //znak stopnia LCD_WriteText("C "); LCD_GoTo(0, 1); LCD_WriteText(" TRAWIENIE "); //#################################### TERMOSTAT ################## if ((temp+1) < nastawa) { PORTB |= NAGRZEWANIE; //włącz grzałkę PORTC |= LED_NAGRZEWANIE; //włącz diodę PC4 } if ((temp-1) > nastawa) { PORTB &= ~NAGRZEWANIE; //wyłącz grzałkę PORTC &= ~LED_NAGRZEWANIE; //wyłącz diodę PC4 } //################################## MIESZANIE ########################### switch (mieszanie) { case 0: //tryb automatyczny //inkrementuj zmienną "licznik czasu" jeśli timer >= 15625 (1s) if(TCNT1 >=15625) { TCNT1=0; licznik_czasu++; } //włącz/wyłącz napowietrzacz i diodę jeśli licznik czasu = czas ustawiony if(licznik_czasu == czas) { MIESZANIE_TOG; LED_MIESZANIE_TOG; licznik_czasu = 0; } break; case 1: //tryb ciągły PORTB |= MIESZANIE; //włącz napowietrzacz PORTC |= LED_MIESZANIE; //włącz diodę sygnalizacyjną break; case 2: //tryb wyłączony PORTB &= ~MIESZANIE; //wyłącz napowietrzacz PORTC &= ~LED_MIESZANIE; //wyłącz diodę sygnalizacyjną break; } } } } ISR (TIMER2_COMP_vect) { if (!(PINC & KEY_ON_OF)) flaga_on_of = 1; if (!(PINC & KEY_NEXT)) flaga_next = 1; if (!(PINC & KEY_PLUS)) flaga_plus = 1; if (!(PINC & KEY_MINUS)) flaga_minus = 1; }
Podczas pisania programu powstała również funkcja "pseudodebouncingu" klawiszy (eliminacji drgań styków). Wykorzystuje ona timer sprzętowy w trybie CTC. W przerwaniach generowanych co ok 175ms (dobrałem to doświadczalnie) sprawdzane są klawisze, i jeśli któryś z nich jest wciśnięty ustawiana jest odpowiednia flaga. Poniżej ów kod, który ma za zadanie zmieniać stan diody, jeśli przycisk jest wciśnięty.
/* * ATmega8 debouncing (eliminacja drgań styków przycisków) * Wykonano: 07.03.2014r. * Autor: Bartłomiej G. */ //#define F_CPU 1000000UL częstotliwość ustaw w opcjach projektu zgodnie z: //http://mikrokontrolery.blogspot.com/2011/03/fcpu-gcc-gdzie-definiowac.html #include <avr/io.h> #include <avr/interrupt.h> #define KEY (1<<PC0) #define LED (1<<PB1) #define LED_TOG PORTB ^= LED volatile uint8_t flaga; int main(void) { DDRB = LED; PORTC = KEY; //podciągnięcie klawisza do Vcc TCCR1B |= (1<<CS00) | (1<<CS02); //timer z preskalerem 1024 TCCR1B |= (1<<WGM12); //tryb CTC TIMSK |= (1<<OCIE1A); //zezwolenie na przerwania Compare Match OCR1A = 195; //195 cykli = ~200ms sei(); //globalne zezwolenie na przerwania while(1) { if(flaga) { LED_TOG; flaga = 0; } } } ISR(TIMER1_COMPA_vect) { flaga = 1; }
Prototyp powstał oczywiście na płytce stykowej. Gdy był już w pełni sprawdzony i działający przeniosłem go na PCB. Płytkę zaprojektowałem w Eagle’u, wytrawiłem termotransferem i pocynowałem stopem Lichtenberga - tak na marginesie, to bardzo polecam ten sposób cynowania ;-).
Płytka sterownika |
Płytka przycisków |
Sercem sterownika jest mikrokontroler Atmega8 pracujący na wewnętrznym oscylatorze 1MHz. Układ ten steruje również poprzez optotriak MOC3041 oraz triak BT138 grzałką oraz napowietrzaczem. Rolę czujnika temperatury pełni DS18b20 produkcji Dallasa. Za wyświetlanie odpowiedzialny jest wyświetlacz LCD 16x2 ze sterownikiem HD44780. Układ zasilany jest z ładowarki od telefonu (akurat miałem w domu).
Grzałka ma moc 100W i podgrzewa roztwór do 40 stopni w około 12-15 min. Czujnik zabezpieczyłem poprzez włożenie go w rurkę termokurczliwą, zalanie silikonem i zaciśnięcie koszulki. Operację tę powtórzyłem po zaschnięciu pierwszej warstwy, więc wytrawiacz raczej sobie z nim nie poradzi. Powietrze jest rozprowadzane przez kurtynę napowietrzającą (dostępna w każdym sklepie akwarystycznym).
Czas kleić akwarium… Powstało ono z 4mm tafli szkła (ciętej oczywiście nożem w warsztacie - tak jak mówiły założenia). Cięcie szkła nie należy do prostych rzeczy ale doszedłem już do wprawy. Przycięte elementy posklejałem silikonem. Akwarium ma wymiary 28cm x24cm x2cm i mieści troszkę powyżej litra płynu. Napowietrzacz i grzałkę miałem już z poprzedniego podejścia do budowy trawiarki – niestety konstrukcja ta nie posiadała żadnego sterowania i nie do końca spełniała swoje zadanie.
Mając te elementy przyszedł czas na obudowę. Wykonałem ją z blachy ocynkowanej oraz kawałka jakiejś wodoodpornej sklejki. Blacha gięta sposobem „na dwa profile” ;D Po prostu wkłada się ją między dwa profile i delikatnie dogina gumowym młotkiem. Następnie obudowa została powiercona, wyszlifowana i pomalowana kilkoma warstwami białego i bezbarwnego spray’u. Moim zdaniem jak na domowe warunki uzyskałem całkiem zadowalając efekt. Gdy wszystko wyschło zamontowałem akwarium i płytki z elektroniką. Ostatnim krokiem było wydrukowanie, zalaminowanie i naklejenie panelu przedniego – to już koniec budowy!
Zdjęcia z etapów budowy
Obudowa przed wierceniem |
Obudowa po wierceniu |
Obudowa z akwarium |
Obudowa z akwarium |
Podczas składania |
Mocowanie LCD i przycisków |
UWAGA!
W układzie występują napięcia (230V) niebezpieczne dla życia i zdrowia!
W układzie występują napięcia (230V) niebezpieczne dla życia i zdrowia!
Opis działania
Po włączeniu zasilania wyświetla się napis powitalny. Po 3 sekundach naszym oczom ukazuje się menu ustawień. Możemy tu ustawić temperaturę procesu trawienia (w zakresie od 30 do 60 stopni), tryb mieszania (automatyczny, ciągły lub wyłączony) oraz czas przerw w mieszaniu. Temperatura trawienia nie jest zapisywana do EEPROM a jej początkowa wartość to 40 stopni, co jest w 99% temperaturą, której potrzebuję. Histereza jest programowo ustawiona na +/-1 stopień. Po kliknięciu przycisku włączającego proces na ekranie wyświetlana jest aktualna oraz ustawiona temperatura. Po jego ponownym kliknięciu przechodzimy z powrotem do trybu ustawień. Diody sygnalizują aktualny stan grzałki i napowietrzacza.Do pobrania
Do obrania komplet plików do wykonania PCB oraz program w raz z plikiem hex: Trawiarka.rar (kopia)
Podsumowanie
Urządzenie, które wykonałem nie jest skomplikowane, jednak w 100% spełnia swoje zadanie. Podczas jego budowy nauczyłem się wielu rzeczy. Teraz już pisanie programów staje się co raz prostsze (kod do sterownika nauczył mnie na prawdę bardo dużo), szyby nie stawiają takich oporów, a prostoliniowe cięcie blachy nie jest trudne!Koszty jakie poniosłem przy budowie to około 50 zł. Większość elementów miałem – musiałem kupić tylko spray’e oraz kilka układów elektronicznych. Reszta potrzebnych rzeczy leżała gdzieś w zaciszu domowych szuflad.
Jestem bardzo zadowolony z pracy trawiarki. Bardzo ułatwia i umila wykonywanie płytek drukowanych. Polecam każdemu elektronikowi zbudowanie podobnej konstrukcji!
Na koniec kilka zdjęć finalnego wyglądu oraz filmik z działania urządzenia.
Panel przedni |
Przyciski |
Czujnik temperatury |
Obudowa z tyłu |
Finalny wygląd |
Finalny wygląd |
Pozdrawiam !
Bartek
Witam. Mam pytanie co do panelu przedniego ??? kolega sam laminował czy oddał żeby zrobili gdzieś punkcie introligatorskim ???
OdpowiedzUsuńLaminowałem w punkcie ksero ale musiałem to robić bodajże 4 razy bo za każdym razem coś musieli zepsuć. A to źle zgrzali, a to porobili fałdki... Po 3 razie znalazłem drugi punkt ksero gdzie zalaminowali bardzo ładnie ;)
Usuńpróbuje znaleźć jak to zrobić samemu w sensie tego okienka na wyświetlacz...bo jak podłożyłem drugą warstwę folii (klejem to siebie wzajemnie) to wyszły mi plamy kleju :/
UsuńJa wycinałem otwór w papierze i w ksero pani po prostu nakładała a całość folię i zgrzewała. Robię tak we wszystkich swoich konstrukcjach z wyświetlaczami, ponieważ zabezpiecza to LCD przed uszkodzeniem i kurzem ;) Ponadto efekt jest bardzo ładny.
UsuńNo właśnie o to samo mi chodzi :/ ale mi wychodzą plamy :((
UsuńCześć, projekt fajny i przydatny, ale czy grzałka jest zabezpieczona przed wytrawiaczem?
OdpowiedzUsuńNie, grzałka jest sama w sobie zabezpieczona przed wodą, więc i wytrawiacz jej nie "zje", ponieważ wykonana jest z gumy i szkła. Urządzenie trawiło już wiele razy i z grzałką nic się nie dzieje.
UsuńProjekt fajny. Tylko jedno mnie martwi. Kuweta z roztworem jest umieszczona bezpośrednio w obudowie nad elektroniką gdzie panuje napięcie 230V. W przypadku rozszczelnienia kuwety roztwór zalewa wnętrze i urządzenie robi się bardzo niebezpieczne. Należało by zrobić tak obudowę i ją uszczelnić aby w takim przypadku roztwór nie zalewał wnętrza.
OdpowiedzUsuńUwaga oczywiście słuszna, jednak rozszczelnienie zbiornika to już raczej sytuacja "tropikalna" i gdyby wszystkie podobne brać pod uwagę koszty urządzenia zwiększyły by się bardzo mocno. Jest to konstrukcja amatorska na własne potrzeby, więc niestety ma jakieś niedopracowane rzeczy. W razie zalania elektroniki przepali się bezpiecznik i prawdopodobieństwo porażenia prądem jest przwie zerowe (no chyba, że we wtyczce mamy podmylone przewody fazowy i neutralny ;p)
OdpowiedzUsuńGratulacje wykonania projektu. Wydaje mi się jednak, że jedna nóżka RD1 na PCB jest zbyt blisko masy sygnałowej i około 1 milimetr dzieli część wysokonapięciową od niskonapięciowej. Bezpieczniej jest zwiększyć trochę rozmiar płytki drukowanej, wtedy łatwiej byłoby porozmieszczać elementy mające styczność z 220V
OdpowiedzUsuńWojtek
Możecie mi powiedzie czemu nie mogę wgrać tego programu przez arduino isp na atmege8
OdpowiedzUsuńcały czas podkreśla linijkę " DDRB = NAGRZEWANIE | MIESZANIE; //wyjœcia grza³ki i napowietrzacza "
Jeżeli przerabiałeś ten program, to prawdopodobnie w błąd jest w innym miejscu niż sygnalizowany. Zmieniałeś coś w programie?
UsuńNo właśnie nic nie zmieniałem po prostu go otwarłem.
OdpowiedzUsuńZałóż wątek na naszym forum, pokaż kod i opisz dokładnie sytuację. A tutaj wklej link do tematu na forum, bym wiedział gdzie szukać Twojego tematu.
UsuńZałożyłem wątek na forum link: http://www.elektroda.pl/rtvforum/topic2935253.html
UsuńWkleiłem tam kod programu i błędy pojawiające się.
Podczas programowania pojawiają się błędy co robić ?
OdpowiedzUsuńJakie?
UsuńWitam,fajny projekt, opierając się tylko na tym projekcie jak i na jego opisie mam problem, gdzie znajdę biblioteki do obsługi ds18b20? Na stronie radzio.dxp.pl nie mogę znaleźć..
OdpowiedzUsuńja też szukam tej biblioteki
OdpowiedzUsuńpodczas ładowania w arduino ide pokazuje błędy :
OdpowiedzUsuńSterownik Trawiarki.c:17:21: error: HD44780.c: No such file or directory
Sterownik Trawiarki.c:18:47: error: HD44780.h: No such file or directory
Sterownik Trawiarki.c:20:21: error: ds18b20.c: No such file or directory
Sterownik Trawiarki.c:21:48: error: ds18b20.h: No such file or directory
Witam.
OdpowiedzUsuńPrzyglądałem się projektowi i muszę pogratulować wykonania całości.
W sieci jest wiele skopanych projektów ten jednak charakteryzuje się przemyślaną konstrukcją z dopracowanymi własnoręcznie detalami co sprawia ,że projekt wyróżnia się na tle innych.
Jako akwarysta a za razem elektronik amator podpowiem , że tzw. brzęczyk, który napowietrza zbiornik z czynnikiem trawiącym powinien być umieszczony nad poziomem płynu trawiącego najlepiej poza obudową trawiarki. Dlaczego? Po wyłączeniu trawiarki może (ale nie musi ) nastąpić wsteczne zassanie płynu poprzez wężyk do którego przymocowany jest kamień napowietrzający. Kiedyś taką sytuację miałem z moim akwarium. Minę sąsiada z dołu pamiętam do dzisiaj ;). Od tamtej pory wszelkie pompki i napowietrzacze trzymam zawsze powyżej lustra wody w akwarium. Eliminujemy także w ten sposób zagrożenie porażenia prądem w razie nieszczelności zbiornika - płyn nie ścieka bezpośrednio na pompkę.
Jeszcze raz gratuluję i życzę kolejnych udanych i tak estetycznie zaprojektowanych i wykonanych projektów.
pozdrawiam
Paweł
Dobrze, że wytrawiacz nie jest tak żrący jak ślina "Obcego 8-go pasażera Nostromo" :)
UsuńPrzecież zawsze montuje się zawór zwrotny na przewodzie powietrza więc nie ma możliwości zassania płynu
OdpowiedzUsuńA ja mam pytanie gdzie poprać biblioteki do obsługi ds bo na stronie radzia nie mogę znaleźć
OdpowiedzUsuń