Hallo,
ich habe mich in letzter Zeit mit der Spannungsmessung der Batterien beschäftigt und möchte meine Erkenntnisse hier zur Diskussion stellen.
Meiner Meinung nach funktioniert die Akku-Spannungsmessung so wie sie in der Nibobeelib implementiert ist nicht.
Für die Messung der analogen Signale wird die AVcc als Referenzspannung benutzt, auch für die Messung der Akkuspannung. Da sich ein Spannungsteiler von 2*47K (R43,R44) am Eingang ADC4 (=VBAT) befindet, wird man immer den Wert von ca. 512 als Resultat der Akkuspannung erhalten.
Das kommt daher, dass der ADC immer den Wert 1024 für den Vollausschlag für die Spannung an AVcc heranzieht. Woher soll also der ADC wissen, dass die Akkuspannung und damit AVcc in die Knie geht?
Will man also die Akkuspannung messen, so braucht man eine Referenzspannung an AVcc, die konstant ist und von der Akkuspannung unabhängig ist. Dazu kann man die interne 2.56V Referenzspannung im ATMega16 benutzen.
Ich hoffe, dass ich das bis hierher richtig wiedergegeben habe und möchte mal nachfragen, ob ihr das genauso seht.
Nun habe ich hier mal ein kleines Programm geschrieben, das auf diese Weise zu den richtigen Ergebnissen führt. Da ich nicht in der Nibobeelib herumdoktern wollte, ist es gewissermassen ein "Workaround", um den Fehler zu korrigieren ohne die anderen ADKanäle zu stören oder zu verändern.
Vielleicht wird ja der Fehler in einer neuen Nibobeelib behoben.
Nun bin ich mal auf eure antworten gespannt.Code:int Batterie(void) { unsigned char temp1,temp2; uint16_t ADCresult; while ((ADMUX & 0x07) != 0x04); cli(); while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete ADCSRA |= (1 << ADIF); // clear ADCIF //Registerinhalte retten temp1 = ADCSRA; temp2 = ADMUX; ADMUX = (1 << REFS0) | (1 << REFS1) | ANALOG_VOLT; //internal 2.56V reference with external capacitor //ADCSRA löschen und neu setzen ADCSRA = 0; ADCSRA |= ((1 << ADPS2) | (1 << ADPS1) | (1 << ADPS0)); //ADC clock = Clock/128 ADCSRA |= (1 << ADEN); //Enable ADC (das aktiviert die 2.56V Referenz) //Warten bis Kondensator an ARef = 2.56V hat //Messung an ARef ergab 1,2msec delay(6); // = ca. 5*Tau //1. ADC Wandlung starten und Ergebnis ignorieren ADCSRA |= (1 << ADSC); // Start conversion while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete ADCSRA |= (1 << ADIF); // clear ADCIF //2. ADC Wandlung starten und Ergebnis übernehmen ADCSRA |= (1 << ADSC); // Start conversion while (!(ADCSRA & (1 << ADIF))); // wait for conversion complete ADCSRA |= (1 << ADIF); // clear ADCIF ADCresult = ADCL + (ADCH << 8); //Registerinhalte wiederherstellen ADMUX = temp2; ADCSRA = temp1 & ~(1 << ADSC); //Warten bis Kondensator an ARef = AVcc hat //Messung ergab sehr steile Flanke delay(2); //nicht notwendig, nur zur Sicherheit ADCSRA |= (1 << ADSC); // Start conversion sei(); return ADCresult; }
Viele Grüsse
Skroete







Zitieren

Lesezeichen