mikrocontroller.net

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


Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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;

Autor: Ohforf Sake (ohforf)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk A. (Gast)
Datum:

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

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
und es ist auch nicht der grund, schade eigentlich

Autor: Ohforf Sake (ohforf)
Datum:

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

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß...

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie gibst du die Werte aus? Display, seriell...?

Autor: Benni L. (sutter_cain)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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,

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Dirk A. (Gast)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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 :-)

Autor: Dirk A. (Gast)
Datum:

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

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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
:-)

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
zum berechnen, sonst rundet er doch etwas zu stark

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Dirk A. (Gast)
Datum:

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

Autor: theo (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,
was mir noch auffiel, die auskommentierte Festlegung der 
Referenzspannung:
//ADMUX  |=  (0<<REFS1) | (0<<REFS2); // externe Referenzspannung,
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

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Flo (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Dirk A. (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.