Programmierfehler Zeit zwischen Interrupts

Ich habe einen kleinen Sketch geschrieben, der mir die Zeit zwischen 2 Interrupts liefern soll. Leider funktioniert dies nicht, da die Werte für Time und Timealt immer gleich sind und damit die Differenz = 0 ist. Damit die Loop nicht unterbrochen wird, habe ich versuchsweise die NoInterrupt-Funktion eingesetzt in die ISR mit Aufhebung am Ende der Loop, leider auch ohne Änderung.

<

unsigned long Time = 0;
unsigned long Timealt = 0;
int Intervallzeit;

unsigned long Aktuellmillis;
const unsigned long periode = 100;


void setup() {
  
  Serial.begin(115200);                                          //Serielleverbindung aufbauen
  attachInterrupt(digitalPinToInterrupt(4), Intervall, RISING);  //Interrupt Event 

}

void Intervall() {
  
  Time = millis();      //Bei Interrupt Zeitspeichern in ms-Wert
  noInterrupts();
}

void loop() {
  Aktuellmillis = millis();
  Intervallzeit = Time - Timealt;
  Intervallzeit = Intervallzeit * 100;
  if (Intervallzeit < 2500) {   
    Serial.print ("Aktuellmillis = ");
    Serial.println(Aktuellmillis);
    Serial.print ("Time = ");
    Serial.println (Time);
    Serial.print ("Timealt = ");
    Serial.println (Timealt);
    Serial.print ("Intervallzeit = ");
    Serial.println(Intervallzeit);       
  }   
  Timealt =  Time;
  interrupts();
}

Hier ist ein Auszug aus dem Seriellen Monitor bei einem Wechsel der Werte:

12:41:27.587 -> Aktuellmillis = 566161

12:41:27.587 -> Time = 389922

12:41:27.587 -> Timealt = 389922

12:41:27.587 -> Intervallzeit = 0

12:41:27.587 -> Aktuellmillis = 566167

12:41:27.587 -> Time = 566164

12:41:27.587 -> Timealt = 566164

12:41:27.587 -> Intervallzeit = 0

Ich habe ein dünnes Brett vor dem Kopf, kann aber nicht mal das bohren. Kann mir jemand dabei helfen?

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Ich habe den deutschen Teil des Forums geöffnet und dort ein neues Topic geschrieben. Anscheinend wird das neue Topic automatisch dann im englischen Forum platziert. Mir ist das schon öfter passiert. Wie kann ich das ändern?

Variablen, die Du in der Interruptroutine änderst, müssen volatile sein und sollten atomar ausgelesen (umkopiert) werden.

Gruß Tommy

Neben dem Hinweis von Tommy musst Du auch berücksichtigen, das loop() das ist, was der Name sagt: eine Schleife. Das heißt nach der Ausführung der letzten Anweisung geht es gleich wieder von vorne los. D.h. was ganz am Ende von loop() steht, könnte auch ganz am Anfang stehen, das macht kaum einen Unterschied. Und wenn Du unter dem Gesichtspunkt deinen Sketch nochmal anschaust, siehst Du, dass dein

praktisch unmittelbar vor dem

steht. Ist also kein Wunder, dass da praktisch immer 0 rauskommt ( Es sei denn, der Interrupt konmt zufällig genau zwischen den beiden Anweisungen ).

Du must das Timealt auch in der ISR setzen, unmittelbar bevor Du Time neu setzt.

Eine Anregung, getsetet mit UNO:

volatile unsigned long Time = 0;
unsigned long Timealt = 0;
int Intervallzeit;
bool neu = false;
unsigned long Aktuellmillis;
const unsigned long periode = 100;

void setup() {
  Serial.begin(115200);                                          //Serielleverbindung aufbauen
  Serial.println("\nStart ...");
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), Intervall, RISING);  //Interrupt Event
}

void Intervall() {
  Time = millis();      //Bei Interrupt Zeitspeichern in ms-Wert
  neu = true;
}

void loop() {
  if (neu)
  {
    neu = false;
    Aktuellmillis = millis();
    Intervallzeit = Time - Timealt;
    Serial.print("Aktuellmillis = ");
    Serial.print(Aktuellmillis);
    Serial.print("\tTime = ");
    Serial.print(Time);
    Serial.print("\tTimealt = ");
    Serial.print(Timealt);
    Serial.print("\tIntervallzeit = ");
    Serial.println(Intervallzeit);
    Timealt =  Time;
  }
}

Was dir auch öfter passiert, ist das vergessen, Ross und Reiter zu benennen.

In einer ISR die Interrupts abschalten?
Welchen Sinn das wohl haben mag.....
Wieviel Takte das erwünschte Verhalten wohl durchhält?

Agmue

Vielen Dank, funktioniert einwandfrei. Wenn ich das richtig verstanden habe, wird die If-Anweisung nur durchgeführt, wenn neu = true ist. Liege ich da richtig?

Tipp:
Wenn man sich ein C++ Buch anschafft, oder etwas im Internet sucht,......, wie if funktioniert.

Ich halte es für existentiell wichtig die Grundlagen auf dem Schirm zu haben.
z.B. das Verhalten von if!

Ja.

Combie

Deine Einwände verstehe ich wirklich nicht. Den Grund für die Abschaltung der Interrupts hab ich doch beschrieben. Ansonsten sind Deine Kommentare wie immer sehr nützlich,

MikroBahner

auch für Deinen Tip vielen Dank. Funktioniert auch prima.
Nochmal vielen Dank für tatsächliche Unterstützungen.

MikroBahner

wie oben beschrieben: "Dünnes Brett". Man kommt manchmal nicht auf die einfachsten Sachen (wieder Steilvorlage für Combie)

Und ich habe dir versucht zu sagen, wie Sinnfrei die Operation doch ist.
(die Wirkungslosigkeit, du wohl erkannt hast)

Ich erwarte wirklich, dass man if verstanden hat, wenn man programmieren möchte.


Zudem glaube ich nicht, dass loop() eine Schleife ist.
Meines bescheinen Wissens nach, ist das nur eine relativ gewöhnliche Funktion, welche in einer Schleife aufgerufen wird.

Man vergleiche, mit dem Stall und dem Pferd.
Wenn man ein Pferd in einem Stall stellt, dann wird der Stall vielleicht zu einem Pferdestall, oder das Pferd zu einem Stallpferd, aber nicht das Pferd zu einem Stall oder umgekehrt.

Klare Gedanken!
(dazu ist zu raten)

Nicht lange genug getestet, um die Fehler zu sehen.

Du verwendest eine volatile Variable, die größer als ein byte ist, außerhalb der ISR,
ohne dafür die Interrupts auszuschalten.

Du meinst, um einer Variablenspaltung vorzubeugen, könnte man sie atomar behandeln?

#include <util/atomic.h>
volatile unsigned long Time = 0;
unsigned long Zeit = 0;
unsigned long Timealt = 0;
int Intervallzeit;
bool neu = false;
unsigned long Aktuellmillis;
const unsigned long periode = 100;

void setup() {
  Serial.begin(115200);                                          //Serielleverbindung aufbauen
  Serial.println("\nStart ...");
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(digitalPinToInterrupt(2), Intervall, RISING);  //Interrupt Event
}

void Intervall() {
  Time = millis();      //Bei Interrupt Zeitspeichern in ms-Wert
  neu = true;
}

void loop() {
  if (neu)
  {
    ATOMIC_BLOCK(ATOMIC_RESTORESTATE)
    {
      Zeit = Time;
      neu = false;
    }
    Aktuellmillis = millis();
    Intervallzeit = Zeit - Timealt;
    Serial.print("Aktuellmillis = ");
    Serial.print(Aktuellmillis);
    Serial.print("\tZeit = ");
    Serial.print(Zeit);
    Serial.print("\tTimealt = ");
    Serial.print(Timealt);
    Serial.print("\tIntervallzeit = ");
    Serial.println(Intervallzeit);
    Timealt =  Zeit;
  }
}

Das musst du genauso bei den anderen Lesezugriffen machen.

Wegen Zeit = Time; doch eigentlich nicht, oder?

Kann sein, dass mich die Namen verwirrt haben, da hast du recht.

Könnt Ihr mir mitteilen, wie ich die library atomic.h downloaden kann?