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.
ist doch nur Punktrechnung drinn... naja, versuchen kann ichs, aber das dürfte nicht der grund sein
Hnn... du hast recht, das wird ja von links nach rechts gerechnet... Schande über mich.
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 :-)
hmm, also das umformen mit itoa hatte schon funktioniert, auch bei ner float variablen, hab halt dann nur keine komma stellen!
Dann frag ich mal naiv, warum du überhaupt float verwendest, wenn du die Nachkommastellen sowieso über Board wirfst ? http://www.mikrocontroller.net/articles/Festkommaarithmetik :-)
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
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.
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 bei ADMUX = 0x1f; ist der wert 0 bei ADMUX = 0x1e; liegt der wert bei 53, 55, 58
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
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
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
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.