Drehzahlmesser, Problem mit einlesen

Für alle die es interessiert. Ich habe die Drehzahlberechnung nun über die Zeit zwischen zwei Impulsen gelöst.
Das Programm funktioniert jetzt ziemlich zuverlässig. Ist bestimmt nicht die Effektivste Art den Code zu schreiben aber für meine Verhältnisse und Ansprüche ist es auf jeden Fall gut genug. Danke an alle die mir hier geholfen haben.

int pin = 3;
unsigned long time;       //Zeitwert
unsigned long period;     //Abstand zwischen zwei Impulsen
unsigned long Drehzahl =0;//Drehzahl
void setup(){
  pinMode(pin, INPUT);
  pinMode(5,OUTPUT);
  pinMode(6,OUTPUT);
  pinMode(8,OUTPUT);
  pinMode(9,OUTPUT);
  pinMode(10,OUTPUT);
  pinMode(11,OUTPUT);
  pinMode(12,OUTPUT);
  pinMode(13,OUTPUT);
  digitalWrite(5,LOW);
  digitalWrite(6,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  attachInterrupt(digitalPinToInterrupt(pin),Signal,RISING);
}
 
void loop(){

Drehzahl=(1/(period*0.000001))*120;

  if(Drehzahl<1000){
    digitalWrite(5,LOW);
     digitalWrite(6,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>1000&&Drehzahl<2000){
    digitalWrite(5,HIGH);
     digitalWrite(6,LOW);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>2000&&Drehzahl<3000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,LOW);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>3000&&Drehzahl<4000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,LOW);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>4000&&Drehzahl<5000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,HIGH);
  digitalWrite(10,LOW);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>5000&&Drehzahl<6000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,LOW);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>6000&&Drehzahl<7000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(12,LOW);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>7000&&Drehzahl<8000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(12,HIGH);
  digitalWrite(13,LOW);
  }
  if(Drehzahl>8000&&Drehzahl<9000){
    digitalWrite(5,HIGH);
     digitalWrite(6,HIGH);
  digitalWrite(8,HIGH);
  digitalWrite(9,HIGH);
  digitalWrite(10,HIGH);
  digitalWrite(11,HIGH);
  digitalWrite(12,HIGH);
  digitalWrite(13,HIGH);
  }
 
}
void Signal(){
  period = micros() - time;
  time = micros();
}

für meine Verhältnisse und Ansprüche ist es auf jeden Fall gut genug

Alle anderen sollten bedenken, dass period als volatile deklariert werden muss und atomic, also unter geschlossenem Interrupt, aus der ISR übernommen werden muss, wenn man es nicht auf ein byte reduzieren kann.

uwefed:
1200 RPM.
Bei einem 4-Takter ist nur bei jeder 2. Umdrehung ein Zündimpuls.
Grüße Uwe

Hmmm...

Das "Wasted Spark" Verfahren ist erstaunlich weit verbreitet.
Da sich der Zündgeber leichter an der Kurbelwelle unter bringen lässt.
Mit an/im Generator.

Alle anderen sollten bedenken, dass period als volatile deklariert werden muss und atomic, also unter geschlossenem Interrupt, aus der ISR übernommen werden muss, wenn man es nicht auf ein byte reduzieren kann.

Volatile muss es sowieso sein, wenn es im Hauptprogramm und ISR genutzt wird.
Wenn größer als Byte, dann auch atomar ausgelesen werden.

michael_x:
Alle anderen sollten bedenken, dass period als volatile deklariert werden muss und atomic, also unter geschlossenem Interrupt, aus der ISR übernommen werden muss, wenn man es nicht auf ein byte reduzieren kann.

Was ist denn volatile? Was ist an der Art wie ich es gemacht habe schlecht/falsch? Kenne mich mit Interrupts nicht wirklich aus. War froh, dass ich es soweit bekommen habe, dass es funktioniert.

Hi

Nun denn - man könnte z.B. nach diesem Wort suchen.

Google hat dazu bestimmt einige Millionen Treffer ... aber klar, warum nicht im Forum fragen, was man auch selber in deutlich kürzerer Zeit herausfinden könnte.

Du suchst nach volatile und atomar, cli/sti könnten dabei auch auftauchen.

MfG

postmaster-ino:
Nun denn - man könnte z.B. nach diesem Wort suchen.

Das habe ich getan, trotzdem erschließt sich mir der Sinn davon nicht wirklich, da alles wie gewollt funktioniert. Habe jetzt im nachhinein auch gesehen, dass sie es im Beitrag über Interrupt auch verwendet haben. Trotzdem habe ich keinen Unterschied bemerkt.

FloriaN___K:
Trotzdem habe ich keinen Unterschied bemerkt.

OK, dann nimm " alle anderen " gern wörtlich und ehrlich.
Eine Variable die in einer ISR verändert wird, kann in dieser Zeit aus Sicht der loop den alten, den neuen oder einen falschen Wert haben, wenn sich eines der Bytes dieser Variablen schon geändert hat, andere aber nicht. Außerdem weist das Schlüsselwort volatile den Compiler darauf hin, dass er dies beim Optimieren berücksichtigen soll.

Das passiert nur selten und in deinem Fall der Drehzahl-Anzeige evtl. nur so, dass es leicht übersehen wird.

In anderem Zusammenhang gilt oft die Grundregel, dass seltene Fehler die schlimmsten sind.
Daher wollte ich meinen Senf hier nicht für mich behalten.

Daher wollte ich meinen Senf hier nicht für mich behalten.

Ich stimme dir da ausdrücklich und intensiv zu!

Jeder, jede und jedes, was oder wer, mit ISRs zu tun hat, sollte wissen, dass und warum, gemeinsame Variablen volatile sind, sein müssen.
Auch der atomare Zugriff sollte nicht nur bekannt und beherrscht, sondern auch angewendet werden.

Der Grund:
Denn sonst baut man nur Zufallsgeneratoren und sucht sich dumm und dull beim debuggen.

Mahimus:
Klar, nur sind 10/s zu wenig um zehnmal pro Sekunde über N Werte zu mitteln, wenn N sinnvollerweise >> 1 sein soll. Das meinte ich.

Das muss offenbar nicht so sein. Erfahrungsberichte im Netz sagen mal so mal so. Ich weiß nur sicher, dass bei meinem Möp der Zündgeber an der KW sitzt. Es wäre in dem Fall nur praktikabel einmal pro Umdrehung zu zünden.

Ein Zünden im Auslasstakt ist sinnlos, verschleisst die Zündkerze und kann im dümmsten Fall sogra in den Ansaugkanal zurück schlagen. Ich bin mir sicher, das kein Moped das so macht. 1 Zylinder haben also alle 2 Umdrehungen einen Impuls. 2 Zylinder haben 1 Impuls pro Umdrehung, 4 Zylinder 2 Impulse pro Umdrehung. Das wird mechanisch über Nocken gesteuert. Mechanisch beim Einzylinder wird entweder der Impulsgeber an ein Getriebe oder direkt auf Kurbelwelle, aber dann wird der Zündfunken bei jeder Umdrehung mal zur Zündkerze und mal zur Ableitwiderstand geleitet.

Aber eines muss ich doch erwähnen, es gab mal ein Moped das wirklich 2 Zündungen gemacht hat. Das war die DR Big, 800er Suzi Einzylinder. Aber da war einlass noch nicht offen, die hatte viel Frühzündung, die hat noch in Auslass gezündet. Normalerweise hast eine Ein/Auslassüberschneidung von 20 oder mehr Grad, wobei kurz nach OT der Auslass zu macht, also der Einlass schon 15° vor OT offen. Und bei 10° Frühzündung zündet man also in den Einlass. DR hatte nur 12° überschneidung und 15° Frühzündung. War halt dem Gurkenglass geschuldet, den dieses Moped als Zylinder benutzte. Daher haben die handelüblichen Nachrüst Drehzahlmesser bei der DR auf 2 Zylinder gestellt werden müssen um richtig anzuzeigen.

Die Regel ist aber, das Zünden via Übersetzung anzupassen.

michael_x:
OK, dann nimm " alle anderen " gern wörtlich und ehrlich.
Eine Variable die in einer ISR verändert wird, kann in dieser Zeit aus Sicht der loop den alten, den neuen oder einen falschen Wert haben, wenn sich eines der Bytes dieser Variablen schon geändert hat, andere aber nicht. Außerdem weist das Schlüsselwort volatile den Compiler darauf hin, dass er dies beim Optimieren berücksichtigen soll.

Das passiert nur selten und in deinem Fall der Drehzahl-Anzeige evtl. nur so, dass es leicht übersehen wird.

In anderem Zusammenhang gilt oft die Grundregel, dass seltene Fehler die schlimmsten sind.
Daher wollte ich meinen Senf hier nicht für mich behalten.

Alles klar danke, ich werde es ändern und mich auch nochmal genauer mit dem Thema ISR beschäftigen.
Wie würde sich ein solcher Fehler denn bemerkbar machen ?

Wie würde sich ein solcher Fehler denn bemerkbar machen ?

Wenn volatile fehlt, kann es sein, dass der Compiler fälschlich meint, dass sich die Variable gar nicht ändert während eines loop - Durchlaufs. (Blockierende Schleifen innerhalb von loop, die auf einen Wechsel warten, sind aber sowieso Käse)
Wenn eine int Variable nicht unter geschlossenem Interrupt ( "atomar" ) behandelt wird,
kann beim Wechsel 0x00FF -> 0x0100 auch mal fälschlich kurzzeitig 0x0000 oder 0x01FF erkannt werden.

Hochzählen sähe dann evtl. selten mal so aus: ..., 255, 0, 256, 257... oder ..., 255, 511, 256, ...
Natürlich genauso bei allen Überläufen von einem Byte ins nächste.

FloriaN___K:
Alles klar danke, ich werde es ändern und mich auch nochmal genauer mit dem Thema ISR beschäftigen.
Wie würde sich ein solcher Fehler denn bemerkbar machen ?

Lies mal das, hat mir sehr geholfen:

Ein Zünden im Auslasstakt ist sinnlos, verschleisst die Zündkerze und kann im dümmsten Fall sogra in den Ansaugkanal zurück schlagen. Ich bin mir sicher, das kein Moped das so macht. 1 Zylinder haben also alle 2 Umdrehungen einen Impuls. 2 Zylinder haben 1 Impuls pro Umdrehung, 4 Zylinder 2 Impulse pro Umdrehung. Das wird mechanisch über Nocken gesteuert. Mechanisch beim Einzylinder wird entweder der Impulsgeber an ein Getriebe oder direkt auf Kurbelwelle, aber dann wird der Zündfunken bei jeder Umdrehung mal zur Zündkerze und mal zur Ableitwiderstand geleitet.

Deine Ideen und Ansichten in Ehren, nur, sieht die Realität etwas anders aus.

Ich bin mir sicher, das kein Moped das so macht.
Soviele, so dass man schon fast sagen kann, ALLE 4Takt 4Zylinder Motorräder arbeiten nach dem Wasted Spark Prinzip.
Auch alle 1Zylinder mit Sensor an der Kurbelwelle.

Nur Möppis mit Verteiler(MvAugusta), oder Modelle mit Zündspulen für jeden einzelnen Zylinder, weichen davon ab.

Zusatz:
z.B. Die Yamaha XS650 hat Kontakte an der Nockenwelle.
Weicht also auch ab.
Die XS850 hat 3 Spulen für 3 Zylinder, aber Sensoren an der Kurbelwelle.
Weicht also von der Abweichung ab. Also "Wasted Spark", ja.

Für mich ganz präsentes Beispiel, meine XJ900 Modell: 31A

Hier ein Schaltplan davon.
Steht hier vor der Tür!
Kannste dir anschauen.

Zündsensor an der Kurbelwelle!

"verschleisst die Zündkerze"
Meine sind jetzt ca 40 Millonen Meter drin.
Einmal nachgebogen.

aber dann wird der Zündfunken bei jeder Umdrehung mal zur Zündkerze und mal zur Ableitwiderstand geleitet.
Das habe ich noch nie gesehen!
Niemals.

Ich habe zu dem Thema recherchiert, weil mich das jetzt gejuckt hat. Ich hab spezifisch nach meinem Bike geschaut (Kawa 4T Einzylinder Crosser) und das hier gefunden, was ich sehr interessant fand:efi-measurements

Long story short: Wie gesagt hat das Bike eine Positionserkennung nur an der Kurbelwelle, nach den ersten Zündungen erkennt aber der Lufttdrucksensor im Ansaugtrakt in welchem Takt das Bike ist. Ab da wird keinFunke mehr verschwendet. Das hat so auch jemand gemessen, siehe Link.

Warum man sich die Mühe macht wäre allerdings auch noch nett zu wissen. Wie Combie glaube ich an keinen großen Verschleiß der ZK durch die Anzahl der Zündungen. Aber vielleicht ist gerade bei einer Cross manchmal noch zündfähiges Gemisch da, schließlich muss da nicht extra mager gefahren werden wegen Anforderungen an Verbrauch oder Abgaswerte.

Wie gesagt hat das Bike eine Positionserkennung nur an der Kurbelwelle, nach den ersten Zündungen erkennt aber der Lufttdrucksensor im Ansaugtrakt in welchem Takt das Bike ist. Ab da wird keinFunke mehr verschwendet.

Auch eine interessante Variante!

Warum man sich die Mühe macht wäre allerdings auch noch nett zu wissen.

Dafür kann ich zumindest eine Hypothese liefern....

Vermutlich funktioniert die Zündung nach dem CDI Prinzip.
Also mit Speicherkondensator.
Für dessen Ladung steht dann die doppelte Zeit zur Verfügung.

Damit auch mehr Energie für jede einzelne Zündung.
Das Gemisch wird dann auch unter ungünstigen Bedingungen zuverlässiger entzündet.

Naja...
Eine Hypothese, mehr nicht.