Hallo, ich mache gerade ein Projekt, wobei ich die Drehzahl von einem Rad abrufen muss. Ich habe mir einen Reedsensor mit Magnet gekauft und versuche die Drehzahl auf einem LCD Display anzuzeigen. Das mit dem Display funktioniert einwandfei, aber bei der Messung ist etwas faul. Der Reedsensor gibt , wenn der Magnet in der Nähe ist ein High Signal aus. Ich habe es versucht mit folgendem Program die Dauer zwischen zwei Impulsen zu messen, aber die Messung gibt mir manchmal Minuszahlen aus und laut messung ist der Impulsabstand wenn sich das Rad schneller dreht, länger, als wenn es sich langsamer dreht.
Wenn willst Du wohl eher die Zeit erfassen, in Der Du den Magneten NICHT siehst.
Hier wirst Du die Zeit erfassen, Die der Magnet am Reed-Sensor ist.
Die Sache mit den Datentypen ist zu Dir durchgedrungen?
Dein Snipped - 'sollte so funktionieren' ... funktioniert Der auch so?
Könnte mir vorstellen, daß laufend 0 (Null) raus kommt.
(Wenn, ändere die 60 in 60.0, sonst einfach ignorieren)
Wenn willst Du wohl eher die Zeit erfassen, in Der Du den Magneten NICHT siehst.
Hier wirst Du die Zeit erfassen, Die der Magnet am Reed-Sensor ist.
Die Sache mit den Datentypen ist zu Dir durchgedrungen?
Dein Snipped - 'sollte so funktionieren' ... funktioniert Der auch so?
Könnte mir vorstellen, daß laufend 0 (Null) raus kommt.
(Wenn, ändere die 60 in 60.0, sonst einfach ignorieren)
MfG
ich habe den float auf double geändert und das High auf Low und jetzt funktioniert es einwandfrei, danke für die Hilfe
Der code mit pulseIn() hat einen kleinen Fehler. Man misst dabei die Dauer vom Ende eines Pulses bis zum Anfang des nächsten Pulses, sollte man nicht vom Ende eines Pulses bis zum Ende des nachfolgenden Pulses messen, um die Drehzahl richtig zu messen?
Wenn ich das richtig verstehe, möchte der TO die absolute Drehzahl. Dazu braucht's die Zeit für eine ganze Umdrehung. Wäre das Puls/Pause Verhältnis über den gesamten Drehzahlbereich konstant, könnte man das rausrechnen. Aber ob man bei einem mechanischen Schalter davon ausgehen kann ? Das hängt natürlich dann auch noch vom zu erfassenden Drehzahlbereich ab.
Sicherer ist jedenfalls, immer von der gleichen Flanke aus zu messen. Wobei ich den Moment bevorzugen würde, wo das Reedrelais zum ersten mal auf den vorbeidrehenden Magnet reagiert. Dann kann einem sogar Prellen egal sein. Ich gehe mal davon aus, dass die Prellzeit deutlich kleiner ist, als die kützeste Zeit für eine Umdrehung .
MicroBahner:
Wenn ich das richtig verstehe, möchte der TO die absolute Drehzahl. Dazu braucht's die Zeit für eine ganze Umdrehung. Wäre das Puls/Pause Verhältnis über den gesamten Drehzahlbereich konstant, könnte man das rausrechnen. Aber ob man bei einem mechanischen Schalter davon ausgehen kann ? Das hängt natürlich dann auch noch vom zu erfassenden Drehzahlbereich ab.
Sicherer ist jedenfalls, immer von der gleichen Flanke aus zu messen. Wobei ich den Moment bevorzugen würde, wo das Reedrelais zum ersten mal auf den vorbeidrehenden Magnet reagiert. Dann kann einem sogar Prellen egal sein. Ich gehe mal davon aus, dass die Prellzeit deutlich kleiner ist, als die kützeste Zeit für eine Umdrehung .
dxaxhxix:
Ich habe den Code so verändert, dass er von falleder Flanke zu fallender Flanke misst:
f=pulseIn(2, LOW, 10000000);
t=pulseIn(2, HIGH, 10000000);
f=60000000.0/(f+t);
Wie kann man die Prellzeit ausblenden?
Meiner Meinung nach ist PulseIn für dich nicht das Richtige. Du willst ja eigentlich keine Pulsdauer messen, sondern immer von positiver Flanke zu positiver Flanke. ( ader auch negativ-negativ ). Außerdem ist PulseIn blockierend, was in deinem Fall eigentlich einer Dauerblockade gleichkommt.
Je nach Drehzahlen, um die es geht ( das solltest Du uns mal mitteilen ) wäre dein erster Ansatz schon gar nicht so schlecht. Im Interrrupts misst Du die Zeit seit der letzten Flanke. Wenn diese Zeit zu klein ist (Prellen) ignorierst Du den Interrupt. Ansonsten nimmst Du die Zeit als Umdrehungszeit, und startest eine neue Messung.
Das Einrichten des Interrupts machst Du aber im setup(), und deine Zeitvariable für den Interrupt musst Du als globale Variable und als volatile definieren. Wenn Du im loop() auf die Zeitvariable aus dem IRQ zugreifst, musst Du den IRQ sperren, damit Du keine ungültigen Zwischenwerte liest.
MicroBahner:
Meiner Meinung nach ist PulseIn für dich nicht das Richtige. Du willst ja eigentlich keine Pulsdauer messen, sondern immer von positiver Flanke zu positiver Flanke. ( ader auch negativ-negativ ). Außerdem ist PulseIn blockierend, was in deinem Fall eigentlich einer Dauerblockade gleichkommt.
Je nach Drehzahlen, um die es geht ( das solltest Du uns mal mitteilen ) wäre dein erster Ansatz schon gar nicht so schlecht. Im Interrrupts misst Du die Zeit seit der letzten Flanke. Wenn diese Zeit zu klein ist (Prellen) ignorierst Du den Interrupt. Ansonsten nimmst Du die Zeit als Umdrehungszeit, und startest eine neue Messung.
Das Einrichten des Interrupts machst Du aber im setup(), und deine Zeitvariable für den Interrupt musst Du als globale Variable und als volatile definieren. Wenn Du im loop() auf die Zeitvariable aus dem IRQ zugreifst, musst Du den IRQ sperren, damit Du keine ungültigen Zwischenwerte liest.
Ich brauche eine Drehzahl von ca. 600 Umdrehungen pro Minute.
Ich verstehe das nicht mit dem Setup und Loop was du da geschrieben hast, wärst du bitte so nett und würdest es mir erklären?
Bei 600 Umdrehungen die Minute haben wir 10 Umdrehungen die Sekunde - in der Zeit, die der Arduino NICHTS zu tun hat, wachsen Dem graue Haare!!
Bei so schnarchlahmem Zeug braucht Es definitiv keinen Interrupt, keinen atomaren Zugriff und keine volatile Variable.
(die unbekannten Worte lassen sich prima einer Suchmaschine zum Fraß vorwerfen, solltest Du auf Interrupt bestehen)
Mein Weg wäre den Sensor zu pollen, also in jedem loop()-Durchlauf nachzugucken, ob Da gerade der Magnet erkannt wird.
Wenn Das letzte Mal bereits > 20ms her ist, wird diese Erkennung 'genommen' - ist der erste Kontakt und kein Prellen.
Der nächste Kontakt ist in 100ms (10 Umdrehungen die Sekunde) zu erwarten, eigentlich ist Alles unter 100ms Prellen (oder Du fährst zu schnell ).
So brauchst Du nur eine Variable, in Der Du Dir die Zeit der letzten Erkennung merkst.
if (Sensor==AN){
if (millis()-merkzeit>prellzeit){
//neue Umdrehung
zeitproumdrehung=millis()-letzteerkennung;
letzteerkennung=millis();
}
merkzeit=millis();
}
Fertsch.
Bei //neue Umdrehung berechnest Du die vergangene Zeit/die Geschwindigkeit.
Ausgaben auf's Display nur, wenn sich was geändert hat.
Alles zu kurz/schnell wie möglich.
Lieber eine Aktion in zwei Einzelaktionen aufteilen, als z.B. bei der Ausgabe der Geschwindigkeit ein Flackern zu bekommen (State-Maschine).
Also 600 U/min sind definitv kein Problem mit Pollen. Da brauchts keinen Interrupt.
Bei 6000 U/min würde ich schonmal ein wenig ins Grübeln geraten. Je nachdem wie genau ich das brauche, und was der Arduino sonst noch alles machen soll, könnte da schon die Interrupt-Variante ins Spiel kommen.