Beschleunigungsmessung

Hallo, ich versuche jetzt seit einigen Tagen einen Beschleunigungsmesser hinzubekommen, also 0-100,
geschwindigkeit kommt über canbus rein, das funktioniert soweit, aber das richtige resetten bei 0km/h klappt nicht, hab im moment 3 Felder für aktuel laufende zeit ab 1km/h, die zuletz gestoppte Zeit und die bestzeit das gefahren wurde, mir geht es im moment nur darum das erste zum laufen zu bekommen,
hab mal auch ein video gemacht wie es im moment läuft

#include <FlexCAN.h>

static CAN_message_t rxmsg;
int VSS = 0;
unsigned long lastMillis = 0;
unsigned long startMillis = millis();
float lastTime = 0.00;
float startTime = 0.00;

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

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

      lastMillis = millis() - startMillis;
      lastTime = lastMillis / 1000.00;
      startMillis = millis();
      startTime = startMillis / 1000.00;

      Serial1.print("t402.txt=");
      Serial1.write(0x22);
      Serial1.print(startTime);
      Serial1.write(0x22);
      Serial1.write(0xff);
      Serial1.write(0xff);
      Serial1.write(0xff);
    }
  }
  if (VSS >= 100) {
    Serial1.print("t403.txt=");
    Serial1.write(0x22);
    Serial1.print(lastTime);
    Serial1.write(0x22);
    Serial1.write(0xff);
    Serial1.write(0xff);
    Serial1.write(0xff);
  }
}

Hallo,

was passiert denn mit deinem Code wenn VSS größer 1 wird? Eigentlich möchtest du nur in dem Moment wo VSS > 1 wird die Startzeit speichern. Dein Code überschreibt dir aber ohne Pause die Startzeit. Das bedeutet, du musst nach Startzeitnahme dieses erneute überschreiben verhindern. Dazu nimmt man boolsche Flags.

so ich das gemacht hab, zeigt er sobald VSS 1 oder größer ist die eigentliche laufzeit in ms, aber er soll eigentlich von 0 anfangen und sobald die 100er marke erreicht ist, die zeit in letzte zeit abspeichern und auch in beste zeit, die beste zeit wird aber nur gespeichert wenn eine bessere zeit gemessen wird, das soll alles im eeprom landen, aber dazu später, erstmal nur das saubere 0-100

Hallo,

dann überschreibst du solange die Startzeit wie VSS = 0 ist.

if (VSS == 0) {                              // starte Zeiterfassung
  startMillis = millis();
}

ungetestet ...

if (VSS == 0 && state_Start == false) {             // Startzeit speichern
  startMillis = millis();
}


if (VSS > 0 && state_Start == false) {              // Startzeit sperren
  state_Start = true;
}


if (VSS >= 100 && state_Start == true && state_Ende == false;) {  // Endzeit
  endMillis = millis();
  state_Ende = true;
}


if (state_Start == true && state_Ende == true) {     // Zeitenberechnung
  time = endMillis - startMillis;
  state_Start = false;
  state_Ende = false;
}

Irgendwo ist der wurm drin. jetzt startet er nur wenn 100 und darüber ist

#include <FlexCAN.h>

static CAN_message_t rxmsg;
int VSS = 0;
unsigned long startMillis = millis();
unsigned long endMillis = millis();
float time = 0.00;
boolean state_Start = false;
boolean state_Ende = false;

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

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

    if (VSS == 0 && state_Start == false) {             // Startzeit speichern
      startMillis = millis();
    }

    if (VSS > 0 && state_Start == true) {              // Startzeit sperren
      state_Start = true;
    }

    if (VSS >= 100 && state_Start == true && state_Ende == false) {  // Endzeit
      endMillis = millis();
      state_Ende = true;
    }

    if (state_Start == true && state_Ende == true) {     // Zeitenberechnung
      time = endMillis - startMillis;
      time=time/1000;

      Serial1.print("t403.txt=");
      Serial1.write(0x22);
      Serial1.print(time);
      Serial1.write(0x22);
      Serial1.write(0xff);
      Serial1.write(0xff);
      Serial1.write(0xff);

      state_Start = false;
      state_Ende = false;
    }
  }
}

Hallo,

kann ich mir nicht so ganz vorstellen. Da helfen nur Debugausgaben über die serielle.
Mehr wie eine zyklische Debugausgabe kann ich dir da nicht in die Hand geben.
Notfalls müssen noch mitten im Code Debugausgaben rein.
In der loop rufste nur die Funktion serieller_Monitor auf.

void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long last_millis = 0;

  if ( millis() - last_millis > intervall )  {    // aller x [ms] frische Daten
    last_millis = millis(); 
    Ueberschriftszeile();
    Serial.print(state_Start); Serial.print('\t');
    Serial.print(state_Ende); Serial.print('\t');
    Serial.print(VSS); Serial.print('\t');
    Serial.println();
  }  
}


void Ueberschriftszeile ()
{
  static int counter = 33;

  counter++;
  
  if (counter<25) return; // Zeit noch nicht erreicht, Funktion abbrechen
  
  counter = 0; 
  Serial.print(F("Start")); Serial.print('\t');
  Serial.print(F("Ende")); Serial.print('\t');
  Serial.print(F("VSS")); Serial.print('\t');
  Serial.println();
}

Ich bin da leider nicht so fit in sachen Arduino, hab jetzt mal den Code eingefügt und bekom im Serialmonitor nur 0 angezeigt, geschwindigkeit ist da, der rest nicht,

Hallo,

weil du beim Startzeit sperren auf true prüfst und nicht auf false?

bool 0 ... steht für false bool 1 ... steht für true

ja tatsächlich hab ich die falsche abrage drin gehabt, zeit kommt rein und wird angezeigt, aber das reseten sobald er unter 100 ist funktioniert noch nicht

#include <FlexCAN.h>

static CAN_message_t rxmsg;
int VSS = 0;
unsigned long startMillis = millis();
unsigned long endMillis = millis();
float time = 0.00;
boolean state_Start = false;
boolean state_Ende = false;

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

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

    if (VSS == 0 && state_Start == false) {             // Startzeit speichern
      startMillis = millis();
    }

    if (VSS > 0 && state_Start == false) {              // Startzeit sperren
      state_Start = true;
    }

    if (VSS >= 100 && state_Start == true && state_Ende == false) {  // Endzeit
      endMillis = millis();
      state_Ende = true;
    }

    if (state_Start == true && state_Ende == true) {     // Zeitenberechnung
      time = endMillis - startMillis;
      time = time / 1000;

      Serial1.print("t403.txt=");
      Serial1.write(0x22);
      Serial1.print(time);
      Serial1.write(0x22);
      Serial1.write(0xff);
      Serial1.write(0xff);
      Serial1.write(0xff);

      state_Start = false;
      state_Ende = false;
    }
  }
}
void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long last_millis = 0;

  if ( millis() - last_millis > intervall )  {    // aller x [ms] frische Daten
    last_millis = millis();
    Ueberschriftszeile();
    Serial.print(state_Start); Serial.print('\t');
    Serial.print(state_Ende); Serial.print('\t');
    Serial.print(VSS); Serial.print('\t');
    Serial.println();
  }
}
void Ueberschriftszeile ()
{
  static int counter = 33;

  counter++;

  if (counter < 25) return; // Zeit noch nicht erreicht, Funktion abbrechen

  counter = 0;
  Serial.print(F("Start")); Serial.print('\t');
  Serial.print(F("Ende")); Serial.print('\t');
  Serial.print(F("VSS")); Serial.print('\t');
  Serial.println();
}

wenn man jetzt unter 100 ist und wieder überschreitet dann macht er gerade die zeit weiter, hab echt kein plan mehr

Hallo,

ich kann jetzt nicht noch eine Baustelle betreuen. Leider. Lerne die Grundlagen, überlege was der Code in der Reihenfolge abarbeitet und warum er es so macht und überlege was anders gemacht werden muss. Bzw. was noch zusätzlich rein muss damit auch VSS rückwärts selbst zum Anfang findet. Zum Bsp. frage dich warum du im Monitor kein state_Ende '1' siehst, obwohl der Code von 0 bis > 100 funktioniert. Das hat hier weniger mit programmieren zu tun sondern mehr die Logik die da rein kommt. Erstelle dir einen Ablaufplan, dann kommste sicherlich selbst drauf. Dein Vorhaben ist wirklich nicht schwer.

Ok, versuch mal mein Glück, dennoch viellen dank für die Hilfestellung, hab ja noch paar Tage frei :)

Hallo,

einen Hinweis kann ich dir noch mitgeben. Du wirst sicherlich noch mehr solche sich selbst sperrenden Funktionaufruf Konstrukte benötigen.

if (VSS > 0 && state_Start == false) {              // Startzeit sperren
   state_Start = true;
}

Bevor du im boolschen Statusflag erstellen Kaos versinkst, schau dir den Datentyp enum und deren Verwendung an.

ok, Vielen dank, das werd ich mir mal anschaun

Also hab mir mal das ganze mit enum angeschaut, aber erlichgesagt fehlt mir die logic das ganze richtig einzusetzen, ist ja ein aufzählungstyp so wie ich das verstanden hab, was mir aber gerade nicht so recht in den Kop geht, wieso setzt er das ganze im letzten satz nicht wieder auf false

  if (state_Start == true && state_Ende == true) {        // Zeitenberechnung
      time = endMillis - startMillis;
      time = time / 1000;
      state_Start = false;
      state_Ende = false;

Hallo,

enum eignet sich wunderbar für eine Ablaufsteuerung, man kann mit leichter lesbarer Zustandsbenennung arbeiten statt hunderte Variablen und dessen Namen die nur true oder false kennen. Man hat eine enum Variable und beschreibt diese mit einem neuen Zustand oder fragt den Zustand ab. Würde denken das passt zu deiner Aufgabe. Es gibt aber sicherlich verschiedene Lösungen.

Deine if Abfrage wird entweder nie gültig oder sie wird immer aufs neue gültig. Die Frage ist, wie werden state_Start und state_Ende behandelt im restlichen Code.

Hallo,

wenn dich das jetzt hoffentlich nicht zu sehr verwirrt, ein Bsp. vielleicht passend für dich.

typedef enum {
  STOP, START, ENDE, CALC
} state;                    // Name vom neuen Datentyp
state Zustand = STOP;       // Variable vom Datentyp 'state' initialisiert mit Wert 'STOP'

Die neue Variable kannste nun jederzeit auf die Werte bzw. Zustände STOP, START, ENDE, CALC setzen und auf diese hin abfragen. Du kannst dir auch mal den Spass machen die Zuweisungen zu ändern und die Variable mit Serial.print dir anzeigen lassen. Dann weißt du was hinter der Kulisse abläuft.

Mit allerhöchster wahrscheinlichkeit ist das hier falsch

#include <FlexCAN.h>

static CAN_message_t rxmsg;
int VSS = 0;
unsigned long startMillis = millis();
unsigned long endMillis = millis();
float time = 0.00;

typedef enum {STOP, START, ENDE, CALC} state;                 // Name vom neuen Datentyp

void setup() {
  Serial.begin(115200);
  Serial1.begin(115200);
  Can0.begin(500000);
  state Zustand = STOP;                                         // Variable vom Datentyp 'state' initialisiert mit Wert 'STOP'
}

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

    if (VSS == 0 &&  STOP ) {                  // Startzeit speichern
      startMillis = millis();
    }

    if (VSS > 0 && STOP) {                     // Startzeit sperren
      state Zustand = START;
    }

    if (VSS >= 100 && START) {                 // Endzeit
      endMillis = millis();
      state Zustand = ENDE;
    }

    if (ENDE) {                                // Zeitenberechnung
      time = endMillis - startMillis;
      time = time / 1000;
      state Zustand = STOP;
      Serial1.print("t403.txt=");
      Serial1.write(0x22);
      Serial1.print(time);
      Serial1.write(0x22);
      Serial1.write(0xff);
      Serial1.write(0xff);
      Serial1.write(0xff);
    }
  }
}

finde leider auch kaum beispiele die für einen Anfänger verständlich erklärt wird

Hallo,

naja, Bsp. gibts sicherlich wie Sand am Meer, es wird nur fast nie die 100% Vorlage für einen existieren. Man muss immer lesen, verstehen und abändern, wenn man andere Bsp. als Vorlage verwenden möchte.

Du möchtest 2 Dinge abfragen, den Wert von VSS und den Zustand, nur fragst du den Zustand nicht ab …
Zustand ist durch enum genau so eine Variable wie VSS.

if (VSS > 0 && STOP) {

Da ich gefallen daran gefunden hatte, habe ich ein allgemeines Bsp. erstellt. Den Rest musste selbst machen.
Anschauen, testen, verstehen, ausbauen …

/*
  Doc_Arduino - german Arduino Forum
  27.03.2017
  Zeit der Beschleunigung wird gemessen
  Ereignissteuerung / Ablaufsteuerung
*/

typedef enum {
  STOP, READY, RUN, CALC, ENDE
} state;                        // Name vom neuen Datentyp
state Zustand = STOP;           // Variable vom Datentyp 'state' initialisiert mit Wert 'STOP'

const byte analogPin = A0;
unsigned int VSS = 0;

unsigned long startMillis = 0;  // nur für seriellen Monitor global
unsigned long endMillis = 0;
unsigned long Zeit = 0;

void setup() {
  Serial.begin(250000);
  
}

void loop() {
  
  VSS = analogRead(analogPin)/4;  // 0 ... 255
  
  Verarbeitung();

  serieller_Monitor();
  
}

void Verarbeitung ()
{
    //static unsigned long startMillis = 0;   // nur für seriellen Monitor global
    //static unsigned long endMillis = 0;
    //unsigned long Zeit = 0;
    
    if (VSS == 0 && Zustand == STOP) {        // Stillstand erkannt
      Zustand = READY;
      Serial.println("READY");                // Debugausgabe
    }
    
    if (VSS > 0 && Zustand == READY) {         // Start erkannt
      startMillis = millis();                  // Zeit merken
      Zustand = RUN;                           // nächster Schritt
      Serial.println("RUN");                   // Debugausgabe
    }

    if (VSS > 100 && Zustand == RUN) {         // Endmarke erkannt
      endMillis = millis();                    // Zeit merken
      Zustand = CALC;                          // nächster Schritt
      Serial.println("ENDE");                  // Debugausgabe
    }

    if (Zustand == CALC) {                     // Zeit berechnen
      Zeit = endMillis - startMillis;
      Zeit = Zeit/1000;
      Zustand = ENDE;
      Serial.println("CALC");                  // Debugausgabe
    }

    if (VSS < 1 && Zustand == ENDE) {          // zurück auf Anfang warten
      Zustand = STOP;                          // nächster Schritt
      Serial.println("STOP");                  // Debugausgabe
    }
  
}


void serieller_Monitor ()
{
  static unsigned int intervall = 500;
  static unsigned long last_millis = 0;

  if ( millis() - last_millis > intervall )  {    // aller x [ms] frische Daten
    last_millis = millis();
    Ueberschriftszeile();
    Serial.print(VSS); Serial.print('\t');
    Serial.print(startMillis); Serial.print('\t');
    Serial.print(endMillis); Serial.print('\t');
    Serial.print(Zeit); Serial.print('\t');
    Serial.print(Zustand); Serial.print('\t');
    Serial.print(millis() ); Serial.print('\t');
    Serial.println();
  } 
}


void Ueberschriftszeile ()
{
  static int counter = 33;

  counter++;
 
  if (counter<25) return; // Zeit noch nicht erreicht, Funktion abbrechen
 
  counter = 0;
  Serial.print("VSS"); Serial.print('\t');
  Serial.print("start"); Serial.print('\t');
  Serial.print("ende"); Serial.print('\t');
  Serial.print("Zeit"); Serial.print('\t');
  Serial.print("state"); Serial.print('\t');
  Serial.print("millis"); Serial.print('\t');
  Serial.println();
}

Alles klar, vielen dank und sorry das ich so auf die nerven fall