Forum: Mikrocontroller und Digitale Elektronik Großer Offsetfehler ADC Attiny44a


von Andy S. (1632andys)


Lesenswert?

Hi,

ich versuche mit einem ATtiny44a über einen Shunt den Stromfluss in eine 
Batterie zu messen.
Dabei wird Differentiell gemessen, wobei auch der Bipolar Modus zum 
Einsatz kommt um sowohl Lade- als auch Entladeströme zu erfassen.

Da die interne 1.1V Ref verwendet wird, beabsichtige ich zuvor eine 
Offsetkalibrierung der Differentiellen Eingänge um den Fehler nach 
Möglichkeit klein zu halten. (also den Gain fehler der nachgeschalteten 
Verstärkerstufe im ADC)

Ich bin jetzt soweit nach dem Datasheet verfahren, komme jedoch zu kein 
vernüftiges Ergebnis.

Wird der Unipolar modus verwendet, dann beträgt der Offset ca. 10-15 LSB

Wird jedoch der Bipolar modus angewandt, so schnell der Offset auf 50-60 
LSB hoch.

Das erscheint mir doch etwas zu viel, zumal im Datasheet ca. 8 LSB als 
typ. angegeben wird.

Habt ihr schon ähnliche Erfahrungen gemacht? Woran könnte es denn 
liegen?


-Andy

von Carsten R. (kaffeetante)


Lesenswert?

Da laufen gerade ein paar Sachen durcheinander.

Andy S. schrieb:
> Dabei wird Differentiell gemessen, wobei auch der Bipolar Modus zum
> Einsatz kommt um sowohl Lade- als auch Entladeströme zu erfassen.

Der Bipolar Modus ist der Differenzbetrieb. "Wobei auch..." läßt aber 
vermuten daß Du das anders aufgefaßt hast.

Andy S. schrieb:
> Da die interne 1.1V Ref verwendet wird

Die ist ungenau. Ist der Kondensator dran der da hingehört? Je nach 
Schaltung und je nach Meßmethode geht der Fehler stärker oder schwächer 
ein. Was wird wie kalibriert? Ohne Schaltplan und Code und ohne genau zu 
wissen was womit abgeglichen wird ist das nicht beurteilbar wie stark 
die Abweichung das Endergebnis verfälscht.

Andy S. schrieb:
> Wird der Unipolar modus verwendet, dann beträgt der Offset ca. 10-15 LSB

Das ist nicht möglich. Es ist ein 10 Bit Wandler. LSB bedeutet Least 
Significant Bit. Ein Fehler von 3 LSB bdeutet das die letzten 3 Bits 
Grütze sind. Das Ergebnis kann also um 0 bis 2^3=8 Abweichen. 15 
verkehrte Bits sind nicht möglich. So viele Bits hat der Wandler nicht.

Andy S. schrieb:
> Wird jedoch der Bipolar modus angewandt, so schnell der Offset auf 50-60
> LSB hoch.

Fehler in verketteten Operationen verstärken sich. Ist der erste Wert 
verkehrt, dazu die Referenz falsch und dann das ganze verstärkt, so wird 
auch der Endfehler entsprechend verstärkt. Hinzu kommt, daß die 
Verstärkung selbst auch noch einen eigenen Fehler mitbringt. Das kann 
sich wie schon gesagt aufsummieren/multiplizieren. Ohne Kenntnis des 
genauen Verfahrens ist das nicht beurteilbar wie sehr sich das 
aufschaukelt.

Andy S. schrieb:
> Das erscheint mir doch etwas zu viel, zumal im Datasheet ca. 8 LSB als
> typ. angegeben wird.

Das ist in der Tat blöd formuliert im Handbuch. Das ist ein Fehler. Du 
beziehst dich vermutlich auch die Angabe absolute Accuracy auf Sete 179. 
Da steht 8 LSB. Eine Genauigkeit gibt man nicht in  LSB an. Da müßte 
entweder MSB für Most Significant Bit oder einfach nur Bit stehen.

LSB bei Genauigkeit macht einfach keinen Sinn, es sei denn man möchte 
damit zum Ausdruck bringen, daß es um das niedrigste noch gültige Bit 
geht. Das wäre aber eine unübliche, eigenwillige Neuinterpretation. Das 
wäre zudem noch inkonsistent, da zuvor LSB noch in der üblichen Art und 
Weise verwendet wird. In anderen Atmel-Handbüchern für andere Modelle 
steht es auch anders geschrieben. Es ist also eher ein 
Flüchtigkeitsfehler bei der Eintragung der Einheiten im Dokument.

Ferner wäre noch von Bedeutung wie schnell du mißt. Der ADC hat einen 
eigenen Takt. Dieser wird über einen Taktteiler aus dem Haupttakt 
erzeugt. Ich meine damit aber NICHT die Samplingrate. Die gibt nur an 
wie oft gemessen wird. Die beiden Werte sind nur indirekt 
zusammenhängend in sofern, daß der Takt angibt wie hoch die Samplingrate 
maximal sein kann. Ist der ADC Takt zu hoch, wird die Wandlung zunehmend 
ungenau. Der Taktteiler des ADC ist also je nach Haupttakt entsprechend 
anzupassen.

Auch ist zu beachten daß nach der (re)Konfiguration des ADC das erste 
Ergebnis machmal Schrott ist, ja nachdem was man gerade umgeändert hat. 
Z.B. ist die erste Messung nch dem Setzen der Referenz ungültig. Dann 
muß also vor dem eigentlichen Messen eine zusätzliche Dummy-Messung 
vorab erfolgen, dessen Ergebnis verworfen wird.

Also ich empfehle noch einmal das Tutorial hier zum ADC und das 
Datenblatt in Ruhe zu lesen und ein paar Projekte ebenso um einen 
Überblick über die Stolperfallen beim ADC zu erhalten.

von Carsten R. (kaffeetante)


Lesenswert?

Irgendwie ist der ganze Block im jenem Datenlatt etwas kruddelig.

von Carsten R. (kaffeetante)


Lesenswert?

Um dieses Dokument geht es

http://www.atmel.com/Images/doc8183.pdf

Carsten R. schrieb:
> LSB bei Genauigkeit macht einfach keinen Sinn

Machmal wird das zwar auch gemacht, dann ist aber gemeint, "Genau bis 
auf die letzten 2 Bits" bei 2 LSB. Das macht Atmel auch. Aber dann im 
selben Dokument zu schreiben Genauigkeit 8 LSB macht bei einem 10 Bit 
ADC nun wirklich gar keinen Sinn. Dann bleiben nur noch 2 Bit übrig^^ Da 
geht in dem besagten Dokument ein bissl was durcheinander. Und das dann 
auf Seite 178 steht 15 LSB macht es nicht besser. Da kann an sich auch 
nicht mehr herausreden mit: Es sollte eigentlich 1.5 LSB heißen. Was 
soll dann die 8 auf der nächsten Seite?

Wie gesagt, die anderen Datenblätter wie zum Beispiel das vom ATtiny261 
sind besser.

http://www.atmel.com/Images/Atmel-2588-8-bit-AVR-Microcontrollers-tinyAVR-ATtiny261-ATtiny461-ATtiny861_Datasheet.pdf

Aufgrund der Ähnlichkeit der Chips würde ich in diesem Falle also auch 
mal die anderen Datenblätter nutzen bis dieses überarbeitet wurde.

@Andy

Da hast Du bezüglich der Dokumentation für den Einstieg genau den 
richtigen Chip erwischt ;-)

von Andy S. (1632andys)


Lesenswert?

Carsten R. schrieb:
> Andy S. schrieb:
>> Dabei wird Differentiell gemessen, wobei auch der Bipolar Modus zum
>> Einsatz kommt um sowohl Lade- als auch Entladeströme zu erfassen.
>
> Der Bipolar Modus ist der Differenzbetrieb. "Wobei auch..." läßt aber
> vermuten daß Du das anders aufgefaßt hast.

Ist schon klar. Jedoch besteht die Möglichkeit die Basis für die 
Differezmessung auf 0-1023 fest zu legen wie es bei der Unipolaren 
Methode ist, oder halt von -512 bis + 511 wie es bei der Bipolaren 
Methode der Fall ist.
Der einzige Unterschied zw. Single Ended Messungen und der 
Differnezmessung im Unipolaren Modus ist der, dass du dein GND beliebig 
legen kannst (also logisch im bereich von Gnd - Vcc) und halt nicht 
unbedingt auf den AGND angewiesen bist.

Carsten R. schrieb:
> Aber dann im
> selben Dokument zu schreiben Genauigkeit 8 LSB macht bei einem 10 Bit
> ADC nun wirklich gar keinen Sinn. Dann bleiben nur noch 2 Bit übrig^^ Da
> geht in dem besagten Dokument ein bissl was durcheinander.

Das hab ich mir auch gedacht ^^
Ich habe es dann einfach so interpretiert, dass Atmel damit +- 8(dez.) 
bezeichnet und logischer weise nicht +-8 bit.

Vielleicht sollte ich noch erwähnen, dass die Angaben die ich weiter 
oben gemacht habe, also die Ungenauigkeit dann natürlich als 10-15 
(dez.), respektiv 50-60 (dez.) zu interpretieren sind.


Zurück zum Thema:

Selbst wenn die Genauigkeit bei 1.5 LSB (bit) oder von mir aus auch bei 
3 LSB (bit) liegen mag, sind die Werte von bis zu 60(dez.) als Offset 
deutlich darüber. Mich wundert es halt, dass so große Abweichungen 
auftreten, damit lässt sich nicht schön arbeiten.

von Andy S. (1632andys)


Lesenswert?

Carsten R. schrieb:
> Also ich empfehle noch einmal das Tutorial hier zum ADC und das
> Datenblatt in Ruhe zu lesen und ein paar Projekte ebenso um einen
> Überblick über die Stolperfallen beim ADC zu erhalten.

Da steht leider nix über Differentielle Messungen so wie ich sie gerne 
hätte.

Es ist auch nicht das Erste mal für mich, dass ich mit einem ADC 
Messungen anstelle. Soll heißen: Der ADC wurde meines Wissens nach 
richtig konfiguriert.
Also das Übliche halt: Takt nicht zu hoch Referenz richtig gesetzt. 
(Muss hier nicht mit einem externen Kondensator entkoppelt werden, 
glaube dazu gibt es auch einen Thread hier im Forum der sich damit 
beschäftigt. Es wird auf jeden fall nicht explizit im Datasheet verlangt 
und die V_REF Spannung wird auch nicht nach drausen geführt)
Aktualisierung der MUX Einstellungen erst nach erfolgreicher Wandlung 
usw.

von Andy S. (1632andys)


Lesenswert?

Hier ist noch der Teil des Source-Codes der sich mit dem ADC 
beschäftigt:

Zur Schaltung gibt es nicht viel zu sagen:

ATtiny 44a mit minimal Beschaltung zu testzwecken. Also das Übliche... 
alle ic´s mit 100n entkoppelt Bypass Kondensator an den Messeingängen 
Spannungen mit Multimeter abgleichen.
Saubere DC als Vcc.


 void init_all(void)
 {
   //UART
   init_suart();
   //ADC
  ADCSRA|=_BV(ADPS1)^_BV(ADPS2);  //ADC an Fosc/64
   ADMUX|=_BV(REFS1);  //Interne 1.1V
   ADCSRB|=_BV(BIN);  //Bipolar iput mode
   offset_calib();

 }

 int16_t get_adc(uint16_t mux)
 {
   ADMUX&=~ADC_MUX_MASK;  //ADC mux löschen
   ADMUX|=mux;  //Kanal einstellen

   ADCSRA|=_BV(ADEN)^_BV(ADSC);  //einzelne Messung starten
   while (!(ADCSRA & (1 << ADIF)));  //Warten bis fertig
   ADCSRA|=(1<<ADIF);  //interrupt bit löschen

  ADCSRA&=~_BV(ADEN);
   return(ADC);
 }

 void offset_calib(void)
 {
   int16_t sum=0;
   for (uint8_t i=0;i<16;i++)
   {
     sum+=get_adc(ADC_MUX_OFFSETT_CALC);
     //convert_transmit(sum,MITVZ);
   }

   offset_adc=(sum/16);
 }


int main(void)
{
  init_all();
  //sei();
    while(1)
    {
    _delay_ms(1000);
    convert_transmit(get_adc(6),MITVZ);  //Single ended
    convert_transmit(get_adc(0b00100100),MITVZ);  //Diff gain1 pos und 
neg beide an adc3 --> offset calib
    sputchar('\n');
    }
}

von Carsten R. (kaffeetante)


Lesenswert?

Andy S. schrieb:
> Muss hier nicht mit einem externen Kondensator entkoppelt werden,

Richtig. Aber man kann. Dann ist der Pin allerdings damit belegt und 
nicht mehr anderwertig nutzbar. Man macht das also nur, wenn notwendig 
oder wenn der Pin ohnehin frei ist und man unbedingt Teile verbauen 
will. Somit haben wir beide Recht.

Zum Code:

Er ist ja nur auszugsweise und ich schreibe in Assembler. Daher bin ich 
mir bei ein oder zwei Details nicht sicher ob sie von Dir oder von einer 
der Standard-Deklarationen stammen. Wie auch immer.

Deine offset_calib(void) hinterlegt den Offset in offset_adc. Danach 
wird das Teil nicht mehr angefasst. Ich kenne zwar ADC_MUX_OFFSETT_CALC 
nicht, aber ich nehme an das ist irgendwo schon richtig deklariert und 
definiert.

Mir ist jetzt nicht klar wo Dir nun der Offset ausgegeben wird. In der 
offset_calib(void) ist es ja auskommentiert. Also bleibt nur die Stelle 
am Ende der Main(). Beide stützen sich auf get_adc. Und da hakt es.

1. Du setzt die Referenz und kalibrierst dann. Die erste Messung ist 
Schrott (s.O. Referenz ändern). Also vor dem Kalibrieren Dummymessung 
einführen.

2. Dann wird in der get_adc(xxx) jedesmal der MUX neu gesetzt. Bei 
differentiellen Messungen braucht der Verstärker Zeit zum Einschwingen 
vor der Messung. Daß du jedesmal zwar den selben Kanal wählst ändert 
daran nichts. Den Hinweis findest du auf Seite 144 unten. Auch hier 
Dummymessung einfügen und verwerfen oder durch Ein- und Ausschalten eine 
long conversion erzwingen.

3. Du mißt im Pollingbetrieb anstatt im Sleep. Die CPU arbeitet weiter 
und erzeugt so Störungen.

4. Du verwendest keinen Kondensator zum stabilisieren der Referenz.

Jeweils einzelnd mag das noch gehen. Aber in der Summe schaukelt es sich 
dann auf. Weitere Störquellen, eventuell auch Schaltungstechnische 
Störungen, sind nicht ausgeschlossen.

Ich hoffe ich konnte Dir weiterhelfen.

schönes WE

Carsten

von Andy S. (1632andys)


Lesenswert?

Carsten R. schrieb:
> 2. Dann wird in der get_adc(xxx) jedesmal der MUX neu gesetzt. Bei
> differentiellen Messungen braucht der Verstärker Zeit zum Einschwingen
> vor der Messung. Daß du jedesmal zwar den selben Kanal wählst ändert
> daran nichts. Den Hinweis findest du auf Seite 144 unten. Auch hier
> Dummymessung einfügen und verwerfen oder durch Ein- und Ausschalten eine
> long conversion erzwingen.

Wird ja hier gemacht. Nach jeder Messung wird der ADC angehalten und vor 
jeder Messung erneut gestartet.

   ADCSRA|=_BV(ADEN)^_BV(ADSC);  //einzelne Messung starten
   ...

   ADCSRA&=~_BV(ADEN);


Dies sollte meines Wissens nach eine längere Wandlung erzwingen.

Das mit dem Dummy-Read sowie dem Tip mit ADC Noise Reduction und doch 
mal die V_REF mit einem Kondensator entkoppeln werde ich mal 
ausprobieren.

Danke soweit!

von Carsten R. (kaffeetante)


Lesenswert?

Ah sorry,

das hatte ich glatt überlesen. _BV(ADEN) ist für meine Augen etwas 
ungewohnt^^ Da hast du recht. Damit sollte eine long conversion 
erzwungen werden.

Somit wäre Nummer 2 zu streichen. Im zweifel würde ch trotzdem mal eine 
zusätzliche Dummymessung testen wenn man nicht weiterkommt. Nummer 1, 
das Setzen der Referenz, bleibt trotz An- und Abschalten per ADEN ein 
Problem. Hier sollte die erstn Messung auf jeden Fall verworfen werden.

Viel Glück bei der Optimierung der Genauigkeit.

Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.