Autor: Dondu
Artykuł jest częścią cyklu: SmartPIP - Elektroniczny dręczyciel
Nadszedł czas na przetestowanie opracowanego czujnika światła. Schemat układu testowego ograniczymy do niezbędnego minimum:
Do powyższego schematu należy dodać jedną z wersji interfejsu RS-232, które znajdziesz tutaj: RS-232: Komunikacja ATmega8 z komputerem. Na schemacie zaznaczyłem etykietami MIKR-RXD oraz MIKR-TXD piny, które należy połączyć z pinami interfejsu RS-232 oznaczonych tymi samymi etykietami.
Zamiast RS-232 możesz wykorzystać wyświetlacz LCD, ale to już opracuj we własnym zakresie.
Dioda LED dodana jest wyłącznie w celach testowych (np. gdyby terminal nie wyświetlał danych), więc nie musi być zamontowana. Jeżeli ją zamontujesz, to w kierunku zgodnym z powyższym schematem, by nie pobierała prądu z pinu mikrokontrolera. Rezystor diody LED oznaczony jako R2 jest nieco większy niż standardowy, ponieważ chcemy ograniczyć skoki prądu w czasie testów. Najlepszym rozwiązaniem będzie usunięcie diody w czasie, gdy terminal będzie prawidłowo odbierał dane.
Schemat naszego układu testowego w zakresie minimalnych podłączeń odpowiada wersji totalne minimum. Dlaczego stosujemy wersję "totalne minimum"? Ponieważ spokojnie wystarczy nam rozdzielczość pomiarowa 8-bitów, a dodatkowy kondensator na pinie AREF, to dodatkowa upływność, której nie chcemy w naszym SmartPIP'ie.
Opis algorytmu
Program przygotowany jest (jak w każdej części cyklu o SmartPIP'ie) w wersji wieloplikowej z podziałem na funkcjonalności:
- pomiar światła,
- komunikacja RS-232,
- program główny.
W programie na razie nie wykorzystujemy jeszcze licznika czasu, a opóźnienie między pomiarami wykonujemy za pomocą funkcji _delay_ms(x). Jest to celowy zabieg uproszczenia programu testowego, który w wersji wieloplikowej jest i tak (na pierwszy rzut oka) wystarczająco skomplikowany :-). Licznik czasu będziemy używać już w następnym artykule, gdzie dokonywać będziemy pierwszych pomiarów dobowych.
Do testowania czujnika będziemy dokonywać pomiarów światła z uwzględnieniem wykorzystania usypiania mikrokontrolera do trybu ADC Noise reduction, który jak już ustaliliśmy będziemy wykorzystywać w celu zwiększenia dokładności pomiaru i redukowania pobieranego prądu z baterii.
Dla potrzeb tego testu na stałe włączymy elementy czujnika światła (zasilanie czujnika i masę rezystora).
Wyniki pomiarów będziemy obserwować za pośrednictwem komputera podłączonego do mikrokontrolera za pomocą prostego interfejsu RS-232. Algorytm wysyłania opracowany jest dla wersji opartej o przerwania i tablicę bufora tekstu w pamięci SRAM mikrokontrolera.
dd_swiatlo.c
dd_swiatlo.h
Pliki te zawierają funkcjonalności dot. pomiaru światła za pomocą naszego czujnika z wykorzystaniem przetwornika ADC.
dd_swiatlo_adc_ini()
Funkcja odpowiedzialna za przygotowanie do pomiarów, czyli:
Włączenie czujnika - ustawienie odpowiednich stanów na pinach zasilania fototranzystora oraz masy rezystora, według ustalonych wcześniej zasad.
Inicjalizacja przetwornika ADC - ustawienie parametrów przetwornika ADC realizowane jest przez funkcję:
- ustawiamy kanał wejściowy ADC1 (PC1) zgodnie ze schematem,
- włączamy zasilanie czujnika światła oraz masę jego rezystora,
- ponieważ używamy tylko ośmiu najbardziej znaczących bitów, stąd wykorzystujemy dostępne w tym przypadku wyrównanie wyniku do lewej (ADLAR).
- preskaler ADC ustawiamy go na 8, co daje nam częstotliwość taktowania przetwornika ADC równą 125kHz (przy taktowaniu mikrokontrolera wewnętrznym generatorem RC o częstotliwości 1MHz).
- włączamy przerwania zakończenia pomiaru ADC, by móc wykorzystać tryb ADC Noise reduction oraz przygotowujemy odpowiedni tryb snu.
dd_swiatlo_adc_pomiar_start()
Funkcja ta zawiera jedynie rozkaz uśpienia mikrokontrolera dlatego, że tę funkcję będziemy rozbudowywać w dalszych artykułach o SmartPIP'ie.
ISR(ADC_vect)
Funkcja przerwania wywoływana po zakończeniu pomiaru przez przetwornik ADC jest pusta, a przyczyna wyjaśniona w komentarzu w kodzie. Podobnie jak funkcja powyżej, także i ta będzie rozbudowywana w dalszych artykułach.
Plik dd_swiatlo.c:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_swiatlo.c * Opis: Funkcjonalności dot. pomiaru światła **************************************************************************/ #include <avr/io.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include "dd_main.h" #include "dd_swiatlo.h" //------------------------------------------------------------------------- void dd_swiatlo_adc_ini(void){ //Funkcja włącza czujnik światła oraz inicjuje przetwornik ADC //KROK 1 - włącz czujnik światła //włącz zasilanie fototranzystora ADC_PIN_ZAS_DDR |= (1<<ADC_PIN_ZAS_NAZWA); //wyjście ADC_PIN_ZAS_PORT |= (1<<ADC_PIN_ZAS_NAZWA); //załącz napięcie //włącz masę rezystora pomiarowego ADC_PIN_REZ_DDR |= (1<<ADC_PIN_REZ_NAZWA);//wyjście ADC_PIN_REZ_PORT &= ~(1<<ADC_PIN_REZ_NAZWA);//załącz masę (zero) //KROK 2 - przygotuj przetwornik ADC //korzystamy tylko z 8 najbardziejznaczących bitów (wyrównanie do lewej) //częstotliwość ADC = 1MHz + preskaler 8 = 125kHz //ustaw pin pomiarowy ADC ADC_PIN_POM_DDR &= ~(1<<ADC_PIN_POM_NAZWA); //wejście ADC_PIN_POM_PORT &= ~(1<<ADC_PIN_POM_NAZWA); //wyłącz pull-up //inicjuj przetwornik ADC ADMUX = (1<<REFS0) //VCC jako napięcie referencyjne | (1<<ADLAR) //wyrównaj pomiar do lewej | ADC_PIN_POM_MUX; //przełącz na kanał wybranego pinu ADC ADCSRA = (1<<ADEN) //włącz ADC | (1<<ADIE) //włącz przerwania | (1<<ADPS0) //preskaler 8 | (1<<ADPS1); //ustaw tryb snu ADC Noise Reduction set_sleep_mode(SLEEP_MODE_ADC); sleep_enable(); } //------------------------------------------------------------------------- void dd_swiatlo_adc_pomiar_start(void){ //Funkcja odpowiedzialna za rozpoczęcie pomiaru światła //rozpocznij pomiar światła poprzez uśpienie mikrokontrolera sleep_cpu(); } //------------------------------------------------------------------------- ISR(ADC_vect){ //Przerwanie ADC - pomiar zakończony //Funkcja pusta ponieważ odczyt ADC dokonujemy w main() //tej funkcji nie można usunąć po nieważ pomiar światła //dokonywany jest w trakcie snu mikrokontrolera //a pomiar kończy się przerwaniem }
Plik dd_swiatlo.h:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_swiatlo.h * Opis: Plik nagłówkowy pliku dd_swiatlo.c *************************************************************************/ //Definicje pinów czujnika światła oraz ustawienia kanału multipleksera ADC //pin pomiarowy #define ADC_PIN_POM_DDR DDRC #define ADC_PIN_POM_PORT PORTC #define ADC_PIN_POM_NAZWA PC1 #define ADC_PIN_POM_MUX (1<<MUX0) //kanał multipleksera //pin zasilania czujnika #define ADC_PIN_ZAS_DDR DDRC #define ADC_PIN_ZAS_PORT PORTC #define ADC_PIN_ZAS_NAZWA PC0 //pin masy rezystora #define ADC_PIN_REZ_DDR DDRC #define ADC_PIN_REZ_PORT PORTC #define ADC_PIN_REZ_NAZWA PC2 //--- Funkcje ------------------------------- extern void dd_swiatlo_adc_ini(void); extern void dd_swiatlo_adc_pomiar_start(void);
dd_usart.c
dd_usart.h
Obserwacja wyników za pomocą RS-232 i terminal zrealizujemy, wykorzystują opisane wcześniej rozwiązanie wraz z omówieniem obsługi programu terminala Realterm. W związku z tym, nie będę tutaj opisywał dokładnie jak działa transmisja RS-232. Dodam jedynie tę część programu by można było ją przeanalizować.
Plik dd_usart.c:
Plik dd_usart.h:
dd_main.c
dd_main.h
Program główny zawiera jedynie funkcję main() wraz z niezbędnymi definicjami w pliku nagłówkowym.
Zadania:
Sądzę, że nie trzeba tutaj omawiać dokładnie każdego z powyższych punktów, bo są opisane w kodzie programu.
Fusebity
Należy wspomnieć, że poniższy program pracuje poprawnie z domyślnymi ustawieniami fusebitów (fabrycznymi), czyli:
Plik dd_main.c:
Plik dd_main.h:
Do pobrania
Poniżej link do spakowanego:
Plik: SmartPIP_Czujnik_testowanie.zip
Wyniki pomiarów
W przypadku mojej wersji czujnika światła i powyższego programu zgodnie z założeniami, czujnik na oświetlenie reaguje w sposób bardzo "agresywny", co przejawiać się będzie stromymi zboczami na wykresie pomiarów, gdyż już przy niewielkim oświetleniu wartości pomiarów szybko rosną.
Taka charakterystyka czujnika jest podyktowana wymogiem oszczędzania baterii i w niczym nam nie będzie przeszkadzać, a wręcz pomagać podczas analizy wyników przez program.
Efekt jaki powinieneś zobaczyć na terminalu Realterm, jest następujący:
Specjalnie pokazuję zakładkę Port, abyś wiedział jak ustawić parametry odbioru. Po ich ustawieniu kliknij przycisk Change. W prawym dolnym rogu są (w skrócie) pokazane aktualne ustawienia terminala - muszą być identyczne, by program działał poprawnie.
W zakładce Display, możesz włączyć opcję Ansi, co wyłączy pokazywanie znaków specjalnych:
Więcej o ustawieniach terminala Realterm pisałem tutaj.
Podsumowanie
Mamy już przetestowany i działający czujnik światła, o dość agresywnej charakterystyce. Jest on prosty i zużywa bardzo mało energii z baterii. Powinniśmy teraz przetestować jakie straty poniesiemy, na kondensatorze pomiarowym i o tym będzie kolejny artykuł.
Artykuł jest częścią cyklu: SmartPIP - Elektroniczny dręczyciel
Obserwacja wyników za pomocą RS-232 i terminal zrealizujemy, wykorzystują opisane wcześniej rozwiązanie wraz z omówieniem obsługi programu terminala Realterm. W związku z tym, nie będę tutaj opisywał dokładnie jak działa transmisja RS-232. Dodam jedynie tę część programu by można było ją przeanalizować.
Plik dd_usart.c:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_usart.c * Opis: Funkcje komunikacji RS-232 *************************************************************************/ #include <avr/io.h> #include <avr/interrupt.h> #include "dd_usart.h" //USART - tablica bufora wysyłki oraz zmienna indeksu tablicy char usart_bufor[USART_BUFOR_DLUGOSC] = "Testowanie czujnika swiatla:"; volatile unsigned int usart_bufor_ind; //-------------------------------------------------------------- void usart_inicjuj(void) { //definiowanie parametrów transmisji za pomocą makr zawartych w pliku //nagłówkowym setbaud.h. Jeżeli wybierzesz prędkość, która nie będzie //możliwa do realizacji otrzymasz ostrzeżenie: //#warning "Baud rate achieved is higher than allowed" #define BAUD 9600 //tutaj podaj żądaną prędkość transmisji #include <util/setbaud.h> //linkowanie tego pliku musi być //po zdefiniowaniu BAUD //ustaw obliczone przez makro wartości UBRRH = UBRRH_VALUE; UBRRL = UBRRL_VALUE; #if USE_2X UCSRA |= (1 << U2X); #else UCSRA &= ~(1 << U2X); #endif //Ustawiamy pozostałe parametry moduł USART //zobacz: http://mikrokontrolery.blogspot.com/2011/04/Pulapki-AVR-Rejestry-pod-tym-samym-adresem.html UCSRC = (1<<URSEL) | (1<<UCSZ1) | (1<<UCSZ0); //bitów danych: 8 //bity stopu: 1 //parzystość: brak //włącz nadajnik UCSRB |= (1<<TXEN); } //-------------------------------------------------------------- void usart_wyslij_bufor(void){ //funkcja rozpoczyna wysyłanie, wysyłając pierwszy znak znajdujący się //w tablicy wynik[]. Pozostałe wyśle funkcja przerwania, //która zostanie wywołana automatycznie po wysłaniu każdego znaku. //Dodaj do tekstu wyniku znaki końca linii (CR+LF), by na //ekranie terminala wyniki pojawiały się w nowych liniach unsigned int z; for(z=0; z<USART_BUFOR_DLUGOSC; z++){ if(usart_bufor[z]==0){ //czy to koniec tekstu w tablicy //tak znaleziono koniec tekstu, dodajemy znaki CR i LF usart_bufor[z] = 13; //znak powrotu karetki CR (Carrige Return) usart_bufor[z+1] = 10; //znak nowej linii LF (Line Feed) usart_bufor[z+2] = 0; //znak końca ciągu tekstu w tablicy break; //przerwij pętlę for() } } //Zaczekaj, aż bufor nadawania będzie pusty while (!(UCSRA & (1<<UDRE))); //następny znak do wysyłki to znak nr 1 usart_bufor_ind = 0; //włącz przerwania pustego bufora UDR, co rozpocznie transmisję //aktualnej zawartości bufora UCSRB |= (1<<UDRIE); } //-------------------------------------------------------------- ISR(USART_UDRE_vect){ //przerwanie generowane, gdy bufor nadawania jest już pusty, //odpowiedzialne za wysłanie wszystkich znaków z tablicy usart_bufor[] //z wyjątkiem pierwszego //static unsigned char znak = 1; //sprawdzamy, czy bajt do wysłania jest znakiem końca tekstu, czyli zerem if(usart_bufor[usart_bufor_ind]!= 0){ //załaduj znak do rejestru wysyłki i ustaw indeks na następny znak UDR = usart_bufor[usart_bufor_ind++]; }else{ //osiągnięto koniec napisu w tablicy usart_bufor[] UCSRB &= ~(1<<UDRIE); //wyłącz przerwania pustego bufora nadawania } }
Plik dd_usart.h:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_usart.h * Opis: Plik nagłówkowy pliku dd_usart.c *************************************************************************/ //USART - tablica bufora wysyłki oraz zmienna indeksu tablicy #define USART_BUFOR_DLUGOSC 30 //rozmiar bufora extern char usart_bufor[USART_BUFOR_DLUGOSC]; //bufor extern volatile unsigned int usart_bufor_ind; //indeks bufora //Funkcje extern void usart_inicjuj(void); extern void usart_wyslij_bufor(void);
dd_main.c
dd_main.h
Program główny zawiera jedynie funkcję main() wraz z niezbędnymi definicjami w pliku nagłówkowym.
Zadania:
- dobre praktyki w zakresie dbania o to, by każdy pin miał wymuszony poziom napięcia,
- wywołanie funkcji przygotowujących mikrokontroler do pracy,
- wysłanie początkowego napisu do terminala,
- inicjowanie pomiarów,
- przetwarzanie wyniku,
- inicjowanie wysłania wyniku do terminala.
Sądzę, że nie trzeba tutaj omawiać dokładnie każdego z powyższych punktów, bo są opisane w kodzie programu.
Fusebity
Należy wspomnieć, że poniższy program pracuje poprawnie z domyślnymi ustawieniami fusebitów (fabrycznymi), czyli:
- low: 0xE1
- high: 0xC9
- low: 0xC1
- high: 0xC9
Plik dd_main.c:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_main.c * Opis: Testowanie czujnika światła * * Mikrokontroler: ATmega8A * Fusebity: low: 0xC1 * high: 0xC9 * Kompilator: GCC * * W opcjach projektu należy ustawić: zegar: 1000000Hz * optymalizację: -Os *************************************************************************/ #include <avr/io.h> #include <stdio.h> #include <util/delay.h> #include <avr/interrupt.h> #include <avr/sleep.h> #include "dd_main.h" #include "dd_usart.h" #include "dd_swiatlo.h" //------------------------------------------------------------------------- int main(void) { //--- Dobre praktyki --- //Po resecie (włączeniu zasilania) piny ustawione są domyślnie jako //wejścia. Włączamy rezystory pull-up. To bardzo istotne w projektach //zasilanych z baterii! Dla ATmega8A włączamy wszystkie z wyjątkiem //pinu RESET ponieważ mamy tam podłączony zewnętrzny rezystor pull-up //szczegóły: http://mikrokontrolery.blogspot.com/2011/04/zakocenia-w-pracy-mikrokontrolerow.html PORTB = 0xff; PORTC = 0xff; PORTD = 0x3f; //jeżeli włączony tryb testowy (szczegóły w pliku dd_main.h) #ifdef TRYB_TEST //Ustaw pin LED jako wyjście LED_TEST_DDR |= (1<<LED_TEST_PIN_NAZWA); LED_TEST_ON; #endif //przygotuj moduł USART do transmisji danych do komputera usart_inicjuj(); //włącz przerwania globalne sei(); //wysyłamy napis początkowy domyślnie umieszczony w tablicy usart_bufor[] //patrz plik: dd_usart.c usart_wyslij_bufor(); //opóźnienie na poprawne wysłanie napisu startowego _delay_ms(1000); //przygotuj czujnik światła oraz przetwornik ADC dd_swiatlo_adc_ini(); //pętla główna while(1){ //wykonaj pomiar dd_swiatlo_adc_pomiar_start(); //konwertuj wynik na ciąg znaków i umieść w tablicy usart_bufor[] sprintf(usart_bufor, "%u", ADCH); //wyślij dane do komputera usart_wyslij_bufor(); #ifdef TRYB_TEST //zmień stan LED na przeciwny LED_TEST_TOGGLE; #endif //opóźnienie między kolejnymi pomiarami _delay_ms(2000); } }
Plik dd_main.h:
/************************************************************************* * SmartPIP - Elektroniczny dręczyciel * * Data: kwiecień 2013 * Autor: Dondu * www: http://mikrokontrolery.blogspot.com/2011/04/SmartPIP-elektroniczny-dreczyciel-spis-tresci.html * * Plik: dd_main.h * Opis: Plik nagłówkowy pliku dd_main.c * *************************************************************************/ //======= TESTOWE ===================== //Definicje do fragmentów programu wykorzystywanych do testów #define TRYB_TEST 1 //zakomentowanie tej linijki wyłącza tryb testowy #ifdef TRYB_TEST //definicje dot. testowej diody LED #define LED_TEST_DDR DDRB #define LED_TEST_PORT PORTB #define LED_TEST_PIN_NAZWA PB0 #define LED_TEST_ON LED_TEST_PORT &= ~(1<<LED_TEST_PIN_NAZWA) #define LED_TEST_OFF LED_TEST_PORT |= (1<<LED_TEST_PIN_NAZWA) #define LED_TEST_TOGGLE LED_TEST_PORT ^= (1<<LED_TEST_PIN_NAZWA) #endif
Do pobrania
Poniżej link do spakowanego:
- projektu AVR Studio 4,
- plików .c oraz .h
- pliku .hex skompilowanego dla 1MHz i fusebitów określonych powyżej.
Plik: SmartPIP_Czujnik_testowanie.zip
Wyniki pomiarów
W przypadku mojej wersji czujnika światła i powyższego programu zgodnie z założeniami, czujnik na oświetlenie reaguje w sposób bardzo "agresywny", co przejawiać się będzie stromymi zboczami na wykresie pomiarów, gdyż już przy niewielkim oświetleniu wartości pomiarów szybko rosną.
Taka charakterystyka czujnika jest podyktowana wymogiem oszczędzania baterii i w niczym nam nie będzie przeszkadzać, a wręcz pomagać podczas analizy wyników przez program.
Efekt jaki powinieneś zobaczyć na terminalu Realterm, jest następujący:
Specjalnie pokazuję zakładkę Port, abyś wiedział jak ustawić parametry odbioru. Po ich ustawieniu kliknij przycisk Change. W prawym dolnym rogu są (w skrócie) pokazane aktualne ustawienia terminala - muszą być identyczne, by program działał poprawnie.
Pierwszy pomiar
Na powyższym ekranie możesz zauważyć, że pierwszy pomiar znacząco odbiega od pozostałych. Jest to związane z faktem, że po zmianie ustawień ADC (wybór napięcia odniesienia) pierwszy pomiar może być nieprawidłowy.
Informację w tej sprawie znajdziesz w dalszej części tego cyklu.
Na powyższym ekranie możesz zauważyć, że pierwszy pomiar znacząco odbiega od pozostałych. Jest to związane z faktem, że po zmianie ustawień ADC (wybór napięcia odniesienia) pierwszy pomiar może być nieprawidłowy.
Informację w tej sprawie znajdziesz w dalszej części tego cyklu.
W zakładce Display, możesz włączyć opcję Ansi, co wyłączy pokazywanie znaków specjalnych:
Więcej o ustawieniach terminala Realterm pisałem tutaj.
Podsumowanie
Mamy już przetestowany i działający czujnik światła, o dość agresywnej charakterystyce. Jest on prosty i zużywa bardzo mało energii z baterii. Powinniśmy teraz przetestować jakie straty poniesiemy, na kondensatorze pomiarowym i o tym będzie kolejny artykuł.
Artykuł jest częścią cyklu: SmartPIP - Elektroniczny dręczyciel
Terminal Realterm a nie realtime ;)
OdpowiedzUsuńDzięki za znalezienie byków :-)
UsuńMam pytanie czy pojawią się kolejne części cyklu?
OdpowiedzUsuńNiestety dopiero jesienią. Teraz muszę rozpocząć obiecany temat dot. robotów.
UsuńKtórego roku?
Usuń