mikrocontroller.net

Forum: Compiler & IDEs Drehzahlmessung


Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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++;
}

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kommentare wären schön...

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
|| (Ueberlauf >= 2)

sollte das nicht eher || (Ueberlauf <= 2) heissen?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>>sollte das nicht eher || (Ueberlauf <= 2) heissen
Das ist richtig. Habe ich auch gesehen, bringt aber auch nicht den
Durchbruch

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Habe ich der Übersichtlichkeit weggeleassen.

LOL

Welche maximale Frequenz liefert dein Lüfter?
Mit welcher Frequenz läuft dein Controller?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das bringt auch nichts. Sobald der Lüfter steht hängt das Programm.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@Magnus: nein, In der If Schleife (Also wenn ISR 2mal aufgetreten und
die Drehzahl berechnet wurde); wird p = 1 gesetzt.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Was noch interessant wäre: Wie groß ist die niedrigste
Drehzahl/Frequenz?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja genau, das hab ich gemeint. Muss ich mich vertippt haben. Das war
mein Gedankengang auf ungleich 1 zu prüfen.

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> 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

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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...)

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Reading FLASH.. OK!
WARNING: FLASH byte adress 0x0032 is 0x40(should be 0xCD).. FAILED!
Leaving programming mode.. OK!

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann hat dein Controller einen an der Waffel...(mal gegen einen anderen
tauschen?)
Das hat nichts mit deinem Programm zu tun...

Autor: Magnus Müller (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>> Dann hat dein Controller einen an der Waffel...

...oder der Programmer?
...oder die ISP-Strippe?

Autor: FrankW (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... oder den Controller vor dem Flashen nicht gelöscht ?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@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?

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Ja ist der Richtige.

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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)

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Überlauf-Interrupt wird aber ausgelöst, wenn der Lüfter steht?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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.

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
volatile vergessen?

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Nein

Autor: Matthias (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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??

Autor: inoffizieller WM-Rahul (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>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...)

Autor: Andreas (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.