Forum: Mikrocontroller und Digitale Elektronik Mein AD-Wandler macht nicht was er soll.


von Dirk A. (Gast)


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;

von Ohforf S. (ohforf)


Lesenswert?

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.

von Dirk A. (Gast)


Lesenswert?

ist doch nur Punktrechnung drinn... naja, versuchen kann ichs, aber das 
dürfte nicht der grund sein

von Dirk A. (Gast)


Lesenswert?

und es ist auch nicht der grund, schade eigentlich

von Ohforf S. (ohforf)


Lesenswert?

Hnn... du hast recht, das wird ja von links nach rechts gerechnet... 
Schande über mich.

von Dirk A. (Gast)


Lesenswert?

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ß...

von Flo (Gast)


Lesenswert?

Wie gibst du die Werte aus? Display, seriell...?

von Benni L. (sutter_cain)


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.

von Dirk A. (Gast)


Lesenswert?

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,

von Flo (Gast)


Lesenswert?

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 :-)

von Dirk A. (Gast)


Angehängte Dateien:

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!

von Flo (Gast)


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 :-)

von Dirk A. (Gast)


Lesenswert?

hmm, also das umformen mit itoa hatte schon funktioniert, auch bei ner 
float variablen, hab halt dann nur keine komma stellen!

von Flo (Gast)


Lesenswert?

Dann frag ich mal naiv, warum du überhaupt float verwendest, wenn du die 
Nachkommastellen sowieso über Board wirfst ?

http://www.mikrocontroller.net/articles/Festkommaarithmetik
:-)

von Dirk A. (Gast)


Lesenswert?

zum berechnen, sonst rundet er doch etwas zu stark

von Flo (Gast)


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

von Dirk A. (Gast)


Lesenswert?

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

von Flo (Gast)


Lesenswert?

setz ADMUX mal testweise auf 0x1F (0x1E), da müssten dann in der Messung 
0V (1,22V)rauskommen, um zu schaun, ob die AD-Wandlung tut.

von Dirk A. (Gast)


Lesenswert?

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

von Dirk A. (Gast)


Lesenswert?

also bei ADMUX = 0x1f; ist der wert 0
bei ADMUX = 0x1e; liegt der wert bei 53, 55, 58

von theo (Gast)


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

von Dirk A. (Gast)


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...

von Flo (Gast)


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?

von Karl H. (kbuchegg)


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.

von Dirk A. (Gast)


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

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.