PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Spannungsmessen ergibt falschen Wert?



Schmiddi
01.09.2012, 14:05
Hallo zusammen,

ich bin neu hier im Forum und was Microcontroller angeht noch absoluter Anfänger. Ich bastle bereits seit einigen Tagen mit einem Arduino Einsteigerset herum und hatte auch schon so meinen ein oder anderen Erfolg damit.

Jetzt versuche ich mit dem Arduino eine externe Spannung zu messen, im aktuellen Fall die Gesamtspannung eines 4-Mignon Akkupacks (ca 5,2 Volt). Im Internet habe ich eine Möglichkeit gefunden die aktuelle Betriebsspannung zu messen (readVCC), aus dieser (Referenzspannung) berechne ich dann die gemessene Spannung. Um den Controller nicht zu beschädigen arbeite ich mit einem Spannungsteiler, die Messpannung sollte dann also 2,6V ergeben (Mit Mulimeter nachgemessen). Der Controller misst jedoch nur eine Spannung mit 2,0V. Ist es falsch die gemessene Vcc als Referenzspannung in der Berechnung zu nutzen?

Hier mein Code:



int Betriebsspannung = 0;
int Messspannung = 0;
int ADC0=0;

void setup() {
Serial.begin(9600);
}

void loop() {
Betriebsspannung = readVcc(); //Millivolt
Messspannung = readInput0();
Serial.print("Betriebsspannung: ");
Serial.print(Betriebsspannung);
Serial.println(" Volt");
Serial.print("Messspannung: ");
Serial.print(Messspannung);
Serial.println(" Volt");
Serial.println("");
delay(1000);
}

int readInput0()
{
int Ergebnis1024 = analogRead(ADC0);
int Ergebnis = Betriebsspannung / 1024 * Ergebnis1024;
return Ergebnis;
}

//Funktion zum Auslesen der Betriebsspannung Vcc des Controllers
int readVcc() {
int Ergebnis; //Variable für Millivolt
// Lesen der 1.1V Referenz gegen AVcc
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
delay(2); // Wartet bis Vref abgeglichen ist
ADCSRA |= _BV(ADSC); // Umwandeln
while (bit_is_set(ADCSRA,ADSC));
Ergebnis = ADCL;
Ergebnis |= ADCH<<8;
Ergebnis = 1126400L / Ergebnis; // Back-calculate AVcc in mV
return Ergebnis;
}


Vielen Dank!

Schmiddi
01.09.2012, 15:09
Hallo nochmal,

ich bin jetzt nach langem rumprobieren und manuellem nachrechnen drauf gekommen dass es so funktioniert:



int readInput0()
{
long Ergebnis1024 = analogRead(ADC0);
return Betriebsspannung * Ergebnis1024 / 1024;
}



So funktioniert es jedoch NICHT: (2,12V statt 2,54V)


int readInput0()
{
long Ergebnis1024 = analogRead(ADC0);
long Ergebnis = Betriebsspannung / 1024 * Ergebnis1024;
return Ergebnis;
}


Kann mir das jemand erkläen?!

Che Guevara
01.09.2012, 15:52
Hi,

ich selbst behersche zwar kein C (nur in Grundzügen), aber ich denke es liegt daran, dass du im zweiten Beispiel erst dividierst und dann multiplizierst, dadurch verlierst du Auflösung ;)

Gruß
Chris

shedepe
03.09.2012, 14:37
Du solltest auch noch bedenken, dass long ein ganzzahliger Datentyp ist. Und damit keine Kommazahlen aufnehmen kann. Bei der Rechenoperation die du durchführst kommt allerdings mit recht hoher Wahrscheinlichkeit meistens eine Kommazahl raus. (Die Nachkomma stelle wird abgeschnitten)

RoboHolIC
03.09.2012, 21:41
Da gibt es auch noch das Ding mit der Auswertung von Ausdrücken. Die beiden Varianten sind für mich uneindeutig, weil eine Klammerung fehlt, die den Zähler vom Nenner trennt, sprich: den Buchstrich erkennbar macht.
Wenn man z.B. den Ausdruck a / b * c (mit a, b, c ganzzahlig positiv) von links mit dem Taschenrechner auszurechnen beginnt, so wird das Ergebnis mit wachsendem c ebenfalls größer. Fängt man dagegen rechts mit der Auswertung an (das ist bei Programmiersprachen bzw. deren Compilern nicht unüblich), so wird das Ergebnis mit wachsendem c immer keiner!

Schmiddi
04.09.2012, 22:56
@RoboHolIC: Daran hatte ich gar nicht gedacht, ich bin tatsächlich davon ausgegangen dass von links nach rechts gerechnet wird, interessanter Aspekt!

@shedepe: Das war mir soweit schon klar, ich hatte das ganze davor auch schon mit float getestet. Da es sich hier im mV handelt habe ich die Nachkommastellen vernachlässigt.

Ok, jetzt hab ich das ganze soweit kapiert und mein Programm funktioniert nun bestens.

Vielen Dank für eure Antworten!