Zeit zwischen zwei steigenden Flanken messen

Hallo Leute,

ich hänge schon eine ganze weile an einem Problem und komme einfach nicht weiter...

Ich möchte die Zeit zwischen einer steigenden und der jeweils folgenden steigenden Flanke mittels Interrupt messen. Durch Polling komme ich schon auf das gewünschte Ergebnis und auch die Zeitmessung zwischen der steigenden und fallenden Flanke funktioniert mit folgendem Code ganz gut.

long dauer;
long start;
long ende;

void setup() {
  attachInterrupt(3, test, CHANGE);
  Serial.begin(9600);
}

void loop() {
  print();
}

void test() {
 attachInterrupt(3, test1, HIGH);
 start=micros();
}

void test1() {
  attachInterrupt(3, test, LOW);
  dauer=micros()-start;
}
void print() {
  Serial.println(dauer);
}

Eigentlich war meine Lösung einfach das Ergebnis der Zeit zwischen steigend und fallend sowie zwischen fallend und steigend zusammen zu zählen und fertig aber irgendwie will das nicht so recht :frowning:

Ich bitte um eure Hilfe!
Danke schon mal!

Sebi

PS. Ich verwende den Teensy 3.2, falls das irgendwie von Bedeutung ist.

Über welche Zeiten sprechen wir denn und welche Genauigkeit erwartest Du?

Die Steuerung welche ich verwende liefert mir ein Signal mit 400Hz, sprich 2500 micros müssten es sein.
Bei der Genauigkeit hoffe ich auf wenige micros Abweiung, sprich maximal +-5.

Ich möchte die Zeit zwischen einer steigenden und der jeweils folgenden steigenden Flanke mittels Interrupt messen.

Dann solltest du das auch tun, denke ich mal…

Mein ungetesteter Vorschlag lautet:

#include <util/atomic.h>
#define CriticalSection ATOMIC_BLOCK(ATOMIC_RESTORESTATE)


volatile uint32_t dauer;



void zeitMessAutomat() 
{
  static bool start         = true;
  static uint32_t startZeit = 0;
  if(start) startZeit = micros();
    else dauer = micros() - startZeit;
  start = !start;  
}


void setup() 
{
  pinMode(2,INPUT_PULLUP);
  attachInterrupt(0, zeitMessAutomat, FALLING);
  Serial.begin(9600);
  Serial.println("start");
  
}

void loop() 
{
  uint32_t tempDauer;
  CriticalSection
  {
    tempDauer = dauer; 
  }
  Serial.println(tempDauer);
  delay(1000);
}

Edit: Verbesserte Version

Schön kompakter Code, combie.

Ich staune immer über solche mir bis dato unbekannte Syntax:

if(start) startZeit = micros();

Leider kann ich mir das nicht merken bis ich’s wieder brauche und dann kommt halt wieder die Standardsyntax zum Einsatz :relaxed:

Erstmal: Danke für die Blumen!

Ich staune immer über solche mir bis dato unbekannte Syntax:

Was ist dir daran unbekannt?
Oder anders, was ist "die Standardsyntax"?

Vielleicht kann ich dir ja dabei helfen das zu behalten.....

Klaus_ww:
Schön kompakter Code, combie.

Ich staune immer über solche mir bis dato unbekannte Syntax:

if(start) startZeit = micros();

Leider kann ich mir das nicht merken bis ich's wieder brauche und dann kommt halt wieder die Standardsyntax zum Einsatz :relaxed:

Merke Dir eine der wesentlichen Grundlagen von C/C++: 0 (numerisch 0) oder NULL (Pointer) ist false, alles andere ist true.

Dann hast Du genau diese kurze Schreibweise.

Gruß Tommy

@Tommy: das ist mir schon klar

@combie: Standard ist bei mir

if (Bedingung true)
{
  // action A
}
else
{
  // action B
}

Also der Wust mit den Klammern.
Da gibt’s noch ne Variante mit ? … aber die vergess ich auch immer :angry:

Dann hatte ich Dein Posting falsch verstanden.

Die Variante mit den Klammern hat den Vorteil, dass man schnell mal was in den Zweig einfügen kann (z.B. ein Serial.print) ohne die Logik zu zerstören.

Ich war mal in einem Projekt tätig, da waren die geschweiften Klammern für die Bedingungs-/Schleifenkörper aus genau diesem Grund Pflicht.

Gruß Tommy

Es ist sicher lesbarer mit den Klammern, aber so knackig kurz - ach, mir gefällt's einfach.

byte temp=(testvar==2)?1:3;

byte temp;
if (testvar==2){
  temp=1;
}else{
  temp=3;
}

Nur, daß Du damit auch direkt in der Zeile rechnen kannst.
Wenn die Bedingung vor dem ? wahr ist, wird der Wert hinter dem ? übergeben, sonst der Wert hinter dem :
Aber: Ja, Damit kann man sich auch prima selber hinters Licht führen :wink:

MfG

Ja, der ? Operator kann ganz schnell nach hinten los gehen.
Ich benutze ihn in der Regel nur für einfache Entscheidungen, sonst verliert man leicht (besonders nach ein paar Wochen) den Überblick.

Gruß Tommy

Klaus_ww:
Also der Wust mit den Klammern.

Aha, jetzt verstehe ich, was du meinst…

Da habe ich einen anderen Betrachtungswinkel…
Ich lerne nicht das “was”, sondern lieber das “warum”.
Dann kann ich jederzeit das “was” aus dem gelernten “warum” ableiten.
:smiling_imp: So muss ich mir weniger merken :smiling_imp:
(das kommt meiner Faulheit sehr entgegen)

Und das kann ich dir mal versuchen vorzuführen…

Die allgemeine Form eines IF Statements ist:

 if(bedingung) anweisung else anweisung

Eine Anweisung kann in diesem Fall:

 startZeit = micros();

sein.

Will man mehrere Anweisungen in einem if Zweig ausführen, muss man sie in einem Block zusammenfassen.

{
  tuwas();
  tunochwas();
}

Die Grundform ist die, welche ich in dem Programm verwendet habe.
Es ist keine besondere, oder gar vereinfachte, Syntax.
(darum habe ich dein Problem auch erst nicht verstanden)

Es ist eher so, dass deine Block Variante eine erweiterte Syntax darstellt.

Das gilt übrigens nicht nur für if, sondern auch für die ganzen Schleifen
Einzig die Funktionsdefinition ist auf einen Anweisungsblock angewiesen.
Schleifen kommen auch gut ohne Block aus!

byte i = 0;
while(i++<42) tuwas(i);

Anweisungsblocks darf man überall verwenden, wo einzelne Anweisungen erlaubt sind.

Also auch hier:

if(start)
{
  tuwas();
  { // innerer Block
    byte x = 3;
    tunochwas(x);
  }
}

Die Variable x ist nur in dem inneren Block sichtbar

vielen Dank für die schnelle Hilfe, echt cool wie zügig einem Anfänger wie mir geholfen wird.

@ combie
der Code funktioniert super :slight_smile:

SeBaLeu:
vielen Dank für die schnelle Hilfe, echt cool wie zügig einem Anfänger wie mir geholfen wird.

@ combie
der Code funktioniert super :slight_smile:

Fein!
Auch dir: Danke für die Blumen!

(ich hoffe nur, dass du jetzt auch das richtige gelernt hast)