Redakcja: dondu
Drzaśkowy pamiętnik: Spis treści
Mikrokontroler jest z gruntu układem cyfrowym, ale budując urządzenie często zachodzi potrzeba pomiaru wielkości zewnętrznych, czyli analogowych.
Opisałem już obsługę i uruchomienie przetwornika ADC, który jest bez wątpienia jednym z najbardziej atrakcyjnych urządzeń peryferyjnych wbudowanych w mikrokontroler Atmega8.
Nie zawsze jednak zachodzi potrzeba dokładnego zmierzenia napięcia. Czasami wystarczy jedynie porównanie dwóch napięć. Do tego celu służy komparator analogowy, który również jest na wbudowany w mikrokontroler Atmega8.
Już ze schematy blokowego w dokumentacji mikrokontrolera można z grubsza poznać, jakie możliwości daje układ komparatora analogowego w danym mikroprocesorze.
Jak widać komparator posiada 2 wejścia analogowe:
- AIN0 (wejście dodatnie)
- AIN1(wejście ujemne).
Zgodnie ze schematem wejście dodatnie (AIN0) komparatora może być wejściem napięcia analogowego z pinu AIN0 mikrokontrolera lub może być wewnętrznie podłączone do wbudowanego napięcia referencyjnego.
Napięcie to zależy od napięcia zasilania i od temperatury:
W temperaturze pokojowej, przy zasilaniu mikrokontrolera napięciem 5V jak widać napięcie to wynosi około 1,2V.
Wejście ujemne (AIN1) komparatora może być również wejściem napięcia analogowego z pinu AIN1 lub może być podłączone do tego samego multipleksera, który używany jest przy ADC, pod warunkiem, że zostanie ustawiony („1”) Bit 3 – ACME: Analog Comparator Multiplexer Enable w rejestrze SFIOR oraz jeśli ADC jest wyłączony, czyli jest skasowany („0”) Bit 7 – ADEN: ADC Enable rejestru ADCSRA.
Jak widać na schemacie wynik porównania dwóch napięć jest równy:
- 1 - gdy napięcie na wejściu dodatnim jest większe od napięcia na wejściu ujemnym,
- 0 - gdy jest przeciwnie lub napięcia są równe.
Wynik odczytać można z bitu ACO w rejestrze ACSR – Analog Comparator Control and Status Register lub może zostać wygenerowane przerwanie przy jakiejkolwiek zmianie stanu na wyjściu komparatora lub przy jednej, określonej zmianie.
Tylko teraz gdzie co podłączyć i jak skonfigurować?
Najpierw zlokalizowałem możliwe wejścia na schemacie obudowy DIP mikrokontrolera Atmega8.
Rys. Atmega8, obudowa DIP. |
Ponieważ komparator to urządzenie analogowe, bardzo istotne jest dbanie o eliminowanie wszelkich możliwych zakłóceń. Sugeruję więc byś zapoznał się z działem: Zasilanie i zakłócenia
Eksperyment 1 - podstawowe działanie
Na początku postanowiłem spróbować prostego eksperymentu. Podłączam dwa napięcia analogowe do wejść AIN0 oraz AIN1, i w zależności od tego, czy napięcie na wejściu AIN0 jest większe od napięcia na wejściu AIN1, to zapala się dioda LED, a jeśli jest mniejsze to dioda gaśnie.
We wszystkich eksperymentach Atmega pracuje na wewnętrznym oscylatorze RC 1MHz.
Schemat układu:
Pobierz schemat: eagle1.rar
I napisałem prosty program:
#include <avr/io.h> void main(void) { DDRD=0x01; //wyjście LED for(;;) //pętla główna { if( ACSR & (1<<ACO) ) //jeśli AIN0>AIN1 PORTD |= 0x01; //zapal diodę LED else //w przeciwnym wypadku PORTD &= ~0x01; //zgaś diodę LED } }Pobierz program: ac1.rar
Jako, że komparator jest domyślnie włączony, nie musiałem go konfigurować dla takiej aplikacji.
Eksperyment 2 - multiplekser z ADC
Następnie spróbowałem wykorzystać inne wejście jako wejście ujemne komparatora, dzięki zastosowaniu multipleksera z ADC.
Pobierz schemat: eagle2.rar
I program:
#include <avr/io.h> void main(void) { DDRD=0x01; //wyjście LED //Konfiguracja multipleksera SFIOR |= (1<<ACME); //włącza multiplekser ADMUX |= (1<<MUX1); //ADC2 jako wejście ujemne for(;;) //pętla główna { if( ACSR & (1<<ACO)) //jeśli AIN0>ADC2 PORTD |= 0x01; //zapal diodę LED else //w przeciwnym wypadku PORTD &= ~0x01; //zgaś diodę LED } }Pobierz program: ac2.rar
Eksperyment 3 - Bandgap voltage
Kolejną rzeczą jaką wypróbowałem było wykorzystanie wbudowanego w mikrokontroler napięcia referencyjnego (bandgap voltage) jako wejście dodatnie mikrokontrolera.
Pobierz schemat: eagle3.rar
Program:
#include <avr/io.h> void main(void) { DDRD=0x01; //wyjście LED //Konfiguracja multipleksera SFIOR |= (1<<ACME); //włącza multiplekser ACSR |= (1<<ACBG); //wybór bandgab voltage jako AIN0 ADMUX |= (1<<MUX1); //ADC2 jako wejście ujemne for(;;) { if( ACSR & (1<<ACO)) //jeśli Napięcie wewnętrzne (2.56V)>ADC2 PORTD |= 0x01; //zapal diodę LED else //w przeciwnym wypadku PORTD &= ~0x01; //zgaś diodę LED } }Pobierz program: ac3.rar
Eksperyment 4 - przerwanie
Sprawdzanie w pętli wyjścia komparatora (bitu ACO w rejestrze ACSR) może stać się kłopotliwe, gdy program wykonuje skomplikowane i czasochłonne operacje a my chcemy wykonać natychmiastową reakcję gdy nastąpi zmiana wyjścia komparatora.
Z pomocą przychodzi tutaj możliwość generowania przerwań przez komparator w zależności od zmiany stanu na wyjściu komparatora. Odpowiadają za to bity ACIS1 oraz ACIS0 w rejestrze ACSR.
Do wyboru w tym mikrokontrolerze jest:
Tab. Atmega8 |
Czyli przerwanie przy jakiejkolwiek zmianie stanu na wyjściu komparatora, przerwanie przy zmianie 0-1 lub przerwanie przy zmianie 1-0.
Do tego celu użyłem układu ze schematu w eksperymencie pierwszym:
Pobierz schemat: eagle1.rar
Program:
#include <avr/io.h> #include <avr/interrupt.h> void main(void) { DDRD=0x01; //wyjście LED //uruchomienie obsługi przerwań ACSR |= (1<<ACIE); //ACIS0 i ACIS1 = 0 więc przerwanie przy //jakiejkolwiek zmianie ACO sei(); //włączenie obsługi przerwań for(;;); } ISR(ANA_COMP_vect) //obsługa przerwania { if( ACSR & (1<<ACO)) //jeśli AIN0>AIN1 PORTD |= 0x01; //zapal diodę LED else //w przeciwnym wypadku PORTD &= ~0x01; //zgaś diodę LED }Pobierz program: ac4.rar
Podsumowanie
Atmega8 posiada tylko jeden komparator analogowy, który nie jest zbyt rozbudowany. Nowsze mikrokontrolery posiadają większą ilość bardziej funkcjonalnych komparatorów.
Jednak nawet w tym małym i dość prostym mikrokontrolerze, łącząc odpowiednio część sprzętową z oprogramowaniem można przy pomocy komparatora mierzyć i poniekąd przetwarzać na postać cyfrową wiele wielkości analogowych.
"W temperaturze pokojowej, przy zasilaniu mikrokontrolera napięciem 5V jak widać napięcie to wynosi około 1,2V."
OdpowiedzUsuńA więc Vref~1,2V
Natomiast w Eksperymencie 3 zostało użyte na wejście nieodwracające napięcie Vref, a do wejścia odwracającego zostało dołączone wejście z ADC.
Przy linijce 14 czytamy:
"if( ACSR & (1<ADC2 "
Jest tutaj napięcie wewnętrzne opisane w komentarzu jako 2.56V co jest napięciem referencyjnym ADC, a nie komparatora.
Możliwe, że jest tutaj błąd, albo ja coś nie rozumiem.
Mam też pytania: jak wykorzystuje się Vref do wejścia odwracającego, to można niezależnie od tego używać pinu AIN0 jak wyjście, bo przecież ten pin nie służy nam w tym wypadku jako wejście?
Jest jakaś różnica przy wykorzystywaniu wejść z multipleksera ADC, a normalnego AIN1? Bo rozumie, że przy wykorzystywaniu ADC możemy programowo zmieniać, które wejście ADC chcemy użyć, ale dla jednego pomiaru wystarczy AIN1?
Możliwe, że DS jest trochę mylny jak się czyta: It is possible to select any of the ADC7:0 pins to replace the negative input to the Analog Comparator. Co można zrozumieć jako "jeśli nie ma się napięcia ujemnego", ale komparator jako WO może mieć podane napięcie dodatnie na wejście odwracające. Być może to też mój toporny angielski. :)
Przepraszam za zamieszanie i dziękuję za prowadzenie tego bloga, który jest pomocny przy nauce.
Witam. Postanowiłem że podzielę się z Wami jednym ważnym spostrzeżeniem bo może komuś zaoszczędzę pracy w przyszłości. Otóż wówczas gdy korzystamy z multipleksera (za pomocą którego możemy ustalić pin źródłowy wejścia odwracającego komparatora) to wówczas nie możemy oczywiście stosować instrukcji: PRR|=(1<<PRADC); czyli nie możemy stosować instrukcji wyłączającej taktowanie modułu przetwornika ponieważ ten cały multiplekser jest wewnętrzną składową właśnie tegoż przetwornika. Nie chce mi się dowodzić skąd i czy w ogóle procek bierze jakieś napięcie na wejście odwracające jeśli ktoś tą instrukcję wykona w takim układzie natomiast wiem jedno, może natrafić na zonka także uwaga taka tylko. Pozdrawiam dociekliwych : AdamZad.
OdpowiedzUsuńA czy można w głównej pętli while odczytywać z dwóch wejść adc jako ujemne ?? z moich prób się nie udało.
OdpowiedzUsuń