Hallo Zusammen,
welche Atmegas können denn Differential ADC? Ich habe was von Atmega 16,
32 und 128 gefunden. Funktioniert das bei denen auch im PDIP Package?
Das war bis jetzt mein Code um Spannungen mit einem Atmega 8 zu messen:
1
voidADC_Init(void)
2
{
3
//Initialisierung fuer Spannungsmessung
4
uint16_tresult;
5
6
// interne Referenzspannung als Refernz für den ADC wählen:
Steffen Ha schrieb:> Wie läuft das dann beim Differential ADC?
genauso, nur das halt nicht gegen GND sonder gegen einen anderen ADC
gemessen wird. Steht eigentlich recht gut beschrieben im Datenblatt.
Eine Formel zur Berechnung des ADC Werts habe ich schon mal gefunden:
ADC = ((VPOS – VNEG) ⋅ GAIN ⋅ 512) / VREF
mit Werten:
ADC = ((3,32V - 1,81V) 1 512) / 2,56V
ADC = 300.64
Die Tabelle vom Atmega 1284P auf Seite 259 verwirrt mich noch ein
bischen. Ich verstehe noch nicht ganz wie ich das im Programm ändern
muss. Über MUX3 / MUX 4 müsste ich doch festlegen welchen Port mit
welcher Verstärkung zum Messen genommen werden soll oder?
Gruß Steffen
Steffen Ha schrieb:> Die Tabelle vom Atmega 1284P auf Seite 259 verwirrt mich noch ein> bischen. Ich verstehe noch nicht ganz wie ich das im Programm ändern> muss. Über MUX3 / MUX 4 müsste ich doch festlegen welchen Port mit> welcher Verstärkung zum Messen genommen werden soll oder?
du musst einfach in MUX(0..4) den Wert eintragen der in der Tabelle
steht.
Wenn du zwischen ADC3 und ADC2 mit 10 facher verstärkung messen willst
dann must du für MUX 01101 eintragen.
Das ist nichts anderes als die Zahl 16. (das binäre Muster)
Müsste auch im Datenblatt im Grunde so stehen, weil die von dir gewählte
Kombination in der Zeile 16 steht (bei 0 angefangen zu zählen)
> Dies würde dann doch das ersetzen:>>
1
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);//Kanal waehlen, ohne > andere Bits zu beeinflußen
Lass das einfach so.
Setzte channel auf 16 und alles ist gut.
Nimm das Wort 'channel' nicht zu wörtlich. Lies es als 'Messmodus'. Im
Regelfall ist das tatsächlich einfach nur die Kanalnummer. Bei dir eben
nicht. Bei dir ist das dann eben ein "Spezialkanal", der nicht nur einen
Eingang berücksichtigt sondern deren 2 (samt Gain). Aber in den ADC
Routinen behandelst du den wie jeden anderen Kanal auch.
Steffen Ha schrieb:> Vielen Dank. Man lernt immer wieder was dazu. Eins würde mich noch> interessieren. Wie funktioniert das Kanal wählen ohne andere Bits zu> beeinflussen?
ADMUX = (ADMUX & ~(0x1F)) | (channel & 0x1F);
0x1F ist binär 0b00011111
also lauter 1 Bits dort, wo die neuen Kanalbits reinkommen
~0x1F ist die Umkehrung davon, also 0b11100000
Das verundet mit ADMUX ergibt ein Byte, welches an den Stellen an denen
in diesem Maskenbyte ein 0-Bit steckt, ebenfalls auf jeden Fall ein
0-Bit steht
Hatte ADMUX also den Bitinhalt (ich benenne die Bits mal mit Buchstaben)
abcdefgh, dann kommt mit der Verundung raus abc00000. Das ist: die Bits
abc stammen noch aus dem Original von ADMUX. Die restlichen Bits (dortr
wo die Kanalbits sitzen) sind auf jeden Fall 0. Damit ist die alte
Kanalinfo aus dem aus ADMUX ausgelesenen Byte eliminiert.
2. Teil:
channel & 0x1F
Die Verundung mit 0x1F ist nur zur Vorsicht, damit im Ergebnis diesmal
die 3 höherwertigsten Bits auf jeden Fall 0 sind. die 5 unteren Bits,
die die Kanalinformation tragen, bleiben durch diese Operation
unangetastet. Die 8 Originalbits des Kanalbytes wären zb gewesen
ABCDEFGH. Nach der Verundung hat man 000DEFGH
Jetzt hat man also 2 Einzelteile.
aus ADMUX entstanden aus dem Kanalbyte entstanden
abc00000 000DEFGH
und die beiden werden zusammengeodert. Die in dem einen Byte jeweils ein
0-Bit sitzt, wo im anderen ein Nutzbit sitzt (und vice versa), kommt es
da auch bei den Bits zu keinen INteraktionen. Sie werden sauber durch
das Oder zusammengeführt zu einem Byte
abcDEFGH
bei dem die obersten 3 Bits unverändert aus dem alten ADMUX stammen und
die unteren 5 Bits aus der channel-Angabe.
Et voila: ADMUX kann damit neu gesetzt werden. An der Einstellung der
Modus Bits (die 3 oberen) hat sich nichts geändert. Aber die 5 unteren
Bits für die Kanaleinstellung sind die 5 unteren Bits aus channel.
Ich habe noch mal eine Frage zum differential ADC. Wenn ich aus der
ersten while-Schleife rausspringe habe ich eine kleines Testprogramm
welches mir signalisiert ob der ADC-Wert über oder unter 250 liegt.
Benutze ich aber den differential Modus in meinem Hauptprogramm (Pfeil)
ist er immer so bei 1018 - 1019. Wie kann das sein? Normal hat der
differtial Modus doch nur eine Auflösung bis 512. Am ADC0 liegt über ein
Poti maximal 2,56 V an und ADC1 liegt auf GND.
Vielen Dank. Gruß Steffen
Dein Problem liegt halt einfach in keinster Weise beim ADC oder der
differentiellen Betriebsart desselben. Sondern dir fehlen ganz gehörig
die Grundlagen.
Beim diff. ADC geht auch von 0 bis 1024, logisch. Aber 512 ist dann halt
0. Aus einem 16 Bit Register wird halt nicht einfach mal so ne negative
Zahl. Da musst du schon was für tun.
gruß cyblord
Wenn ich aber am Poti drehe passiert gar nichts was aber bei der
Testschaltung mit den LEDs funktioniert. Außerdem brauch ich keine
negative Spannung. Wie soll ein Akku leerer als leer werden.
Steffen Ha schrieb:> Wenn ich aber am Poti drehe passiert gar nichts was aber bei der> Testschaltung mit den LEDs funktioniert. Außerdem brauch ich keine> negative Spannung. Wie soll ein Akku leerer als leer werden.
Negative Spannungen gehen auch nicht (bezogen auf GND). Trotz diff. ADC
darf an keinem Pin deines Controllers eine Spannung kleiner GND oder
größer VCC+0,5 Volt anliegen. Die differentielle Komponenten bezieht
sich auf VREF bzw. auf die beiden ADC-Eingänge die gewählt sind.
gruß cyblord
Hallo Zusammen,
ich habe immer noch das Problem mit der differentiellen Messung. Wenn
ich wie unten im Programm (siehe Pfeile an markierter Stelle) den ADC2
normal messe und dann den ADCO 0 und den ADC1 differentiell wird mir auf
dem Display für test1 168 und für test2 1019 angezeigt egal was ich
mache. Wenn ich dann aber test1 auskommentiere funktioniert die
differentielle Messung. Zwischen ADC0 und ADC1 hängen drei Widerstände
in Reihe, der mittlere Widerstand von den dreien ist ein Poti. Woran
kann das liegen?
Vielen Dank. Gruß Steffen
Ich möchte gerne die Spannung über einen Isolationsverstärker HCPL-7840
messen und der hat einen differentiellen Ausgang. Deswegen habe ich mir
den Testaufbau mit den drei Widerständen gemacht. Mir kommt es so vor
als könnte der Atmega zwischen der normalen Messung und der
differentiellen Messung nicht umschalten. Aber warum?
Gruß Steffen
Auf Seite 250 des Datenblattes steht etwas, das dich vielleicht weiter
bringen könnte:
"Special care should be taken when changing differential channels.
Once a differential channel has been selected, the gain stage may
take as much as 125μs to stabilize to the new value. Thus conversions
should not be started within the first 125μs after selecting a new
differential channel. Alternatively, conversion results obtained
within this period should be discarded."
Vielen Dank für den Hinweis. Das Datenblatt habe ich mir jetzt auch noch
mal durchgelesen. Im Programm habe ich jetzt mal ein _delay_ms zwischen
die beiden Messungen geschrieben aber der Fehler bleibt der gleiche. Ich
verstehe das nicht.
Steffen Ha schrieb:> Vielen Dank für den Hinweis.
Bitteschön.
> Das Datenblatt habe ich mir jetzt auch noch mal durchgelesen.> Im Programm habe ich jetzt mal ein _delay_ms zwischen die> beiden Messungen geschrieben aber der Fehler bleibt der gleiche.> Ich verstehe das nicht.
Ich verstehe das schon...
> test1 = ADC_Read(2);> _delay_ms(500);> test2 = ADC_Read(16);
Erst beim Aufruf von ADC_Read(16) wird ein Quellenwechsel auf
differentiell vorgenommen. Direkt danach startest du die Wandlung.
Du musst innerhalb von ADC_Read() ein kurzes Delay zwischen dem Switchen
und dem Starten der Messung einbauen.
So z.B.:
1
uint16_tADC_Read(uint8_tchannel){
2
ADMUX=(ADMUX&~(0x1F))|(channel&0x1F);//Kanal waehlen, ohne andere Bits zu beeinflußen