ADC über Komparator
Es gibt einen weiteren Weg, eine analoge Spannung mit Hilfe des Komparators, welcher in fast jedem AVR integriert ist, zu messen. Siehe dazu auch die Application Note AVR400 von Atmel.
Dabei wird das zu messende Signal auf den invertierenden Eingang des Komparators geführt. Zusätzlich wird ein Referenzsignal an den nicht invertierenden Eingang des Komparators angeschlossen. Das Referenzsignal wird hier auch wieder über ein RC-Glied erzeugt, allerdings mit festen Werten für R und C.
Das Prinzip der Messung ist nun dem vorhergehenden recht ähnlich. Durch Anlegen eines LOW-Pegels an Pin 2 wird der Kondensator zuerst einmal entladen. Auch hier muss darauf geachtet werden, dass der Entladevorgang genügend lang dauert. Nun wird Pin 2 auf HIGH gelegt. Der Kondensator wird geladen. Wenn die Spannung über dem Kondensator die am Eingangspin anliegende Spannung erreicht hat schaltet der Komparator durch. Die Zeit, welche benötigt wird, um den Kondensator zu laden kann nun auch wieder als Maß für die Spannung an Pin 1 herangezogen werden.
Ich habe es mir gespart, diese Schaltung auch aufzubauen und zwar aus mehreren Gründen:
- 3 Pins notwendig.
- Genauigkeit vergleichbar mit einfacherer Lösung.
- War einfach zu faul.
Der Vorteil dieser Schaltung liegt allerdings darin, dass damit direkt Spannungen gemessen werden können.
[Bearbeiten] DAC (Digital Analog Converter)
Mit Hilfe eines Digital-Analog-Konverters (DAC) können wir nun auch Analogsignale ausgeben. Es gibt hier mehrere Verfahren.
[Bearbeiten] DAC über mehrere digitale Ausgänge
Wenn wir an den Ausgängen des Controllers ein entsprechendes Widerstandsnetzwerk aufbauen haben wir die Möglichkeit, durch die Ansteuerung der Ausgänge über den Widerständen einen Addierer aufzubauen, mit dessen Hilfe wir eine dem Zahlenwert proportionale Spannung erzeugen können. Das Schaltbild dazu kann etwa so aussehen:

Es sollten selbstverständlich möglichst genaue Widerstände verwendet werden, also nicht unbedingt solche mit einer Toleranz von 10% oder mehr. Weiterhin empfiehlt es sich, je nach Anwendung den Ausgangsstrom über einen Operationsverstärker zu verstärken.
[Bearbeiten] PWM (Pulsweitenmodulation)
Wir kommen nun zu einem Thema, welches in aller Munde ist, aber viele Anwender verstehen nicht ganz, wie PWM eigentlich funktioniert.
Wie wir alle wissen, ist ein Mikrocontroller ein rein digitales Bauteil. Definieren wir einen Pin als Ausgang, dann können wir diesen Ausgang entweder auf HIGH setzen, worauf am Ausgang die Versorgungsspannung Vcc anliegt, oder aber wir setzen den Ausgang auf LOW, wonach dann 0V am Ausgang liegt. Was passiert aber nun, wenn wir periodisch mit einer festen Frequenz zwischen HIGH und LOW umschalten? - Richtig, wir erhalten eine Rechteckspannung, wie die folgende Abbildung zeigt:

Diese Rechteckspannung hat nun einen arithmetischen Mittelwert, der je nach Pulsbreite kleiner oder größer ist.

Wenn wir nun diese pulsierende Ausgangsspannung noch über ein RC-Glied filtern/"glätten", dann haben wir schon eine entsprechende Gleichspannung erzeugt.
Mit den AVRs können wir direkt PWM-Signale erzeugen. Dazu dient der 16-Bit Zähler, welcher im sogenannten PWM-Modus betrieben werden kann.
- Hinweis
- In den folgenden Überlegungen wird als Controller der 90S2313 vorausgesetzt. Die Theorie ist bei anderen AVR-Controllern vergleichbar, die Pinbelegung allerdings nicht unbedingt, weshalb ein Blick ins entsprechende Datenblatt dringend angeraten wird.
Um den PWM-Modus zu aktivieren, müssen im Timer/Counter1 Control Register A TCCR1A die Pulsweiten-Modulatorbits PWM10 bzw. PWM11 entsprechend nachfolgender Tabelle gesetzt werden:
PWM11 |
PWM10 |
Bedeutung |
0 |
0 |
PWM-Modus des Timers ist nicht aktiv |
0 |
1 |
8-Bit PWM |
1 |
0 |
9-Bit PWM |
1 |
1 |
10-Bit PWM |
Der Timer/Counter zählt nun permanent von 0 bis zur Obergrenze und wieder zurück, er wird also als sogenannter Auf-/Ab Zähler betrieben. Die Obergrenze hängt davon ab, ob wir mit 8, 9 oder 10-Bit PWM arbeiten wollen:
Auflösung |
Obergrenze |
Frequenz |
8 |
255 |
fTC1 / 510 |
9 |
511 |
fTC1 / 1022 |
10 |
1023 |
fTC1 / 2046 |
Zusätzlich muss mit den Bits COM1A1 und COM1A0 desselben Registers die gewünschte Ausgabeart des Signals definiert werden:
COM1A1 |
COM1A0 |
Bedeutung |
0 |
0 |
Keine Wirkung, Pin wird nicht geschaltet. |
0 |
1 |
Keine Wirkung, Pin wird nicht geschaltet. |
1 |
0 |
Nicht invertierende PWM.
Der Ausgangspin wird gelöscht beim Hochzählen und gesetzt beim Herunterzählen.
|
1 |
1 |
Invertierende PWM.
Der Ausgangspin wird gelöscht beim Herunterzählen und gesetzt beim Hochzählen.
|
Der entsprechende Befehl, um beispielsweise den Timer/Counter als nicht invertierenden 10-Bit PWM zu verwenden, heißt dann:
alte Schreibweise (PWMxx wird nicht mehr akzeptiert)
TCCR1A = (1<<PWM11)|(1<<PWM10)|(1<<COM1A1);
|
neue Schreibweise
TCCR1A = (1<<WGM11)|(1<<WGM10)|(1<<COM1A1);
|
Damit der Timer/Counter überhaupt läuft, müssen wir im Control Register B TCCR1B noch den gewünschten Takt (Vorteiler) einstellen und somit auch die Frequenz des PWM-Signals bestimmen.
CS12 |
CS11 |
CS10 |
Bedeutung |
0 |
0 |
0 |
Stop. Der Timer/Counter wird gestoppt. |
0 |
0 |
1 |
CK |
0 |
1 |
0 |
CK / 8 |
0 |
1 |
1 |
CK / 64 |
1 |
0 |
0 |
CK / 256 |
1 |
0 |
1 |
CK / 1024 |
1 |
1 |
0 |
Externer Pin 1, negative Flanke |
1 |
1 |
1 |
Externer Pin 1, positive Flanke |
Also um einen Takt von CK / 1024 zu generieren, verwenden wir folgenden Befehl:
TCCR1B = (1<<CS12) | (1<<CS10);
|
Jetzt muss nur noch der Vergleichswert festgelegt werden. Diesen schreiben wir in das 16-Bit Timer/Counter Output Compare Register OCR1A.
Die folgende Grafik soll den Zusammenhang zwischen dem Vergleichswert und dem generierten PWM-Signal aufzeigen.


Ach ja, fast hätte ich's vergessen. Das generierte PWM-Signal wird am Output Compare Pin OC1 des Timers ausgegeben und leider können wir deshalb auch beim AT90S2313 nur ein einzelnes PWM-Signal mit dieser Methode generieren. Andere AVR-Typen verfügen über bis zu vier PWM-Ausgänge. Zu beachten ist außerdem, das wenn der OC Pin aktiviert ist, er nichtmehr wie üblich funktioniert und z. B. nicht einfach über PINx ausgelesen werden kann.
Ein Programm, welches an einem ATmega8 den Fast-PWM Modus verwendet, den Modus 14, könnte so aussehen
#include <avr/io.h>
int main()
{
// OC1A auf Ausgang
DDRB = (1 << PB1 ); //ATMega8
// DDRD = (1 << PD5 ); //ATMega16
//
// Timer 1 einstellen
//
// Modus 14:
// Fast PWM, Top von ICR1
//
// WGM13 WGM12 WGM11 WGM10
// 1 1 1 0
//
// Timer Vorteiler: 1
// CS12 CS11 CS10
// 0 0 1
//
// Steuerung des Ausgangsport: Set at BOTTOM, Clear at match
// COM1A1 COM1A0
// 1 0
TCCR1A = (1<<COM1A1) | (1<<WGM11);
TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS10);
// den Endwert (TOP) für den Zähler setzen
// der Zähler zählt bis zu diesem Wert
ICR1 = 0x6FFF;
// der Compare Wert
// Wenn der Zähler diesen Wert erreicht, wird mit
// obiger Konfiguration der OC1A Ausgang abgeschaltet
// Sobald der Zähler wieder bei 0 startet, wird der
// Ausgang wieder auf 1 gesetzt
//
// Durch Verändern dieses Wertes, werden die unterschiedlichen
// PWM Werte eingestellt.
OCR1A = 0x3FFF;
while( 1 )
;
}
|
PWM-Mode Tabelle aus dem Datenblatt des ATmega8515
Mode |
WGM13 |
WGM12 |
WGM11 |
WGM10 |
Timer/Counter Mode of Operation |
TOP |
Update of OCR1x at |
TOV1 Flag set on |
0 |
0 |
0 |
0 |
0 |
Normal |
0xFFFF |
Immediate |
MAX |
1 |
0 |
0 |
0 |
1 |
PWM, Phase Correct, 8-Bit |
0x00FF |
TOP |
BOTTOM |
2 |
0 |
0 |
1 |
0 |
PWM, Phase Correct, 9-Bit |
0x01FF |
TOP |
BOTTOM |
3 |
0 |
0 |
1 |
1 |
PWM, Phase Correct, 10-Bit |
0x03FF |
TOP |
BOTTOM |
4 |
0 |
1 |
0 |
0 |
CTC |
OCR1A |
Immediate |
MAX |
5 |
0 |
1 |
0 |
1 |
Fast PWM, 8-Bit |
0x00FF |
BOTTOM |
TOP |
6 |
0 |
1 |
1 |
0 |
Fast PWM, 9-Bit |
0x01FF |
BOTTOM |
TOP |
7 |
0 |
1 |
1 |
1 |
Fast PWM, 10-Bit |
0x03FF |
BOTTOM |
TOP |
8 |
1 |
0 |
0 |
0 |
PWM, Phase an Frequency Correct |
ICR1 |
BOTTOM |
BOTTOM |
9 |
1 |
0 |
0 |
1 |
PWM, Phase an Frequency Correct |
OCR1A |
BOTTOM |
BOTTOM |
10 |
1 |
0 |
1 |
0 |
PWM, Phase Correct |
ICR1 |
TOP |
BOTTOM |
11 |
1 |
0 |
1 |
1 |
PWM, Phase an Frequency Correct |
OCR1A |
TOP |
BOTTOM |
12 |
1 |
1 |
0 |
0 |
CTC |
ICR1 |
Immediate |
MAX |
13 |
1 |
1 |
0 |
1 |
Reserved |
- |
- |
- |
14 |
1 |
1 |
1 |
0 |
Fast PWM |
ICR1 |
BOTTOM |
TOP |
15 |
1 |
1 |
1 |
1 |
Fast PWM |
OCR1A |
BOTTOM |
TOP |
Für Details der PWM Möglichkeiten, muß immer das jeweilge Datenblatt des Prozessors konsultiert werden, da sich die unterschiedlichen Prozessoren in ihren Möglichkeiten doch stark unterscheiden. Auch muß man aufpassen, welches zu setzende Bit in welchem Register ist. Auch hier kann es sein, dass gleichnamige Konfigurationsbits in unterschiedlichen Konfigurationsregistern (je nach konkretem Prozessortyp) sitzen.