INSTYTUT CYBERNETYKI TECHNICZNEJ POLITECHNIKA WROCŁAWSKA Wizualizacja danych sensorycznych Tarcza dla wskaźnika laserowego IRb-1400 Prowadzący: dr inż. Bogdan Kreczmer Wykonali: Mariusz Zalewski Krzysztof Klempa
Założenia projektu Tarcza dla IRb-1400 ma być pomocą naukową dla laboratorium z Wprowadzenia do automatyki i robotyki. Dzięki niej studenci będą mieli możliwość kontroli ruchu w/w manipulatora. Tarcza składa się z 16 fotodiod. Dzięki zainstalowanemu na manipulatorze wskaźniku laserowemu możemy oddziaływać na fotodiody umieszczone na tarczy. Możemy zatem powiedzieć, że jeżeli robot wskaże na odpowiedni punkt na tarczy, to będziemy o tym wiedzieli. Sprawdzając odczyty ze wszystkich fotodiod w kolejnych odstępach czasu będziemy wiedzieli jak zachowuje się IRb-1400, a zatem będziemy mogli powiedzieć czy zrealizował on zaplanowaną trasę. Zadaniem studentów będzie takie zaprogramowanie IRb-1400 aby realizował on ruch po pożądanej trasie. Okiem użytkownika Podstawowym elementem tarczy jest 16 fotodiod. Odpowiadają kontrole położenia efektora robota. Przy każdej fotodiodzie umieszczone są dwie diody świecące LED. Jedna zielona, druga czerwona. Sygnalizują one poprawność wskazania na fotodiodę (tj. jeżeli wskaźnik pokaże na odpowiednią diodę dostaniemy sygnał zielony; jeżeli na nieprawidłową - czerwony). Ponadto wyniki są na bieżąco wyświetlane na wyświetlacze LCD 2x16. Użytkownik obsługuje tarcze przy pomocy czterech klawiszy. Odpowiednio od lewej: yes, no, lewo, prawo. Dodatkowo tarcza może komunikować się z komputerem przez złącze RS232. Układ zasilany jest napięciem stałym +18V. Budowa tarczy Jednostka centralna 8-bitowy mikrokontroler Atmel AVR ATMega16. Procesor ten został wybrany do projektu ze względu na sporą (w stosunku da ATMega8) liczbę wyjść, niską cenę oraz dostępność na rynku. W urządzeniu wykorzystywane są 24 wyjścia/wejścia mikrokontrolera. Procesor taktowany jest wewnętrznym rezonatorem o częstotliwości 1MHz, lecz istnieje także możliwość uruchomienia zewnętrznego kwarcu 8MHz, w który to układ jest wyposażony. Mikrokontroler oprogramowany został z języku C w środowisku WinAVR poprzez złącze ISP. Układ zasilający zastosowany mikroprocesor wymaga napięcia zasilania Vcc = +5V. Z tego względu zastosowano regulator napięcia L7805T. Ponieważ maksymalny pobór prądu urządzenia nie powinien przekroczyć jednego ampera, a właściwie nie powinien nawet zbliżyć się do tej granicy, a napięcie zasilanie waha się w okolicach +20V zastosowaliśmy rezystor mocy w celu zmniejszenia napięcia wejściowego na L7805. Na rezystancji 22ohm o mocy 5W odkłada się około 3.5-4V, dzięki czemu stabilizator przetwarza mniejsze napięcie zachowując stałe napięcie wyjścia na poziomie 5V. Wszelkie układy scalone jak i mikroprocesor zasilane są tym źródłem energii. Bezpośrednio na wejście mikroprocesora wpięto kondensator ceramiczny o wartości 100nF mający na celu odfiltrować ewentualne skoki napięć (szpilki).
Odczyt z fotodiod odczyt informacji z tablicy odpowiedzialne są dwa wyjścia cyfrowe mikrokontrolera (PA6, PA7). Sygnał z 16 fotodiod jest na nie sekwencyjnie multipleksowany dwoma układami 74151N. Domyślna wartością na wejściu 74151 jest stan wysoki. Jeżeli podpiąć go poprzez diodę do masy, a następnie reagować na diodę światłem jesteśmy w stanie odczytać czy wskaźnik pokazuje na badaną diodę. Przy pomocy wyjść (PB0, PB1, PB2) wybieramy wejścia multipleksera i badamy kolejno stany na każdym wejściu. Jeden multiplekser odpowiada za odczyt z 8 diod. Sygnalizacja diodami LED jak wspomniano wcześniej poprawność trafień jest sygnalizowana zapaleniem diody czerwonej bądź zielonej. Mamy zatem dla każdej fotodiody dwie diody świecące wykonujące w/w czynność. Do sterowanie tablicą wykorzystano cztery linie zasilająca (PD2, PD3, PD4, PD5) oraz podciąganie do masy poprzez demultiplekser 74138N sterowany wyjściami PB3, PB4, PB5. Prąd zasilający został ograniczony poprzez zastosowanie rezystorów 470 ohm. Zasilając odpowiednią linie i podciągając drugą do masy spowodujemy zapalenie pożądanej diody. Wyświetlacz LCD w urządzeniu został zastosowany wyświetlacz LMC- S2M16 oparty o sterownik HD44780. Użyto 4-bitowego sterowanie wyświetlaczem (PA0, PA1, PA2, PA3). Używamy także wyjść PA4 i PA5 do sterowanie wejściami Enable i Register Select. Szczegółowy opis wyprowadzeń zamieszczam poniżej: 1 VDD - +5V 2 VSS - 0V 3 VO - CONTRAST 4 RS H/L REGISTER SELECT 5 R/W H/L READ/WRITE 6 E H.H->L ENABLE SIGNAL 7 DB0 H/L DATA BIT0 8 DB1 H/L DATA BIT1 9 DB2 H/L DATA BIT2 10 DB3 H/L DATA BIT3 11 DB4 H/L DATA BIT4 12 DB5 H/L DATA BIT5 13 DB6 H/L DATA BIT6 14 DB7 H/L DATA BIT7 Pin 5 został na stałe zwarty do masy, mamy więc możliwy tylko zapis na LCD. Ponieważ stosujemy 4-bitowy zapis danych piny 7-10 także zwarto do masy. Przy pomocy potencjometru podłączonego do pinu 3 lcd ka możemy regulować kontrastem obrazu. Szczegółowe podłączenie układu przedstawiono na schemacie. Złącze RS232 komunikacja z komputerem odbywa się szeregowo poprzez złącze RS232. Sterowanie zrealizowano na układzie max232. Układ wykorzystuje linie rxd i txd (PD0, PD1) oraz rejestr UART mikroprocesora. Ramka wysyłanych danych przedstawia się następująco: Znacznik startu rozkaz argumenty funkcji znacznik końca Znacznik startu = 0x01, Znacznik końca = 0x0D, Dostępne są następujące rozkazy (funkcje): - zapal diodę służąca do przesłania informacji o tym, która z diod jest zapalona. Funkcja jest dwuargumentowa: pierwszy przyjmuje wartości 1-16 i
określa numer diody, drugi przyjmuje wartości 0,1 i określa kolor (0 czerwona, 1 - zielona). - Komunikat o liczbie błędów jednoargumentowa funkcja służąca do przesyłania informacji o liczbie błędów w wykonywanej trajektorii. Argument przyjmuje wartości 0-10. Dane do PC przesyłane są przy okazji zapalenie którejkolwiek z diod (informacja o zapalonej diodzie), oraz po zakończeniu funkcji sprawdzania trasy (informacja o liczbie błędów). Klawiatura aby możliwa była obsługa urządzenia niezbędne było zbudowanie klawiatury użytkownika. Zostały zaimplementowane klawisze: reset, ok, anuluj, <, >, na wejściach mikroprocesora PB6, PB7, PD6, PD7. Każde wyjście jest wewnętrznie podciągane do plusa, natomiast załączenie przycisku powoduje zwarcie do masy. Aby układ pracował prawidłowo nie należy naciskać więcej niż jednego klawisza jednocześnie. Przytrzymanie klawisza przez pewien czas spowoduje wielokrotną akcje przypisaną temu klawiszowi. Reset reset procesora odbywa się poprzez stan niski na linii resetu procesora. W celu uniknięcia samoczynnego resetowania się układu linię tę podciągnięto do plusa przez zewnętrzny rezystor 10k. Układ możemy zresetować zwierając go przyciskiem resetu do masy. Interfejs użytkownika uruchamiając urządzenie użytkownika przywita tekst Politechnika Wrocławska, następnie Tarcza dla IRb-1400. Po chwili będziemy już w menu głównym, w którym to znajdziemy następujące opcje wyboru: - Wybór trajektorii po wywołaniu funkcji przejdziemy do zakładki przeglądania zaprogramowanych w mikroprocesorze tras. Do wyboru będziemy mieli cztery odgórnie zapisane trajektorie. Po wybraniu jednej z nich na tarczy zostaną zapalone kolejne diody (zielone) wybranej trasy, zaś na wyświetlaczu otrzymamy opis kolejnych punktów i ich wartości. W trakcie prezentacji trajektorii nie mamy możliwości przerwania pracy. Należy więc odczekać, aż prezentacja minie by móc powrócić do menu. - Trajektoria własna jeżeli brak jest jakichkolwiek trajektorii zaprogramowanych samodzielnie program automatycznie przechodzi do funkcji dodawania nowej trasy. Poruszając się klawiszami prawo, lewo wybieramy kolejny punkt trasy, zaś klawiszem ok akceptujemy punkt. Proceder ten trwa, aż do zapisania kolejnych 10 punktów trasy. W każdej chwili możemy usunąć poprzedni punkt za pomocą klawisza anuluj. Nie mamy możliwości przerwania dodawanie trajektorii. Aby zakończyć funkcje dodawania nowej trajektorii niezbędne jest wprowadzenie wszystkich 10 punktów. Dopuszczalne jest aby kolejne punkty trasy miały tę samą wartość. Możemy dodać maksymalnie cztery trajektorie własne. Jeżeli mamy już przynajmniej jedną trajektorię własną wchodzimy do menu wyboru pomiędzy przeglądem trajektorii własnych (funkcja analogiczna do przeglądu trajektorii zaprogramowanych odgórnie), a dodaniem kolejnej. Ponieważ nie ma możliwości usunięcia ani edycji trajektorii jedyną drogą by dodać kolejną trajektorię jest zresetowanie układu w celu wyczyszczenia pamięci. - Test diodowy uaktywniamy test diod. Jeżeli zadziałamy światłem na jedną z diod zapali się zielona dioda znajdująca się obok. Przy pomocy tej funkcji możemy łatwo sprawdzić czy wszystkie fotodiody działają poprawnie. Jeżeli
zapalimy więcej niż jedną fotodiodę zapali się tylko jedna dioda LED, ta o wyższym indeksie. - Wlacz tarcze czyli główna część programu, przechodzimy do menu wyboru trajektorii. Pierwsze 4 trajektorie to zdefiniowane domyślnie w programie. Każdą kolejną mogliśmy dodać w zakładce Trajektoria własna. Po wyborze trajektorii rozpoczyna się sekwencja startowa i program oczekuje na wskazanie którejkolwiek z diod wskaźnikiem laserowym. Jeżeli wskazanie jest poprawne zapalana jest zielona dioda i program przechodzi do kolejnej zadanej w trajektorii diody. Jeżeli wskazanie będzie błędne zapalamy czerwoną diodą, oraz naliczamy punkty karne. W przypadku błędnego zapalenie urządzenie nie oczekuje na poprawkę, lecz przechodzi do kolejnego punktu trajektorii. Na wyświetlaczu lcd otrzymujemy na bieżąco informacje o położeniu oczekiwanym kolejnego punktu. Po zakończeniu realizacji trasy otrzymamy informacje o liczbie popełnionych pomyłek. Jeżeli wskaźnik laserowy przejdzie po trajektorii omijającej diody tarcza nie będzie miała o tym żadnych informacji. W takiej sytuacji możemy wyjść z funkcji oczekiwania na trafienie naciskając klawisz anuluj. Zbyt długie zatrzymanie wskaźnika na fotodiodzie spowoduje dwukrotne policzenie tego samego punktu, co może być efektem niepożądanym. - Tworcy zostaje wyświetlona informacja o autorach projektu.
Widok czołowy na tarcze 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 Matryca LCD Reset 1 < > Ok Anuluj Kolejne diody ponumerowane są od 1 do 16 jak pokazano powyżej. Użytkownik obsługuje tarczę przy użyciu klawiszy: Reset, Ok., Anuluj, < i >. Wszelkie niezbędne informacje wyświetlane są poprzez matryce LCD.
Wej'cia i wyj'cia Zasilanie +12V Programator ISP RS 232 do komunikacji z PC Widok ogólny na p ytk1 Uk;ad zasilacza up ATMega16 Wyj9cie LCD Uk;ad obs;ugi RS232 LCD-kontrast
Przykładowe wywołanie programu Politechnika Wroclawska Tarcza dla IRb-1400 Witaj Nacisnij-> //akcja > Wybor trajektorii //akcja yes Wyswietl trajektorie: 1 //akcja < Wyswietl trajektorie: 4 //akcja yes Punkt:1 Wartosc:5 //wyświetlane kolejne punkty na lcd Punkt:2 Wartosc:6 //jak i na diodach LED Punkt:3 Wartosc:7 Punkt:4 Wartosc:8 Punkt:5 Wartosc:12 Punkt:6 Wartosc:11 Punkt:7 Wartosc:15 Punkt:8 Wartosc:14 Punkt:9 Wartosc:10 Punkt:10 Wartosc:9 Wyswietl trajektorie: 4 //akcja no Wybor trajektorii //akcja > Trajektoria wlasna //akcja > Test diodowy //akcja > Wlacz tarcze //akcja yes Wyswietl trajektorie: 4 //akcja yes Przygotuj się! 3 2 1 START Punkt: 1 Oczekiwany: 1 //program oczekuje na wskazanie diody Punkt: 2 Oczekiwany: 2 //jeżeli poprawne zapala zielona diodę, Punkt: 3 Oczekiwany: 3 //inaczej czerwona i nalicza punkty karne... Punkt: 10 Oczekiwany: 10 L. bledow: 4 Nacisnij klawisz //załóżmy, że tyle błędów popełniono Wybierz trajektorie: 1 //akcja no Wlacz tarcze //akcja > Tworcy //akcja yes Mariusz Zalewski Krzysztof Klempa
Schemat układu tarczy
Oprogramowanie mikrokontrolera Main.cpp #include <avr/io.h> #include "lcd_tools.h" #include "uart.h" #include <stdlib.h> char text[20]; int p1,p2,p3,p4; int t[4][12]= 1,2,3,4,5,6,7,8,9,10, 2,6,10,11,12,16,15,14,13,9, 16,15,14,13,9,5,1,2,3,4, 5,6,7,8,12,11,15,14,10,9; //trajektorie zadane int tr[4][12],lr; //trajektorie zadane recznie, lr liczba zadanych trajektorii int diody[16]; //dioda zapalona - wartosc 0, zgaszona 1 int start(); int xl_wait(); int l_wait(); int s_wait(); int int wyswietl_trajektorie(int n,int wybor); int zapal(int poz,int kolor); int wygas(); int dodawanie_trajektorii(int n); int read_input(); void main() long i,j; int menu=0,menu1=1,menu2=1,menu3=1,menu4=1; int blad; cli(); lcd_ini(); //inicjalizacja wyswietlacza uart_ini(); lcd_writetext(" Politechnika "); lcd_gotoline(2); lcd_writetext(" Wroclawska "); xl_wait(); lcd_writetext(" Tarcza dla "); lcd_gotoline(2); lcd_writetext(" IRb-1400 "); xl_wait(); lcd_cls(); //wyczysc ekran DDRB = 0b00000111; //wyjscia do obslugi multiplexerow DDRA &= ~_BV(PA6); //wejscia do odczytu diod DDRA &= ~_BV(PA7); PORTA &= ~_BV(PA6); //bez podciagania do plusa PORTA &= ~_BV(PA7); DDRB = 0b00111000; //wyjscia do obslugi demultiplexerow DDRB &= 0b00111111; //wejscia do obslugi klawiatury (PD6, PD7) PORTB = 0b11000000; //wejscia do klawiatury z wewnetrznym podciaganiem DDRD = 0b00111100; //wyjscia zasilania LED'ek DDRD &= 0b00111111; //wejscia obslugi klawiatury (PC6, PC7) PORTD = 0b11000000; //wejscia do klawiatury z wewnetrznym podciaganiem DDRD = _BV(PD0); //RXD jako wejscie DDRD &= ~_BV(PD1); //TXD jako wyjscie while(1) switch (menu) //glowne menu wyboru case 0: lcd_writetext(" Witaj :-) "); lcd_writetext(" Nacisnij -> ");
break; case 1: lcd_writetext(" Wybor "); lcd_writetext(" trajektorii "); break; case 2: lcd_writetext(" Trajektroria "); lcd_writetext(" wlasna "); break; case 3: lcd_writetext(" Test "); lcd_writetext(" diodowy "); break; case 4: lcd_writetext(" Wlacz "); lcd_writetext(" tarcze "); break; case 5: lcd_writetext(" Tworcy "); lcd_writetext(" "); break; s_wait(); //odczyt klawiatury if (p3) menu--; if (menu<1) menu=5; l_wait(); if (p4) menu++; if (menu>5) menu=1; l_wait(); if ((p1)&&(menu==1)) menu1=1; lcd_writetext(" Wyswietl "); lcd_writetext("trajektrorie: "); while(1) lcd_gotopos(2,15); itoa(menu1,text,10); lcd_writetext(text); s_wait(); if (p3) menu1--; if (menu1<1) menu1=4; l_wait(); if (p4) menu1++; if (menu1>4) menu1=1; l_wait(); if (p2) break; if (p1) wyswietl_trajektorie(menu1,0); if ((p1)&&(menu==2)) if (!lr) dodawanie_trajektorii(lr); else while (1) switch (menu2) case 1: lcd_writetext(" Zobacz "); lcd_writetext(" trajektorie "); break; case 2:
lcd_writetext(" Dodaj "); lcd_writetext(" trajektorie "); break; s_wait(); if (p3) menu2--; if (menu2<1) menu2=2; l_wait(); if (p4) menu2++; if (menu2>2) menu2=1; l_wait(); if (p2) break; if ((p1)&&(menu2==2)) dodawanie_trajektorii(lr); if ((p1)&&(menu2==1)) menu3=1; lcd_writetext(" Wyswietl "); lcd_writetext("trajektrorie: "); while(1) lcd_gotopos(2,15); itoa(menu3,text,10); lcd_writetext(text); s_wait(); if (p3) menu3--; if (menu3<1) menu3=lr; l_wait(); if (p4) menu3++; if (menu3>lr) menu3=1; l_wait(); if (p2) break; if (p1) wyswietl_trajektorie(menu3,1); if ((p1)&&(menu==3)) while(1) read_input(); for (i=0;i<16;i++) if (!diody[i]) zapal(i+1,1); l_wait(); wygas(); if (p2) break; if ((p1)&&(menu==4)) while(1) lcd_writetext(" Wybierz "); lcd_writetext("trajektrorie: "); lcd_gotopos(2,15); itoa(menu4,text,10); lcd_writetext(text); lcd_writetext(" "); s_wait(); if (p3) menu4--; if (menu4<1) menu4=4+lr; l_wait(); if (p4) menu4++; if (menu4>4+lr) menu4=1; l_wait(); if (p2) break; if (p1) blad=start(menu4); itoa(blad,text,10); lcd_cls(); lcd_writetext("l. bledow: ");
lcd_writetext(text); lcd_writetext(" "); lcd_writetext("nacisnij klawisz"); sei(); uart_putc(0x01); //rozpoczecie nadawania uart_putc(0x1e); //rozkaz - blad uart_putc(blad); //przeslanie na RS liczby popelnionych bledow uart_putc(0x0d); //zakonczenie nadawania while (1) s_wait(); if ((p1) (p2) (p3) (p4)) break; if ((p1)&&(menu==5)) lcd_writetext("mariusz "); lcd_writetext("zalewski "); xl_wait(); lcd_writetext("krzysztof "); lcd_writetext("klempa "); xl_wait(); int read_key() p1=p2=p3=p4=0; if bit_is_clear(pinb,pb6) p1=1; if bit_is_clear(pinb,pb7) p2=1; if bit_is_clear(pind,pd6) p3=1; if bit_is_clear(pind,pd7) p4=1; return 0; //funkcja odczytujaca stan klawiatury //odczyt do zmiennych globalnych p1,p2,p3,p4 int wyswietl_trajektorie(int n,int wybor) long j=0; int i=0; for (i=0;i<10;i++) if (!wybor) zapal(t[n-1][i],1); if (wybor) zapal(tr[n-1][i],1); lcd_cls(); lcd_writetext(" Punkt: "); itoa(i+1,text,10); lcd_writetext(text); lcd_writetext(" "); lcd_writetext(" Wartosc: "); if (!wybor) itoa(t[n-1][i],text,10); if (wybor) itoa(tr[n-1][i],text,10); lcd_writetext(text); lcd_writetext(" "); l_wait(); l_wait(); //odczekaj chwilke
wygas(); //zgas wszystkie diody lcd_writetext(" Wyswietl "); lcd_writetext("trajektrorie: "); return 0; int zapal(int poz,int kolor) int linia,demux; //linia - zasilanie, demux - sciaganie do masy if (kolor) linia=((poz-1)/4); //zasilenie odpowiedniej linii demux=((poz-1)%4)*2; //podciagniecie do masy odpwiedniej linii if (!kolor) linia=((poz-1)/4); demux=((poz-1)%4)*2+1; PORTB &= 0b11000111; //zerowanie portow dla demultipleksera PORTB = demux<<3; //przeslanie wartosci PORTD &= 0b11000011; //zerowanie linii zasilania PORTD = 0x01<<(linia+2); //ustawienie linii sei(); uart_putc(0x01); //rozpoczecie nadawania uart_putc(0x1d); //rozkaz - dioda uart_putc(poz); //przeslanie na RS pozycji zapalonej diody uart_putc(kolor); //przeslanie na RS koloru zapalonej diody uart_putc(0x0d); //zakonczenie nadawania int wygas() PORTD &= 0b11000011; //zerowanie lini zasilajacej diody return 0; int dodawanie_trajektorii(int n) long j=0; int i=0,war=1; lcd_cls(); lcd_writetext("punkt: "); lcd_writetext("<- ->"); lr++; l_wait(); while (i<10) lcd_gotopos(1,8); itoa(i+1,text,10); lcd_writetext(text); lcd_writetext(" "); lcd_gotopos(2,4); lcd_writetext(" "); lcd_gotopos(2,4); itoa(war,text,10); lcd_writetext(text); zapal(war,1); s_wait(); if (p3) war--; if (war<1) war=16; l_wait(); if (p4) war++; if (war>16) war=1; l_wait(); if (p1) tr[n][i++]=war; zapal(war,0); l_wait(); if (p2)
wygas(); l_wait(); return 0; i--; l_wait(); if (i<1) i=1; int xl_wait() long j; for (j=0;j<500000;j++) asm("nop"); return 0; int l_wait() long j; for (j=0;j<50000;j++) asm("nop"); return 0; int s_wait() int j; for (j=0;j<10000;j++) asm("nop"); return 0; int read_input() int j; int multiplex; for (multiplex=0;multiplex<8;multiplex++) PORTB &= 0x0F8; PORTB = multiplex; for (j=0;j<100;j++) asm("nop"); if bit_is_clear(pina,pa6) diody[multiplex]=1; else diody[multiplex]=0; if bit_is_clear(pina,pa7) diody[multiplex+8]=1; else diody[multiplex+8]=0; return 0; int start(int traj) int n=0,e=0,i; traj--; lcd_cls(); lcd_writetext(" Przygotuj sie! "); xl_wait(); lcd_writetext(" 3 "); l_wait(); lcd_writetext(" 2 "); l_wait(); lcd_writetext(" 1 "); l_wait(); lcd_writetext(" START "); l_wait(); while(n<10) lcd_writetext(" Punkt: "); itoa(n+1,text,10);
lcd_writetext(text); lcd_writetext(" "); lcd_writetext(" Oczekiwany: "); if (traj<4) itoa(t[traj][n],text,10); else itoa(tr[traj-4][n],text,10); lcd_writetext(text); lcd_writetext(" "); s_wait(); read_input(); if (p2) break; for (i=0;i<16;i++) if (!diody[i]) if (traj<=4) if (t[traj][n]==i+1) zapal(i+1,1); else zapal(i+1,0); e++; if (traj>4) if (tr[traj-4][n]==i+1) zapal(i+1,1); else zapal(i+1,0); e++; l_wait(); l_wait(); l_wait(); n++; wygas(); continue; return e; lcd.cpp #include <avr/io.h> #include <avr/delay.h> #define CPU 1000000 void delay(int us) _delay_loop_2(((cpu/4000)*us)/100); // czekaj µs void lcd_flash_e () PORTA = _BV(PD5); delay(1); PORTA &= ~_BV(PD5) ; delay(32); // Enable = HIGH // krotki impuls // Enable = LOW // czekaj az LCD odbierze dane void lcd_write (uint8_t data, uint8_t rs) uint8_t databits ; if (rs) // write data (RS=1, RW=0) databits=0x10; // RS liegt an Pin 4 = B 0001 0000 = H 10 else // write instruction (RS=0, RW=0) databits=0; PORTA = databits (data>>4); lcd_flash_e (); PORTA = databits (data&0x0f); g lcd_flash_e (); delay(50); // lcd clear
void lcd_cls () lcd_write(0x02,0); delay(50); lcd_write(0x01,0); delay(50); void lcd_writechar ( char zeichen) lcd_write (zeichen, 1); void lcd_writetext ( char *text) uint8_t i = 0; while (text[i]!=0) lcd_writechar(text[i]); i++; void lcd_gotoline (uint8_t zeile) if (zeile == 1) lcd_write(0x80,0); if (zeile == 2) lcd_write(0xc0,0); void lcd_gotopos (uint8_t zeile, uint8_t spalte) if (zeile == 1) lcd_write(0x80+spalte-1,0); if (zeile == 2) lcd_write(0xc0+spalte-1,0); void lcd_ini () DDRA = 0x3F; PORTA=0x00; delay(10000); lcd_write(0x03,0); lcd_write(0x03,0); lcd_write(0x03,0); lcd_write(0x02,0); delay(1000); lcd_write(0x28,0); lcd_write(0x08,0); lcd_cls(); lcd_write(0x0c,0); //seria inicjalizacyjna //czyszczenie z powrotem na pocz linii //bez kursora bez mrugania uart.h #include <avr/signal.h> #include <avr/interrupt.h> #define UART_BAUD_RATE 2400 #define UART_BAUD_CALC(UART_BAUD_RATE,F_CPU) ((F_CPU)/((UART_BAUD_RATE)*16l)-1) #define RBUFFLEN 40 //Dlugosc bufora dla odbioru szeregowego volatile unsigned char rbuff[rbufflen]; volatile uint8_t rbuffpos, rbuffcnt, udr_data; SIGNAL (SIG_UART_RECV) udr_data= UDR; if(rbuffcnt < RBUFFLEN) rbuff[(rbuffpos+rbuffcnt++) % RBUFFLEN] = udr_data; void uart_putc(unsigned char c) while(!(ucsra & (1 << UDRE))); UDR = c; // czekaj na gotowosc UDR // wyslij znak
void uart_puts (char *s) while (*s) // tak dlugo az *s!= NULL uart_putc(*s); s++; void uart_ini () sei(); // Uruchumienie obsługi przerwan UCSRB = (1 << TXEN); // zalaczenie UART TX (wysyalnie) UCSRB = (1 << RXEN ); // zalaczenie UART RX (odbieranie) UCSRB = (1 << RXCIE); // Wyzwowlenie przerwanie dla przychodzacych danych UCSRC = (1<<URSEL) (3<<UCSZ0); // Asynchronicznie, 8N1 UBRRH=(uint8_t)(UART_BAUD_CALC(UART_BAUD_RATE,F_CPU)>>8); // Wybor predkosc w Baudach UBRRL=(uint8_t)UART_BAUD_CALC(UART_BAUD_RATE,F_CPU);