Beschleunigungsmessung

Habs wieder rausgenommen, da er eh nicht funktioniert hat, aktuel sieht der code so aus

#include <FlexCAN.h>
#include <EEPROM.h>

static CAN_message_t rxmsg;
typedef enum {
  STOP, RUN, ENDE, LIVE
} state;
state Zustand = STOP;
int VSS = 0;

unsigned long startMillis = 0;
unsigned long endMillis = 0;
float ZeitA = 0.00;


int Zeit = 0;
int eep = 0;

void setup() {
  Serial1.begin(115200);
  Can0.begin(500000);
}

void loop() {
  char  inByte = Serial1.read();
  switch (inByte) {
    case 'r':
      EEPROM.put( 0, 99990 );
      break;
  }
  display();
  Verarbeitung();
}

void Verarbeitung() {
  if (VSS > 0 && Zustand == STOP) {
    startMillis = millis();
    Zustand = RUN;
  }

  if (VSS > 100 && Zustand == RUN) {
    endMillis = millis() - startMillis;
    ZeitA =  endMillis / 1000.00;
    if (endMillis < EEPROM.get( 0, eep )) {
      EEPROM.put( 0, endMillis );
    }
    Zustand = ENDE;
  }
  if (VSS < 1 && Zustand == ENDE) {
    Zustand = STOP;
  }
}

void display() {
  if (Can0.read(rxmsg)) {
    switch (rxmsg.id) {
      case 1562:
        VSS = (int)(word(rxmsg.buf[0], rxmsg.buf[1]) / 2.76);
        break;
    }
    Serial1.print("t401.txt=");
    Serial1.write(0x22);
    Serial1.print(VSS);                                                               //Geschwindigkeit
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t402.txt=");
    Serial1.write(0x22);
//    Serial1.print(ZeitB);                                                            //Aktual Time
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t403.txt=");
    Serial1.write(0x22);
    Serial1.print(ZeitA);                                                            //Last Time
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t404.txt=");
    Serial1.write(0x22);
    Serial1.print(EEPROM.get( 0 , eep ) / 1000.00);                                   //Best Time
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);
  }
}

Hallo,

ich wollte und möchte aber schon den Teil sehen den du versucht hast, damit man eher und gezielter auf das Problem eingehen kann.

Hatte das so ursprüglich drin aber das ging nicht

if (VSS > 100 && Zustand == RUN) {
    endMillis = millis() - startMillis;
    ZeitB =  startMillis = millis() - endMillis / 1000.00;
    if (endMillis < EEPROM.get( 0, eep )) {
      EEPROM.put( 0, endMillis );
    }
    Zustand = ENDE;
  }

ich versteh nur noch nicht warum nicht der aktuelle wert ausgegeben wird, egal jetzt ob millis oder schon umgerechnet in sekunden

ausgabe hab ich dann auf Serial.print(ZeitB);

Hallo,

Okay, alles klar. Du möchtest die laufende Zwischenzeit ausgeben.
Das wäre laut deiner etwas unglücklichen Bezeichnung endmillis. Aber erstmal egal.
endmillis ist
a) deine laufende Zwischen-Zeitdifferenz
b) deine Zeitdifferenz am Ende

2 Zuweisungen in einer Zeile, habe ich noch nie probiert. :slight_smile:

Dein Problem ist, du willst ja die Zwischenzeiten haben während der RUN läuft.
Du hast im Grunde nichts geändert. Außer eine neue Variable hinzugefügt.
Das alles wird nur ausgeführt, wenn VSS größer 100 und der Zustand RUN ist.
Du möchtest jedoch die Zwischenzeiten haben wenn nur der Zustand RUN ist. Alles andere ist egal.

Du machts jetzt was?

if (VSS > 100 && Zustand == RUN) {

  endMillis = millis() - startMillis;

ZeitB = startMillis = millis() - endMillis / 1000.00; // meckert der Compiler hier nicht rum?
    if (endMillis < EEPROM.get( 0, eep )) {
      EEPROM.put( 0, endMillis );
    }
    Zustand = ENDE;
  }

Hallo,

und wegen dieser Zeile, selbst das stimmt nicht. Habe das durch 1000 mal weggelassen.

ZeitB = millis() - endMillis;

Deine aktuelle Zwischenzeit ist die Differenz von ... ?
Weist du was millis() ist?

Oh gott meine Logik,
da hab ich die falsche enum gewählt
müßte also bei if (VSS > 0 && Zustand == STOP) hier rein,
da müßte ich irgendwie das ganze so machen das er die laufende zeit abzieht, ab dem zeitpunkt wo über 1km ansteht,
ja das funktioniert in einer Zeile und gibt auch kein compilerfehler

Hallo,

überlege nochmal und lies nochmal meinen Text ...

aktuelle Zwischenzeit sollte die Zeit sein, seit Arduinostromversorgung oder reset, naja sollten millisenkunden sein, also 1000 msek = 1 sekunde

Hallo,

haste das probiert?

if (VSS > 0 && Zustand == STOP)

Warum funktioniert das wieder nicht?
Über welchen Zustand reden wie die ganze Zeit?
In welchen Zustand befindet sich das Auto bzw. der Sketch zwischen 1 und 100?
Also der Zustand der dich in dem Moment interessiert.

Im Zustand RUN, aber irgendwie will er nicht,
hab jetzt mal

if (VSS > 0 && Zustand == STOP) {
    startMillis = millis();
    ZeitB =  millis();
    Zustand = RUN;
  }

eingefügt um zu schaun was da passiert sobald 1km anliegt, un bekomm nur einmal die laufzeit in ms angezeigt, also nicht fortlaufen

Hallo,

RUN ist korrekt, nur warum fragst du den nicht ab?
Ich erlöse dich mal vom Ratespiel.

Mehr ist das nicht. Zwischenzeit wird nur ständig berechnet wenn der RUN Modus aktiv ist.
Wie schon beschrieben, deiner Variablen endmillis kommt hier eine Doppelnutzung zu ohne Komplikationen.
Kannst natürlich auch eine neue dafür nehmen, wie du magst.

void Verarbeitung() {
  if (VSS > 0 && Zustand == STOP) {
    startMillis = millis();
    Zustand = RUN;
  }

  if (Zustand == RUN) {
    endMillis = millis() - startMillis;
  }
  
  if (VSS > 100 && Zustand == RUN) {
    endMillis = millis() - startMillis;
    ZeitA =  endMillis / 1000.00;
    if (endMillis < EEPROM.get( 0, eep )) {
      EEPROM.put( 0, endMillis );
    }
    Zustand = ENDE;
  }
  
  if (VSS < 1 && Zustand == ENDE) {
    Zustand = STOP;
  }
}

achso, dachte der erkennt das so, das RUN aktive ist, oh man, denn muß man also immer abrufen wenn danach gefragt wird, jetzt aber

Hallo,

deine Variablen kennen jederzeit ihren Wert. Das stimmt. Nur wenn sie niemand fragt, welchen Wert sie gerade haben, dann behalten die das natürlich für sich. Das bedeutet weiter, das Programm kann damit nichts anfangen, keine Aktionen ausführen die sich auf den Wert irgendeiner Variable beziehen.

Bsp.
Ich kenne meinen Namen. Wenn du mich nicht danach fragst, dann weißt du zwar das ich meinen Namen kenne, aber du kennst ihn deswegen noch lange nicht.

da is was dran :slight_smile:
dann funktioniert das reseten wahrscheinlich genauso, probiers mal und melde mich ein paar tage später :confused:

solangsam wirds, das Resetten funktioniert jetzt auch, jetzt hammas doch geschaft bis zum ende
der Code resettet mir die Zeit und wird auf 0 gestellt.
Aber, jetzt hab ich mal den restliche Code eingefügt um das ganze abzurunden mit einem ADXL335 G-Kräfte Sensor, der ganze Process wird um geschätzte 200ms verlangsamt, vielleicht liegts an der Datenmenge, vielleicht ist aber was falsch programmiert, wenn Zeit hast kannst mal ein Auge drauf werfen was hier nicht stimmt.

#include <FlexCAN.h>
#include <EEPROM.h>
#include "Nextion.h"

const int xpin = A8;
const int ypin = A9;
float gForce = 0.0;
long previousMillis = 0;
long interval = 50;
NexWaveform s0 = NexWaveform(0, 5, "s0");
NexWaveform s1 = NexWaveform(0, 6, "s1");

static CAN_message_t rxmsg;

typedef enum {
  STOP, RUN, ENDE
} state;
state Zustand = STOP;
int VSS = 0;
unsigned long startMillis = 0;
unsigned long endMillis = 0;
float Zeit = 0.00;
int eep = 0;

void setup() {
  Serial1.begin(115200);
  Can0.begin(500000);
}

void loop() {
  char  inByte = Serial1.read();
  switch (inByte) {
    case 'r':
      EEPROM.put( 0, 99990 );
      break;
  }
  Verarbeitung();
  gMeter();
  display();
}

void Verarbeitung() {
  if (VSS > 0 && Zustand == STOP) {
    startMillis = millis();
    Zustand = RUN;
  }

  if (Zustand == RUN) {
    endMillis = millis() - startMillis;
    Zeit = endMillis / 1000.00;
  }

  if (VSS > 100 && Zustand == RUN) {
    endMillis = millis() - startMillis;
    if (endMillis < EEPROM.get( 0, eep )) {
      EEPROM.put( 0, endMillis );
    }
    Zustand = ENDE;
  }

  if (VSS < 1 && Zustand == ENDE) {
    Zustand = STOP;
  }

  if (VSS < 1 && Zustand == RUN && Zustand != ENDE) {
    startMillis = startMillis - startMillis;
    Zeit = 0.00;
    Zustand = STOP;
  }
}
void gMeter() {
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;

    int x = analogRead(xpin);
    int y = analogRead(ypin);

    float zeroG = 505.0;
    float scale = -105.0;

    float xAxis = (((float)x - zeroG) / scale);
    float yAxis = (((float)y - zeroG) / scale);
    gForce = max(xAxis, yAxis);

    s0.addValue(0, ((xAxis) * 40) + 80);
    s1.addValue(0, ((yAxis) * 40) + 80);
  }
}


void display() {
  if (Can0.read(rxmsg)) {
    switch (rxmsg.id) {
      case 1562:
        VSS = (int)(word(rxmsg.buf[0], rxmsg.buf[1]) / 2.76);
        break;
    }

    Serial1.print("t400.txt=");
    Serial1.write(0x22);
    Serial1.print(gForce);
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t401.txt=");
    Serial1.write(0x22);
    Serial1.print(VSS);                                                               //Geschwindigkeit
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t403.txt=");
    Serial1.write(0x22);
    Serial1.print(Zeit);                                                             //Last Time
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);

    Serial1.print("t404.txt=");
    Serial1.write(0x22);
    Serial1.print(EEPROM.get( 0 , eep ) / 1000.00);                                   //Best Time
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);
  }
}

und vielen Dank nochmal für die unterstützung

Hallo,

ohne gMeter läuft der Code gefühlt schneller? Viel bis nichts wirste daran nicht machen können. Aber 200ms werden es nicht sein, denke ich, eher weniger.

Wegen deiner Code Erweiterung. Haste das wirklich getestet vorm posten? Ergibt nämlich leider so gar keinen Sinn.
Ich hatte gedacht die Zustandssteuerung hättest du mittlerweile verstanden, also wie der Ablauf und Änderung der Zustände funktioniert. Nimm mal ein Blatt Papier und schreibe dir der Reihe nach auf, was wann den Zustand verändert wenn sich VSS ändert.
Und schau erstmal was der Sketch macht ohne deine Zeilen 65-69. Vielleicht hilft dir das auf die Sprünge.

ohne gMeter läuft er absolut sauber und flüssig, denke schon das ich die zustände und wie sie eingesetzt werden so einigermaßen verstanden hab, hab hierzu mal ein kleines video gemacht um zu sehen wie es läuft, in dem video ist gMeter aktive, da sieht man auch wie die Zahlen stottern, also nicht flüssig wie ohne gMeter, man sieht auch schön das resetten falls es zu einem fehlstart kommt, und die bestzeit im eeprom abgelegt wird

Hallo,

Danke für das Video, jetzt wird mir das klarer was du mit der Zeitanzeige machst.

Nochmal wegen deiner logischen Verknüpfung deiner if Bedingung.

if (VSS < 1 && Zustand == RUN && Zustand != ENDE) {

    [color=blue]startMillis = startMillis - startMillis[/color];

Zeit = 0.00;
   Zustand = STOP;
 }

Du möchtest einen Fehlstart erkennen. Soweit Okay.
Der Zustand befindet sich nach einem Start/Fehlstart in RUN. Soweit Okay.
Jetzt kommt das Auto wieder zum Stillstand, VSS geht in Richtung 0.
Die Bedingung wird wahr, wenn VSS kleiner 1 und Zustand gleich RUN. Soweit klar.
Wenn Zustand aber expliziet auf RUN abgefragt wird und er demzufolge dann auch RUN sein muss, heißt das, er muss zeitgleich verschieden ENDE sein. So ein überflüssiger Verknüpfungsfehler mag hier nicht auffallen, wegen dem == RUN, könnte ansonsten aber böse Folgen für den Code haben. Das mit dem startMillis darin wäre das nächste was ich nicht verstehe was das bewirken soll.

Wegen dem ADXL kann ich dir nicht weiterhelfen, weil ich den nicht habe.
Könnte auch an long statt unsigned long liegen, auch wenn sicherlich 25 Tage noch nicht vorbei sind.
Dabei kannste das alles lokal halten.

void gMeter() {
  
  unsigned long currentMillis = millis();
  static unsigned long previousMillis = 0;
  const float zeroG = 505.0;
  const float scale = -105.0;
	
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;

    int x = analogRead(xpin);
    int y = analogRead(ypin);

    float xAxis = (((float)x - zeroG) / scale);
    float yAxis = (((float)y - zeroG) / scale);
    gForce = max(xAxis, yAxis);

    s0.addValue(0, ((xAxis) * 40) + 80);
    s1.addValue(0, ((yAxis) * 40) + 80);
  }
}

und die globale Variable änderste mal dahingehend ab.

const unsigned int interval = 500;

mit 50ms Intervall und den vielen seriellen Ausgaben könnte es sein, dass die loop fast nur noch damit beschäftigt ist.

hast recht das mit startMillis = startMillis - startMillis; ist überflüssig,
die 50ms hab ich drin wegen der Kurve, die wird alle 50ms aktualisiert, mit 500ms sieht man kaum noch was an der kurve da die daten zu lansam reinkommen, ein gMeter sollte möglichst in echtzeit reinkommen, habs mal auf 500 gesetzt jetzt stottert er die daten alle 500ms