Forum: Mikrocontroller und Digitale Elektronik ADC Messung Fehlerhaft


von Rafi D. (alexanderw)


Lesenswert?

Hallo

hab eine ADC Konvertierung und kriege auch fleißig Daten. Nur bei der 
Berechnung stimmt was nicht.

Beispiel: Am ADC Eingang habe ich eine Spannung von 3,22V und eine 
Referenzspannung von 5V.

Daraus folgt bei dem 10bit Wandler des Atmega164PA, das dies ein 
theoretischer Wert von 660 ist.
Aber die Ausgabe am UART zeigt mir einen Wert von 639 an.

Übersehe ich einen Offset, ist die Formel ADC-Wert = (U_adc * 1024) / 
U_ref falsch?

von spess53 (Gast)


Lesenswert?

Hi

Wie ist dein ADC initialisiert?

MfG Spess

von Rafi D. (alexanderw)


Lesenswert?

void AdcInit (void)
{
ADMUX=(1<<REFS0);
ADCSRA = (1<<ADPS1)|(1<<ADPS2);  /* ADC-Takt Prescaler = 64 */
ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable 
setzen */
}

und mit folgender Funktion lese ich diese aus

uint16_t AdcRead (uint8_t ADC_Kanal)
{
  /* Kanal waehlen, ohne andere Bits zu beeinflußen */
  ADMUX = (ADMUX & ~(0x1F)) | (ADC_Kanal & 0x1F);
  ADCSRA |= (1<<ADSC);
  while (ADCSRA & (1<<ADSC) ) {}
  return ADC;
}

von Rafi D. (alexanderw)


Lesenswert?

Folgend wird dann der Wert ausgewertet:

ADC_wert = AdcRead(PINA1);


if (ADC_wert>=645 && ADC_wert<=758)
{
  //tu was
}
else if (ADC_wert<=644 && ADC_wert>=600)
{
  // tu was anderes
}
else if (ADC_wert<=599)
{
  // tu was ganz anderes
}

von Patrick C. (pcrom)


Lesenswert?

Wie genau ist die 5V Referenzspanning ? Die '5V' von USB ist oft nicht 
sehr genau. Check auch mal ob es einen pull-up Widerstand gibt am 
Eingang.

von Rafi D. (alexanderw)


Lesenswert?

Die 5V kommen aus einem Linearregler und sind, ich sag mal vorsichtig 
relativ glatt. Naja sind dann auch net 5V sondern 4,96V.

Pull-up versteh ich net ganz. Aber die DDR-REgister des ADC Ports werden 
nirgendsweiter im Code angefasst, falls du das damit meinst.

von Fred S. (kogitsune)


Lesenswert?

Rafi Dafi schrieb:
1
> ADMUX=(1<<REFS0);
2
> ADCSRA = (1<<ADPS1)|(1<<ADPS2);  /* ADC-Takt Prescaler = 64 */
3
> ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable
Hiermit setzt Du die DAC-Frequenz auf F_CPU/2; die erste Zeile 
"ADCSRA=..." ist für die Konversion wirkungslos. Bei einer 
10Bit-Konversion sollte die DAC-Frequenz < 200 kHz sein.

von Rafi D. (alexanderw)


Lesenswert?

der bereich der ADC Frequenz soll ja zwischen 50 und 200 kHz.

da ich mit einem Quarz von 7,3728Mhz arbeite, ergeben sich folgende min 
und max Werte für den Prescaler:

36,864 und 147,456, daraus folgt für den Prescaler entweder 64 oder 128.

Laut Tabelle 23-5 ADC Presclaer selctions auf seite 260 aus dem 
Datenblatt des atmega 164PA muss adps1 und adps2 auf high gesetzt werden 
für 64 bzw. adps 1-3 auf High für 128.

ich hab mich jetzt für 64 entschieden, werde aber morgen das mal mit 128 
testen.

schönen tag noch.

von Stefan E. (sternst)


Lesenswert?

Rafi Dafi schrieb:
> Laut Tabelle 23-5 ADC Presclaer selctions auf seite 260 aus dem
> Datenblatt des atmega 164PA muss adps1 und adps2 auf high gesetzt werden

Genau das tust du aber nicht (oder besser gesagt nur für sehr kurze 
Zeit), weil die Zeile danach beide wieder auf 0 setzt.

von Fred S. (kogitsune)


Lesenswert?

Du hast Dich zwar für einen Teilerwert von 64 entschieden, aber Dein 
Code repräsentiert das nicht, denn mit
1
ADCSRA = (1<<ADPS1)|(1<<ADPS2);  /* ADC-Takt Prescaler = 64 */
2
ADCSRA = (1<<ADEN)|(1<<ADSC);/* ADC Enable und ADC Interrupt Enable
setzt Du ADPSx effektiv auf 0, also auf F_CPU/2.

von Patrick C. (pcrom)


Lesenswert?

>Pull-up versteh ich net ganz. Aber die DDR-REgister des ADC Ports werden
nirgendsweiter im Code angefasst, falls du das damit meinst.
Ok das ist was ist meinte. Ich habe selber mal ein solches problem gehat 
weil ich die Pull-Ups aktiviert hatte (oder das die standard aktiviert 
sind, weisz ich nicht mehr). Aber dann erwartete man eine abweichung in 
andere richtung.

Dabei habe ich noch gesehen das der ADC problemen geben kann bei 0V oder 
5V aber das ist hier auch nicht der fall...

von Gerald M. (gerald_m17)


Lesenswert?

ja, da du aber ein "=" anstatt einem "|=" hast, wird der Prescaler 
wieder gelöscht

von Michael K. (Gast)


Lesenswert?

639 zu 660 für einen unkalibrierten AD ohne bandgap Vref ist doch nicht 
schlecht. Ein Blick in die Glaskugel ...

21.7.3
Offset Compensation Schemes
The gain stage has a built-in offset cancellation circuitry that nulls 
the offset of differential mea-
surements as much as possible. The remaining offset in the analog path 
can be measured
directly by selecting the same channel for both differential inputs. 
This offset residue can be then
subtracted in software from the measurement results. Using this kind of 
software based offset
correction, offset on any channel can be reduced below one LSB.

von Rafi D. (alexanderw)


Lesenswert?

vielen Dank an die  Beiträge und antworten...

das war der Fehler "|=".

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.