Interrupt-Routine wird fälschlich aufgerufen (bei jedem Aufstart)

Hallo Kollegen,
ich arbeite gerade an einem Motorrad-tacho, und das ist schon mein x-ter Post hier.. aber ich stoße täglich auf neue Probleme :slight_smile:

ich lese einen eine Reedschalter per Interrupt ein und berechne daraus die Geschwindigkeit.

Komischerweise wird die damit verknüpfte Interrupt-Routine aber bei jedem Aufstart des Arduinos aufgerufen (Konkret erscheint bei jedem Boot des Arduinos die Serielle Ausgabe "UmdrehungErkannt") - ohne dass der Reedschalter überhaupt betätigt wurde.

Was mache ich falsch?

Anbei mein (stark gekürzter, aber compilierender) Code:

#include <EEPROM.h>
#include <RunningAverage.h>
#include <Wire.h>
#include "OneButton.h"
#include <U8g2lib.h>
#include "RTClib.h"

U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE, /* clock=*/ 16, /* data=*/ 17);   // ESP32 Thing, HW I2C with pin remapping
RTC_DS3231 rtc;


const uint16_t Prellzeit = 100; // in ms
volatile uint32_t lastMillis = 0;
RunningAverage myRA(5);
volatile unsigned long dauer = 0; 
short geschwindigkeit;                         
short VAnzeige;
const int buttonPin = 4;
const int reedPin = 3;
int screen = 0;
volatile int RotationCounter = 0;
OneButton button(buttonPin, true);
char Minute[3];
char Stunde[3];
const int RadUmfang = 1862;
// char Uhrzeit[10];
char Temperatur[15];
char Speed[10];
float dummyInterval = (RadUmfang/1000.0 * 161.0);

long GesamtMeter;
long TripMillimeter;
int GesamtMeter_ADDR = 0;
int TripMillimeter_ADDR = GesamtMeter_ADDR + 4;
char TripKm[10];
char GesamtKm[10];
int testMeter = 0;
boolean reset = false;
boolean eineUmdrehung = false;


   
void setup()   {
  Serial.begin(9600);      // open the serial port at 9600 bps:
  pinMode(reedPin, INPUT_PULLUP); // Reed-Sensor an Pin 3
  pinMode(buttonPin, INPUT_PULLUP); // Taster an Pin 2
  attachInterrupt(digitalPinToInterrupt(reedPin), readmillis, RISING);
  myRA.clear();
  delay(500);  
}

void loop() {  
  button.tick();
  if (eineUmdrehung && (millis() - lastMillis >= Prellzeit)) {      //Geschwindigkeit berechnen
       dauer = millis() - lastMillis;                                // Dauer einer Radumdrehung in ms
       lastMillis = millis();                                
       geschwindigkeit = RadUmfang*3.6/dauer;           // Geschwindigkeit: 1 Interrupt alle 1861mm (Radumfang)
       myRA.addValue(geschwindigkeit);                 // Wert zur Mittelwerberechnung hinzufügen
       TripMillimeter += RadUmfang;                    //pro Umdrehung 1861mm gefahren
       RotationCounter += 1; 
       eineUmdrehung = false;
  }

  if (millis()-lastMillis >= 2000) {
    myRA.clear();                       //wenn keine Radumdrehung innerhalb von 2 Sek stattgefunden hat --> Geschwindigkeit nullen
  }        
  VAnzeige = myRA.getAverage();        // Mittelwert errechnen 
}

void readmillis() {
  eineUmdrehung = true;  
  Serial.println("UmdrehungErkannt");
  }

Serial hat in Interrupts so oder so nichts zu suchen

Und wenn du sowieso generell mit millis() arbeitest, bräuchte man auch den Interrupt nicht unbedingt

Serial.println hab ich nur eingebaut um das Problem zu verdeutlichen.

Aber wieso wird die Routine nun doppelt aufgerufen?

(deleted)

Der arduino nano wird per USB meines macbooks gespeist.
Selbst wenn garkein schalter angeschlossen ist tritt dieses Verhalten auf....

(deleted)

Das wäre natürlich möglich, aber ist das plausibel? Bzw treten solche HW Defekte hinreichend oft auf?

Mfg!

Hi

Es ist durchaus ausreichend, wenn dieser Defekt genau 1x bei Dir austritt.

Davon abgesehen - mit 1,872m Radumfang und maximal 10 Umdrehungen die Sekunde (Entprellzeit 100ms !!) sind wir bei knapp über 60km/h - für einen Roller ausreichend, sofern es nicht steil bergab geht :wink:

Wie ist das Kabel verlegt vom Reed-Schalter zum Arduino?
Hast Du diese Störung IMMER, oder nur unter bestimmten Umständen?
Alternativ ignorierst Du die ersten 3 Sekunden jede Radumdrehung - vll. nicht die eleganteste Art, dieses Problem anzugehen, aber immerhin.

MfG

Der tacho ist für ein Motorrad bestimmt, also reden wir hier von maximal 220kmh.

Der Fehler tritt bei jedem aufstart auf (und auch nur da).... Auch wenn der reed Schalter nicht angeschlossen ist

(deleted)

Ja, mit deinem Code tritt das Problem auch auf (siehe Screenshot).

Ich denke nicht, dass das Entprellen mein Problem versacht / lösen würde.

Im Grunde genommen hab ich zur Laufzeit auch kein Problem - mir ist nur schleierhaft, wieso die ISR zu Programmstart einmal aufgerufen wird...

Edit:
Selbst dieser Minimal-Sketch triggert die ISR "ohne Grund".
Vermutlich muss ichmir doch mal einen austausch-Nano organisieren.. .dazu komme ich aber erst nächste Woche :frowning:

const int reedPin = 3;
boolean eineUmdrehung = false;

void setup()   {
  Serial.begin(9600);      // open the serial port at 9600 bps: 
  while(!Serial);
 
  pinMode(reedPin, INPUT_PULLUP); // Reed-Sensor an Pin 3
  attachInterrupt(digitalPinToInterrupt(reedPin), readmillis, RISING);
}

void loop() {
}

void readmillis() {
    Serial.println("Umdrehung erkannt");
}

ausgabe.jpg

Hi

Wirkt irgend etwas an dem Reed-Schalter als Kondensator, was sich erst aufladen muß?
Wenn Du den Arduino im Sekundentakt resettest (also immer, wenn Er gerade angesprungen ist) - wird JEDES Mal diese Erkennung gezeigt?
Wie gesagt, das Serial.print in der ISR ist - äh - unglücklich.
Es würde reichen, wenn Du in der loop() darauf reagierst (wird keine ms später der Fall sein).
Davon abgesehen - mit der ganzen Prellerei werden Dir die Interrupts nur so um die Ohren pfeifen - da bleibt kaum noch Zeit für die Display-Ausgabe.
Du musst Dir ja in der ISR 'merken', daß Du gerade den Reed gelesen hast.
Während Deiner Prellzeit werden wohl weitere Aufrufe ignoriert (Prellzeit auf max 25ms, sonst kommst Du nicht auf Deine 220km/h).
Ich würde Dir aber ebenfalls zu einem Hall-Sensor raten - Der prellt nicht, gibt Dir also ein sauberes 'Magnet da' oder 'Magnet nicht da' zurück - gibt's als Bi-polar mit Latch, Den kannst Du mit einer Magnetseite 'Setzen' und mit der Anderen 'Rücksetzen' - vll. zwei Magnete ans Vorderrad und mit super sauberen Halbumdrehungen rechnen.
Diese müsstest Du auch fast pollen können - 12ms bei Maximal-Geschwindigkeit für den Wechsel High-Low oder umgekehrt.

MfG

Danke für die Tips - ich lass das mal sacken.

Bzgl. Kondensator etc: Der nano zeigt dieses Verhalten auch ohne jegliche Peripherie - also nur Nano mit USB-Kabel.. .

Vermutlich hat der echt ne Macke :frowning:

Hi

Wenn Du den Sensor an einen anderen Pin packst?
Man muß ja nicht jeden defekten Pin benutzen :wink:
(oder zur Not eine Blink-LED als Heart-Beat anbrömmeln - INTERVALL.h einbinden - lässt sich hier irgendwo im Forum finden)

PCINT-fähig sind mehrere Pins, auf eine geforderte Flanke sind's glaube nur 2 und 3 - wäre hier die alternativ-Auswahl dann die 3.

Wie geschrieben, würde ich Das wohl pollen, gerade bei der Prellerei wird der µC so laufend in die ISR springen (deshalb MUSS Diese auch so kurz wie möglich sein!!).
Variablen, Die auch in der ISR verändert (oder gar auch bei Verwendung ?? Bitte Erleuchtung hierzu) werden, als VOLATILE deklarieren - sonst bekommst die loop() davon nicht viel mit.

MfG

Ich hab den Interrupt-Pin auch schon von 3 auf 2 geändert (komplett ohne jegliche angeschlossene Peripherie), aber das Verhalten ist dasselbe. Mittlerweile kann ich mir das auch nur noch durch eine HW-Macke erklären.

Mein Reed-Sensor hat laut Datenblatt eine maximale Prellzeit von 5ms - das sollte also nicht in eine endlose "Prellerei" ausarten. Nichtsdestotrotz werde ich mir die Variante mit Hall-Sensor mal anschauen (obwohl die Bauform hier vermutlich deutlich unattraktiver ist als bei einem Reedswitch).

mfg

Nachtrag : eben bin ich über diesen Beitrag gestolpert... Liest sich wie mein Problem....

http://forum.arduino.cc/index.php?topic=48757.0

Edit:
Dast ist genau dasselbe Phänomen wie bei mir. Hab den Sketch aus dem anderen thread bei mir ausprobiert... selbes Verhalten.

Edit2:
Noch ein Thread . Interrupt problem with Nano - Programming Questions - Arduino Forum

Auch hier tritt das Problem an einem UNO nicht auf, an einem Nano jedoch sehr wohl..

:o :o

Hi

Da Uno und Nano derselbe (sorry, der Gleiche) µC sind, kann Das normal nicht sein, daß sich Nano und Uno verschieden verhalten (Ausnahme A6/A7),
Trotzdem ist Es durchaus interessant, daß diese Probleme 'Hardware-spezifisch' (wobei UNO und NANO der gleiche µC ist) auftreten.

Original oder Nachbau?

MfG

postmaster-ino:
Da Uno und Nano derselbe (sorry, der Gleiche) µC sind, kann Das normal nicht sein, daß sich Nano und Uno verschieden verhalten (Ausnahme A6/A7),

Uno und Nano haben verschiedene Bootloader, oder nicht?
Der Kode läuft vor dem Start des Sketches...

(deleted)

Ja, danke für den Tip.
Aber der fix von hier attachInterrupt(...) should ignore pending interrupts (clear interrupt flag) [imported] · Issue #244 · arduino/ArduinoCore-avr · GitHub hat das Verhalten bei mir nachhaltig gelöst!

EIFR = (1 << INTF1)

Wir kann es denn sein dass dein nano nur manchmal diesen Verhalten zeigt? Ich dachte, so ein System wäre deterministisch.