Hallo! Die Funktionen für den ADC sind aus der Procyon-Library. Wenn ich folgende Schleife ausführe, kommt als Ergebnis nur für den ersten Messwert ein einigermassen korrektes Ergebnis. Die anderen Messwerte verwenden anscheinend immer einen Teil der vorhergehenden Wandlung. Verwende ich für jeden Messwert eine eigene Schleife ist das Ergebnis weitaus besser, eine Dummykonvertierung vor dem eigentlichen Aufruf der kty_measure() routine führt dagegen zu keiner Verbesserung. Hat jemand eine Idee was ich da falsch mache? Ich komme da nicht weiter :-( Die Messwerte sind als structs definiert und mit malloc initialisiert worden. Hier der Code (die wichtigsten Teile): a2dInit(); a2dSetPrescaler(ADC_PRESCALE_DIV32); for(lcount = 0; lcount < 65; lcount++){ kty_measure(TempMotor); kty_measure(TempController); kty_measure(TempFahrakku); } void kty_measure(measureT * m) { uint16_t tmp; if (m->count) { tmp = a2dConvert10bit(m->ioPin); m->tval += tmp; m->count--; } else { m->tval = m->tval / 101; m->tval = m->tval - 150; m->value = m->tval; m->count = 64; m->tval = 82; } } Gruss, Stephan
Hallo Stephan,
>Hat jemand eine Idee was ich da falsch mache?
Dein Programm-Code verstehe ich leider nicht,
aber ich vermute, Dein Mess-Prinzip hat einen gedanklichen Fehler.
Du machst folgendes:
Kanal umschalten
Messen
Kanal umschalten
Messen
usw.
besser wäre:
Kanal umschalten
Messen und Ergebnis verwerfen
Messen
Kanal umschalten
Messen und Ergebnis verwerfen
Messen
usw.
Bernhard
Hallo Bernhard, du meinst sicher folgendes: for(lcount = 0; lcount < 65; lcount++){ a2dConvert10bit(TempMotor->ioPin); kty_measure(TempMotor); a2dConvert10bit(TempController->ioPin); kty_measure(TempController); a2dConvert10bit(TempFahrakku->ioPin); kty_measure(TempFahrakku); } Das habe ich bereits probiert da ich den Hinweis schon irgendwo im Forum gefunden hatte. Leider tritt dadurch keine (sichtbare) Verbesserung ein :-( Gruss, Stephan
> du meinst sicher folgendes: Da kann ich leider nicht mitdiskutieren >Leider tritt dadurch keine (sichtbare) Verbesserung ein Und wenn Du längere Pausen zwischen den Messungen einlegst? Aber wenn Du nur einen einzigen Kanal misst, dann stimmte das Ergebnis?
Ich denke, ich habe das Problem gefunden. Die Eingänge für ADC1/2 (TempController/TempFahrakku) sind derzeit offen. Ich hatte erwartet, dass beim Kanalwechsel das gleiche Ergebnis wie bei einer Wandlung auf nur einem Kanal erscheind. DIES IST ANSCHEINEND NICHT DER FALL grummel. Steht das im Datenblatt vom ATmega128? Ich habs dann wohl beim überfliegen übersehen. Wenn ich einen der nicht benutzten Messwerte auf ADC_CH_AGND lege, stimmt das Ergebnis. Danke Bernhard! Bin dadurch auf die Idee gekommen einen Kanal mal auf GND zu legen. HURRA :-) Gruss, Stephan
>Danke Bernhard! Bin dadurch auf die Idee gekommen einen Kanal mal auf >GND zu legen. Mein Bankverbindung gebe ich Dir später ;) >Die Eingänge für ADC1/2 (TempController/TempFahrakku) sind derzeit >offen. Offene Eingänge sollte man vermeiden, habe auch schon diese zeitraubende Erfahrung machen müssen. Es entstehen undefinierte Spannungswerte an diesen Pins und diese sind sogar noch abhängig von den Pegeln der anderen Pins anderer Ports. Bernhard
Hallo, ich weiß der Threat ist schon etwas älter .... aber ich habe das selbe Problem nur ich verstehe die Lösung nicht denke ich... Ich habe alle Pins (außer den den ich messen will) an GND angelötet. Seltsamerweise bekomme ich aber an allen Pins den selben Messwert... Was ist gemeint mit: Wenn ich einen der nicht benutzten Messwerte auf ADC_CH_AGND lege, stimmt das Ergebnis. Was genau hast du da im Code gemacht? Gruß Michael
@Michael
> Was genau hast du da im Code gemacht?
Kanal umschalten
Messen und Ergebnis "verwerfen"
Messen
Kanal umschalten
Messen und Ergebnis "verwerfen"
Messen
usw.
Bernhard
>Was meinst du mit ergebniss verwerfen?
Es wird gemessen, das Messergebnis wird aber ignoriert (Dummy-Messung),
erst die nächste Messung bringt das richtige Ergebnis
Hallo, hab das mal ausprobiert.. birngt keine Änderung mitsich..... Hast du noch eine Idee? Gruß Michael
Hi, code könnte helfen stimmt :-) also ich hab zwei Versionen. Die eine auf die es mir ankommt mißt nur an einem Pin. Die andere hab ich aus dem Example der Lib und die misst alle AD-Eingänge. Ich wille einen LM35 auslesen. Der ist aber im Moment noch nicht da. Deshalb habe ich ein Potentiometer an AD0 angeschlossen. Ich hab auch mit einem Messgerät nachgemessen. Es ist also alles richtig angeschlossen. Die Hauptschleife sieht so aus: while(1) { rprintf("Gemessener ADC-Wert : %d \r\n",getLM35ADCValue()); //gemessene Spannung short voltage = (short)getLM35MeasuredVoltage(); rprintf("Gemessene Spannung : %d \r\n", voltage); //Gemessene Temperatur short temperature = (short)getLM35MeasuredTemperature(); rprintf("Gemessene Temperatur: %d \r\n",temperature); } ********************************************** **Die Methoden die ich benutzte kommen hier:** ********************************************** void initLM35(){ // turn on and initialize A/D converter a2dInit(); // configure a2d port pin (PORTA) as input unsigned char mask = ~(0x01 << LM35_ADC_CHANNEL); DDRA = DDRA & mask; // pull-up resistor off PORTA = PORTA & mask; //AD-Cahannel wählen a2dSetChannel (LM35_ADC_CHANNEL); //set prescaler a2dSetPrescaler(ADC_PRESCALE_DIV128); //set adc reference a2dSetReference(ADC_REFERENCE_AVCC); } short getLM35ADCValue(){ short adcValue = a2dConvert10bit(LM35_ADC_CHANNEL); return(adcValue); } float getLM35MeasuredVoltage(){ short adcValue = getLM35ADCValue(); float measuredVoltage = (adcValue * REFERENCE_VOLTAGE)/1024; return(measuredVoltage); } float getLM35MeasuredTemperature(){ float LM35MeasuredVoltage = getLM35MeasuredVoltage(); float measuredTemperature = LM35MeasuredVoltage * DIRECTLY_PROPORTIONAL_FACTOR; return(measuredTemperature); } void a2dInit(void) { sbi(ADCSR, ADEN); // enable ADC (turn on ADC power) cbi(ADCSR, ADFR); // default to single sample convert mode a2dSetPrescaler(ADC_PRESCALE); // set default prescaler a2dSetReference(ADC_REFERENCE); // set default reference cbi(ADMUX, ADLAR); // set to right-adjusted result sbi(ADCSR, ADIE); // enable ADC interrupts a2dCompleteFlag = FALSE; // clear conversion complete flag sei(); // turn on interrupts (if not already on) } // configure A2D converter clock division (prescaling) void a2dSetPrescaler(unsigned char prescale) { outb(ADCSR, ((inb(ADCSR) & ~ADC_PRESCALE_MASK) | prescale)); } // configure A2D converter voltage reference void a2dSetReference(unsigned char ref) { outb(ADMUX, ((inb(ADMUX) & ~ADC_REFERENCE_MASK) | (ref<<6))); } // sets the a2d input channel void a2dSetChannel(unsigned char ch) { outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel } // Perform a 10-bit conversion // starts conversion, waits until conversion is done, and returns result unsigned short a2dConvert10bit(unsigned char ch) { a2dCompleteFlag = FALSE; // clear conversion complete flag outb(ADMUX, (inb(ADMUX) & ~ADC_MUX_MASK) | (ch & ADC_MUX_MASK)); // set channel sbi(ADCSR, ADIF); // clear hardware "conversion complete" flag sbi(ADCSR, ADSC); // start conversion //while(!a2dCompleteFlag); // wait until conversion complete //while( bit_is_clear(ADCSR, ADIF) ); // wait until conversion complete while( bit_is_set(ADCSR, ADSC) ); // wait until conversion complete // CAUTION: MUST READ ADCL BEFORE ADCH!!! return (inb(ADCL) | (inb(ADCH)<<8)); // read ADC (full 10 bits); } Ich hoffe das ist nicht zu unübersichtlich ..... schonmal vielen Dank Michael
Hallo, ich geb ja zu es ist jede Menge code.... aber im Prinzip rufe ich nur Methoden aus der ARLib auf. Dabei setze ich einen festen Kanal in die Methoden ein weil der LM35 immer am selben Pin sein wird. Ich glaube ich mache einen Fehler bei der Benutzung der AVRLib. 1) Ich muß doch eigentlich nur die Init Methode aufufen. 2)Dann setze ich die Referenzspannung 3) und den Prescaler. 4) dann setze ich noch den channel 5)Danach kann ich messen 1) a2dInit(); 2)a2dSetReference(ADC_REFERENCE_AVCC); 3)a2dSetPrescaler(ADC_PRESCALE_DIV128); 4)a2dSetChannel (0); 5)a2dConvert10bit(LM35_ADC_CHANNEL); Wo ist mein Fehler?! Gruß Michael
Hups hab mich vertippt... meine mit ARLib natürlich AVRLib
Arbeitet eigentlich außer mir nochjemand mit der AVRLib von der seite http://hubbard.engr.scu.edu/avr/avrlib/docs/html/index.html ??
... verzichte testweise mal auf "sei" cbi(ADCSR, ADFR); // default to single sample convert mode ändern in: sbi(ADCSR, ADFR)
Hallo, das hat leider nichts gebracht... ich messe jetzt ganz seltsame werte ... an GND ist jetzt nichtmehr 0 sondern was zwischen 30 und 40 .... Noch jemand ideen? Gruß Michael
Du hast die "Dummy" Messung nicht gemacht, wenn ich's richtig gelesen habe ?
Hi, das hatte ich schon probiert.... Ich hab gemessen .... den Wert in einer Variablen gespeichert ... (dummy) und dann nochmal gemessen und den Wert in einer anderen Variablen gespeichert.. Der Wert hat dann einfach nicht gestimmt .... Weitere Tipps? Also wie gesgat das meißte aus meinem Code ist aus der AVR-Lib. Hat damit mal jemand erfolgreich A/D gewandelt? Gruß Michael
Hallo, ich habe eben mal den Code aus dem Tutorial verwendet um zu messen. Es geht immernoch nicht.... Das sollte doch heißen dass ich einen Fehler bei der Beschaltung mache oder? Gruß Michael
...wie hast Du ihn beschaltet? Wenn Du nur einen einzigen Kanal misst, klapp's dann wenigstens?
Hi, ich habe einen Poti angeschlossen .... ATMEGA128 Poti GND ------- links AD0 ------- mitte VCC ------- rechts AREF = AVCC = VCC AGND = GND Es klappt auch nicht wenn ich nur einen Kanal messe ... Ich benutze jetzt eins zu eins den Code aus den Code aus dem AVR-GCC-Tutorial .... Ich erhalte immer die selben Werte ... Egal ob ich an einem Kanal messe .. Oder an allen.... Ich messe immer ADCW ungefähr 450 (+/- 20) Gruß Michael
Hallo, ich hab das gesammte Projekt mal in ein Zip gesteckt... Evtl hat ja jemand den Nerv es sich mal anzuschauen... Die main steckt in a2dtest ... Gruß Michael
Hat evtl. jemand schon fertigen code zum A/D wandeln mit dem ATMEGA128 ...? wäre schön wenn man den posten könnte ... dann könnte ich vergleichen wo der Unterschied ist!?
Hat wirklich keiner eine fertige routine in C? Ich hab in der Codesammlung leider auch nichts entsprechendes gefunden. Sowas muß doch jemand haben oder?
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.