Kurs XMEGA: porównywanie napięcia

Przygotujemy dwa programy. Jeden bardzo prosty, żeby zaznajomić się z podstawami działania komparatora. Drugi będzie nieco bardziej praktyczny i będzie wykorzystywał peryferia, omówione w poprzednich odcinkach kursu – zobaczymy jak zrobić bardzo prosty miernik pojemności kondensatorów.

Pierwszy program będzie porównywać dwa napięcia:

  • napięcie z wbudowanego dzielnika podłączymy do wejścia odwracającego (–), a przy pomocy klawiszy 0 i 1 na płytce eXtrino XL będziemy mogli to napięcie regulować
  • do wejścia nieodwracającego (+) podłączymy zewnętrzny potencjometr (o rezystancji w zakresie 1k-100k), którym będziemy mogli w sposób analogowy regulować napięcie. Środkowe wyprowadzenie potencjometru należy połączyć z pinem A6, a wyprowadzenia skrajne podłącz do zasilania 3V3 oraz masy GND

Wynik porównania oraz ustalone napięcie z wbudowanego dzielnika będziemy monitorować na wyświetlaczu (użyłem wyświetlacz VFD 4x20, ale możesz zastosować dowolny wyświetlacz ze sterownikiem HD44780, co opisałem w odcinku Wyświetlacz LCD w XMEGA).

Podłącz potencjometr tak, jak to pokazałem na rysunku:

Schemat potencjometra w eXtrino

Pierwsze dwie linijki funkcji main() to standardowa inicjalizacja wyświetlacza oraz PORTX. Następnie musimy skonfigurować komparator, wpisując odpowiednie bity do zaledwie trzech rejestrów. W rejestrze ACA.AC0MUXCTRL konfigurujemy, z którymi pinami lub źródłami napięcia referencyjnego mają być połączone wejście odwracające i nieodwracające komparatora o numerze 0. Wejście nieodwracające łączymy z pinem A6, natomiast wejście odwracające będzie połączone z wewnętrznym dzielnikiem napięcia.

W rejestrze ACA.CTRLB ustalamy 64-stopniowy dzielnik napięcia zasilającego. Możemy wybrać liczbę z przedziału od 0 do 63. Im wyższa to będzie liczba, tym wyższe napięcie uzyskamy. Uzyskana napięcie można wyliczyć z prostego wzoru:

Wzór

Wynika stąd, że maksymalne napięcie, jakie możemy ustawić, wynosi Vcc, czyli 3,3V. Natomiast napięcie minimalne to 1/64 napięcia Vcc, czyli ok. 0,05V. Dostępny jest jeden dzielnik napięcia na oba komparatory w jednym porcie.

W ostatnim rejestrze, ACA.AC0CTRL, uruchamiamy komparator. Pamiętaj, że w XMEGA komparatory są domyślnie wyłączone, w przeciwieństwie do starych AVR-ów, gdzie po włączeniu zasilania komparator był domyślnie włączony (nie wiadomo po co).

Następnie, w pętli while(1) sprawdzamy, czy wciśnięte są przyciski 0 i 1, podłączone do PORTX. Jeśli tak, to odpowiednio zwiększamy lub zmniejszamy zawartość rejestru CTRLB, pamiętając, że jego zawartość może być liczbą z przedziału od 0 do 63. Dodatkowo, diody LED numer 0 i 1 będą się świecić, a kiedy odpowiadający im przycisk zostanie wciśnięty, diody będą mrugać.

Pliki do pobrania:
 
#define F_CPU 2000000UL
#include <avr/io.h>
#include "extrino_portx.h"
#include "hd44780.h"

int main(void) {
    
    PortxInit();                                  // inicjalizacja PORTX
    LcdInit();                                    // inicjalizacja wyświetlacza
    
    // konfiguracja komparatora 0 w porcie A
    ACA.AC0MUXCTRL    =    AC_MUXPOS_PIN6_gc |    // wejście + PIN A6
                           AC_MUXNEG_SCALER_gc;   // wejście - dzielnik napięcia
    ACA.CTRLB         =    32;                    // początkowe ustawienie dzielnika napięcia
    ACA.AC0CTRL       =    AC_ENABLE_bm;          // włączenie komparatora
    
    while(1) {
        
        // wyświetlanie wyniku z komparatora
        Lcd1;
        Lcd("Vref = ");
        LcdDecComma((330 * (ACA.CTRLB + 1)) / 64, 2);
        Lcd("V");
        Lcd("    ");
        Lcd2;
        if(ACA.STATUS & AC_AC0STATE_bm) {         // badanie wyjścia komparatora
            Lcd("Vin > Vref");
        } else {
            Lcd("Vin < Vref");
        }
        
        // zmiana napięcia referencyjnego
        if(PORTX.IN & PIN0_bm) {                  // jeżeli wciśnięto przycisk 0
            if(ACA.CTRLB > 0) ACA.CTRLB--;        // zmniejszanie Vref
            PORTX.OUTCLR    =    PIN0_bm;         // wyłączenie diody LED 0
            _delay_ms(100);                       // czekanie 100ms
        }
        
        if(PORTX.IN & PIN1_bm) {                  // jeżeli wciśnięto przycisk 1
            if(ACA.CTRLB < 63 ) ACA.CTRLB++;      // zwiększanie Vref
            PORTX.OUTCLR    =    PIN1_bm;         // wyłączenie diody LED 1
            _delay_ms(100);                       // czekanie 100ms
        }
        
        PORTX.OUTSET    =    PIN1_bm | PIN0_bm;   // włączenie diod LED 1 i 0
    }
}