Hallo, ich habe offenbar ein Problem mit meinem A/D Wandler (ATmega323). Ich wollte eine Regelung realisieren. Dabei hatte ich immer innerhalb der ISR einen Ist-wert mit dem A/D Wandler eingelesen. Nun hatte ich das Problem daß meine eingelesenen Werte ständig durch nichtpassende werte gestört wurden. Alle par Werte bekam ich eine 1023 (10 bit ADC -> max. wert), obwohl der Wert dort nichts zu suchen hatte. Nun habe ich nochmal einen Test gemacht, indem ich die Pulsbreite vorgebe mit der ich mein ventil ansteuere und dann einfach den Output des Flusssensors auslese. Da stellte ich fest, daß oft die ersten 4-5 Werte meiner A/D Wandlung Murcks waren. Ich bekam also auch für die ersten werte 1023 und danach pendelte der Wandler sich auf z.B. ~ 800 ein. Ist euch ein derartiges Problem bekannt bzw. wißt ihr Abhilfe? Gruß, Stefan
Das steht soviel ich weiß sogar im Manual der Controller?! Man sollte erst nach einigen Auslesungen (nachdem er gestartet wurde) den Wert verwenden. Ich lasse den ADC meist durchlaufen dann kann ich sofort drauf zugreifen, ansonsten lieferte er mir auch nur Blödsinn.
Hallo, danke erstmal für eure Antworten. Mit Block-C an Aref kann ich leider nichts anfangen. Was bedeutet das? @ Max: den ADC durchlaufen zu lassen habe ich auch schon überlegt. Aber wie machst du das bzw. wie fragst du dann beispielsweise in einer Interrupt Service Routine den aktuellen wert ab? Gruß, Stefan
Hi Also das man die ersten Messungen wegwerfen soll hör ich zum ersten Mal. Kann auch nicht sein da ich in einer Anwendung hier den ADC nach einem bestimmten Ereignis anwerfe und die Werte durchaus sinnvoll sind. Mit Block-C an Aref meinte ich einen Kondensator (etwa 10n) am Pin Aref des Mega. Matthias
wartest Du auch wirklich, bis der A/D-Wandler fertig ist? Nach einem Start dauerts a bisserl, bis er die Wandlung durch hat. Da könnte es sein, daß Dein Programm den Wandler überholt und dadurch Mist einliest. Ich hatte bislang keinerlei Probleme mit den Wandlern, wenn man mal von den typischen EMV-Geschichten absieht. Ich habe meistens eine Interrupt-Routine laufen, die mir bei Ende der Wandlung das Ergebnis ins SRAM reinwirft und dann den nächsten Kanal wandelt. So hat man immer (fast) aktuelle Werte von allen Kanälen (sofern man mehrere braucht). Das Hauptprogramm greift dann nicht mehr auf den A/D-Wandler direkt zu (und muß auch nicht auf ihn warten), sondern liest die Werte aus dem SRAM.
@ thkais: Die Methode den ADC nicht direkt auszulesen sondern die Ergebnisse so wie du beschrieben hast ins SRAM zu packen scheint mir plausibel. Nur wie machst du das genau (zum einen das mit der ISR, zum anderen das Speichern ins SRAM)? Ich bin leider noch ziemlicher Anfänger auf dem Gebiet, darum fehlen mir oft die Basics.... Gruß, Stefan
@ thkais: Könntest du mir mal ein Programmbeispiel zukommen lassen, daß sowohl das mit der ISR als auch mit dem SRAM macht? (wenn dunicht gerade in Assembler programmierst). Ich benutze Codevision AVR. Gruß, Stefan
Die Programme sind in Assembler geschrieben, lassen sich aber einfach auf andere Sprachen umsetzen. Ich werde sie mal rauskramen, wenns zeitlich klappt, male ich ein Flußdiagramm. Ist in der Code-Sammlung echt noch nichts zu diesem Thema?
@ thkais: Wenn du das hinbekommen würdest wäre´s super. In der Codesammlung bin ich nicht so wirklich fündig geworden (dann schon mal ne Frage: malst du Flussdiagramme einfach mit word?) Stefan
@Stefan G. Sorry, hat ein wenig länger gedauert, und zu einem Flußdiagramm hat die Zeit auch nicht gereicht. Ich denke aber, das Prinzip wird aus dem Programm ersichtlich, auch wenn man kein Assembler-Champ ist. In dieser speziellen Version brauchte ich nur 8-Bit Werte, werden alle 10 Bit benötigt, werden natürlich 2 Bytes/Wert gebraucht. Falls noch Fragen sind, einfach Posten. Grundprinzip: Der Wandler wird gestartet, wenn er fertig ist, wird ein Interrupt ausgelöst. In diesem Interrupt wird der Wert gelesen und im SRAM gespeichert, anschließend der nächste Kanal ausgewählt und die nächste Wandlung gestartet. So stehen so ganz nebenbei die Werte aller 6 Kanäle in Reih und Glied im SRAM, und man kann mit dem Hauptprogramm ohne irgendwelche Verzögerungen darauf zugreifen. --------------------------------------------- .include "c:\avrtools\appnotes\4433def.inc" .cseg .org 0 rjmp reset ;Reset handler reti ;External interrupt 0 - Not used reti ;External interrupt 1 reti ;Counter1 capture event reti ;Counter1 compare match reti ;Counter1 overflow reti ;Counter0 overflow reti ;Serial Transfer complete reti ;UART RX complete reti ;UART Data register empty reti ;UART TX complete rjmp adc_int ;ADC Conversion Complete reti ;EEPROM Ready reti ;Analog comparator .equ impuls = 0 .equ adc_puffer= $60 ;$60...$65 ist der A/D-Wandler Puffer .def temp = r16 .def temp2 = r17 .def analog = r0 ;aktueller 8-Bit Analog-Wert .def flag = r25 .def xl = r26 reset: ldi temp,ramend out SPL,temp ldi temp,$FF out DDRD,temp ldi temp,$03 out DDRB,temp ldi temp,$05 out ADMUX,temp ldi temp,(1<<ADEN)+(1<<ADIE)+(1<<ADPS2)+(1<<ADPS1) out ADCSR,temp sei sbi ADCSR,ADSC ;Start Conversion main: rjmp main ;Das Hauptprogramm macht nix. adc_int: ;A/D-Wandler-Interrupt, wird aufgerufen, wenn eine Wandlung fertig ist push temp ;benutzte Register und SREG auf Stack sichern in temp,SREG push temp push xl push temp2 in temp,ADMUX ;welcher Kanal wurde gerade gewandelt? andi temp,$07 ;nur Bit 0..2 verwenden ldi xl,adc_puffer ;Basis-Adresse des SRAM für die Analog-Werte add xl,temp ;Kanal-Nummer addieren in temp,ADCL ;Den aktuell gewandelten Wert in temp1 und temp2 laden in temp2,ADCH ror temp2 ror temp ror temp2 ror temp ;10 Bit nach 8 Bit konvertieren st x,temp ;in Puffer schreiben in temp,ADMUX ;aktuellen Kanal nochmals in temp laden andi temp,$07 ;nur Bit 0..2 verwenden dec temp ;den nächsten Kanal anwählen brpl adc_int_1 ldi temp,$05 ;Kanal 5 anwählen adc_int_1: out ADMUX,temp ;Das MUX-Register mit dem neuen Wert laden sbi ADCSR,ADSC ;nächste Wandlung starten pop temp2 ;die gesicherten Register wiederherstellen pop xl pop temp out SREG,temp pop temp reti
@ thkais: Danke für den Code. Fürs erste habe ichzwar mein Problem gelöst, aber vielleicht kann ich dein Beispiel später immer noch gebrauchen. Vielen Dank und Gruß, Stefan
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.