Guten Abend,
mein AD-Wandler vom ATmega32 tut nicht so ganz was er soll, ich messe
eine Spannung 4 mal, bilde dann den Mittelwert und gebe den zurück.
habe eine externe refernzspannung von 2,5Volt. Meine Spannung liegt bei
1,3Volt, der AD-Wandler gibt mir aber einen wert von 0-3mV zurück, wo
liegt der fehler im unteren code, suche mich schon eine weile dumm und
dämlich... vielleicht kann mir ja einer von euch helfen???
float Spannung_ADC (char Kanal)
{
// Variablen
float Wert=0; // Hilfsvariable zur Mittelwertbildung
char M_ADC; // Zählvariable zur Mittelwertbildung
// ADC initialisieren, eigenes Initialisierungsprogramm???
//ADMUX |= (0<<REFS1) | (0<<REFS2); // externe Referenzspannung,
testen ob die Zeile benötigt wird
ADMUX = 0x00; // versuchen!!!
ADMUX = Kanal;
ADCSRA |= (1<<ADEN); // ADC aktivieren, eventuell nach der Messung
deaktivieren???
ADCSRA |= (1<<ADPS0); // Vorteiler wählen
ADCSRA |= (1<<ADPS2); // Vorteiler wählen = 4MHz / 32
for(M_ADC=0;M_ADC<=4;M_ADC++)
{
ADCSRA |= (1<<ADSC); // ADC starten
while(ADCSRA & (1<<ADSC))
{;} // warten bis die Wandlung beendet ist, muss das
semikolon in der {} sein???
Wert = Wert + ADCW; // Zur Mittelwertbildung 4 Messwerte
aufaddieren
}
Wert = Wert / 4 * 2500 / 1024; // Mittelwert der Spannung in mV,
Formel überprüfen, ist überprüft
return Wert;
Dirk A. schrieb:> Wert = Wert / 4 * 2500 / 1024; // Mittelwert der Spannung in mV,
Ich vermute dass die Formel Klammern braucht, wegen punkt-vor-strich.
Kann jedenfalls nicht schaden.
achso, als zusatz ist mir noch aufgefallen, bei einer sehr kleinen
Spannung, ein paar milli Volt zeigt er mir 230mV an, der Wert ist nun
viel zu groß...
Wird denn 4 * 2500 / 1024 auch in float gerechnet? Könnte ja ein Fehler
in der Typkonvertierung sein. Da ich mal denke, dass der Compiler das zu
Compilierungszeit ausrechnen wird, nur bin ich mir selbst nicht sicher
in welchem Typ.
Ich würde mal versuchen ins disassembly zu schaun und/oder Wert * 9.7xxx
in den Code einfügen.
werte gebe ich auf einem LCD aus. eine einzelne Wandlung hatte auch
schon funktioniert, habe eigentlich nur die schleife mit den 4 messungen
eingebaut, dazu die mittelwert bildung,
mit einer float-Ausgabe? oder hast du bei einer Messung einen Integer
gehabt?
Kannst ja auch mal den gesamten Code anhängen, dann können wir selber
schaun :-)
also, die sache mit der Formel scheint ok zu sein, hab das einfach mal
nach benni L. geändert, aber das hat nicht bewirkt...
im anhang der komplette code, aber der is recht lang, das adc ergebnis
wird in den unterprogrammen laden und entladen verwendet!
In deiner void laden():
float Spannung_neu; //neuer float für Wert
//...
Spannung_neu=Spannung_ADC(1); //einlesen des float-Werts
//...
itoa(Spannung_neu,buffer,10); //hier ist das Problem *
//...
lcd_string(buffer); //hier wird ausgegeben
*Zum Problem:
itoa heist integer to ascii,
sprich hier wird eine implizite Typwandlung von float nach int
vorgenommen,
du bräuchtest eher ftoa (float to ascii).
Hoffe ich liege richtig :-)
float Wert = Wert / 4 * 2500 / 1024;
lässt sich auf Int32 rumrechnen:
uint32_t Wert = Wert * 2500;
Wert = Wert >>12;
;-) geht um einiges schneller, und rundunsfehler sind in den
Zwischenschritten nicht drin, weil zuerst multipliziert wird.
Naja zu deinem Problem denke ich, dass deine Rechnung im Integerbereich
gerechnet wird.
Probier mal:
Wert = Wert * 0.61F ; //das F für floatberechnung mal hintenran
ich hab diese blöde formel jetzt schon rausgenommen, auch das 4fache
messen, leider gibt der mir immernoch murx raus, liegt also nicht an der
berechnung
ark..moment, was machen denn die beiden zeilen, behaken die sich? kanal
ist der erste!
ADMUX = 0x00;
ADMUX = Kanal;
hmm, dürfte ja nix machen.. naja ich probier mal deins aus
Also erstens würde mich stören, dass dies auskommentiert ist und
zweitens die Null in den Klammern. Dann müßteste aber die folgende Zeile
mit ADMUX=0; entfernen oder anpassen - sonst wäre der Wert der
auskommentierten Zeile ja gleich wieder überschrieben.
Bin zwar auch noch eher ein Anfänger in der µC-Programmierung, denke
aber dass diese Zeile schon benötigt wird, da sonst keine Angabe zur
verwendenden Ref-Spannung gemacht wird. Oder ist bei dir irgendwas
externes verschalten?
Ausserdem wird deine for Schleife zur MW-Bildung doch fünf mal
durchlaufen (0-->4 = 5 Durchläufe), teilen tust du aber durch 4.
Es sei denn du verwirfst irgendwo einen ersten Messwert oder etwas in
der Art...was ich jetzt übersehen habe.
Grüße
die Zeile wird nicht benötigt, da weiter unten steht ADMUX = 0x00;
und das mit den schleifendurchläufen ist richtig von dir, danke, hab ich
geändert, verfälscht aber doch nur den wert, und nimmt keinen einfluss
darauf das da was anderes nicht funktioniert...
Dirk A. schrieb:> also bei ADMUX = 0x1f; ist der wert 0> bei ADMUX = 0x1e; liegt der wert bei 53, 55, 58
Im unteren Falls kann was nicht stimmen, wenn du eine Referenz von 2,5
Volt hast.
0x1E heißt, dass testweise 1,2 Volt gemessen werden, was ungefähr in
einem Wert von Max/2 enden sollte, also bei 10bit ungefähr 500.
Passt deine Referenz? Schaltplan?
Ich würde mal einen Schritt zurückgehen:
Die ADC Routinen aus diesem Codewust extrahieren.
Ein eigenes Testprogramm aufsetzen, das nur diese ADC Routine enthält
Als Ausgabe: den Wert, so wie er vom ADC kommt. Ohne irgendwelche
Umrechnungen.
Für meine Begriffe wurde hier wieder mal der Kardinalfehler in der
Softwareentwicklung gemacht: Zuviel Code auf einmal geschrieben, ohne
die essentiellen Teile vorab zu testen. Damit steht man dann irgendwann
mit Unmmengen von Code da, der nicht funktioniert und kein Mensch weiß
wo er mit Fehlersuche anfangen soll.
Und nein: Die ganzen Ausgaben und Benutzersteuerungen sind nicht
essentiell. Essentiell für die Funktion wichtig ist der ADC und nicht,
dass einen das Programm mit 'Willkommen' begrüßt.
Zuerst muss der ADC funktionieren, und erst dann fängt man an sich vom
korrektem ADC Ergebnis in Richtung 'schöne Präsentation'
voranzuarbeiten. Lieber ein Programm, welches funktional richtig ist und
seine Ergebnisse schlecht präsentiert als anders rum. Im ersten Fall hab
ich zumindest ein Programm, mit dem man arbeiten kann. Im zweiten Fall
hab ich aber gar nichts.
gut, das war auch mein gedanke, aber ganz so bin ich da schon nicht
rangegangen, habe eine reine ad-wandlung schon getestet und diese hatte
auch funktioniert, kenn das problem ja mit viel code und dann erst
testen... aber naja, da es nicht geht muss ich das ganze nun trotzdem
nochmal machen... schritt für schritt... ich hoffe ich finde so dann den
fehler