Mein AD-Wandler macht nicht was er soll.

Gast #1729733
Lesenswert?

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;
#1729760
Lesenswert?

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.
Gast #1729769
Lesenswert?

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!
Angehängte Dateien:
Gast #1729780
Lesenswert?

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 :-)
Gast #1729800
Lesenswert?

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
Gast #1729819
Lesenswert?

Hi,
was mir noch auffiel, die auskommentierte Festlegung der 
Referenzspannung:
1
//ADMUX  |=  (0<<REFS1) | (0<<REFS2); // externe Referenzspannung,
2
testen ob die Zeile benötigt wird

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
Gast #1729831
Lesenswert?

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...
Gast #1729956
Lesenswert?

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?
#1729980
Lesenswert?

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.
Gast #1732425
Lesenswert?

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

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren