Kampis Elektroecke

XMega – AC

XMega Blockdiagramm

Die Analogkomparatoren der XMega-Familie können genutzt werden um ohne viel Aufwand auf bestimmte Spannungsschwellen, wie z. B. bei einer Unterspannungsabschaltung, zu reagierenden können. Dazu vergleichen die Komparatoren die Eingangsspannung mit einer oder zwei Referenzspannungen und lösen ggf. einen Interrupt aus, wenn die Eingangsspannung die Referenspannung(en) über-, bzw. unterschreitet.

Jeder Komparatorbaugruppe besteht aus zwei einzelnen Analogkomparatoren, die entweder unabhängig voneinander oder gemeinsam betrieben werden können. Als Spannungsschwellen können dabei externe oder interne Spannungsquellen (z. B. der DAC) genutzt werden. Das Datenblatt liefert einen sehr guten Überblick über den Aufbau der Komparatorbaugruppe.

Schwellwerterkennung mittels Komparator:

Im ersten Beispiel soll der Analogkomparator eine zwei Eingangsspannungen miteinander vergleichen und das Ergebnis dieses Vergleichs an einem I/O ausgeben. Dazu soll der Komparator 0 von Port A verwendet werden. Die Spannungen sollen über die Pins 4 und 5, wobei 4 der positive Eingang und 5 der negative Eingang ist, eingespeist werden.

Für die Initialisierung ergibt sich damit der folgende Code:

ACA.AC0CTRL |= AC_ENABLE_bm;
ACA.AC0MUXCTRL |= AC_MUXPOS_PIN4_gc | AC_MUXNEG_PIN5_gc;
ACA.CTRLA |= AC_AC0OUT_bm;

Für den Komparatorausgang muss der verwendete I/O, hier der Pin 7 von Port A, da der Komparator 0 verwendet wird, als Ausgang konfiguriert werden.

PORTA.DIR |= PIN7_bm;

Nun kann das Programm auch schon gestartet werden. Als Spannung für den negativen Eingang habe ich an einem Netzteil 2 V eingestellt. Die Spannung am positiven Eingang ist variabel.

Auf dem Oszilloskopbild erkennt man sehr schön, dass der Ausgang des Komparators (AC) bei einer Eingangsspannung von über 2 V ein- und bei einer Eingangsspannung von unter 2 V ausgeschaltet wird.

Leider fängt der Komparator in der aktuellen Konfiguration an zu schwingen, wenn eine positive Spannung von 2 V angelegt wird, wodurch der Ausgang des Komparators permanent ein- und ausgeschaltet wird.

Dieses Schwingen lässt sich durch die nicht ideale Ausgangsspannung des Netzteils und durch das Rauschen des Komparators erklären. Durch das Hinzufügen einer Hysterese kann dieses Verhalten verhindert werden. Der Komparator stellt drei Hysteresestufen zur Verfügung:

Die Höhe der Hysterese kann dem entsprechenden Produktdatenblatt entnommen werden, wie z. B. bei einem XMega256A3BU:

Um also eine große Hysterese zu aktivieren, muss der Code folgendermaßen abgeändert werden:

ACA.AC0CTRL |= AC_ENABLE_bm | AC_HYSMODE1_bm;

Softwareseitig kann der Status des Komparators über das AC0STATE-Bit im STATUS-Register abgefragt werden.

while(!(ACA.STATUS & AC_AC0STATE_bm));

Dieses Bit gibt den Zustand des Komparaturausgangs wieder und ist dem entsprechend gesetzt, wenn der Komparator geschaltet hat.

Schwellwerterkennung über Interrupts:

Die Schwellwerterkennung kann zudem noch mit einem zusätzlichen Interrupt versehen werden. Insgesamt stehen drei Modi zur Auswahl:

In diesem Beispiel soll der Mikrocontroller über einen Interrupt mit der Priorität Niedrig eine LED togglen, wenn ein Flankenwechsel am Komparatorausgang stattfindet. Dazu wird zuerst der Ausgang der LED initialisiert:

PORTR.DIR |= (0x01 << 0x00);
PORTR.OUTCLR = (0x01 << 0x00);

Als nächstes wird der Analogkomparator konfiguriert. Die Konfiguration kann dabei komplett vom ersten Beispiel übernommen werden und wird anschließend um die Interruptkonfiguration im CTRL-Register des Komparators erweitert:

ACA.AC0CTRL |= AC_INTMODE_BOTHEDGES_gc | AC_INTLVL_LO_gc | AC_HYSMODE1_bm | AC_ENABLE_bm;
ACA.AC0MUXCTRL |= AC_MUXPOS_PIN4_gc | AC_MUXNEG_PIN5_gc;
ACA.CTRLA |= AC_AC0OUT_bm;
PORTA.DIR |= PIN7_bm;

In der ISR des Komparators soll dann die LED geschaltet werden:

ISR(ACA_AC0_vect)
{
	PORTR.OUTTGL = (0x01 << 0x00);
}

Abschließend werden noch global die Interrupts, sowie Interrupts mit der Priorität Niedrig aktiviert.

PMIC.CTRL = PMIC_LOLVLEN_bm;
sei();

Jetzt kann das Programm ausgeführt werden. Wenn jetzt die Eingangsspannung geändert wird, wird bei jedem Flankenwechsel am Komparatorausgang die LED umgeschaltet.

Komparator im Fenstermodus:

Im letzten Beispiel möchte ich zeigen, wie die Komparatorgruppe im Fenstermodus betrieben werden kann. Die Aufgabe ist es, mittels Fenstermodus zu erkennen, ob sich die Eingangsspannung innerhalb oder außerhalb des eingestellten Fensters befindet. Zusätzlich soll ein Interrupt ausgelöst werden, wenn die Eingangsspannung das Fenster verlässt. In der ISR soll eine LED getoggled werden. Diese befindet sich an Pin R.0 und ist gegen Masse geschaltet.

PORTR.DIR |= (0x01 << 0x00);
PORTR.OUTCLR = (0x01 << 0x00);

Für die Aufgabe werden zudem drei Eingangsspannungen benötigt:

  • Das obere Limit des Fensters
  • Das untere Limit des Fensters
  • Die Eingangsspannung

Außerdem werden zwei Komparatoren benötigt, die miteinander verschaltet werden. Die Funktionsweise des Fenstermodus lässt sich dem Datenblatt entnehmen.

Da mein Netzteil nur zwei Ausgangsspannungen bereitstellen kann, soll der interne DAC die Referenzspannung für das untere Limit des Fensters bereitstellen. Dazu wird der DAC entsprechend konfiguriert (siehe DAC Tutorial), nur das zudem das IDOEN-Bit gesetzt wird:

DACB.CTRLC &= ~(DAC_REFSEL1_bm | DAC_REFSEL0_bm | DAC_LEFTADJ_bm);
DACB.CTRLB &= ~(DAC_CH1TRIG_bm | DAC_CH0TRIG_bm | DAC_CHSEL1_bm | DAC_CHSEL0_bm);
DACB.CTRLA |= (DAC_CH0EN_bm | DAC_ENABLE_bm | DAC_IDOEN_bm);

Die Ausgangsspannung des DAC wird zudem auf 1 V gestellt:

while(!DACB.STATUS & DAC_CH0DRE_bm);
DACB.CH0DATA = 0xFFF;

Für das obere Limit des Fensters soll der Pin 5 und für die Eingangsspannung der Pin 4 verwendet werden. Als Hysterese nehme ich die selben Einstellungen wie im ersten Beispiel.

Mit diesen Informationen werden erst die Komparatoren

ACA.AC0CTRL |= AC_ENABLE_bm | AC_HYSMODE1_bm;
ACA.AC0MUXCTRL |= AC_MUXPOS_PIN4_gc | AC_MUXNEG_PIN5_gc;
	
ACA.AC1CTRL |= AC_ENABLE_bm | AC_HYSMODE1_bm;
ACA.AC1MUXCTRL |= AC_MUXPOS_PIN4_gc | AC_MUXNEG_DAC_gc;

und anschließend wird der Fenstermodus konfiguriert

ACA.WINCTRL |= AC_WEN_bm | AC_WINTMODE1_bm | AC_WINTMODE0_bm | AC_WINTLVL_LO_gc;

Der Fenstermodus wird aktiviert und mit einem Outside-Interrupt von der Priorität niedrig versehen.

Damit ist das Programm fertig und kann auf den Mikrocontroller übertragen werden. Sobald die Eingangsspannung 1 V unterschreitet oder 2 V überschreitet wird der Interrupt ausgelöst und die LED umgeschaltet.

Das komplette Projekt steht in meinem GitHub-Repository zum Download bereit.

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert