Sprawozdanie koocowe Systemy wbudowane. Projekt własny - na układzie Atmega32: Kompas

Podobne dokumenty
Wyświetlacz alfanumeryczny LCD zbudowany na sterowniku HD44780

Programowanie Mikrokontrolerów

Mikroprocesory i Mikrosterowniki Magistrala szeregowa I2C / TWI Inter-Integrated Circuit Two Wire Interface

GND(VSS) i VCC - masa i zasilanie. V0 - regulacja kontrastu

Zewnętrzne układy peryferyjne cz. 1 Wykład 12

Komunikacja w mikrokontrolerach. Magistrala szeregowa I2C / TWI Inter-Integrated Circuit Two Wire Interface

Wbudowane układy komunikacyjne cz. 1 Wykład 10

Magistrala I 2 C. Podstawy systemów mikroprocesorowych. Wykład nr 5 Interfejsy szeregowe c.d.

TECHNIKA MIKROPROCESOROWA

1.2 Schemat blokowy oraz opis sygnałów wejściowych i wyjściowych

Komunikacja w mikrokontrolerach Laboratorium

Programowanie mikrokontrolerów AVR z rodziny ATmega.

Zespół Szkół Technicznych. Badanie wyświetlaczy LCD

Instytut Teleinformatyki

Politechnika Wrocławska

Instytut Teleinformatyki

Komunikacja w mikrokontrolerach Laboratorium

Opis procedur asemblera AVR

4 Transmisja szeregowa na przykładzie komunikacji dwukierunkowej z komputerem PC, obsługa wyświetlacza LCD.

Programowanie mikrokontrolerów. 15 stycznia 2008

Komunikacja w mikrokontrolerach Laboratorium

Programowanie mikrokontrolerów

Wydział Elektryczny. Katedra Automatyki i Elektroniki. Instrukcja. do ćwiczeń laboratoryjnych z przedmiotu: SYSTEMY CYFROWE 1.

4 Transmisja szeregowa, obsługa wyświetlacza LCD.

Systemy wbudowane. Uniwersytet Łódzki Wydział Fizyki i Informatyki Stosowanej. Witold Kozłowski

Mikroprocesory i mikrosterowniki Wydział Elektroniki Mikrosystemów i Fotoniki Politechniki Wrocławskiej Ćwiczenie nr 4

Obługa czujników do robota śledzącego linie. Michał Wendland czerwca 2011

ĆWICZENIE 5. TEMAT: OBSŁUGA PORTU SZEREGOWEGO W PAKIECIE KEILuVISON WYSYŁANIE PORTEM SZEREGOWYM

MODBUS RTU wersja M1.14 protokół komunikacyjny wyświetlaczy LDN

Alfanumeryczny wyświetlacz LCD

Układ transmisji szeregowej AVR

Podstawy systemów mikroprocesorowych. Interfejs USART. Interfejsy szeregowe w mikrokontrolerach AVR

Mikroprocesory i Mikrosterowniki Laboratorium

2. Architektura mikrokontrolerów PIC16F8x... 13

PRUS. projekt dokumentacja końcowa

Programowanie mikrokontrolerów AVR z rodziny ATmega.

Szkolenia specjalistyczne

Laboratorium mikroinformatyki. Szeregowe magistrale synchroniczne.

Programowanie w językach asemblera i C

Gdzie przyjęto, że: IR7...IR4 to starsze bity przesyłanej danej lub rozkazu, IR3...IR0 to młodsze bity przesyłanej danej lub rozkazu.

LABORATORIUM ENERGOOSZCZĘDNEGO BUDYNKU

Instrukcja integracji urządzenia na magistrali Modbus RTU. wersja 1.1

4. Karta modułu Slave

Wizualizacja stanu czujników robota mobilnego. Sprawozdanie z wykonania projektu.

Programowanie mikrokontrolerów. 8 listopada 2007

Cwiczenie nr 1 Pierwszy program w języku C na mikrokontroler AVR

dokument DOK wersja 1.0

interfejs szeregowy wyświetlaczy do systemów PLC

Obsługa modułu wyświetlacza LCD

Niektóre piny mogą pełnić różne role, zależnie od aktualnej wartości sygnałów sterujących.

PROJECT OF FM TUNER WITH GESTURE CONTROL PROJEKT TUNERA FM STEROWANEGO GESTAMI

Uniwersalny asynchroniczny. UART Universal Asynchronous Receier- Transmiter

Poradnik programowania procesorów AVR na przykładzie ATMEGA8

Podstawowe urządzenia peryferyjne mikrokontrolera ATmega8 Spis treści

Instytut Teleinformatyki

Terminal WSP dla sygnalizatorów wibracyjnych

Projekt MARM. Dokumentacja projektu. Łukasz Wolniak. Stacja pogodowa

IIPW_SML3_680 (Z80) przewodnik do ćwiczeń laboratoryjnych

Zygmunt Kubiak Instytut Informatyki Politechnika Poznańska

Inż. Kamil Kujawski Inż. Krzysztof Krefta. Wykład w ramach zajęć Akademia ETI

Hardware mikrokontrolera X51

MOBOT-RCR v2 miniaturowe moduły radiowe Bezprzewodowa transmisja UART

Mikroprocesory i Mikrosterowniki Liczniki Timer Counter T/C0, T/C1, T/C2

Pracownia Transmisji Danych, Instytut Fizyki UMK, Toruń. Instrukcja do ćwiczenia nr 10. Transmisja szeregowa sieciami energetycznymi

INSTRUKCJA instalacji interfejsu USB-RS422/485

Uproszczony schemat blokowy zespołu 8-bitowego timera przedstawiono na rys.1

Listing_ $crystal = deklaracja

2.1 Porównanie procesorów

Start Bity Bit Stop 1 Bit Par Rys. 1

1. Wprowadzenie Programowanie mikrokontrolerów Sprzęt i oprogramowanie... 33

Przemysłowy odtwarzacz plików MP3

1. Poznanie właściwości i zasady działania rejestrów przesuwnych. 2. Poznanie właściwości i zasady działania liczników pierścieniowych.

Wbudowane układy peryferyjne cz. 2 Wykład 8

TECHNIKA MIKROPROCESOROWA

MultiTool instrukcja użytkownika 2010 SFAR

Uczeń/Uczennica po zestawieniu połączeń zgłasza nauczycielowi gotowość do sprawdzenia układu i wszystkich połączeń.

Architektura komputera. Dane i rozkazy przechowywane są w tej samej pamięci umożliwiającej zapis i odczyt

MSW8-LPM. wersja 0.1 (wersja robocza) Dokumentacja użytkownika

Mikrokontrolery AVR Wprowadzenie

WIZUALIZACJA DANYCH SENSORYCZNYCH Sprawozdanie z wykonanego projektu. Jakub Stanisz

Sterownik procesorowy S-2 Komunikacja RS485 MODBUS

2. Format danych i zaimplementowane funkcje MODBUS

Instrukcja do oprogramowania ENAP DEC-1

Sterownik PLC ELPM-8DI8DO z aplikacją ELPM-8DI8DOasRoleta wersja v

INSTRUKCJA PANEL STERUJĄCY MT-5

TV LCD LED Samsung seria UE**Fxxxx

Moduł Ethernetowy. instrukcja obsługi. Spis treści

Opis czytnika TRD-FLAT 2LN ver Naścienny czytnik transponderów UNIQUE w płaskiej obudowie

SZYMAŃSKI ŁÓDŹ Ul. Wiskicka 22 Tel./fax. (042) Tel./fax. (042) Kom

1 Moduł Modbus ASCII/RTU

Interfejsy komunikacyjne pomiary sygnałów losowych i pseudolosowych. Instrukcja do ćwiczenia laboratoryjnego

Zaliczenie Termin zaliczenia: Sala IE 415 Termin poprawkowy: > (informacja na stronie:

start Program mikroprocesorowego miernika mocy generowanej $crystal = deklaracja

INSTRUKCJA instalacji interfejsu USB-RS422/485

TECHNIKA MIKROPROCESOROWA II

3.2. Zegar/kalendarz z pamięcią statyczną RAM 256 x 8

Kod produktu: MP01105

Wyjście do drukarki Centronix

Rozdział ten zawiera informacje na temat zarządzania Modułem Modbus TCP oraz jego konfiguracji.

Funkcje standardowej biblioteki wejść-wyjść do wyświetlania i pobierania danych

Transkrypt:

Artur Majewski lider 143027 szelest@stud.ics.p.lodz.pl Ewa Szewczyk 143108 Michał Orzełek 143053 (grupa laboratoryjna czwartek 12.45) Sprawozdanie koocowe Systemy wbudowane Projekt własny - na układzie Atmega32: Kompas Wykorzystane urządzenia peryferyjne: - kompas CMPS03 - wyświetlacz LCD HD44780 - przyciski - diody - połączenie z komputerem (USB USART) Wykorzystane funkcjonalności MCU: - porty IO (do diod i przycisków) - UART (komunikacja z komputerem) - timer - przerwania - I 2 C

1. Zakres obowiązków poszczególnych członków grupy Funkcjonalności zrealizowane w ramach I checkpointu (odczyt z kompasu i komunikacja z PC) zostały zaimplementowane głównie przez kierownika grupy. Kod obsługi magistrali TWI pisał kierownik grupy razem z Michałem Orzełkiem. Funkcjonalności na II checkpoint (LCD i diody) były zadaniem Michała. Funkcjonalności na III checkpoint obsługa przycisków (wybór pożądanego azymutu) oraz logika aplikacji (wyświetlenie na LCD i przy użyciu diod odchylenia od wybranego kierunku), zostały zrealizowane przez Ewę Szewczyk (przy czym obsługa przycisków była wstępnie przedyskutowana przez wszystkich członków grupy). Odpowiadające poszczególnym funkcjonalnościom części sprawozdania zostały napisane przez odpowiednich członków grupy. 2. Opis działania programu instrukcja użytkownika (i prezentacja działania na zrzutach ekranu oraz opis działania sprzętu) 2.1. I checkpoint Zrealizowany układ odczytuje przez I 2 C dane z kompasu elektronicznego (azymut w postaci jednego bajta typu unsigned char, de facto liczby od 0 do 255, gdzie 0 to północ geograficzna) i przesyła je w postaci stringa (char*), zawierającego liczbę do komputera PC przez port USB(przy użyciu FT232: 9600 bps, 8 bitów danych, bity parzystości: None, bity stopu: 1). Czujnik kompasu jest skalibrowany dla szerokości magnetycznej Polski). Dane przesyłane są co 50 ms. Orientacja kompasu: kompas jest skierowany na północ (przesyła 0), jeśli piny połączeniowe są skierowane w dół, a odpowiadająca im strona urządzenia wskazuje południe. Przykładowy zrzut ekranu, prezentujący działanie (z punktu widzenia komputera PC

2.2 II checkpoint W ramach II checkpointu, zrealizowany układ obsługuje: wyświetlacz LCD (układ HD44780) oraz zestaw ośmiu diod. Głównym celem wyświetlacza jest przedstawienie wcześniej odczytanych przez kompas danych w postaci liczb z przedziału 0-255, mając do dyspozycji dwa wiersze po szesnaście znaków każdy. W naszym przypadku, gdy uzyskana wartośd wynosi 0, wyznacza przy tym geograficzną północ. Zaś wartośd 128 określa kierunek południowy. Funkcjonalnośd diod również polega na określeniu kierunku w jakim w danym momencie ustawiony jest kompas. Odbywa się to według przyjętego przez nas schematu: - Gdy urządzenie skierowane jest na północ zapalamy diody: Zapalone 2 środkowe diody - Jeśli przechylone trochę (do 1/8 kąta pełnego) w stronę wschodu: - Jeśli przechylone od 1/8 do 2/8 kąta pełnego: - Jeśli przechylone od 2/8 do 3/8 kąta pełnego: - Jeśli przechylone od 3/8-4/8 kąta pełnego:

ale nie dla kąta półpełnego, czyli 180 stopni - Jeśli skierowane na południe dla kąta półpełnego Przechylanie urządzenia na zachód (licząc od północy), odpowiednio: 2.3 Wersja koocowa W ostatecznej wersji dodano obsługę przycisków. Pierwszy przycisk umożliwia przełączenie się pomiędzy trybem wyboru azymutu, na jaki urządzenie ma nas kierowad (tak, jak w poprzednim podpunkcie), a trybem wyświetlania azymutu względem północy (zmiana dotyczy zarówno LCD, jak i diod; dane wysyłane przez USB pozostają takie same). Wybieramy azymut od 0 do 350 - przy pomocy przycisków nr 2 i 3 (pierwszy zmniejsza wartośd o 10, lub ustawia 350, jeśli uprzednio wynosiła 0; drugi zwiększa o 10 lub ustawia 0, jeśli było 350). Stany przycisków są sprawdzane cyklicznie, więc po 100 ms dla pierwszego przycisku lub 50 dla pozostałych następuje reakcja). Po wyborze, na LCD pojawia się kąt, o jaki należy przekręcid urządzenie (od 0 do 180) i strzałeczka, określająca kierunek obrotu, np.: Azymut do 200 108-> Diody w trybie wyboru azymutu działają analogicznie do II checkpointu, wskazując jednak wybrany kierunek (niekoniecznie północ).

3. Opis działania programu (od strony programisty) 3.1 Odczyt z kompasu przez TWI 3.1.1 Teoria I 2 C (od IIC Inter Integrated Circuit, czyli Pomiędzy układami scalonymi jest szeregową, dwukierunkową magistralą, zaprojektowaną w celu przesyłania danych między układami elektronicznymi. W przypadku produktów Atmela, interfejs I2C określany jest (ze względów licencyjnych) jako TWI (Two Wire Interface). Standard I2C zakładał istnienie jednego urządzenia typu master, tj. takiego, które może inicjowad transmisję, jednak dzięki istnieniu mechanizmu detekcji kolizji, możliwa jest praca w trybie multi-master. Ilośd urządzeo slave (zaadresowanych przez mastera) jest natomiast ograniczona 7-bitową przestrzenią adresową, co oznacza, iż może ich byd maksymalnie 128. TWI (przyjmijmy termin Atmela ze względu na użycie układu ATmega) wykorzystuje do transmisji dwie dwukierunkowe linie, SDA (Serial DAta line) i SCL (Serial CLock Line), obie muszą byd stale podciągnięte do źródła zasilania przez rezystor podciągający. Transmisja jest inicjowana i przerywana przez urządzenie master (poprzez wydawanie przez niego warunków START i STOP na magistralę). Pomiędzy tymi warunkami, magistrala jest uznawana za zajętą. Wyjątkiem jest nadanie nowej sekwencji START pomiędzy START a STOP oznacza to, iż master zaczyna nową transmisję bez zwalniania linii. Adres układu na magistrali TWI ma 9 bitów. Poza wspomnianymi siedmioma, określającymi adres, jeden bit określa zapis / odczyt (1 odczyt), i jeden jest bitem potwierdzenia (ACK). Sekwencja adresująca zawiera adres slave a i bit odczytu (1) / zapisu (0). Adres slave jest dowolny, poza 0000 000 (do wszystkich slave). Dane przesyłane przez TWI mają również 9 bitów, 8 danych i jeden potwierdzenia. Za przesyłanie bitu potwierdzenia (0), odpowiedzialny jest slave. Działanie magistrali wiąże się z kilkoma rejestrami: - TWDR (Data Register), zawierający wysyłane lub odebrane dane. - TWAR (Adress Register) powinien zawierad adres slave, gdy układ pracuje w trybie slave - TWSR (State Register) bity 1 i 0 określają wartości prescalera bitrate, bity 3..7 odzwierciedlają stan układu TWI i magistrali - TWCR (Control Register) Algorytm transmisji (odbioru) danych przez TWI jest następujący:

1) TWI wysyła sekwencję startową odbywa się to poprzez ustawienie odpowiedniej wartości w TWCR (ustawienie bitów TWSTA, TWINT, TWEN). 2) Aplikacja powinna sprawdzid w TWSR, czy sekwencję wysłano poprawnie 3) Ładujemy daną do wysłania (lub adres danej do odebrania) do TWDR i ustawiamy TWCR. Zerujemy TWINT, żeby zacząd transmisję. 4) Sprawdzamy, czy adres został wysłany poprawnie poprzez wartośd TWSR 3.1.2. Implementacja W naszym programie korzystamy z gotowych funkcji (komentarze własne): void TWI_Start(void) //sekwencja startowa TWCR = (1<<TWINT) (1<<TWSTA) (1<<TWEN); while (!(TWCR & (1<<TWINT))); a następnie TWI_Write(0xC0); // adres (implementacja funkcji jest następująca: char TWI_Write(char data) //wysyła /data/ przez TWI TWDR = data; //dana do wysłania / adres TWCR = (1<<TWINT) (1<<TWEN); //sekwencja startowa while (!(TWCR & (1<<TWINT))); //sprawdzamy czy TWINT==0, czy można odbierać if((twsr == ADRW_ACK) (TWSR == DATA_ACK)) //sprawdzamy, czy wysłanie ok przez TWSR return 0; else return 1; Ponieważ odczyt danych spod konkretnego adresu odbywa się tak, że master najpierw wysyła adres sprzętowy uzupełniony zerem, później adres komórki pamięci, a później

po ponownym wygenerowaniu sygnału START ponownie adres, tym razem jedynką; odczyt danych z naszego urządzenia (kompasu CMPS03) wygląda tak: TWI_Write(0xC0); // adres urzadzenia - ostatni bit WRITE TWI_Write(0x01); //z http://www.robotelectronics.co.uk/htm/cmps3tech.htm TWI_Start(); TWI_Write(0xC1); ctrlregister = TWI_Read(NACK); Na koniec generujemy sygnał STOP funkcją TWI_Stop() o następującej treści: TWCR = (1<<TWINT) (1<<TWEN) (1<<TWSTO); 3.2. Wysyłanie odczytu przez USART 3.2.1. Teoria USART - uniwersalny synchroniczny i ansynchroniczny odbiornik i nadajnik, jest urządzeniem szeregowym do transmisji danych. USART składa się z trzech modułów: generatora zegara, nadajnika i odbiornika Generator zegara może pracowad w czterech trybach: - zwykły asynchroniczny - asynchroniczny podwójnej prędkości - Master synchroniczny - Slave synchroniczny Rejestr UBRR (Baud Rate Register) przechowuje wartośd dla licznika, odliczającego w dół. Zawsze, gdy licznik wyniesie 0, generowany jest zegar. Chcąc obliczyd potrzebny do uzyskania danego baud rate przy określonej częstotliwości taktowania mikrokontrolera, korzystamy ze wzoru: BAUD = fck / (16(UBRR+1)) W ramach inicjalizacji USART należy określid szybkośd transferu, poprzez zapisanie jej do pary rejestrów UBRRH i UBRRL (rejestrów szybkości transmisji). Następnie w rejestrze statusu i kontroli UCSRC określamy parametry ramki (ilośd bitów danych, parzystości, stopu). Transmisja (nadawanie) USART jest włączana poprzez ustawienie bitu TXEN w rejestrze UCSRB. Zwykłe operacje na portach są wtedy "nadpisane" przez USART.

Proste nadawanie jest operacją nieskomplikowaną: Sprawdzamy, czy flaga UDRE w rejestrze UCSRA (określająca, czy rejestr danych jest pusty) jest ustawiona. Jeśli tak, możemy zapisad wysyłaną daną w rejestrze UDR. 3.2.2. Implementacja W naszym programie najpierw inicjalizujemy transmisję (gotowa funkcja USART_Init(int baud)): UBRRH = (unsigned char)(baud>>8); //szybkość transferu UBRRL = (unsigned char)baud; //c.d. UCSRB = (1<<RXEN) (1<<TXEN);//odbiór i nadawanie (my tylko nadajemy) UCSRC = (1<<URSEL) (3<<UCSZ0); //parametry ramki URSEL: 1 bit parzystości i 8 (<<3) bitów w ramce a następnie wysyłamy dane w postaci ciągów charów, gotową funkcją: USART_PutString(char* s) while(*s) USART_PutChar(*s++); przy czym (również funkcja dostarczona przez producenta): void USART_PutChar(unsigned char data) while (!(UCSRA & (1 << UDRE))); //czeka aż flaga UDRE==1 UDR = data; //wysyła dane przez wpisanie do UDR 3.3 Wyświetlacz LCD 3.3.1 Teoria Obecnie, ze względu na swoją niską cenę, alfanumeryczne wyświetlacze LCD są bardzo często stosowane w układach zbudowanych w oparciu o mikrokontrolery. Wśród scalonych sterowników wyświetlaczy LCD od wielu lat najpopularniejszym rozwiązaniem jest układ HD44780. Interfejs i funkcjonalnośd tego układu stanowią nieformalny standard w dziedzinie alfanumerycznych modułów wyświetlających. Układ doczekał się kompatybilnych implementacji praktycznie u wszystkich wiodących producentów. Dane odczytywane z lub zapisywane do wyświetlacza przekazywane są przez magistralę DataBus (wyprowadzenia DB7 DB0). Sterowanie odbywa się na zasadzie wysyłania odpowiednich komend oraz zapisu danych do wewnętrznej pamięci wyświetlacza. Komendy i dane są rozróżniane na podstawie stanu linii RS (0 - komendy; 1 - dane). Kierunek transmisji jest określany stanem linii R/W. Sterownik HD44780 posiada dwa rodzaje pamięci : pamięd generatora znaków (CGROM) oraz pamięd danych (DD RAM). Pamięd generatora znaków

zawiera graficzną postad znaków wyświetlanych na wyświetlaczu (można porównad do czcionki). Oprócz znaków zdefiniowanych na stałe przez producenta sterownika do dyspozycji użytkownika pozostaje 8-znakowa pamięd RAM (CGRAM), w której można zdefiniowad własne znaki (np. polskie znaki diakrytyczne). Pamięd danych DD RAM ma pojemnośd 80 bajtów (jeden sterownik HD44780 może obsłużyd maksymalnie 80 znaków, czyli np. 2 linie po 40 znaków, lub 4 linie po 20 znaków). Poniższa tabela ukazuje zbiór rozkazów jakie oferuje sterownik kontrolera: 3.3.2. Implementacja Opis rozkazów (z zaznaczeniem ich implementacji w naszym kodzie): Display clear (RS=0, RW=0, magistrala DB= 0 0 0 0 0 0 0 1) wypełnienie wyświetlacza spacjami, przejście w tryb zapisu danych od pozycji w gornym, lewym rogu wyświetlacza, wyłączenie trybu przesuwania okna maksymalny czas wykonywania operacji 1,52ms, U nas gotowa funkcja: void LCD_Clear(void) LCD_WriteCommand(HD44780_CLEAR); //0x01 _delay_ms(2);, gdzie void LCD_WriteCommand(unsigned char commandtowrite) LCD_RS_PORT &= ~LCD_RS; _LCD_Write(commandToWrite);, natomiast:

void _LCD_Write(unsigned char datatowrite) LCD_E_PORT = LCD_E; _LCD_OutNibble(dataToWrite >> 4); LCD_E_PORT &= ~LCD_E; LCD_E_PORT = LCD_E; _LCD_OutNibble(dataToWrite); LCD_E_PORT &= ~LCD_E; _delay_us(50); Display/Cursor home (RS=0, RW=0, magistrala DB= 0 0 0 0 0 0 1 X gdzie X- nieistotne) - przejście w tryb zapisu danych od pozycji w górnym, lewym rogu wyświetlacza maksymalny czas wykonywania operacji 1,52ms, U nas: j.w. (LCD_WriteCommand) tym razem z wartością 0x02. Entry mode (RS=0, RW=0, magistrala DB= 0 0 0 0 0 1 I/D S) określa zachowanie się kursora podczas wprowadzania danych, bit I/D decyduje o kierunku przemieszczania się kursora po wprowadzeniu każdej danej, natomiast S umożliwia włączenie/wyłączenie przesuwania się kursora maksymalny czas wykonywania operacji 37μs, Display ON/OFF (RS=0, RW=0, magistrala DB= 0 0 0 0 1 D C B) odpowiada za sterowanie wyświetlaniem znakow, bit D włącza/wyłącza wyświetlacz, bit C odpowiada za wyświetlanie kursora a B czy ma byd on statyczny czy migający maksymalny czas wykonywania operacji 37μs, Display/Cursor shift (RS=0, RW=0, magistrala DB= 0 0 0 0 S/C R/L X X) odpowiada za przesuwanie wprowadzone tekstu, bit R/L decyduje o kierunku, natomiast S/C, czy ma byd przesuwany kursor czy całe okno - maksymalny czas wykonywania operacji 37μs, Function set (RS=0, RW=0, magistrala DB= 0 0 1 DL N F X X) opisuje podstawowe parametry pracy wyświetlacza, bit DL decyduje o trybie pracy magistrali, N o ilości wyświetlanych linii, natomiast F pozwala na wybór rodzaju matrycy znakowej - maksymalny czas wykonywania operacji 37μs,

CG RAM set (RS=0, RW=0, magistrala DB= 0 1 ADRES) ustala adres komórki i określa, że kolejna operacja odczytu/zapisu będzie dotyczyła pamięci CG - maksymalny czas wykonywania operacji 37μs, DD RAM set (RS=0, RW=0, magistrala DB= 1 ADRES) ustala adres komorki i określa, że kolejna operacja odczytu/zapisu będzie dotyczyła pamięci DD - maksymalny czas wykonywania operacji 37μs, U nas w LCD_GoTo(): LCD_WriteCommand(HD44780_DDRAM_SET (x + (0x40 * y))); Przy czym HD44780_DDRAM_SET = 0x80 oraz: void LCD_WriteCommand(unsigned char commandtowrite) LCD_RS_PORT &= ~LCD_RS; _LCD_Write(commandToWrite); Busy flag/address counter read (RS=0, RW=1, magistrala DB= BF ADRES) odczytuje bieżący adres pamięci oraz zwraca bit zajętości BF- maksymalny czas wykonywania operacji 0s, Data write (RS=1, RW=0, magistrala DB= zapisywana dana) zapis danej do wcześniej wybranej I zaadresowanej pamięci, (u nas: patrz niżej) Data read (RS=1, RW=1, magistrala DB= odczytywana dana) odczyt danej z wcześniej wybranej I zaadresowanej pamięci, Podstawowe funkcje, które tyczą się obsługi wyświetlacza dostarczone są przez producenta. Na przykład: LCD_Initialize(), LCD_GoTo() albo LCD_Clear(). Wypisanie na ekran wyświetlacza danych z kompasu wygląda następująco: LCD_GoTo(0,0); LCD_WriteText("Azymut: "); LCD_GoTo(0,1); LCD_WriteText(itoa(res/10,writeTAB2,10)) Gdzie LCD_GoTo(0,0) ustawia kursor na lewym górnym rogu. Funkcja LCD_WriteText( xxx ) wyświetli na ekranie tekst xxx. W naszym przypadku jest to wartośd odczytana z kompasu w postaci dziesiętnej. Biblioteczna definicja funkcji: void LCD_WriteText(char * text) while(*text) LCD_WriteData(*text++);

W pętli poruszając się po wskaźniku char a wywoływane jest LCD_WriteData: void LCD_WriteData(unsigned char datatowrite) LCD_RS_PORT = LCD_RS; _LCD_Write(dataToWrite); Przy czym procedura wyświetlenia znaku na ekranie wygląda następująco: Wyświetlenie znaku na LCD wymaga dwukrotnego przesłania danych do sterownika: 1) ustalenia adresu DDRAM na n, gdzie n jest pozycją znaku na wyświetlaczu (rozkaz: RS=0, RW=0, D7=1, D6-D0 = 0000011) U nas w LCD_GoTo: LCD_WriteCommand(HD44780_DDRAM_SET (x + (0x40 * y))); Przy czym HD44780_DDRAM_SET = 0x80 oraz: void LCD_WriteCommand(unsigned char commandtowrite) LCD_RS_PORT &= ~LCD_RS; _LCD_Write(commandToWrite); 2) zapisania stosownej danej (ośmiobitowego kodu znaku) do DDRAM (rozkaz: RS=1, RW=0, D7=1, D6-D0 = /dana/) U nas w LCD_WriteData(): LCD_RS_PORT = LCD_RS; _LCD_Write(dataToWrite); gdzie _LCD_Write(): LCD_E_PORT = LCD_E;//PORTA,(1 << PA6) _LCD_OutNibble(dataToWrite >> 4); LCD_E_PORT &= ~LCD_E; LCD_E_PORT = LCD_E;

gdzie _LCD_OutNibble(): void _LCD_OutNibble(unsigned char nibbletowrite) if(nibbletowrite & 0x01) LCD_DB4_PORT = LCD_DB4; else LCD_DB4_PORT &= ~LCD_DB4; if(nibbletowrite & 0x02) LCD_DB5_PORT = LCD_DB5; if(nibbletowrite & 0x04) LCD_DB6_PORT = LCD_DB6; else LCD_DB6_PORT &= ~LCD_DB6; (...) 3.4 Licznik Obsługa wyświetlacza odbywa się w ramach obsługi przerwania pochodzącego od układu porównującego licznika (licznika - timera). ISR(TIMER0_COMP_vect) //timer 0 - compare match //obsługa LCD i diod W funkcji main pozostaje zainicjalizowad timer 0 i uruchomid obsługę przerwao. To ostatnie odbywa się po prostu poprzez wywołanie funkcji: sei(); natomiast inicjalizacja timera wygląda tak: // inicjalizacja timera (licznika) T0 (8bitowego): void TimerInit(void)

TCCR0=0b00001100; //ustawienie licznika przez rejestr kontrolny // tryb CTC, prescaler: /256. OCR0=249;//0b11111010; //wartosc do ktorej porownujemy //(licznik jest //zerowany, gdy zliczy do 249 //wg wzoru: 16.000.000/(2* 256* (249+1)) //= 16 mln / 128*4*250 = 1 mln / 8*4*250 = 125.000 / 250 / 4 = 125.000 / 125 / 8=125 Hz TIMSK=TIMSK 0b00000010; //zezwolenie na przerwania od układu //porównującego licznika Licznik może byd taktowany wewnętrznie, poprzez prescaler (jak u nas) lub źródło zewnętrznego zegara dołączonego do wejścia T0. Wynik porównania rejestru komparatora (OCR0) jest stale porównywany z zawartością licznika i może byd użyty do wytworzenia przerwania. Istnieją 4 tryby pracy licznika. W normalnym np. licznik zawsze zlicza w górę i jest zerowany po zliczeniu do 0xFF. W trybie CTC, z którego korzystamy, używany jest rejestr OCR0. Licznik w tym trybie jest zerowany, gdy zliczy do wartości z owego rejestru i w ten sposób określamy jego rozdzielczośd. Częstotliwośd przebiegu jest określana wzorem: (n=0) U nas 16.000.000/(2* 256* (249+1)) = 125 Hz. Tak więc w naszym przypadku częstotliwośd wywoływania przerwania od przepełnienia timera wynosi 125 Hz. 3.5 Diody i algorytm wyznaczania odchylenia do wybranego azymutu (logika aplikacji) Schemat wyświetlania się diod został zaprezentowany wyżej. W celu zapalenia np. dwóch środkowych diodek należy na port do którego owe diody są podłączone (w naszym przypadku jest to port B) wysład wartośd 11100111. Zero oznacza włączenie diody, jedynka zaś jej wyłączenie. Aby wysład dane na port zamienia się wartośd binarną na dziesiętna. Dla powyższego przykładu będzie to wyglądało: 00011000(bin) = 24(dec) ~24 = 11100111, gdzie ~ jest operatorem negacji bitowej. W sytuacji, gdy chcemy zapalid dwie lampki po lewo od środka można również przeliczad na wartośd binarna, bądź wysład wartośd taką jak poprzednio (zanegowane 24), tylko

przesuniętą w lewo o 1, przy pomocy operatora przesunięcia bitowego w lewo <<. Wysyłane jest więc po prostu ~(24<<1). Implementacja tego jest następująca: (kod z II checkpointu, w wersji koocowej uległ pewnym uzupełnieniom opisane poniżej) if(ctrlregister==0) // jeśli wskazanie == północ PORTB=~(24);//CP 2: diodki, zanegowane 00011000 if(ctrlregister>=1 && ctrlregister<32) //>= niż północ, ale < niż(256/8) PORTB=~(24>>1); //zanegowane 00001100 if(ctrlregister>=32 && ctrlregister<64)//>= niż 256/8, ale mniej niż 2*(256/8) PORTB=~(24>>2); //zanegowane 00000110 if(ctrlregister>=64 && ctrlregister<96) // i tak dalej PORTB=~(24>>3); if(ctrlregister>=96 && ctrlregister<127) PORTB=~(24>>4); if(ctrlregister>=127 && ctrlregister<=129) //południe PORTB=~(129); // zanegowane 1000001 if(ctrlregister>129 && ctrlregister<=160)//> niż (256/8)*4, <= (256/8)*5 PORTB=~(24<<4); // if(ctrlregister>160 && ctrlregister<=192) PORTB=~(24<<3); if(ctrlregister>192 && ctrlregister<=224) PORTB=~(24<<2); if(ctrlregister>224 && ctrlregister<=255) PORTB=~(24<<1); W koocowej wersji programu, obliczamy odchylenie od wybranego kąta (ustawionego azymutu: if(wynik<2 wynik>-2) //ok 0 PORTB=~24; if(wynik>=2 && wynik<45) PORTB=~(24>>1); if(wynik>=45 && wynik<90) PORTB=~(24>>2); if(wynik>=90 && wynik<135) PORTB=~(24>>3); if(wynik>=135) PORTB=~(24>>4); if(wynik>=179 wynik<=-179) PORTB=~129; if(wynik<=-2 && wynik>-45) PORTB=~(24<<1); if(wynik<=-45 && wynik>-90)

PORTB=~(24<<2); if(wynik<=-90 && wynik>-135) PORTB=~(24<<3); if(wynik<=-135) PORTB=~(24<<4); Przy czym wartośd zmiennej wynik (a więc docelowy kierunek) obliczamy następująco: Początkowo sprawdzamy, w której połowie znajduje się azymut, czy w przedziale od 0 do 180 czy od 180 do 360. Następnie przy pomocy pięciu instrukcji if sprawdzamy, w którym przedziale znajduje się odczyt. Za pomocą obliczonych wartości dowiadujemy się o jaki kąt należy obrócid kompas aby wyznaczad kierunek azymutu. Algorytm jest bardzo prosty. Jeśli otrzymamy wynik poniżej zera to oznacza, że kompas powinien zostad obrócony w lewo. Jeśli wynik jest dodatni, analogicznie w prawo. Wartośd to różnica pomiędzy kątami, lub suma różnic pomiędzy kątami a kątem pełnym (np. dla azymutu 5 stopni i odczytu 355 stopni 5+5=10 stopni w lewo). int odczyt = (int)((float)ctrlregister*360.0/255.0); //odczytany azymut int azymut = (int)(ustawiony_azymut*10); //ustawiony (int) //wynik zmienia się w zależności od położenia wybranego kierunku i odczytu //zmienna będzie zawierać odchylenie od -180 do 180 if(azymut>=0 && azymut<180 && odczyt>azymut && odczyt<azymut+180) //azymut od północy przez wschód wynik = (odczyt-azymut); //do południa, odczyt w przeciwległej połowie "róży wiatrów" (... ) if(wynik>0) //wynik > 0 -> na LCD stosowna strzałka i wartość LCD_WriteText("<-"); LCD_WriteText(itoa((int)(wynik),writeTAB3,10)); else if(wynik<0) // <0 - analogicznie, wartość * - 1, bo interesuje nas moduł LCD_WriteText(" "); //wyrównanie na LCD LCD_WriteText(itoa((int)(-wynik),writeTAB3,10)); //* -1 LCD_WriteText("->"); else // wynik==0, nie ma strzałki LCD_WriteText(" "); //wyrównanie LCD_WriteText(itoa((int)(-wynik),writeTAB3,10));

3.6 Przyciski W koocowej wersji programu, dodano obsługę przycisków. Realizowana ona jest tak, że w pętli cyklicznie sprawdzamy, czy przycisk jest wciśnięty. if(!(pind&key)) //KEY ==1, pierwszy przycisk Oczywiście stosowne piny portu D zostały przedtem ustawione jako wejściowe: DDRD &= ~KEY; PORTD = KEY; DDRD &= ~KEY2; PORTD = KEY2; DDRD &= ~KEY3; PORTD = KEY3; Po wykryciu zmiany stanu przycisku odczekujemy 50 ms w celu zniwelowania drgao zestyków i kontroli nad wynikiem (tzn. żeby stan ustawianej flagi / wartości nie zmieniał się zbyt często) if (!(PIND&KEY) ) for(int i=0;i<5;i++) _delay_ms(10); if(!(pind&key)) if(tryb==0) tryb=1; ( ) 4. Analiza skutków awarii Zrealizowany układ kompas realizuje cztery zasadnicze funkcjonalności: odczyt danych z czujnika CMPS03, wysyłanie tych danych przez USB do komputera PC, wskazywanie północy bądź wybranego kierunku przy pomocy linijki diod i wyświetlacza LCD typu 2x16, oraz wskazywanie wybranego przy pomocy przycisków azymutu (też przy pomocy linijki diod i LCD). Za główną funkcjonalnośd należy uznad odczyt z czujnika danych i udostępnienie ich za pośrednictwem co najmniej jednego urządzenia wyjścia. Przyjmijmy, że przez awarię urządzenia we/wy rozumiemy uszkodzenie samego urządzenia (np. wyświetlacza LCD) lub połączenia (np. rozłączenie przewodu) pomiędzy tym urządzeniem a mikrokontrolerem. Awaria czujnika kompasu, lub awaria wszystkich urządzeo wyjściowych jednocześnie (USB, diody LED, LCD) jest awarią krytyczną w pierwszym przypadku system po prostu nie będzie spełniał swojej funkcji (czyli wskazywania kierunku), w drugim nie będzie możliwości poinformowania użytkownika o wyniku. Awarią krytyczną byłoby także takie uszkodzenie kabla lub gniazda USB, które uniemożliwiałoby zasilanie układu.

Uszkodzenie mikrokontrolera jest w ogólności awarią krytyczną (chyba że dotyczy np. tylko któregoś z portów obsługujących komunikację z urządzeniami wyjścia lub przyciskami). Awaria jednego lub dwóch z urządzeo wyjścia (USB wyłączając żyły zasilające, diody, LCD) ogranicza funkcjonalnośd układu, nie jest jednak awarią krytyczną czujnik wciąż może informowad o kierunku, w jakim jest skierowany za pośrednictwem pozostałych, działających urządzeo. Awaria wszystkich jednocześnie jest krytyczna działanie kompasu traci sens, jeśli użytkownik w żaden sposób nie jest informowany o odczycie. Uszkodzenie przycisków lub uszkodzenie, uniemożliwiające korzystanie z nich nie uniemożliwia poprawnego działania systemu. Określenie odchylenia od wybranego azymutu staje się mniej wygodne, ale wciąż jest możliwe. Podsumowanie skutków awarii elementów systemu: Element Mikrokontroler Kompas (czujnik CMPS03) Kabel USB - zasilanie Wyświetlacz LCD Diody (lub dioda) USB poza przewodami zasilającymi Przyciski Skutki Krytyczne Krytyczne Krytyczne Średnie Średnie Średnie Niegroźne Przy czym skutki krytyczne oznaczają, że system przestanie działad lub będzie działad, ale w sposób nieprawidłowy (np. LCD się świeci, ale nie ma odczytu z kompasu), średnie oznaczają, że uszkodzenie ma skutki krytyczne tylko, jeśli uszkodzone zostaną wszystkie elementy z tej grupy (w przeciwnym razie awarię traktujemy jako niegroźną), niegroźne funkcjonalnośd systemu zostanie ograniczona, ale awaria nie uniemożliwi mu działania w sposób całkowity. Potencjalne metody autodiagnozy awarii układu (i informowania o awarii): - uszkodzenie czujnika Jeśli czujnik ulegnie uszkodzeniu, to najprawdopodobniej przestanie przekazywad odczyt na magistralę I2C. Brak odczytu powinien więc powodowad wyświetlenie komunikatu na LCD, wysłanie komunikatu przez UART, oraz sygnalizację diodami np. poprzez naprzemienne zapalanie i gaśnięcie wszystkich (informacja byłaby jednoznaczna, ponieważ zapalenie oznaczałaby, że diody nie są uszkodzone, a jednocześnie w przypadku prawidłowej pracy układu, zgaśnięcie wszystkich diod nie jest możliwe). Można również założyd, że czujnik jest uszkodzony, jeśli odczytywane dane nie zmieniają się przez wybrany okres czasu, a warunki pracy urządzenia są takie, że powinny np. w wodnych środkach transportu. Należy zwrócid uwagę, iż urządzenie zawiera rejestry interfejsu I2C, umożliwiające przeprowadzenie testów wewnętrznych: Register Function 0 Software Revision Number, Rev14 or higher - for earlier Revisions click here

1 Compass Bearing as a byte, i.e. 0-255 for a full circle Compass Bearing as a word, i.e. 0-3599 for a full circle, representing 0-359.9 2,3 degrees. 4,5 Internal Test - Sensor1 processed difference signal - 16 bit signed word 6,7 Internal Test - Sensor2 processed difference signal - 16 bit signed word 8,9 Internal Test - Sensor1 raw data - 16 bit signed word 10,11 Internal Test - Sensor2 raw data - 16 bit signed word Unlock code1 - Unlock codes are required for I2C address change or restoring 12 factory calibration 13 Unlock code2 14 Unlock code3 15 Command Register - See text. Tabela z dokumentacji (w załączniku), na czerwono zaznaczono interesujące nas funkcje diagnostyczne. Jak widad, odczyt z rejestrów o adresach 0xC8 0xCB, to nieprzetworzone dane z sensorów. Umożliwiają one sprawdzenie, czy urządzenie nie działa niepoprawnie np. z powodu błędnej kalibracji. - uszkodzenie przycisków Możliwe jest także zdiagnozowanie niektórych uszkodzeo przycisków jeśli odczyt z któregoś pinu będzie przez bardzo długi okres czasu (zależnie od zastosowao, np. 1 minutę) wskazywał, że przycisk jest wciśnięty, należałoby wyświetlid na LCD (i wysład przez USB) informację o potencjalnym błędzie mogło nastąpid np. zwarcie. - diagnoza diod i LCD Uszkodzenie diod można łatwo wykryd (właściwie zasygnalizowad) przez np. zapalenie i zgaszenie ich (przez np. 1 s) na początku programu użytkownik, po uruchomieniu urządzenia zobaczy, że któraś dioda się nie pali. Jeśli chodzi o LCD, to HD44780 częściowo diagnozuje się sam jeśli kontroler wyświetlacza nie zostanie poprawnie zainicjowany, zapali się rząd prostokątów. Możemy także odczytad zawartośd pamięci CGRAM i/lub DDRAM i sprawdzid, czy nie są one uszkodzone (w przypadku pamięci DDRAM, oczywiście po jej zapisaniu). Informację o uszkodzeniu można, jak wyżej, przekazad poprzez diody (np. dwukrotne zapalenie i zgaszenie) lub USB. - uszkodzenie mikrokontrolera Możliwe jest zdiagnozowanie portów wejściowych i I2C (opisano wyżej), poza tym uszkodzenie mikrokontrolera lub np. odłączenie się go od reszty układu - spowoduje, że cały system przestanie działad (jest krytyczne).