# Drehzahlmesser am Auto

**URL:** <https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866>\
**Category:** Deutsch\
**Created:** [July 20, 2025, 7:20pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866 "2025-07-20T19:20:02Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 20, 2025, 7:20pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/1 "2025-07-20T19:20:02Z")

</div>

Guten Abend in die Runde. Ich habe mir einen Drehzalmesser für meinen alten Fiat Ducato gebaut. Auslesung der Impulse erfolgt über den originalen Kurbelwellensensor der mit dem Arduino Nano verbunden ist und der dann die Drehzahl auf einen kleinen Display anzeigt. Der entsprechende Programmcode ist unten angehangen. Das funktioniert auch soweit ganz toll. Nur halt nicht im Drehzahlbereich 850 (Leerlauf) bis etwa 1200 U/min. Also wenn ich im Standgas bin zeit er 850 an und wenn ich langsam Gas gebe zeigt das Display erst ab etwa 1200 U/min auch die Drehzahl an. Über 1200 funktioniert alles wie es soll. Vielleicht hat jemand ne Idee woran es liegt?

```arduino
unsigned long myTimeDZMImpuls=0;  
unsigned long myTimeZeitIm=0;  
double Drehzahl=0;
int impulszz=0;
int zeitimpuls=0;

void setup()
{
pinMode(3, INPUT); 
attachInterrupt(digitalPinToInterrupt(3), ImpulsLesen, FALLING);
]

void ImpulsLesen(){

  if(micros()-myTimeDZMImpuls>2){
impulszz=impulszz+1;
myTimeDZMImpuls = micros();

  }

void Loop()
{
if (impulszz>1610)
{ 
zeitimpuls=millis()-myTimeZeitIm; 
        
 Drehzahl=(60000/zeitimpuls);
Drehzahl=Drehzahl*10;
impulszz=0;
myTimeZeitIm=millis();
}
}

```

---

<div class="post-metadata">

**Author:** ![combie](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/combie/32/217369_2.png) [@combie](https://forum.arduino.cc/u/combie)\
**Post date:** [July 20, 2025, 8:02pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/2 "2025-07-20T20:02:54Z")

</div>

AVR?

Dann: [avr-libc: \<util/atomic.h\> Atomically and Non-Atomically Executed Code Blocks](https://www.nongnu.org/avr-libc/user-manual/group __util__ atomic.html)

Ich sehe keine Ausgaben!

Was ist dieses für eine Magie?

> `if (impulszz>1610)`

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 20, 2025, 8:18pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/3 "2025-07-20T20:18:01Z")

</div>

Moin @ardi902010 ,

anscheinend ist der von Dir gepostete Code nicht komplett. Mindestens der Anteil zur Ausgabe auf dem Display fehlt. Dort könnte durchaus auch die Ursache zu finden sein...

Ansonsten hat @combie bereits auf kritische Schwachstellen im veröffentlichten Sketch hingewiesen.

ec2021

---

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 20, 2025, 8:20pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/4 "2025-07-20T20:20:56Z")

</div>

> [@ec2021](#):
>
> anscheinend ist der von Dir gepostete Code nicht komplett. Mindestens der Anteil zur Ausgabe auf dem Display fehlt. Dort könnte durchaus auch die Ursache zu finden sein...

Ich habe den Code auf das nötigste heruntergebrochen hier. Im Display wird dann nur die Variable "Drehzahl" angezeigt.

---

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 20, 2025, 8:23pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/5 "2025-07-20T20:23:19Z")

</div>

> [@combie](#):
>
> Was ist dieses für eine Magie?
> 
> > `if (impulszz>1610)`

Der Kurbelwellensensor generiert 161 Impulse pro Umdrehung (161 Zähne am Starterzahnkranz). Es wird also gewartet bis 10 Umdrehungen der Kurbelwelle absolviert sind und dann wird anhand der benötigten Zeit dafür auf die Umdrehungen pro Minute hochgerechnet.

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 20, 2025, 9:13pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/6 "2025-07-20T21:13:22Z")

</div>

Schon verstanden ...

Es wäre allerdings nicht der erste Sketch, bei dem die Ursache für Probleme im nicht veröffentlichten Teil des Codes zu finden ist. 🙂

Auf jeden Fall hilft das komplette Posten, diese Möglichkeit auszuschließen.

Die im Interrupt und in der loop() verwendete Variable sollte als volatile deklariert werden, um Fehler durch Compiler-Optimierungen (Halten des letzten Wertes in einem Register) zu vermeiden. Zusätzlich besteht die Gefahr, dass der Interrupt gerade beim Auswerten oder Ändern der Variablen in der loop() zuschlägt. Um das zu Vermeiden gibt es die bereits oben verlinkten Mechanismen.

Man könnte das Messverfahren ggf. auch von fixen 10 Umdrehungen auf eine vorgegebene Messzeit umstellen. Also die Anzahl der Impulse z.B. alle 100 ms auswerten.

Bei max. 3000 U/min wären das 50 U/s = 8050 Impulse/s. Damit also 805 pro 0.1 s. Im Leerlauf 228 in 0.1s.

Du könntest erstmal prüfen, ob die Rohdaten so stimmen.

---

<div class="post-metadata">

**Author:** ![combie](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/combie/32/217369_2.png) [@combie](https://forum.arduino.cc/u/combie)\
**Post date:** [July 21, 2025, 5:43am UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/7 "2025-07-21T05:43:57Z")

</div>

> volatile

Ich setze schon lange, in solchen Fällen, kein volatile mehr ein.  
Weil es eben die Optimierung unterbindet.  
Ein Stock in die Speichen des Optimizers.

Die oben genannten Macros setzen "Memory Barriers".  
Soweit mir bekannt, eine "Full Barrier".

Das habe ich lange getestet, den generierten ASM Code untersucht.  
Die Empfehlung solche Variablen volatile zu machen scheint doch eher historisch oder übervorsichtig zu sein.

Teste das doch mal!

Übrigens:  
volatile ist beim AVR-Gcc weiterhin nötig, wenn auf Hardware Register zugegriffen wird, denn die können sich wirklich außerhalb des Programms ändern, was sich auch nicht durch Interrupt sperren verhindern lässt.

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 12:07pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/8 "2025-07-21T12:07:43Z")

</div>

Danke für die Auffrischung 😉

Habe zu dem Thema aktuell noch mal recherchiert, hier die Ergebnisse

> **Volatile und ATOMIC\_BLOCK**
>
> Deine Erkenntnisse bzgl. des Einsatzes der avr-lib werden hier bestätigt und die Zusammenhänge zwischen dem ATOMIC\_BLOCK-Makro und der memory barrier erläutert:
> 
> [https://www.mikrocontroller.net/topic/570524](https://www.mikrocontroller.net/topic/570524)
> 
> Die memory-Barriere wird bei der AVR Library sowohl in dem Makro sei() wie auch bei cli() eingesetzt:
> 
> [https://github.com/avrdudes/avr-libc/blob/main/include/avr/interrupt.h](https://github.com/avrdudes/avr-libc/blob/main/include/avr/interrupt.h)
> 
> Die Verwendung von sei() und cli() im atomic.h ruft damit automatisch die memory barrier Funktionen auf:
> 
> [https://github.com/avrdudes/avr-libc/blob/main/include/util/atomic.h](https://github.com/avrdudes/avr-libc/blob/main/include/util/atomic.h)
> 
> Die Entwickler der atomic.h haben die volatile Deklaration in ihrem Beispiel dann allerdings inkonsequent beibehalten; siehe atomic.h Zeile 154 (Stand der letzten Änderung vom 29. März 2025)

Unabhängig von der derzeit unsicheren Umsetzung bzgl. der Variablen impulszz kann ich im obigen Code keine unmittelbare Ursache erkennen, die erklären würde, warum nun gerade Drehzahlwerte zwischen 850 und 1200 nicht ermittelt werden sollten.

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 12:16pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/9 "2025-07-21T12:16:51Z")

</div>

Beim Reduzieren Deines Sketches haben sich ein paar Fehler eingeschlichen:

- setup() { ] endet mit einer eckigen anstatt einer geschweiften Klammer
- ImpulsLesen() -\> hier fehlt die abschließende geschweifte Klammer
- Loop() sollte sicher loop() heißen

Spricht etwas dagegen, dass wir mal einen Blick auf den kompletten Code werfen dürfen? Manchmal verstecken sich Fehlerursachen hinter scheinbar unverdächtigen Code-Anteilen ...

---

<div class="post-metadata">

**Author:** ![combie](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/combie/32/217369_2.png) [@combie](https://forum.arduino.cc/u/combie)\
**Post date:** [July 21, 2025, 12:41pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/10 "2025-07-21T12:41:39Z")

</div>

Ich danke dir für diese Untersuchung.

Ach ja, die Untersuchung des Programms habe ich abgebrochen, als ich bemerken musste, dass das untestbarer Code ist.

Zudem hätte ich sicherlich Timer1 im ZählerMode verwendet und so wohl ganz auf die ISR verzichtet. Würde also auch aus dem Grund (für mich) keinen Sinn machen.

---

<div class="post-metadata">

**Author:** ![noiasca](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/noiasca/32/1126910_2.png) [@noiasca](https://forum.arduino.cc/u/noiasca)\
**Post date:** [July 21, 2025, 1:23pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/11 "2025-07-21T13:23:25Z")

</div>

> [@ardi902010](#):
>
> Also wenn ich im Standgas bin zeit er 850 an und wenn ich langsam Gas gebe zeigt das Display erst ab etwa 1200 U/min auch die Drehzahl an.

mit diesen Sketch bekomm ich auch (handgedrückte) kleinere Werte z.B. 60, 100, 110:

```arduino
unsigned long myTimeDZMImpuls = 0;
unsigned long myTimeZeitIm = 0;
double Drehzahl = 0;
unsigned int impulszz = 0;
unsigned int zeitimpuls = 0;

void ImpulsLesen() {
  if (micros() - myTimeDZMImpuls > 2) {
    impulszz = impulszz + 1;
    myTimeDZMImpuls = micros();
  }
}

void setup() {
  pinMode(3, INPUT);
  attachInterrupt(digitalPinToInterrupt(3), ImpulsLesen, FALLING);
  Serial.begin(115200);
}

void loop() {
  if (impulszz > 1610) {
    zeitimpuls = millis() - myTimeZeitIm;
    Drehzahl = (60000 / zeitimpuls);
    Drehzahl = Drehzahl * 10;
    Serial.println(Drehzahl);
    impulszz = 0;
    myTimeZeitIm = millis();
  }
}
```

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 2:48pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/12 "2025-07-21T14:48:56Z")

</div>

Hier mal ein Sketch, der die erforderlichen Maßnahmen für im Interrupt veränderte Variable berücksichtigt und die Drehzahlpulse per Timer simuliert, so dass man den Code auch ohne die Hardware testen kann:

Siehe auch hier: [https://wokwi.com/projects/437089934882609153](https://wokwi.com/projects/437089934882609153)

```arduino
/*
  Forum: https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/8
  Wokwi: https://wokwi.com/projects/437089934882609153

  Version mit ATOMIC_BLOCK und Simulation der Drehzahlpulse per Timer
  auf Basis des Originalsketches

  2025/07/22
  ec2021

*/

#include <util/atomic.h>

constexpr byte inPin {3};
constexpr unsigned long pulseProRotation {161};
unsigned long letzterPuls = 0;
unsigned long letzteBerechnung = 0;
uint16_t Drehzahl = 0;
uint16_t impulsZaehler = 0;
unsigned long zeitFuerZehnRotationen = 0;
boolean zehnRotationen = false;

void setup() {
  Serial.begin(115200);
  pinMode(inPin, INPUT);
  attachInterrupt(digitalPinToInterrupt(inPin), ImpulsLesen, FALLING);
  starteSimulation(990);
}

void ImpulsLesen() {
  if (micros() - letzterPuls > 2) {
    letzterPuls = micros();
    impulsZaehler++;
  }
}

void drehzahlMessung() {
  ATOMIC_BLOCK(ATOMIC_FORCEON)
  {
    if (impulsZaehler >= pulseProRotation * 10) {
      zehnRotationen = true;
      impulsZaehler = 0;
    }
  }
  if (zehnRotationen) {
    zeitFuerZehnRotationen = millis() - letzteBerechnung;
    letzteBerechnung = millis();
    zehnRotationen = false;
    Drehzahl = round(60000.0 / zeitFuerZehnRotationen) * 10;
    Serial.println(Drehzahl);
  }
}

void loop() {
  drehzahlMessung();
}

/ ************************************************************************************* /
/* Dieser Teil ist für das Simulieren der Pulse für die Drehzahlmessung erforderlich */
#include <TimerOne.h>
constexpr byte outPin {4};
unsigned long interval;
float zielDrehzahl = 1260;
byte togglePin = 0;

void starteSimulation(float ziel) {
  pinMode(outPin, OUTPUT);
  togglePin = 1 << outPin;
  zielDrehzahl = ziel;
  interval = round(1000000.0 / ((zielDrehzahl / 60.0) * pulseProRotation));
  Serial.println(interval);
  Timer1.initialize(interval);
  Timer1.attachInterrupt(timer_isr);
}

void timer_isr() {
  PIND = togglePin;
  delayMicroseconds(3);
  PIND = togglePin;
}

/ ************************************************************************************* /

```

Die Berechnung der Drehzahl auf diese Weise

> Drehzahl = round(60000.0 / zeitFuerZehnRotationen) \* 10;

sorgt dafür, dass sie auf Zehnerwerte gerundet wird.

Die Variablenbezeichnungen habe ich ein wenig angepasst, um die Nachvollziehbarkeit (hoffentlich) zu erleichtern.

Bei der Funktion starteSimulation() im setup() kann man die zu simulierende Drehzahl als Parameter einsetzen; kommentiert man sie aus, sollte der Sketch auch in Deinem Umfeld funktionieren. Die Ausgabe erfolgt allerdings momentan per serieller Schnittstelle.

Viel Erfolg!  
ec2021

P.S.: Da wie oben angegeben ATOMIC\_BLOCK die Deklaration als volatile überflüssig macht. habe ich darauf verzichtet.

Und hier Deine Version inkl. der Drehzahlsimulation zum Testen auf Wokwi:

[https://wokwi.com/projects/437099518400803841](https://wokwi.com/projects/437099518400803841)

> **Sketch**
>
> ```arduino
> /*
> Forum: https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/8
> Wokwi: https://wokwi.com/projects/437099518400803841
> 
> Version auf Basis des Originalsketches zzgl.
> - der Simulation der Drehzahlpulse per Timer
> - der seriellen Ausgabe der Drehzahl
> 
> 2025/07/22
> ec2021
> 
> */
> 
> unsigned long myTimeDZMImpuls = 0;
> unsigned long myTimeZeitIm = 0;
> double Drehzahl = 0;
> int impulszz = 0;
> int zeitimpuls = 0;
> 
> void setup()
> {
> pinMode(3, INPUT);
> attachInterrupt(digitalPinToInterrupt(3), ImpulsLesen, FALLING);
> starteSimulation(1000);
> }
> 
> void ImpulsLesen() {
> if (micros() - myTimeDZMImpuls > 2) {
> impulszz = impulszz + 1;
> myTimeDZMImpuls = micros();
> }
> }
> 
> void loop()
> {
> if (impulszz > 1610)
> {
> zeitimpuls = millis() - myTimeZeitIm;
> 
> Drehzahl = (60000 / zeitimpuls);
> Drehzahl = Drehzahl * 10;
> impulszz = 0;
> myTimeZeitIm = millis();
> Serial.println(Drehzahl);
> }
> }
> 
> / ************************************************************************************* /
> /* Dieser Teil ist für das Simulieren der Pulse für die Drehzahlmessung erforderlich */
> #include <TimerOne.h>
> constexpr byte outPin {4};
> constexpr unsigned long pulseProRotation {161};
> unsigned long interval;
> float zielDrehzahl = 1260;
> byte togglePin = 0;
> 
> void starteSimulation(float ziel) {
> Serial.begin(115200);
> pinMode(outPin, OUTPUT);
> togglePin = 1 << outPin;
> zielDrehzahl = ziel;
> interval = round(1000000.0 / ((zielDrehzahl / 60.0) * pulseProRotation));
> Serial.println(interval);
> Timer1.initialize(interval);
> Timer1.attachInterrupt(timer_isr);
> }
> 
> void timer_isr() {
> PIND = togglePin;
> delayMicroseconds(3);
> PIND = togglePin;
> }
> 
> / ************************************************************************************* /
> 
> ```

---

<div class="post-metadata">

**Author:** ![michael\_x](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/michael_x/32/628623_2.png) [@michael\_x](https://forum.arduino.cc/u/michael_x)\
**Post date:** [July 21, 2025, 3:30pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/13 "2025-07-21T15:30:29Z")

</div>

> [@ec2021](#):
>
> Die Ausgabe erfolgt allerdings momentan per serieller Schnittstelle

Eine Funktion sollte nur das machen, was ihre Aufgabe ist.  
Und, wenn möglich, keine globalen Variablen verwenden.

Die Serielle Ausgabe - oder was sonst auch immer - gehört in die Testumgebung.

Vorschlag:

```arduino
bool drehzahlMessung(uint16_t& ergebnis) {
// liefert true, falls neues Ergebnis vorliegt
  ATOMIC_BLOCK(ATOMIC_FORCEON)
  {
    if (impulsZaehler >= pulseProRotation * 10) {
      zehnRotationen = true;
      impulsZaehler = 0;
    }
  }
  if (zehnRotationen) {
    zeitFuerZehnRotationen = millis() - letzteBerechnung;
    letzteBerechnung = millis();
    zehnRotationen = false;
    ergebnis = round(60000.0 / zeitFuerZehnRotationen) * 10;
    return true;
  }
  return false; // kein neuer Wert
}

void loop() {
  if (drehzahlMessung(Drehzahl)) Serial.println(Drehzahl);
}

```

Drehzahl muss keine globale Variable sein, wenn sie (per Referenz) übergeben wird.

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 3:49pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/14 "2025-07-21T15:49:17Z")

</div>

Sehr schön, aber das Problem des TO liegt tatsächlich wohl an ganz anderer Stelle.

Da die serielle Schnittstelle in der Originalanwendung sowieso raus fliegen wird und der Sketch außerhalb der Meßroutine aus Post 1 unbekannt ist, halte ich weitere Detailoptimierungen derzeit für begrenzt hilfreich. Das kann ja alles noch kommen, wenn die Ursache für das geschilderte Problem gefunden und behoben wurde ...

Die Wokwi-Versionen zeigen jedenfalls, dass es in der Messroutine keine Begrenzungen für Werte zwischen 850 und 1200 U/min gibt.

😉

---

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 21, 2025, 7:25pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/15 "2025-07-21T19:25:03Z")

</div>

Das tritt übrigens nur beim Gas geben auf. Wenn man Gas weg nimmt wird die Drehzahl auch zwischen 850 und 1200 angezeigt. Ich werde die Vorschläge hier mal im Code umsetzen vielleicht bringt es etwas.

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 7:27pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/16 "2025-07-21T19:27:28Z")

</div>

Das klingt ja irgendwie nach einem Schwellwert, der erst einmal überschritten werden muss, damit wieder Anzeigen erscheinen ... ?!?

Ist das Verhalten so:

- START
- Leerlauf-Anzeige mit 850 U/min
- Anzeige bei Drehzahlerhöhung erst ab 1200 U/min
- Danach sowohl aufwärts wie auch abwärts bis Leerlauf
- Ab 850 U/min --\> weiter mit START

?

---

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 21, 2025, 8:07pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/17 "2025-07-21T20:07:38Z")

</div>

Ja genau so. Die angezeigte Drehzahl sollte auch stimmen wenn ich sie mit dem Bericht der Hauptuntersuchung abgleiche: Leerlauf 862 (HU Bericht) und 854 (Anzeige), Max Drehzahl 4892 (HU Bericht) und 4908 (Anzeige).

Ich habe unten mal den Testsketch angehangen. Der bringt genau beschriebenes Verhalten. Der Testsketch ist aus dem eigentlichen Hauptsketch herauskopiert, das Ergebnis ist aber das selber. Der Hauptsketch ist aber noch wesentlich umfangreicher da dort noch Wegfahrperre, Scheibenwischerintervall und diverse Funktionen für das Wohnmobil einprorammiert sind. Ich glaube nicht das hier einer durchsieht wenn ich das hier poste. Aber der Testsketch produziert ja das selbe Ergebnis.

```arduino
#include "MFRC522.h"
#include <Arduino.h>
#include <U8g2lib.h>

#ifdef U8X8_HAVE_HW_SPI
#include <SPI.h>
#endif
#ifdef U8X8_HAVE_HW_I2C
#include <Wire.h>
#endif

unsigned long myTimeDZM=0; //Zeit Drehzahlmesser
int timerDZM=500; //Zeit für Drehzahlmesser 
unsigned long myTimeDZMImpuls=0; //Zeit Drehzahlmesser
unsigned long myTimeZeitIm=0; //Zeit für Impuls DZM

//Pins
#define pinImpuls 3 // Pin für Drehzahlimpuls

//OLED Display
#define pinOSDA 5  
#define pinOSLK 6 
U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ pinOSLK, /* data=*/ pinOSDA, /* reset=*/ U8X8_PIN_NONE); // Adafruit Feather M0 Basic Proto + FeatherWing OLED

// Drehzahlmesser
double Drehzahl=0;
int impulszz=0;
int zeitimpuls=0;

  
void setup()
{
//Pin In Output
pinMode(pinImpuls, INPUT); //Pin Impuls
attachInterrupt(digitalPinToInterrupt(pinImpuls), ImpulsLesen, FALLING);

  SPI.begin();
  u8g2.begin(); //OLED Display
  
}

void loop()
{

if (impulszz>1610){ //Führe aus wenn x Impulse gemessen wurden

zeitimpuls=millis()-myTimeZeitIm; 
        
 Drehzahl=(60000/zeitimpuls);
Drehzahl=Drehzahl*10;
impulszz=0;
myTimeZeitIm=millis();
}
    
   

    if((millis()-myTimeDZM)>timerDZM){
 
u8g2.clearBuffer();
//u8g2.clearDisplay();
// u8g2.setFont(u8g2_font_9x18_mn);
//u8g2.setFont(u8g2_font_chargen_92_mr);
u8g2.setFont(u8g2_font_fub30_tr);
 u8g2.setFontRefHeightExtendedText();
 u8g2.setDrawColor(1);
 u8g2.setFontPosTop();
 u8g2.setFontDirection(0);
 u8g2.setCursor(20,1); 
u8g2.print(Drehzahl,0);
u8g2.sendBuffer();

/*
 u8g2.setDrawColor(1);
 u8g2.drawBox(0, 15, (impuls*128)/6000, 17);
u8g2.setDrawColor(0);
u8g2.drawBox((impuls*128)/6000, 15, 129-(impuls*128)/6000, 17);
*/
/*
u8g2.clearBuffer();
u8g2.clearDisplay();
u8g2.setFont(u8g2_font_9x18_tf);
 u8g2.setFontRefHeightExtendedText();
 u8g2.setDrawColor(1);
 u8g2.setFontPosTop();
 u8g2.setFontDirection(0);
 u8g2.setCursor(5,20); // set cursor position lcd
 //u8g2.print(zeitimpuls);
 u8g2.print(impuls);
*/
//u8g2.sendBuffer();
              myTimeDZM=millis();
      }
 } 

 

 

void ImpulsLesen(){
        
  if(micros()-myTimeDZMImpuls>2){
 impulszz=impulszz+1;            
myTimeDZMImpuls = micros();
  }
}

```

---

<div class="post-metadata">

**Author:** ![ec2021](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ec2021/32/997272_2.png) [@ec2021](https://forum.arduino.cc/u/ec2021)\
**Post date:** [July 21, 2025, 10:38pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/18 "2025-07-21T22:38:58Z")

</div>

Oha, das ist insofern schon mal interessant, weil die Anzeigeroutine

```arduino

  if (millis() - myTimeDZM > timerDZM) {
    unsigned long start = millis();

    u8g2.clearBuffer();
    u8g2.setFont(u8g2_font_fub30_tr);
    u8g2.setFontRefHeightExtendedText();
    u8g2.setDrawColor(1);
    u8g2.setFontPosTop();
    u8g2.setFontDirection(0);
    u8g2.setCursor(20, 1);
    u8g2.print(Drehzahl, 0);
    u8g2.sendBuffer();

    myTimeDZM = millis();
    Serial.println(myTimeDZM - start);
  }

```

den Controller schon ca. eine Drittelsekunde in Beschlag nimmt.

In dieser Zeit einlaufende Pulse, die dazu führen, dass impulszz deutlich größer wird als 1610, werden bei der Abfrage "if (impulszz \> 1610)" und der folgenden Umrechnung ignoriert. Es wird so gearbeitet, als wenn **jeder** Wert über 1610 genau 10 Umdrehungen entspricht.

Das kann man hier bei Wokwi sehr gut sehen:  
[https://wokwi.com/projects/437119968369247233](https://wokwi.com/projects/437119968369247233)

Ausgabe bei simulierten 850 U/min

```arduino
Start
U8G2 [ms] 325
Impulse 1611
U8G2 [ms] 331
Impulse 1611
U8G2 [ms] 331
Impulse 1611
U8G2 [ms] 331
Impulse 1611
U8G2 [ms] 331
Impulse 1898
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 328
Impulse 1894
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 329
Impulse 1895
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 329
Impulse 1895
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1896
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 329
Impulse 1895
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1894
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 329
Impulse 1895
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 329
Impulse 1895
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1893
U8G2 [ms] 328
Impulse 1893
U8G2 [ms] 329
Impulse 1894
U8G2 [ms] 329
Impulse 1896
U8G2 [ms] 329

```

wobei sich hier noch zugunsten der Daten auswirkt, dass die Zeit myTimeDZM erst nach dem Abarbeiten der Anzeige gesetzt wird. Das führt dazu, dass bei höheren Drehzahlen zwischen den Anzeigen der Schwellwert zweimal überschritten wird. Hier für simulierte 1250 U/min, man beachte die letzte Impulsanzahl vor der Anzeige U8G2:

```arduino
Impulse 2419
Impulse 1611
U8G2 [ms] 340
Impulse 1611
U8G2 [ms] 340
Impulse 2421
Impulse 1611
U8G2 [ms] 340
Impulse 1536
U8G2 [ms] 339
Impulse 2490
Impulse 1611
U8G2 [ms] 340
Impulse 1611

```

Ich habe Deinen Sketch jetzt im Wesentlichen wie folgt angepasst:

- Verwendung des ATOMIC\_BLOCK-Makros
- Berechnung der Drehzahl und Anzeige in der selben Funktion
- Ermittlung der tatsächlich vergangenen Zeit nach dem letztem Rücksetzens des Zählers.
- Berechnung der Drehzahl aus der Anzahl der Pulse, die in diesem so ermittelten Zeitraum eingegangen sind
- Berechnung der Drehzahl weitgehend mit float-Werten, um Rundungsfehler beim Dividieren zu minimieren
- Ein delay() in der loop(), um die zeitliche Auswirkung weiterer Funktionen zu simulieren.

> **Sketch**
>
> ```arduino
> /*
> Forum: https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866
> Wokwi: https://wokwi.com/projects/437123436443317249
> 
> 2025/07/22
> ec2021
> 
> */
> 
> //#include "MFRC522.h"
> #include <Arduino.h>
> #include <U8g2lib.h>
> #include <util/atomic.h>
> 
> #ifdef U8X8_HAVE_HW_SPI
> #include <SPI.h>
> #endif
> #ifdef U8X8_HAVE_HW_I2C
> #include <Wire.h>
> #endif
> 
> unsigned long myTimeDZM = 0; //Zeit Drehzahlmesser
> int timerDZM = 500; //Zeit für Drehzahlmesser
> unsigned long myTimeDZMImpuls = 0; //Zeit Drehzahlmesser
> unsigned long myTimeZeitIm = 0; //Zeit für Impuls DZM
> 
> //Pins
> #define pinImpuls 3 // Pin für Drehzahlimpuls
> 
> //OLED Display
> #define pinOSDA A4
> #define pinOSLK A5
> U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ pinOSLK, /* data=*/ pinOSDA, /* reset=*/ U8X8_PIN_NONE); // Adafruit Feather M0 Basic Proto + FeatherWing OLED
> 
> // Drehzahlmesser
> double Drehzahl = 0;
> uint16_t impulszz = 0;
> uint16_t impulszz_copy = 0;
> int zeitimpuls = 0;
> constexpr uint16_t PulseProRotation {161};
> 
> void setup()
> {
> //Pin In Output
> pinMode(pinImpuls, INPUT); //Pin Impuls
> attachInterrupt(digitalPinToInterrupt(pinImpuls), ImpulsLesen, FALLING);
> 
> SPI.begin();
> 
> u8g2.begin(); //OLED Display
> starteSimulation(1200);
> 
> }
> 
> void loop()
> {
> if (millis() - myTimeDZM >= timerDZM) {
> ATOMIC_BLOCK(ATOMIC_FORCEON)
> {
> impulszz_copy = impulszz;
> impulszz = 0;
> }
> uint16_t messIntervall = millis() - myTimeDZM;
> myTimeDZM = millis();
> Drehzahl = (1.0 * impulszz_copy / PulseProRotation) * (60000.0 / messIntervall) ;
> 
> u8g2.clearBuffer();
> u8g2.setFont(u8g2_font_fub30_tr);
> u8g2.setFontRefHeightExtendedText();
> u8g2.setDrawColor(1);
> u8g2.setFontPosTop();
> u8g2.setFontDirection(0);
> u8g2.setCursor(20, 1);
> u8g2.print(Drehzahl, 0);
> u8g2.sendBuffer();
> }
> delay(300);
> }
> 
> void ImpulsLesen() {
> 
> if (micros() - myTimeDZMImpuls > 2) {
> impulszz = impulszz + 1;
> myTimeDZMImpuls = micros();
> }
> }
> 
> / ************************************************************************************* /
> /* Dieser Teil ist für das Simulieren der Pulse für die Drehzahlmessung erforderlich */
> #include <TimerOne.h>
> constexpr byte outPin {4};
> constexpr unsigned long pulseProRotation {161};
> unsigned long interval;
> float zielDrehzahl = 1200;
> byte togglePin = 0;
> 
> void starteSimulation(float ziel) {
> pinMode(outPin, OUTPUT);
> togglePin = 1 << outPin;
> zielDrehzahl = ziel;
> interval = round(1000000.0 / ((zielDrehzahl / 60.0) * pulseProRotation));
> Timer1.initialize(interval);
> Timer1.attachInterrupt(timer_isr);
> }
> 
> void timer_isr() {
> PIND = togglePin;
> delayMicroseconds(3);
> PIND = togglePin;
> }
> 
> / ************************************************************************************* /
> 
> ```

Auf Wokwi zum Testen: [https://wokwi.com/projects/437123436443317249](https://wokwi.com/projects/437123436443317249)

Ich habe dabei so wenig wie möglich an Deinem Sketch geändert, da ist sicher noch Luft nach oben ...

Gerne mal in der originalen Anwendung ausprobieren!

Viel Erfolg!  
ec2021

---

<div class="post-metadata">

**Author:** ![fony](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/fony/32/936882_2.png) [@fony](https://forum.arduino.cc/u/fony)\
**Post date:** [July 22, 2025, 9:15am UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/19 "2025-07-22T09:15:25Z")

</div>

> [@ardi902010](#):
>
> `U8G2_SSD1306_128X32_UNIVISION_F_SW_I2C u8g2(U8G2_R0, /* clock=*/ pinOSLK, /* data=*/ `

Warum Software I2C die ist doch auch sehr langsam, nim HW\_I2C.

---

<div class="post-metadata">

**Author:** ![ardi902010](https://dub1.discourse-cdn.com/arduino/user_avatar/forum.arduino.cc/ardi902010/32/1099297_2.png) [@ardi902010](https://forum.arduino.cc/u/ardi902010)\
**Post date:** [July 22, 2025, 5:10pm UTC](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866/20 "2025-07-22T17:10:42Z")

</div>

Danke, werde ich so mal probieren.

[Next page](https://forum.arduino.cc/t/drehzahlmesser-am-auto/1396866.md?page=2)
