Ich will die Drehzahl von einem Lüfter messen. Ich bewerkstellige dies mit dem Input Capture Interrupt auf einem AT MEGA 644.Das funktioniert auch ganz gut. Allerdings hängt er wenn der Lüfter steht(Signal des Lüfters ist dann high). Das UP Drehzahlermittlung wird von main aufgerufen und die Drehzahl anschließend in main seriell audgegeben. #include <avr/io.h> #include <stdint.h> #include <avr/interrupt.h> uint32_t abs_Zaehler=0; uint8_t Ueberlauf=0; uint8_t Ueberlauf_alt=0; uint32_t Zaehler[2]; uint8_t i=0; uint8_t p=0; uint32_t Drehzahl1; int Drehzahlermittlung(void) { i=0; p=0; Drehzahl1=0; Zaehler[0]=0; Zaehler[1]=0; Ueberlauf=0; Ueberlauf_alt=0; abs_Zaehler = 0; OCR1A = 11520; TIMSK1 |= (1<<ICIE1)|(1<<OCIE1A); TCCR1B |= (1<<WGM12)|(1<<CS11)|(1<<CS10); PORTC |= (1<<PC4); do { if(i==2) { abs_Zaehler= ( (Zaehler[1] - Zaehler[0])+((Ueberlauf- Ueberlauf_alt)*11520) ); Drehzahl1 = ( (60*115200)/(abs_Zaehler) ); return Drehzahl1; p=1; } else { Drehzahl1 = 0; } }while( (p |= 1) || (Ueberlauf >= 2) ); if( (p==0)&&(Ueberlauf >= 3) ) { Drehzahl1 = 0; return Drehzahl1; } PORTC &= ~(1<<PC4); } ISR(TIMER1_CAPT_vect) { Zaehler[i] = ICR1; if(i==0) { Ueberlauf_alt = Ueberlauf; } i++; } ISR(TIMER1_COMPA_vect) { Ueberlauf++; }
Habe ich der Übersichtlichkeit weggeleassen. ISR(TIMER1_COMPA_vect) //tritt auf wenn der Counter 11520 (OCR1A) erreicht ISR(TIMER1_CAPT_vect) // kopiert Zählerstand bei Capture Event in Variable. // bei erstem Auftreten wird der Stand des Überlaufzählersin //Überlauf_alt gespeichert int Drehzahlermittlung(void) //OCR1A = Counter Obergrenze //TIMSK1 Input Capture Interrupt enable und Counter Interrupt enable //(wenn Counter Obergrenze erreicht) //TCCR1B CTC(Clear Counter on Compare Match) Mode4 Prescaler 64 //(Fcpu=7,3728MHz //if Schleife, falls Capture event 2 mal aufgetreten ist // berechnet den absoluten Zähler aus Differenz der beiden //Counterwerte + Eventuelle Counterüberlaufe*der Counterobergrenze // Drehzahl wird mit der Counterfrequenz berechnet. (1/min!) //Drehzahl wird an main zurückgegeben und seriell ausgegeben //falls Capture event noch nicht 2mal aufgetreten, dann Drehzahl =0 //In der do while Schleife wird gewartet bis Capture event 2 mal //aufgetreten ist und die Drehzahl berechnet wurde. Im Fall, dass der //Lüfter steht wird gewartet bis der Counter 2 Mal übergelaufen ist //(Da dann keine ISR auftritt Ich hoffe das macht meine Absicht deutlich
>>sollte das nicht eher || (Ueberlauf <= 2) heissen
Das ist richtig. Habe ich auch gesehen, bringt aber auch nicht den
Durchbruch
>Habe ich der Übersichtlichkeit weggeleassen.
LOL
Welche maximale Frequenz liefert dein Lüfter?
Mit welcher Frequenz läuft dein Controller?
Der Lüfter hat maximal 116HzHört sich sehr wenig an sind immerhin 6720 1/min). CPU läuft mit 7,3728MHz, nach dem Prescaler des Counters sind dann noch 115,2kHz übrig.
Du benutzt globale Variablen, die sowohl in der ISR als auch im Hauptprogramm verwendet werden. Die müssen volatile deklariert werden, damit der Compiler da nicht dran rumoptimiert.
do { ... }while( (p |= 1) || (Ueberlauf >= 2) ); Äh... while((p|=1)...) ist doch immer wahr, oder? Wie kommst du dann jemals aus dieser Schleife raus? Gruß, Magnetus
@Magnus: nein, In der If Schleife (Also wenn ISR 2mal aufgetreten und die Drehzahl berechnet wurde); wird p = 1 gesetzt.
>If Schleife
Gibt es nicht. Es handelt sich dabei um eine Abfrage und keine
Schleife. Schleifen können eine Abfrage zwecks
Abbruchbedingungserfüllungprüfung haben...
p |= 1
Danach ist p auf jeden Fall ungleich 0.
Meinst du vielleicht p!= 1?
Auf dem Lüfter steht 8...13,2V. Bei 8V macht er ein Rechtecksignal mit 68Hz. er schafft aber auch noch weniger bis 26Hz darunter ist es kein Rechteck mehr.
Ja genau, das hab ich gemeint. Muss ich mich vertippt haben. Das war mein Gedankengang auf ungleich 1 zu prüfen.
>> Ja genau, das hab ich gemeint. Muss ich mich vertippt haben. Das >> war mein Gedankengang auf ungleich 1 zu prüfen Und funktionierts nun? Gruß, Magnetus
Kann ich noch nicht sagen, bei Programmieren kommt beim anschließenden lesen ein Fehler, der besagt dass er an einer Speicherstelle etwas anderes erwartet wie das was er ausließt.
>der besagt dass er an einer Speicherstelle etwas >anderes erwartet wie das was er ausließt. Und was schreibt der Compiler nun wirklich? (Bin des enlischen mächtig...)
Reading FLASH.. OK! WARNING: FLASH byte adress 0x0032 is 0x40(should be 0xCD).. FAILED! Leaving programming mode.. OK!
Dann hat dein Controller einen an der Waffel...(mal gegen einen anderen tauschen?) Das hat nichts mit deinem Programm zu tun...
>> Dann hat dein Controller einen an der Waffel...
...oder der Programmer?
...oder die ISP-Strippe?
@FrankW: Daran lag, das Häkchen bei Erase Device before programming muss ich versehentlich weggeclickt haben. Danke Aber um Grundproblem: Das Programm hängt weiterhin, wenn der Lüfter steht. Ist das der richtige interrupt auf den ich warte. Tritt der Counter1 Output Compare A Match auf, wenn mein Counter den Wert in OCR1A erreicht hat?
>Ist das der richtige interrupt auf den ich warte Eigentlich schon... Vielleicht ist aber auch der Overflow-Interrupt... Teste es doch mit einer LED, die du im Overflow-Interrupt umschaltest. Das Flackern sollte man schon erkennen können.
ICh habe das Problem eingrenzen können. Der Drehzahl 0 Fall tritt nicht auf, da Ueberlauf nicht wächst. (Habe es nach der do ahile Schleife abgefragt). Hat jemand eine Idee wie ich es anstatt lösen kann. Ich brauche eine Konstruktion, die wartet bis der Capture Interrupt 2 mal aufgetreten ist, aber maximal bis zB 200ms(wenn der Lüfter steht)
Ja genau, der Überlauf Interrupt wird ausgelöst und mein Zähler wird auch hochgezählt, wenn ich aber nach der do while Schleife den Zähler abfrage ist er 0.
Ich glaube, dass ganze hängt mit der Masse zusammen. Halte ich die Masse des Lüfters mit der meiner Schaltung getrennt, bekomme ich auch eine Ausgabe wenn der Lüfter steht, allerdings nichts sinnvolles, sogar negative Werte. Da fällt mir überhaupt auf, darf man 2 returns in einem Programm haben??
>Da fällt mir überhaupt auf, darf man 2 returns in einem Programm >haben?? ja, allerdings wird, so weit ich weiß, die Funktion dann auch beendet. (Siehe k&r...)
Hi, ich habe so ziemlich das gleiche Problem wie du. da hier seit langer zeit nichts mehr geschrieben wurde, geh ich davon aus, dass dein problem erledigt ist. könntest du mir vllt. den final funktionierenden code zusenden? danke und grüße
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.