Forum: Mikrocontroller und Digitale Elektronik Probleme mit Drehzahlmessung in C


von Christian K (Gast)


Angehängte Dateien:

Lesenswert?

Hallo Leute,

ich hab mir einen Drehzahlmesser für meinen Atmega 8 gebastelt. Dieser 
nimmt die Drehzahl mit einem Sensor auf (3 Pulse/ Umdrehung) und gibt 
die aktuelle Drehzahl auf einem Display aus.
Soweit kein Problem und funktioniert auch. Es wird bei der ersten Flanke 
der momentane Timerwert als Startwert gespeichert und von dem Timerwert 
bei der zweiten Flanke abgezogen etc.. siehe Anhang.

Mein Problem jetzt ist, da ich immer nur zwischen zwei Flanken die Zeit 
messe und mir daraus die Drehzahl berechne, kann es sein, dass die 
Anzeige immer noch eine Drehzahl anzeigt obwohl der zu messende Motor 
bereits steht, da der Motor genau zwischen zwei Flanken stehen geblieben 
ist....

Das kann ich so aber leider nicht gebrauchen, wenn zwischen zwei Flanken 
z.B mehr als eine Sekunde liegt dann darf das Display ruhig "0 U/min" 
anzeigen( genauer brauche ich das gar nicht..).
Hat jemand eine Idee wie man das in meinen Quelltext einbauen kann?

--

Alternativ wäre auch ne Möglichkeit die Messung von Zeit abhängig zu 
machen.
Es würde mir reichen, nur alle 0,5 Sekunden einen Mittelwert auf dem 
Display anzuzeigen. dann erkennt der MC ja auf jeden Fall wenn der Motor 
steht.
Ich hab aber leider keine Idee wie man das macht...
Wäre super wenn mir da jemand helfen könnte oder einen Beispielquelltext 
zur Hand hat.

Aller besten Dank
Christian K

von hans (Gast)


Lesenswert?

Hallo Christian,

geht recht einfach:

- im Overflow testen ob mehr als x Überläufe (Flanke ist überfällig)
  dann Messung zurücksetzen, Flag für drehzahl "0" setzen

- in main/while zusätzlich dieses Flag testen, wenn gesetzt
  Ausgabe mit Drehzahl=0 (Berechnung entfällt ja)

gruß hans

von christian K (Gast)


Lesenswert?

Hallo,

Stimmt das hört sich einfach an, ist ne gute Idee!!

Wenn ich das richtig verstanden hab dann müste das so aussehen (ich 
kanns grad nicht testen bin auffe arbeit..):

----------------------------------------

ISR( TIMER1_OVF_vect )
{
  NrOverflows++;


      if(NrOverflows == 61)
        {
  Null_Anzeigen = 1 ;  //Job Flag wird im Hauptprogramm verarbeitet
        }


      else
        {
   Null_Anzeigen = 0 ;
        }
}

----------------------------------------


Ich hab das jetzt da eingebaut wo die ISR die Overflows zählt.
Ist das so richtig?

Danke und Gruß
gerd




PS: mich würde trotzdem noch interessieren wie man nen Drehzahlmesser 
programmiert, der immer alle Zeiteinheit einen Mittelwert ausgibt. Also 
wenn da noch jemand ne Idee hat, würde ich diese begeistert lesen; )

von Karl H. (kbuchegg)


Lesenswert?

christian K schrieb:

> PS: mich würde trotzdem noch interessieren wie man nen Drehzahlmesser
> programmiert, der immer alle Zeiteinheit einen Mittelwert ausgibt. Also
> wenn da noch jemand ne Idee hat, würde ich diese begeistert lesen; )

Na ja, was ist denn ein Mittelwert?

Man hat mehrere Messungen, die summiert man auf und dividiert durch die 
Anzahl der Messungen.

Was wird man daher für einen Mittelwert benötigen?
Die letzten n Messungen, die man sich zb in einem Array 
zwischenspeichert. Nach jeder Messung speichert man den neuesten Wert im 
Array und verwirft den ältesten. Trick: kann man am einfachsten so 
machen, dass das Array reihum 'im Kreis' beschrieben wird, dann 
überschreibt der neueste Wert automatisch immer den ältesten).

von Karl H. (kbuchegg)


Lesenswert?

christian K schrieb:

> Ich hab das jetzt da eingebaut wo die ISR die Overflows zählt.
> Ist das so richtig?

Ist eine Möglichkeit.

Aber warum nicht einfach die Anzahl der Overflows dort berücksichtigen, 
wo die Auswertung gemacht wird.
1
void Drehzahl_berechnen(void)
2
{
3
  if( NrOverflows > 61 )
4
    drehzahl = 0.0;
5
6
  else {
7
    Erg = (NrOverflows * 65536) + EndTime - StartTime;
8
9
                            // ... mit der bekannten Taktfrequenz ergibt sich dann die Signalfrequenz
10
    Erg = F_CPU / Erg;      // f = 1 / t   
11
12
                            //aus der Frequenz berechnet sich die Drehzahl
13
    drehzahl = Erg * 20;    // Drehzahl berechnen aus der Frequenz 
14
                            //f*(20sec also 60sec/3Pulse pro Umdrehung)= U/min
15
  } 
16
}

von hans (Gast)


Lesenswert?

@Karl heinz Buchegger

Weil er die Berechnung nur macht wenn er 2 Flanken hatte.
Daher das Zusatzflag "0", und dann braucht er auch nicht
rechnen.

gruß hans

von christian K (Gast)


Lesenswert?

Hallo Karl Heinz,

Danke für die Antwort, so wie du es vorgeschlagen hast gehts natürlich 
noch einfacher und kompakter, gefällt mir; )) Besten Dank!


Mein Problem bei der zweiten Version ist eigentlich nicht der Mittelwert 
selbst, sondern die Tatsache dass sich mein Programm immer nur bei 
anstehender Flanke aktualisiert. Wenn ich jetzt wenig Signale bekomme 
läuft das Programm auch nur langsam durch, bei vielen Signalen halt 
schneller..
Ich müsste also wissen wie ich ihn dazu bekomme sich z.b. nur alle 0,5 
sek das Display aktualisiert wird. aber trotzdem weiterin alle Takte 
gezählt werden. aus den gezählten Takten wird dann entsprechend die 
Drehzahl mit einem Mittelwert über die 0,5sek berechnet..


danke und Gruß
christian

von Karl H. (kbuchegg)


Lesenswert?

hans schrieb:
> @Karl heinz Buchegger
>
> Weil er die Berechnung nur macht wenn er 2 Flanken hatte.
> Daher das Zusatzflag "0", und dann braucht er auch nicht
> rechnen.

Du hast recht, hab nicht aufgepasst.

Aber im schnelle drüberschauen spricht doch auch nichts dagegen, main()
noch ein bischen umzugestalten
1
  while(1)
2
  {
3
    Drehzahl_berechnen();
4
    Messwerte_ausgeben();
5
  }

Ob der Prozessor jetzt in der main() Däumchen dreht, oder ständig 
rechnet sollte doch eigentlich egal sein. Für NrOverflows bräucht man 
dann allerdings noch eine Backupvariable. Ich denke aber, die bräuchte 
man sowieso. So ganz koscher kommt mir der jetzige Code in der Beziehung 
eh noch nicht vor. Wenn die startende Flanke zu schnell kommt, ist 
NrOverflows schon wieder 0, noch ehe die Drehzahlberechnung gelaufen 
ist.

von Mücke (Gast)


Lesenswert?

so wie ich den Quellcode verstehe misst man immer die Zeit zwischen zwei 
Flanken. Erste Flanke start, zweite Flanke stop. Dritte Flanke start, 
vierte Flanke stop. Man misst also nur zwischen 1,2 und 3,4...

Kann mans auch so programmieren, dass man nach jeder Flanke die Drehzahl 
berechnet, also 1,2 und 2,3 und 3,4...?

Was müsste man im Code hierfür ändern?

von Karl H. (kbuchegg)


Lesenswert?

Mücke schrieb:

> Kann mans auch so programmieren, dass man nach jeder Flanke die Drehzahl
> berechnet, also 1,2 und 2,3 und 3,4...?

Sicher.
Der Timer läuft ja sowieso weiter.

> Was müsste man im Code hierfür ändern?

jedesmal wenn der Input Capture anschlägt benötigt man
* den Zählerstand an dem der Input Captuer zuletzt angeschlagen hat
* den jetzigen Zählerstand

der jetzige Zählerstand wird dann per Programm zum Zählerstand an dem 
der Input Capture zuletzt angeschlagen hat.

   Endstand = ICP
   Berechne Drehzahl aus Endstand uns Startstand
   Startstand = Endstand


Jedesmal wenn diese Sequenz ausgeführt wird, wird aus dem vorherigen ICP 
Wert und dem jetzigen ICP Wert die Drehzahl berechnet.

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
Noch kein Account? Hier anmelden.