Du kannst den Timer automatisch bei steigender bzw. fallender Flanke auslösen lassen. Musst mal im Datenblatt schauen, da steht das genau drin, hab das selber auch noch nicht gemacht.
Nabend,
ich möchte in meinem Auto mittels des ATMEGA32 den Benzinverbauch messen. Dazu ist es nötig ein PWM-Signal auszuwerten. Die Länge des Signals wird sich im ms-Bereich bewegen (eine ms entspricht 26ul eingespritztem Kraftstoff). Ich habe leider kein Oszilloskop um das genau prüfen zu können.
Für die Berechnung brauche ich also den Zeitabstand von steigender zu fallender Flanke. Über die Suche bin ich zu folgender Verfahrensweise gelangt: per Input-Capture die steigende Flanke erkennen, zeitgleich Timer auslösen, dann per Input-Capture die fallende Flanke erkennen und den Timer stoppen/reseten. Die Differenz der beiden Timerwerte ergibt die Dauer des Impulses. Funktioniert mein Ansatz oder schlagt ihr Alternativen vor?
Ich bin noch relativ neu auf dem Gebiet der AVR-Programmierung, kann mir jemand einen Beispielcode zur Verfügung stellen? Mir geht es nur um die grundlegenden Befehle in Bascom.
Du kannst den Timer automatisch bei steigender bzw. fallender Flanke auslösen lassen. Musst mal im Datenblatt schauen, da steht das genau drin, hab das selber auch noch nicht gemacht.
Es gibt von Atmel dazu eine Application note (AVR135). Da wird das Verfahren beschrieben. Vermutlich mit Code in C.
http://www.atmel.com/dyn/products/ap...?family_id=607
@kugelfisch
Dein Ansatz ist im Prinzip schon richtig.
Man stellt den Interrupt ( ICP, INTx ) auf steigende Flanke.
Wird der Interrupt ausgelöst wird der Timer ( bzw. das ICR ) ausgelesen und der Wert abgespeichert. Gleichzeitig wird das Interrupt sensing auf "fallende Flanke" umgestellt.
Tritt dan der Interrupt bei fallender Flanke wiederum auf, liest man den Timer ( ICR ) erneut aus und zieht den vorher abgespeicherten Wert ab.
Das Interrupt Sensing wird für die nächste Messung dann wieder auf "steigende Flanke" gestellt.
Wenn man unsigned Variablen benutzt ist auch die Berechnung bei Überlauf der Timers kein Problem.
Den Timer ( TCNT1 ) per Software auf 0 zu setzen kann u.U. einen Messfehler verursachen.
Ich nehm für solche Sachen gerne den Timer1 mit einem Quarz von 8MHz und einem Prescaler von 8 her, weil dann die Werte direkt in µs ausgegeben werden.
Ein weiteres Problem könnte noch sein, das eine Einspritzdüse während eines Zündvorganges mehrmals mit unterschiedlichen Zeiten einspritzen kann.
Das könnte man eventuell dadurch lösen, das man einen Drehzahlsensor anbringt und die Einspritzzeiten einer Umdrehung aufaddiert.
Grundsätzlich gilt für so eine Zeitmessung, wie für alle Interrupts, die Interruptroutinen so kurz wie möglich zu halten.
Eventuell wäre Assembler sinnvoll.
Das sollte das Ergebnis ja eigentlich nicht verfälschen - solange man die Gesamteinspritzzeit bei einer konstanten Einspritzmenge feststellt, ist es egal wie of die Düse pro Umdrehung einspritzt, es wird ja nur die Gesamtmenge in Relation zur Zeit benötigt.Zitat von wkrug
Die Application Note habe ich gelsen und verstehe den Pseudocode auch so weit ganz gut. Das bestätigt mich in meiner geplanten Vorgehensweise.
Ich fahre einen alten Audi 80, der verfügt noch über eine Zentraleinspritzung (ähnlich Vergaser). Ich habe für alle 4 Zylinder nur eine Einspritzdüse. Damit dürfte das von dir beschriebene Problem entfallen, trotzdem vielen Dank für den Hinweis.Zitat von wkrug
Mein konkretes Problem ist nach wie vor, dass ich die Theorie verstehe, es aber nicht in Bascom umsetzen kann. Im Wiki gibt es leider auch keinen entsprechenden Artikel zum Theme ICP mit Codebeispielen in Bascom. Hat jemand ein paar entsprechende Codeschnipsel?
Ich habe in einem Lehrbuch einen Beispielcode gefunden und versucht diesen auf mein Beispiel umzuschreiben. Ziel ist es die Dauer des High-Pulses an PortB.0 zu messen. Leider funktioniert das Programm in der jetzigen Form nicht. Wo liegt mein Fehler?
Code:$regfile = "m32def.dat" $framesize = 32 $swstack = 32 $hwstack = 32 $crystal = 8000000 'LCD: Config Lcd = 16 * 2 Config Lcdpin = Pin , Db4 = Portc.5 , Db5 = Portc.1 , Db6 = Portc.4 , Db7 = Portc.0 , E = Portc.2 , Rs = Portc.3 Config Lcdbus = 4 'Variable: Dim Pulswert As Word 'Funktionen: Declare Function Hochpuls() As Word 'Port B.0: Config Pinb.0 = Input Set Portb.0.0 Pulsmesserpin Alias Pinb.0 'Timer1: Config Timer1 = Timer , Prescale = 1024 Enable Timer1 On Timer1 Interrupttimer1 Nosave Enable Interrupts Cls Do Cursor Off Noblink Locate 1 , 1 Pulswert = Hochpuls() Lcd "Puls:" ; Pulswert Loop End Function Hochpuls() As Word While Pulsmesserpin <> 1 : Wend 'warte auf Lo-Hi an PB0 Tcnt0 = 0 'reset timer1 Start Timer1 While Pulsmesserpin = 1 : Wend Stop Timer1 Hochpuls = Tcnt0 End Function Hochpuls() 'Overflow Timer1 stoppt Timer1 und setzt TCNT1 zu Null (timeout) Interrupttimer1: !push r24 Stop Timer1 Tcnt0 = 0 !pop r24 Return
Lesezeichen