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
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
>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
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...)
@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