Forum: Mikrocontroller und Digitale Elektronik ATmega32 differentielle Messung, ADCH und ADCL steigen nicht über 495


von Tobi R. (ccommander)


Lesenswert?

Hallo zusammen,

ich möchte eine Spannung differentiell zwischen ADC1 und ADC0 mit 
10facher Verstärkung messen.
Als Referenzspannung verwende ich AVCC. (5 V)

In einer Testschaltung gebe ich mithilfe eines Spannungsteilers 
verschiedene positive Spannungen auf ADC1. ADC0 liegt auf Ground.

Gebe ich keine Spannung auf ADC1, so gibt das ADC-Register einen Wert 
von 1023 aus.

Wenn ich eine Spannung von 0,5 Volt auf ADC1 gebe, sollte das Register 
einen Wert von 511 ausgeben. Tut es aber nicht. Egal was ich tue, ich 
kann das register nicht über den Wert 495 hinaus erhöhen.

Habt ihr eine Idee, woran es liegen kann?

Ich takte extern mit 8 MHz und setze den Prescaler für den ADC daher auf 
128.

Ich habe auch schon ausprobiert, ob vielleicht das BIT4 defekt ist. Dies 
ist aber nicht der Fall.

Viele Grüße
Tobias

hier noch ein paar Code-Schnipsel:
1
int ADC_read_diff(void)
2
{
3
4
     int ADC_temp, ADCH_temp;
5
6
7
8
     ADC_START_CONVERSION;
9
        while(!(ADCSRA & 0x10)); // wait for conversion done, ADIF flag active
10
        ADCSRA|=(1<<ADIF);
11
12
        ADC_temp = ADCL;         // read out ADCL register
13
        ADCH_temp = ADCH;        // read out ADCH register
14
    ADC_temp +=(ADCH_temp << 8);
15
16
17
18
    return ADC_temp;
19
}
20
21
void readDifferentialVoltage()
22
{
23
     int value;
24
     float volt;
25
26
     ADMUX = (1<<REFS0) | (1<<MUX0) | (1<<MUX3);
27
28
     _delay_ms(1);
29
       value = ADC_read_diff();
30
     //erste Messung soll laut Datenblatt verworfen werden.
31
     _delay_ms(1);
32
     value = ADC_read_diff();
33
34
35
     char buffer[64];
36
     int viertesBit = (value & (1<<4)) >> 4;
37
38
     sprintf(buffer, "\nADC-Wert = %d von 1023, viertes Bit: %d", value, viertesBit);
39
     transmitString2(buffer);
40
41
}

: Bearbeitet durch User
von c-hater (Gast)


Lesenswert?

Tobi R. schrieb:

> Gebe ich keine Spannung auf ADC1, so gibt das ADC-Register einen Wert
> von 1023 aus.

Mit "keine Spannung" meinst du 0V, also Anschluß an GND?

Dafür paßt aber der Meßwert nicht, der übrigens nicht 1023 ist, sondern 
in wirklichkeit -512. Bei differentieller Messung entstehen 
vorzeichenbehaftete Meßwerte, allerdings begrenzt auf die gewählte Zahl 
von 8 bzw. hier 10 Bits.

Bei 8 bit ist das kein Problem, da kannst du einfach mit signed char 
bzw. besser int8_t arbeiten. Bei 10 Bit gibt's aber keinen direkt 
passenden Datentyp, da mußt du selber Hand anlegen, um die 10 Bit 
vorzeichenrichtig auf die 16 Bit von int bzw. besser int16_t zu 
erweitern.

Aber das nur nebenbei, der eigentliche Punkt ist: Bei 0V Differenz hat 
auch bei diffenzieller Messung mit vorzeichenbehafteten Zahlen natürlich 
Null im Register zu stehen. Da stimmt also schon grundsätzlich was nicht 
an der Hardware.

von Fritz (Gast)


Lesenswert?

Wenn du die differentiellen Kanäle nutzt kannst du AVCC nicht als 
Referenzspannung verwenden, die muss min. 0,5V niedriger sein. 
(Datenblatt, Electrical ADC Characteristics)

von spess53 (Gast)


Lesenswert?

Hi

>Aber das nur nebenbei, der eigentliche Punkt ist: Bei 0V Differenz hat
>auch bei diffenzieller Messung mit vorzeichenbehafteten Zahlen natürlich
>Null im Register zu stehen. Da stimmt also schon grundsätzlich was nicht
>an der Hardware.

1023 wären -1. Also recht nah an Null heran.

> Tut es aber nicht. Egal was ich tue, ich
>kann das register nicht über den Wert 495 hinaus erhöhen.

Das ist eine Abweichung von knapp über 3%. Würde mich eher wundern, wenn 
es bei differentieller Messung und Gain 10 ohne Kalibrierung besser 
wäre.

AppNotes zum ADC:

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

http://www.atmel.com/Images/Atmel-8456-8-and-32-bit-AVR-Microcontrollers-AVR127-Understanding-ADC-Parameters_Application-Note.pdf

MfG Spess

von Ingo (Gast)


Lesenswert?

Tobi R. schrieb:
> while(!(ADCSRA & 0x10)); // wait for conversion done, ADIF flag active
>         ADCSRA|=(1<<ADIF);

ich würde hier, wie im Datenblatt empfohlen, das ADSC Bit in ADCSRA 
pollen, statt des Interruptflags! Bei mir gab das schonmal Probleme...
1
while (ADCSRA & (1<<ADSC));

> ADC_temp = ADCL;         // read out ADCL register
>         ADCH_temp = ADCH;        // read out ADCH register
>     ADC_temp +=(ADCH_temp << 8);
... würde ich ebenfalls gegen:
1
ADC_temp = ADC;
ersetzen


Ingo

von Tobi R. (ccommander)


Lesenswert?

Vielen Dank für eure Hilfe!

Ich denke, Fritz hat den Fehler gefunden.

Fritz schrieb:
> Wenn du die differentiellen Kanäle nutzt kannst du AVCC nicht als
> Referenzspannung verwenden, die muss min. 0,5V niedriger sein.
> (Datenblatt, Electrical ADC Characteristics)

Allerdings finde ich die Information nicht in meinem Datenblatt.

http://www.atmel.com/Images/Atmel-8155-8-bit-Microcontroller-AVR-ATmega32A_Datasheet.pdf

An einer Stelle steht:
"If differential channels are used, the selected reference should not be 
closer to AVCC than indicated in Table 27-4
on page 303."

Aber diese Tabelle gibt es nicht auf Seite 303 und ich habe sie auch 
nicht auf einer anderen Seite gefunden.

von Fritz (Gast)


Lesenswert?

Steht auch in dem Datenblatt im gleichen Abschnitt, da ist nur der 
"Link" im pdf falsch. (Tabelle 28-4, Seite 286 wäre richtig)

von Fritz (Gast)


Lesenswert?

Ähh, jetzt habs ich auch falsch gemacht:
Tabelle 28-5, Seite 286 ist richtig

von Tobi R. (ccommander)


Lesenswert?

Super!
Vielen, vielen Dank!

Fritz schrieb:
> Ähh, jetzt habs ich auch falsch gemacht:
> Tabelle 28-5, Seite 286 ist richtig


Habt ihr eventuell noch Tipps, wie ich jetzt eine genaue Spannung messen 
kann?

Ich habe mit dem Multimeter AREF gemessen und messe 2,59 V anstatt 2,56.

Das habe ich in den Code zum ermitteln der Spannung eingebaut.
Jetzt sollte mein Mikrocontroller doch eigentlich die gleiche Spannung 
zwischen ADC1 und ADC0 ausgeben, wie ein mit dem Multimeter gemessener 
Wert, oder?

Allerdings zeigt das Multimeter 0,126 V und der Mikrocontroller 0,130 V.

: Bearbeitet durch User
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.