mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik ATxmega: Batteriespannung messen mit int. Referenz und AVCC/10


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
Autor: Thomas L. (delfinis)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo,
ich versuche die Batterie mit den internen Bordmitteln des ATxmega32E5 
zu messen (Interne 1V Referenz und AVCC/10), da ich ein 
Batteriebetriebenes Projekt hab und nicht noch extern eine Referenz und 
einen Spannungsteiler einsetzen wollte, was zu zusätzlichem 
Stromverbrauch führen würde.

Bei 3.0V, meiner normalen 2xAA Batteriespannung funktioniert die Messung 
relativ genau ( (0.3 *2047) / 1 ) = 614, gewandelt 597 = 3% Fehler.
Wenn ich nun die Spannung des Speisegerätes runterdrehe, geht erst auch 
der Messwert linear runter. Aber ab einer Spannung von 2.76V und weiter 
unten sinkt plötzlich der gewandelte Wert rapide innerhalb von nur ein 
paar millivolt auf etwa 40% (230) und bleibt dort, auch wenn ich die 
Spannung noch weiter absenke.
Ich hab schon vieles ausprobiert und getestet, aber das Verhalten ist 
immer dasselbe. Ich hab den Code mal auf eine möglichst einfache 
Konfiguration gesetzt (keine Mittelung, kein Gain usw). Auch die Sample 
Rate hab ich auf 8kHz runtergedrückt, weil es im Datenblatt heisst, dass 
die internen Signale nur langsamer gesampelt werden können (Manual S.352 
mitte), jedoch hab ich im Datenblatt dazu nichts gefunden.
Auch der Versuch mit der umgekehrten Variante (int. Bandgap referenz als 
Eingang und AVCC/1.6 als referenz) hat nicht gefruchtet. Der Wert 
springt (logischerweise umgekehrt) von 1208(3V) auf 2047(2.73V)


Hier mal der Code:
void adc_init(void) {
  ADCA.CTRLA = ADC_ENABLE_bm;                     // Enable ADC
  ADCA.CTRLB = ADC_CURRLIMIT_HIGH_gc | ADC_CONMODE_bm | ADC_RESOLUTION_MT12BIT_gc;  // No power saving, signed singleended mode, average resolution
  ADCA.REFCTRL = ADC_REFSEL_INT1V_gc;             // Use internal 1V reference (same as DAC)
  ADCA.EVCTRL = ADC_EVACT_NONE_gc;                // Do not use events
  ADCA.PRESCALER = ADC_PRESCALER_DIV512_gc;         // ADC clock = 8kHz  speed
  ADCA.SAMPCTRL = 0x10;                           // Sampling time: shorter sampling time = lower impedance.

  ADCA.CH0.CTRL = ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_INTERNAL_gc; // x gain, use internal input (from DAC)
  ADCA.CH0.MUXCTRL = ADC_CH_MUXINT_SCALEDVCC_gc;        // Use 1/10 scaled VCC as input to ADC
  ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;   // No interrupts
  ADCA.CH0.SCAN = 0;                              // No channel scanning
//  ADCA.CH0.AVGCTRL = ADC_CH_SAMPNUM_1024X_gc | (4 << ADC_CH_RIGHTSHIFT_gp); // Oversampling to 16-bit resolution 1024 = best stability
  ADCA.CH0.AVGCTRL = ADC_CH_SAMPNUM_1X_gc; // No oversampling
}

// Test with internal bandgap reference as input and AVCC as reference (inverse measuring)
/*void adc_init(void) {
  ADCA.CTRLA = ADC_ENABLE_bm;                     // Enable ADC
  ADCA.CTRLB = ADC_CURRLIMIT_HIGH_gc | ADC_CONMODE_bm | ADC_RESOLUTION_MT12BIT_gc;  // No power saving, signed singleended mode, average resolution
  ADCA.REFCTRL = ADC_REFSEL_INTVCC_gc;            // ==>  Use internal AVCC/1.6
  ADCA.EVCTRL = ADC_EVACT_NONE_gc;                // Do not use events
  ADCA.PRESCALER = ADC_PRESCALER_DIV8_gc;         // ADC clock = 0.5 MHz    speed
  ADCA.SAMPCTRL = 0x10;                           // Sampling time: shorter sampling time = lower impedance.

  ADCA.CH0.CTRL = ADC_CH_GAIN_1X_gc | ADC_CH_INPUTMODE_INTERNAL_gc; // x gain, use internal input (from DAC)
  ADCA.CH0.MUXCTRL = ADC_CH_MUXINT_BANDGAP_gc;        // Use Bandgap reference as input to ADC
  ADCA.CH0.INTCTRL = ADC_CH_INTMODE_COMPLETE_gc | ADC_CH_INTLVL_OFF_gc;   // No interrupts
  ADCA.CH0.SCAN = 0;                              // No channel scanning
  ADCA.CH0.AVGCTRL = ADC_CH_SAMPNUM_1024X_gc | (4 << ADC_CH_RIGHTSHIFT_gp); // Oversampling to 16-bit resolution 1024 = best stability
}*/

// returns the battery voltage in x10mv - 800mV (For correct value add 80(x10mV) )
uint16_t ubat_read(void) {
  uint16_t res;
  uint16_t adc_res;
//  PORTD_OUTSET = 0x02;
  ADCA.CH0.INTFLAGS = ADC_CH_IF_bm;               // Clear ADC interrupt flag
  ADCA.CH0.CTRL |= ADC_CH_START_bm;               // Start ADC single conversion
  while (!(ADCA.CH0.INTFLAGS & ADC_CH_IF_bm));    // Wait for ADC to complete
  adc_res = ADCA.CH0.RES;
//  res = (adc_res * UBAT_FACT) - 80;          // Return result in x10mV (243 + 80 = 2.23V)
//  PORTD_OUTCLR = 0x02;
//  return res;
  return adc_res;
}



Anfangs hab ich das ganze auf einem Steckbrett zusammengebaut und 
getestet. Dies hat auch super funktioniert.
Dann hab ich eine Leiterplatte machen lassen und darauf funktioniert's 
nun nicht mehr, obwohl ich die Verdrahtung schon überprüft hab :-( .
Zum Schema: Einfach nur UBat an VCC, und mit einem Filter wie im DB auf 
AVCC. Beide GND zusammen auf GND.

: Bearbeitet durch User

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.