Wie Überlauf abfangen oder sinnvoll behandeln

Hallo,

ich berechne an Hand zweier millis() Zeiten die Fahrgeschwindigkeit eines Modelleisenbahnzuges. Diese 2 Zeiten T1A und T2B sind unsigned long.

Mit dem Code kann ich aus beiden Richtungen die Geschwindigkeit ermitteln. Aber was mache ich wenn es einen millis Überlauf gibt? Dann stimmt in dem einen Fall nichts mehr. Ist zwar etwas theoretisch, weil die Modellbahn wohl nie 49 Tage am Stück laufen wird, aber fragen möchte ich dennoch nach einer Lösung.

Mir fiele jetzt nur ein auf eine von beiden Richtungsmessung verzichten zu müssen.

if (status_T2 == true && status_T1 == true)  {

    if (T2A > T1B)  {
      Speed_12 = 169344/(T2A-T1B);   // 392[mm]*36*12/x[ms] = km/h real
    }
    else  { 
      Speed_12 = 169344/(T1B-T2A);   // 392[mm]*36*12/x[ms] = km/h real
    }

    status_T2 = false;
    status_T1 = false;
}

Hmm…

T2A > T1B
Der Vergleich ist unglücklich, da du damit nicht Fahrtrichtung und Überlauf unterscheiden kannst.

Mein Vorschlag:
Erst die Differenz bilden.
Wenn diese “negativ” ist, fährt der Zug rückwärts
Und Überläufe können dich nicht erschüttern.

Hallo,

die Fahrtrichtungserkennung ermittel ich extra mit 2 Sensoren. Das ist absolut sicher.

Mit der Geschwindigkeitsmessung wird abhängig von der Lok dessen aktuelle km/h ermittelt und dann auf Soll-km/h (Vmax) errechnet und beschleunigt. Nur wenn die Messung nicht stimmt, kommt ungeahnter Müll raus.

Du meinst ich muß die millis in unsigned long speichern und wenn negativ, dann die Messung verwerfen. Dann würde der Zug bis zum nächsten Bahnhof langsam mit seiner Grundgeschwindigkeit weiterfahren.

Bei dem Dir möglicherweise ( :wink: ) bekannten BlinkWithoutDelay wird millis()-altMillis>=intervall gerechnet. Davon ausgehend habe ich diesen Sketch entworfen, der anstelle unsigned long das ebenfalls vorzeichenlose byte verwendet:

byte T1, T2;
byte u, v;
void setup() {
  Serial.begin(9600);
  Serial.println("Anfang");
  T1 = 240;
  T2 = 250;
  aus();
  Serial.println();
  T1 = 250;
  T2 = 240;
  aus();
}

void loop() {
}

void aus() {
  for (byte j = 0; j < 20; j++) {
    T1++;
    T2++;
    u = T1 - T2;
    v = T2 - T1;
    Serial.print("j=");
    Serial.print(j);
    Serial.print("\tT1=");
    Serial.print(T1);
    Serial.print("\tT2=");
    Serial.print(T2);
    Serial.print("\tu=");
    Serial.print(u);
    Serial.print("\tv=");
    Serial.print(v);
    if (u < v) {
      Serial.print("\t\tErgebnis: ");
      Serial.print(u);
    } else {
      Serial.print("\t\tErgebnis: ");
      Serial.print(v);
    }
    Serial.println();
  }
}

Damit die Bahn sicher und pünktlich ankommt!

Hallo,

möglicherweise und vielleicht kenne ich das ;) und dachte es wäre hier in der bekannten Form nicht anwendbar.

Tue mich aktuell etwas schwer mit dem Code. Du suchst dir am Ende immer den kleineren Wert raus von beiden Ergebnissen? Ist das nicht gefährlich? In dem Fall klappt das, du weist das der kleinerer der Richtige ist. Was wäre wenn die Sensoren auf großen Abstand sitzen? Ich habe mehrere Sensoren verbaut und könnte eigentlich jederzeit mit zwei x beliebigen davon eine Messung machen.

Oder klappt das hier immer, weil die erwartete Differenz im Verhältnis zum Endwert von unsigned long immer deutlich kleiner bleibt?

Eine Richtungsauswertung unabhängig der Zeitnahmen steht auch noch zur Verfügung.

[u]Edit:[/u] ich habe es erstmal übernommen, funktioniert ja, und baue mal wieder größere Teile komplett um ... Danke erstmal für die Idee. :)

Schau dir agmue's Beispiel genauer an ;)

Da unsigned long viel zu groß sind, um den Überblick zu behalten, demonstriert er es mit unsigned byte (0 .. 255)

von 240 bis 250 sind es natürlich 10 Schritte von 250 bis 4 sind es nochmal 10 Schritte, da braucht man keine if - Abfragen o.ä. von 4 bis 240 sind es natürlich 236 Schritte, was aber das gleiche wie -20 Schritte zurück wäre.

Die Zahl 236 und die Zahl -20 sind übrigens gleich. Das gleiche Bitmuster, die gleiche Berechnung ((byte)240 neu - (byte)4 alt) . Je nachdem ob du das Ergebnis als unsigned byte (236) oder als signed char (-20) interpretierst.

In deinem Fall: Wenn du Richtungsinfo zusätzlich hast, kannst du für das Intervall unsigned long annehmen, im anderen Fall kann das Ergebnis als signed interpretiert werden und enthält also auch eine Richtungsinformation, bei nur max. halber Größe.

Hallo,

hiermit erhalte ich +236 und +20

byte T1, T2;
byte u, v;

T1 = 240;
T2 = 4;

u = T1 - T2;
v = T2 - T1;

mach u und v zu int erhalte ich +236 und -236

achso, die -236 und +20 sind binär das Gleiche.

Ich glaube so langsam dämmerts wieder. Lange nicht benötigt und als gegeben hingenommen.

Danke für die schöne Erklärung und Hilfe, Euch beiden. :)

Doc_Arduino: Was wäre wenn die Sensoren auf großen Abstand sitzen?

Wenn die Sensoren so weit auseinander liegen, daß die Lok mehr als 24 Tage von einem zum anderen braucht, müßte man nochmal neu nachdenken.

Zusammen mit einer Richtungsinformation ginge möglicherweise auch:

Wenn an Sensor2 Richtung weg von Sensor1, dann Zeit2-Zeit1. Wenn an Sensor1 Richtung weg von Sensor2, dann Zeit1-Zeit2.

Probier mal, ob das auch beim Übergang nach 49 Tagen funktioniert.

Hallo,

im großen Projekt zur Zeit wegen Umbauarbeiten nicht einpflegbar, aber mit kleinen Testcode funktioniert das.

zwar etwas sinnloser Code, aber man sieht was gemacht werden soll, funktioniert ebenfalls.

byte T1, T2;
byte u, v;
bool direction = false;

void setup() {
  Serial.begin(9600);

  T1 = 240;
  T2 = 4;

  if (direction == false)  {
  u = T1 - T2;
  
  Serial.print("T1=");   Serial.print(T1);
  Serial.print("\tT2="); Serial.print(T2);
  Serial.print("\tu=");  Serial.print(u);
  Serial.println();
  }

  direction = true;
  T1 += 10;
  T2 += 260;

  if (direction == true)  {
  v = T2 - T1;
  Serial.print("T1=");   Serial.print(T1);
  Serial.print("\tT2="); Serial.print(T2);
  Serial.print("\tv=");  Serial.print(v);
  }      
}

void loop() {
}

Ergebnis:

T1=240  T2=4    u=236
T1=250  T2=8    v=14

Vielen Dank. Manchmal benötige ich eine Auffrischung. :)