Mehrfachauslösung/Prellen bei Lichtschranke?

Guten Abend,
ich bin gerade dabei einen Drehzahlmesser für einen Propeller (Modellbau) zu erstellen.
Dafür nutze ich eine Lichtschranke, durch die der Propeller dreht. Ich bin mir aber nicht sicher ob ich das Thema mit steigender und fallender Flanke richtig verstanden habe, denn momentan messe ich nur Mist.

Meine Lichtschranke sendet [0 für nicht_Unterbrochen, 1 für Unterbrochen]
Ich frage die Impulse über folgende Zeile ab:

attachInterrupt(digitalPinToInterrupt(2), zaehlen, RISING); 

void zaehlen(){
  impulse++;
}

Wenn ich das richtig verstanden habe, löst der Interrupt aus, sobald die Flanke an Pin2 ansteigt(RISING), sprich von 0 auf 1 wechselt.
Das würde bedeuten, sobald der Propeller die Schranke unterbricht==positive Flanke==Interrupt!==impuls++
Verlässt der Propeller wieder die Schranke sinkt der Pegel wieder von 1 auf 0, was den Interrupt NICHT auslösen lässt…

Wenn ich jedoch die impulse ausgeben lasse muss ich feststellen, dass der Interrupt deutlich öfter auslöst als er theortisch sollte.

Zum Beispiel starte ich das Programm, unterbreche die Lichtschranke und halte sie durchgehend unterbrochen, trotzdem werden mir nach einer Minute mehrere Impulse angezeigt.
Eigentlich sollte es doch nur eine einzige steigende Flanke geben, und damit einen einzigen Impuls, oder?

Nun habe ich etwas über Prellen gelesen, dachte aber so etwas gibt es nur bei mechanischen Bauteilen wie Taster. Kann eine Lichtschranke ebenfalls prellen?
Es handelt sich dabei um folgendes Modell:
https://funduino.de/arduino-lichtschranke

Anbei mein ganzer Code.
Im Prinzip aktiviere ich den Interrupt, warte 2s lang, deaktiviere den Interrupt wieder und zähle wie oft die ISR in diesen 2s aufgerufen wurde. Damit berechne ich die Drehzahl, gebe sie auf einem LCD aus und beginne wieder von vorne.

Liebe Grüße :slight_smile:

#include <Wire.h>
#include <LiquidCrystal_I2C.h>    
LiquidCrystal_I2C lcd(0x23, 16, 2);

double zeitintervall = 30000.0;  //30s messen (für Testzwecke, sonst 2000 ms)
long letzteMessung = 0;          //Zeitpunkt letzte Messung
volatile int impulse = 0;        //Anzahl der Auslösungen des Interrupts (Propellerimpuls)
int lichtschranke = 2;           //Pin auf dem die Lichtschranke liegt
double RPM = 0;                  //Variable für Drehzahl (Kommazahl)


void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0,0);
  lcd.print("Drehzahl: ");
  lcd.setCursor(10,1);
  lcd.print("RPM");

  pinMode(lichtschranke, INPUT);    //PinMode konfiguieren(Eingang)

  attachInterrupt(digitalPinToInterrupt(lichtschranke), zaehlen, RISING);   //Interrupt (Pin, ISR, Auslöseereignis)
  
}

void loop() {
  // put your main code here, to run repeatedly:

  if(millis() > letzteMessung + zeitintervall){                 //Wenn zeitintervall seit letzter Messung verstrichen, dann...
   detachInterrupt(digitalPinToInterrupt(lichtschranke));       //Interrupt deaktivieren um Unterbrechungen/Verfälschungen zu vermeiden
   ausgabe();                                                   //Methodenaufruf Ausgabe (berechnet Drehzahl und gibt sie auf LCD aus)
   attachInterrupt(digitalPinToInterrupt(lichtschranke), zaehlen, RISING);  //Nachdem Methode Ausgabe abgearbeitet, Interrupt wieder aktivieren
  }else{}
  
}


void zaehlen(){             //ISR zählt Impulse des Propellers hoch
  impulse++;
}


void ausgabe(){
  RPM = impulse/zeitintervall*60000;    //Drehzahlrechnung (impulse/Zeit)*60.000 (für 1/min)
  Serial.println(impulse);              //Testausgabe Fehleranalyse
  RPM = RPM/2;                          //Drehzahl halbieren, weil Propeller 2x pro Umdrehungen Impuls gibt
  lcd.setCursor(0,1);                   //Folgend LCD Ausgabe
  lcd.print(RPM);
  impulse = 0;                          //Impulse resetten für nächste Zählung
  letzteMessung=millis();               //Zeitpunkt der abgeschlossenen Messung festhalten
}

Die prellt nicht, es können aber Reflexionen am Propeller auftreten oder Du hast Fremdlichteinfluss.

Um welche Frequenz geht es denn? Meist brauchst Du keinen Interrupt.

Gruß Tommy

Der zu messende Bereich sollte von 100/min bis idealerweise 8.000/min reichen. Sprich ~135Hz.
Bei 2 Impulsen/Umdrehung sollte die „Auflösung“ also 2x135=270Hz betragen, wenn ich mich nicht täusche.

Fremdlichteinfluss/Reflexionen sollte ich mit einem dunklen Raum überprüfen können?

Herzlichen Dank :slight_smile:

Fremdlicht ja, Reflexionen eher nein.

Gruß Tommy

Hallo,

ich hätte eine Frage die vorher ansetzt.
Welches Signal gibt die Lichtschranke an den Arduino?
Ihr analoges oder ist das schon mit Komparator in ein rein digitales geformt?
Fehlt vielleicht ein Pullup/down Widerstand?

Hi

Was für einen Ausgang hat die Lichtschranke?
PushPull - würde keine Fehlsignale erwarten
OpenCollector/OpenDrain - vll. passt der PullUP nicht.

MfG

PS: Widerstand - nur mit einem i (von wider=gegen)
Sorry, war ein anderer Thread, wo mir eben per Wiederstand ein Augentränen entlockte

Tommy56:
Fremdlicht ja, Reflexionen eher nein.

Gruß Tommy

Hm, es ist eine Gabellichtschranke, keine Reflektionsschranke, also der empfangende phototransistor befindet sich auf der anderen Seite des Propellers/der Lichtquelle. Kann es hier trotzdem irgendwo zu Reflexionen kommen?

Doc_Arduino:
Hallo,

ich hätte eine Frage die vorher ansetzt.
Welches Signal gibt die Lichtschranke an den Arduino?
Ihr analoges oder ist das schon mit Komparator in ein rein digitales geformt?
Fehlt vielleicht ein Pullup/down Widerstand?

Laut Beschreibung ein digitales Signal, 0 für frei, 1 für unterbrochen. Einen extra Pullup oder ähnliches habe ich nicht verwendet. Habe die Platine mit der Lichtschranke lediglich an +5V, GND und Pin2 (digital) angeschlossen.
Auf der Platine befindet sich ein LM393, also ein Komparator?
Anbei ein Foto meiner Lichtschranke.

postmaster-ino:
Was für einen Ausgang hat die Lichtschranke?
PushPull - würde keine Fehlsignale erwarten
OpenCollector/OpenDrain - vll. passt der PullUP nicht.

PushOull und OpenCollector/OpenDrain sagt mir ehrlich gesagt noch nichts :roll_eyes:

Hast Du einen Link zu dem Teil?

Reflexionen können auch an den Kanten / Rundungen des Propellers auftreten und zu Mehrfachauslösungen führen.

Gruß Tommy

Tommy56:
Hast Du einen Link zu dem Teil?

Reflexionen können auch an den Kanten / Rundungen des Propellers auftreten und zu Mehrfachauslösungen führen.

Gruß Tommy

Ja klar, hier der Link:
Gabellichtschranke

Hi

Da die Lichtschranke als fertige Platine daher kommt, sollte man meinen, das Ding 'tut'.
Der LM293 hat nur einen OC-Ausgang (man hätte danach googeln können), kann also den OUTPUT-Pin nur nach GND schalten.
Ändere bitte Mal
pinMode(lichtschranke, INPUT); //PinMode konfiguieren(Eingang)
in
pinMode(lichtschranke, INPUT_PULLUP); //PinMode konfiguieren(Eingang)
Normal sollte zwar die Platine Da noch etwas bieten - aber kA - einen Versuch ist's wert.

... ok ... in dem Beispiel ist der Pin auch nur INPUT (nicht eingestellt sind alle Pins INPUT, aus OUTPUT und INPUT_PULLUP muß man selber umstellen).
Somit befürchte ich keine wirklich Verbesserung.
Schaltplan kam mir nicht unter.

MfG

Hallo,

wenn der Hersteller schlau war ist der Ausgangspullup schon dran, eine Led meine ich auch zu erkennen.
Wissen wir aber nicht genau, deswegen ist INPUT_PULLUP nicht falsch und schadet auch nicht.
Dein Sketch ist auch etwas wild aufgebaut mit dem ständigen nicht notwendigen detach und attach und falsche Datentypen.
Habe mir erlaubt umzubauen mit sachten aber notwendigen Änderungen.

Wegen den Reflexionen hilft vielleicht mattes Klebeband am Propeller oder anschleifen/aufrauen o.ä.

#include <util/atomic.h>

const byte pinSENSOR = 2;            // Pin auf dem die Lichtschranke liegt
const unsigned long MESS_INTERVALL = 1000;
unsigned long count;                        // Zwischenpuffer zum ISR auslesen
volatile unsigned long impulse;             // Zähler in ISR
float rpm;


void setup() {
  Serial.begin(9600);
  pinMode(pinSENSOR, INPUT_PULLUP);   // PinMode konfiguieren(Eingang)
  attachInterrupt(digitalPinToInterrupt(pinSENSOR), zaehlen, RISING);   //Interrupt (Pin, ISR, Auslöseereignis)
}

void loop()
{
  messung(MESS_INTERVALL);
  ausgabe(2000, MESS_INTERVALL);
}


void messung (const unsigned long interval)
{
  static unsigned long lastMillis = 0;
  unsigned long ms = millis();

  if (ms - lastMillis >= interval)
  {
    lastMillis = ms;
    ATOMIC_BLOCK (ATOMIC_RESTORESTATE)
    {
      count = impulse;
      impulse = 0;
    }
  }
}


void ausgabe (const unsigned long interval, const unsigned long messzeit)
{
  static unsigned long lastMillis = 0;
  unsigned long ms = millis();

  if (ms - lastMillis >= interval)
  {
    lastMillis = ms;
    // Formel funktioniert bis 71582 counts
    rpm = (float)(60000.0 * count / messzeit);  // Drehzahlrechnung (impulse/Zeit)*60.000 (für 1/min)
    Serial.print(count);                        // Testausgabe Fehleranalyse
    Serial.print('\t');
    rpm = rpm / 2;                              // Drehzahl halbieren, weil Propeller 2x pro Umdrehungen Impuls gibt
    Serial.println(rpm);
  }
}


void zaehlen()                                  // ISR zählt Impulse des Propellers hoch
{
  impulse++;
}

Erstmal riesenDank an alle bis dahin!
Ich habe den Code ausprobiert, aber es hat wohl keinen Wert mit dieser Lichtschranke.
Im Anhang mal die Ergebnise. Die echte Drehzahl müsste bei knapp unter 60/min liegen, mit dem Auge gemessen/gezählt.

Ich habe gestern allerdings im Conrad noch eine nackte Gabellichtschranke gekauft, ohne Platine.
EE-SX1041.
Mit der scheint es tatsächlich deutlich zuverlässiger zu funktionieren!
Im Anhang die Messwerte, beider Lichtschranken im Vergleich. Bei selber Drehzahl und selbem Propeller.

Nun habe ich nur das Problem, dass alle paar Durchläufe ein Impuls weniger/mehr erfasst wird, das heißt die Drehzahl fällt immer mal wieder kurz ab.

Das mit dem attach/detach des Interrupts habe ich gemacht um das Messintervall sauber abzugrenzen, damit nicht während der Berechnung/Ausgabe nochmal ein Impuls gezählt wird. :blush:

Hallo,

Das mit dem attach/detach des Interrupts habe ich gemacht um das Messintervall sauber abzugrenzen, damit nicht während der Berechnung/Ausgabe nochmal ein Impuls gezählt wird.

dafür sichert man den aktuellen Stand zum Zeitpunkt des auslesens. Entweder nullt man dabei oder lässt weiterzählen. Jedenfalls rechnet man dann mit dem richtigen Wert weiter. Dafür benötigt man atomic.

Nun habe ich nur das Problem, dass alle paar Durchläufe ein Impuls weniger/mehr erfasst wird, das heißt die Drehzahl fällt immer mal wieder kurz ab.

Hab ich mir schon fast gedacht. Problem ist es werden Impulse pro Zeit gezählt. Du kannst entweder die Messzeit erhöhen, ist ja schon vorbereitet, oder du misst nicht die Counts pro Zeitdauer, sondern die Periodendauer des Impulses. Ist für langsame Frequenzen besser geeignet.
Überlege dir einmal warum du derzeit die Schwankung in der Messung hast und wie damit gerechnet wird. Stell dir den zeitlichen Ablauf dar. Dann kommste darauf das die Zählung grundsätzlich okay ist aber wie gesagt für sowas langsames ungeeignet.

Deine neue Lichtschranke nutzt vielleicht den Schmitt-Trigger Effekt vom I/O Pin. Sollte eigentlich nichts an der Zählweise ändern. Ich würde extern einen echten Schmitt-Trigger davor setzen. Der Komparator auf der anderen Lichtschranke schaltet ohne Hysterese. Egal wie, ich würde es nicht dabei belassen das analoge Signal einem digitalen Pin zu zuführen. Was man dagegen probieren könnte bei den langsamen Frequenzen wäre, analog zu messen und in Software die Hysterese einzubauen.

Ich denke die "Ungenauigkeit" kommt daher, dass das Messintervall zu unterschiedlichen Zeitpunkten anfängt. Mal vielleicht kurz nachdem der Propeller vorbei ist, das nächste mal wieder gerade kurz bevor der Propeller da ist. Je kleiner das Messintervall, desto größere Auswirkung hat es gleich, wenn 1 Impuls nach unten oder oben abweicht. Oder habe ich einen Denkfehler? ::slight_smile:
Werde nachher mal probieren die Zeit zwischen den Impulsen auszuwerten, wichtiger sind allerdings die hohen Frequenzen erfassen zu können.
Das funktioniert leider noch nicht.

Die Impulse werden nur bis ~78 erfasst. Das entspricht einer Drehzahl von ~2.200/min.
Die Lichtschranke ist zu träge, oder?

Hilft hier der externer Schmitt-Trigger?

Kennt jemand eine Lichtschranke/optischen Sensor, der schnell genug ist Drehzahlen bis 7.000/min zu messen? Darf auch was kosten.

Hi

Das dürfte so ziemlich jeder Photo-Transistor hinbekommen - nur kosten die Dinger nicht wirklich was, man muß aber selber Elektronik drum herum basteln, damit Der tut, was man von Ihm will.
Etwas einfacher ist's vll., wenn man einfach nachliest, was man mit der erworbenen Hardware wohl machen können soll.
Wenn Da Grenzfrequenz 100Hz steht, wird's wohl nicht schneller gehen und wir müssen uns was Anderes suchen.
Denke aber, daß die dort auszugrabenen Zahlen wesentlich beeindruckender sind.

Man kann auch die Welle erfassen - man muß ja nicht an den Propeller selber, dann wäre auch die Anzahl der Blätter komplett außen vor.
Und man köme mit EINEM Impuls pro Umdrehung hin, statt 2...6 (ka, wie viele Blätter möglich/sinnvoll sind) und hat auch mit den Reflektionen der Formen/des Material keinerlei Berührungen.

Die Geschwindigkeit eines Sensor wird nicht schneller, wenn man das Signal bearbeitet.
Ein Schmitt-Trigger formt aus dem analogen Signal nur ein Rechteck - und kann Das auch dabei verzerren - Dieser muß hier auch schnell genug sein.

7000r/min sind nur noch 116 2/3tel Umdrehungen pro Sekunde - da wird sich der Arduino aber ganz schön langweilen müssen - Das wird man wohl sogar pollen können, ohne großartige Einbußen hinnehmen zu müssen.

Meiner Meinung ist Deine Lichtschranke noch lange nicht ausgereizt - bei maximaler Drehzahl (7000r/min) sind Das knapp unter 117 r/s - Mal die Anzahl der Propeller kommen 'ein paar' dazu - aber bis 8 Blätter bist Du bei über 1ms 'Wartezeit', bis das nächste Rotor-Blatt vorbei kommt.

Oder wo biege ich gedanklich falsch ab?

MfG

Vor einiger Zeit habe ich für meine China-Mini-CNC-Fräse einen "Drehzahlsensor" gebaut, um die Drehzahlen der Spindel abschätzen und einstellen zu können.
Dabei habe ich eine Reflexionslichtschranke verwendet (QRD1114).
Reflexlichtschranke deshalb, weil eine Gabellichtschranke nicht praktikabel gewesen wäre.

drehzahlmessung.png

Das Programm ist sehr ähnlich wie in #10
Damit habe ich Drehzahlen bis ca. 15000/min erfassen können - mehr macht der Spindelmotor nicht.

Wenn ich die Datenblätter der beiden Lichtschranken vergleiche dann fällt folgendes auf:

Meine Reflexions-Lichtschranke
QRD1114
Fototransistor:
Rise Time: 10 µs
Fall Time: 50 µs

Deine Gabellichtschranke
EE-SX1041
Fototransistor:
Rise Time: 4 µs
Fall Time: 4 µs

Das bedeutet, dass die Lichtschranke, die du verwendest, viel schneller reagiert als die die ich verwendet habe.
Ich denke also, dass der Sensor den du verwendest schnell genug sein sollte.

drehzahlmessung.png

Patrick88199:
Ich denke die "Ungenauigkeit" kommt daher, dass das Messintervall zu unterschiedlichen Zeitpunkten anfängt. Mal vielleicht kurz nachdem der Propeller vorbei ist, das nächste mal wieder gerade kurz bevor der Propeller da ist. Je kleiner das Messintervall, desto größere Auswirkung hat es gleich, wenn 1 Impuls nach unten oder oben abweicht. Oder habe ich einen Denkfehler? ::slight_smile:

Hallo,

jetzt hast du es, nein, kein Denkfehler, eine wichtige Erkenntnis für dich.
Deine hohen Drehzahlen sind wie du schon sagtest auch nur 270Hz. Das juckt den µC nicht wirklich.

Wie misst du denn die Periodendauer? Was über 2200 U/min nicht funktionieren soll.

Die CNC Fräse ist auch ein sehr schönes Projekt ???

Ich habe mir auch nochmal das Datenblatt angesehen, mit 4us sollte die theoretisch tatsächlich ausreichend schnell sein.

Ich habe auch nochmal nachgerechnet wie lange der Propeller die Schranke unterbricht, vielleicht ist der ja zu dünn.
Laut meiner Rechnung hab ich bei 7.000/min an der Blattspitze ~44m/s. Der Propeller ist an der Messstelle 5mm breit. Mit t=s/v ergibt das knapp 110us in denen die Schranke unterbrochen ist. Da fallen die 4us aus dem Datenblatt ja eigentlich ausreichend rein.

Ich habe aber trotzdem mal schnell einen "T-Propeller" gedruckt, der an den Enden 38mm breit ist. Das wären ~800us.
Und jetzt konnte ich komischerweise Drehzahlen bis über 10.000/min messen, die meiner Meinung nach auch noch sinnvoll erscheinen :o

Doc_Arduino:
Wie misst du denn die Periodendauer? Was über 2200 U/min nicht funktionieren soll.

Bei 7.000/min wäre eine Periode == 1 Umdrehung == 1/116 == 8ms ?
Ich glaube ich stehe aber gerade auf dem Schlauch. :-[

postmaster-ino:
Man kann auch die Welle erfassen - man muß ja nicht an den Propeller selber, dann wäre auch die Anzahl der Blätter komplett außen vor.

Hm der Motor ist ein kleiner BLDC Outrunner, da wird das glaub ich etwas schwieriger :slightly_frowning_face:

Hallo,

Bei 7.000/min wäre eine Periode == 1 Umdrehung == 1/116 == 8ms ?
Ich glaube ich stehe aber gerade auf dem Schlauch.

Mach dir da keine Sorgen, es gibt noch micros() und wenn das zu ungenau ist programmiert man sich einen Timer.

So wie ich das lese liegt dein Hauptproblem derzeit bei der Erfassung des Propellers in der Lichtschranke.
Kannst du dir das Signal, welches von der Lichtschranke zum I/O führt, mit einem Oszi anschauen?
Das würde wahnsinnig helfen.

Vielleicht fehlt die Formung zu einem Digitalsignal.
Vielleicht ist auch nur der Umschaltpunkt des Komparators der ersten Lichtschranke ungünstig gewählt.
Dann müßtest du selbst einen auf- und anbauen mit einstellbaren Umschaltpunkt.
Ich vermute das analoge Signal "flattert" bei hohen Drehzahlen in einem ungünstigen Bereich.
Der Fotosensor wird nur durch Licht und Dunkelheit beeinflusst. Er wird sicherlich nie voll in beide "Sättigungen" gezwungen.

Hi,

es stimmt, die Dinger prellen. Das ist auch meine Erfahrung. Bei einem mal durch die Schranke fahren schalten die x mal um. Lösung für mich war erstmal die ISR durch Change triggern lassen und ein softwareseitiges entprellen.

Ich hab außerdem ein Set mit den Lichtschranken und einer weiteren Platine, auf der man den Umschaltpunkt einstellt. Das in kombi funktioniert, die Schranke allein hatte mir auch kein tolles Ergebnis beschert. Lange hab ich das mit dem Setup wie du es hast nicht probiert aber ich empfehle das Set mit zwei Schranken und der Platine mit Potis, das geht dann auf jeden Fall.