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ń