Hilfe bei Radarfalle für Modellbahn

Habe es nochmal leicht geändert, jedoch Zählt das Display jetzt direkt von 99 runter auf 0 und die BlitzLed ist dauerhaft an, die Sensoren L+R machen gar nichts mehr.

Hier der ganze Sketch:

#include <SevSeg.h>
SevSeg sevseg; //Ein sieben Segment Objekt initialisieren

// Digital sensor input Left and Right
const byte SENSOR_L = 4;
const byte SENSOR_R = 5;
const byte blitzLed = A1;


//Distance from sensor Left to sensor Right - your distance (mm)
const double distance = 150.0; 

//Your model scale 1/xx
const unsigned int scale = 87;

//Waiting time for train, to move out of measurement array (ms)
const unsigned int waitingtime = 12000;

//Name of variables for time and speed measuring
unsigned long int deltatime, starttime;


void setup()  
{

  byte numDigits = 2; //Hier wird die Anzahl der Ziffern angegeben
  byte digitPins[] = {2, 3}; //Die Pins zu den Ziffern werden festgelegt
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12}; //Die Pins zu den //Segmenten werden festgelegt
  sevseg.begin(COMMON_ANODE, numDigits, digitPins, segmentPins);
  
  //Sensor Input
  pinMode(SENSOR_L, INPUT_PULLUP); 
  pinMode(SENSOR_R, INPUT_PULLUP);
  pinMode(A1,OUTPUT);
 
 

  //Interface baud rate
  Serial.begin(9600);

 
}

void loop()  {
  if (digitalRead(SENSOR_R)== LOW);{
    starttime = millis();
    starttime = true;
  }
    //waiting for signal sensor Left
  if (starttime = true && digitalRead(SENSOR_L)== HIGH);{
    deltatime = (millis() - starttime);
    sevseg.setNumber(scale*distance/deltatime*3.6, 0);
    deltatime = true;
             }
    sevseg.refreshDisplay();
    sevseg.setBrightness(90);
 {
    if (scale*distance/deltatime*3.6<50){
    digitalWrite(blitzLed, HIGH);
    delay(29);
    digitalWrite(blitzLed, LOW);

  }
   else {  
   digitalWrite(blitzLed,LOW);
  }
    }   
} //End of loop

Der Ablauf sollte ja eigentlich wie folgt sein:

Sensor R wartet auf Signal
if (digitalRead(SENSOR_R)== LOW);{

Dann wird die Startzeit angestoßen.
starttime = millis();

Anschließend wartet Sensor L auf das Signal
if (starttime = true && digitalRead(SENSOR_L)== HIGH);{

Danach wird die deltazeit genommen .
deltatime = (millis() - starttime);
Diese wird dann berechnetet:
sevseg.setNumber(scaledistance/deltatime3.6, 0);
und auf dem Display ausgegeben.

Diese Rechnung wird dann ergänzt ob der Wert größer 50 ist.
if (scaledistance/deltatime3.6<50){
Wenn ja, dann soll die Blitzled kurz angehen.
digitalWrite(blitzLed, HIGH);
delay(29);
digitalWrite(blitzLed, LOW);
Wenn nein, dann ausbleiben
else {
digitalWrite(blitzLed,LOW);
}

Teile doch deinen Sketch in Funktionen auf. Eine für das Messen der Zeit und eine für deine Anzeige.
Dadurch wird dein Sketch übersichtlicher und du findest deine Fehler leichter.

Du solltest aber nicht für eine Startzeit in Millisekunden und für ein Starttime-Flag dieselbe Variable verwenden:

starttime = millis();
starttime = true;

Damit sitzt starttime auf 1, nicht aber auf dem aktuellen millis().

Hier fehlt - wenn das Flag gemeint ist - dann noch ein Gleichheitszeichen:

if (starttime = true &&...  // falsch!
if (starttime == true &&... // wäre besser!
if (starttime &&... // ginge auch

Hallo,

ich hab keine Anzeige, deshalb hab ich das jetzt mal weggelassen. Die Skalierung für für Deine Messstrecke muss Du noch ändern.

mein Vorschlag basierend auf dem Ablauf von #16, es geht noch einfacher, aber so kannst Du das eventuell nachvollziehen.

Heinz

const byte SENSOR_R = 2;
const byte SENSOR_L = 3;
const byte Led = 13;

int distance = 1; //meter
float scale = 1.0;
bool messenstart; // Satus variable 
bool messenende;
unsigned long startzeit, deltatime;
float geschw;

void setup() {
  Serial.begin(115200);
  pinMode(SENSOR_R, INPUT_PULLUP);
  pinMode(SENSOR_L, INPUT_PULLUP);
  pinMode(Led, OUTPUT);
}

void loop()  {
  // start Flanke erkennen
  if (digitalRead(SENSOR_R) == LOW && !messenstart) {
    startzeit = millis();
    messenstart = true;
    Serial.println("messen start");
  }
// ende erkennen
  if (digitalRead(SENSOR_L) == LOW && messenstart) {
    messenende = true;
    Serial.println("messen ende");
  }
// auswerten
  if (messenstart & messenende) {
    messenende = false;
    messenstart = false;  
    deltatime = (millis() - startzeit);
    geschw = scale *3600* distance/deltatime;
    
    Serial.print("Messzeit ms "); Serial.println(deltatime);
    Serial.print("Speed Km/h "); Serial.println(geschw,4);
    //sevseg.setNumber(speed);
    //sevseg.refreshDisplay();
    //sevseg.setBrightness(90);

    if (geschw > 10) {
      digitalWrite(Led, HIGH);
      delay (100);
      digitalWrite(Led, LOW);
    }
  }

}

madze90:
Titel habe ich mal angepasst.

Dann bin ich dabei :slight_smile:

Daher habe auch ich ein Programm als Anregung erstellt, leider ebenfalls ohne Siebensegmentanzeige, da ich keine habe. Ich möchte eine Schrittkette einbringen, wobei sich meine jetzt auf nur zwei Schritte reduziert hat. Dafür habe ich Funktionen für das Blitzen und die Anzeige.

Vermutlich kann man meinen Vorschlag noch besser machen, aber es soll ja auch nur eine Anregung sein.

const byte SENSOR_L = 4; // Pin-Nummer Lichtschranke_L
const byte SENSOR_R = 5; // Pin-Nummer Lichtschranke_R
const byte BLITZER = A1; // Pin-Nummer Blitzer

const uint16_t distance = 150; // welche Einheit?
const uint16_t scale = 87; //Your model scale 1/xx
const byte maxspeed = 50;
const uint32_t flashintervall = 30;
const uint32_t blinkintervall = 200;

void setup()
{
  Serial.begin(9600); // Interface baud rate
  Serial.println("\nStart");
  pinMode(SENSOR_L, INPUT_PULLUP); //Lichtschranke_L
  pinMode(SENSOR_R, INPUT_PULLUP); //Lichtschranke_R
  pinMode(BLITZER, OUTPUT); // LED-Blitzer
}

enum class Schritte {WAIT_R, WAIT_L};

void loop()  {
  static uint16_t speed;
  static uint32_t starttime;
  static Schritte schritt = Schritte::WAIT_R;
  switch (schritt) {
    case Schritte::WAIT_R:
      if (digitalRead(SENSOR_R) == LOW) {
        starttime = millis(); //Sensor Right was activated, start time = system time (ms)
        schritt = Schritte::WAIT_L;
      }
      break;
    case Schritte::WAIT_L:
      if (digitalRead(SENSOR_L) == LOW) {
        speed = scale * distance / (millis() - starttime) * 3.6;
        if (speed > maxspeed) {
          flash(true);
        }
        speed_display(speed, true);
        schritt = Schritte::WAIT_R;
      }
      break;
  }
  flash(false);
  speed_display(speed, false);
}

void flash(bool ein) {
  static uint32_t vorhin = 0;
  if (ein) {
    digitalWrite(BLITZER, HIGH);
    vorhin = millis();
  } else {
    if (millis() - vorhin >= flashintervall) {
      digitalWrite(BLITZER, LOW);
    }
  }
}

void speed_display(uint16_t v, bool ein) {
  static uint32_t vorhin = 0;
  static bool EINaus = true;
  if (ein) {
    EINaus = true;
    anzeige(v, true);
  } else {
    if (v > maxspeed) {
      if (millis() - vorhin >= blinkintervall) {
        vorhin = millis();
        anzeige(v, EINaus);
        EINaus = !EINaus;
      }
    }
  }
}

void anzeige(uint16_t v, bool einaus) {
  if (einaus) {
    Serial.print("Speed: ");
    Serial.print(v);
    Serial.println(" km/h");
  } else {
    Serial.println("----");
  }
}

madze90:
Diese Rechnung wird dann ergänzt ob der Wert größer 50 ist.
if (scaledistance/deltatime3.6<50){
Wenn ja, dann soll die Blitzled kurz angehen.
digitalWrite(blitzLed, HIGH);

Ich fühl mich verarscht.
In dieser Reihenfolge: #10 #15 #18

agmue:
Dann bin ich dabei :slight_smile:

Daher habe auch ich ein Programm als Anregung erstellt, leider ebenfalls ohne Siebensegmentanzeige, da ich keine habe. Ich möchte eine Schrittkette einbringen, wobei sich meine jetzt auf nur zwei Schritte reduziert hat. Dafür habe ich Funktionen für das Blitzen und die Anzeige.

Vermutlich kann man meinen Vorschlag noch besser machen, aber es soll ja auch nur eine Anregung sein.

Vielen Dank
habe es mal gerade eingespielt und es sieht erstmal sehr gut aus, bekomme nur leider die 7Segmentanzeige noch nicht mit ans laufen, sprich die Sevseg., jedoch bleibt bei mir jetzt die LED immer an.
ab Sie blitzt bei entsprechender Geschwindigkeit. =)
@ALL
Schonmal vielen Dank an alle die sich hier die Mühe machen um mir zu Helfen, echt Top :slight_smile:

my_xy_projekt:
Ich fühl mich verarscht.
In dieser Reihenfolge: #10 #15 #18

Ich möchte hier keinen Verarschen, leider verstehe ich das mit der Reihenfolge nicht.

madze90:
Ich möchte hier keinen Verarschen,

Doch das machst Du.

leider verstehe ich das mit der Reihenfolge nicht.

Du hast schlichtweg gelogen.
in #18:

@my-xy_Projekt
Ja habe ich gelesen und eingefügt.

Aber hast ja genügend Leute gefunden die Dir Deinen Code geschrieben haben. Nu hast blos das Problem, das Du probieren musst, damit Dein Display geht.

Ich würde einen Merker nehmen der von mir aus "blitzer" heißt. Der hat die "0". Also "byte blitzer = 0;".
Für den gibt es im Verlauf deß Programmes drei Zustände. 0 / 1 / 2

An einer Stelle hast du eine Lichtschranke, an der das Auto erst mal durch kommt. Da gibst du dem Merker "blitzer" die "1".

Wenn das Programm an die Stelle kommt, wo du die "Blitzerled" einschaltest weil der Merker "blitzer == 1", dann schaltest du die LED ein, startest die Zeit für die LED Leuchtzeit, und gibst dem Merker "blitzer = 2".

Dann gibt es eine Stelle im Programm, an der geschaut wird, ob die Leuchtzeit der LED abgelaufen ist. Das wird hier nur getestet wenn der Merker "blitzer ==2".

Ist an dieser Stelle der blitzer == 2 && zeit ist abgelaufen, dann schalte ich die LED aus und setze den Merker "blitzer = 0". Somit ist die LED aus, der Blitzer ist deaktiviert (weil "blitzer ==0"), alles gut.

Wenn dann wieder ein Auto durch die Lichtschranke fährt, geht der Merker "blitzer" wieder auf die "1" und das Spiel geht von vorne los. So ist jede Phase sicher nur einmal im Ablauf.

Wenn du delay´s im Programm hast, dann vergesse alles was ich geschrieben habe, denn dann funktioniert das nicht. Dabei wird der LOOP ja x-mal durchlaufen, bis der Merker von 0 bis auf 2 geht und wieder zurück auf 0.

madze90:
... bekomme nur leider die 7Segmentanzeige noch nicht mit ans laufen, ...

Um Dir helfen zu können, mußt Du uns Deinen Versuch zeigen. Ich kann und will nicht in Deinen PC schauen ;D

Weil Dein Display mit einer Matrix arbeitet, muß sevseg.refreshDisplay(); ständig aufgerufen werden, wenn eine Zahl dargestellt werden soll.

Ich habe hier noch eine Anzeige mit MAX7219 runliegen, da funktioniert auch die Geschwindigkeitsanzeige, die oberhalb 50 km/h blinkt:

#include <U8g2lib.h>
U8G2_MAX7219_32X8_F_4W_SW_SPI u8g2(U8G2_R0, /* clock=*/ 13, /* data=*/ 11, /* cs=*/ 10, /* dc=*/ U8X8_PIN_NONE, /* reset=*/ U8X8_PIN_NONE);

const byte SENSOR_L = 4; // Pin-Nummer Lichtschranke_L
const byte SENSOR_R = 5; // Pin-Nummer Lichtschranke_R
const byte BLITZER = A1; // Pin-Nummer Blitzer

const uint16_t distance = 150; // welche Einheit?
const uint16_t scale = 87; //Your model scale 1/xx
const byte maxspeed = 50;
const uint32_t flashintervall = 30;
const uint32_t blinkintervall = 200;

void setup()
{
  Serial.begin(9600); // Interface baud rate
  Serial.println("\nStart");
  pinMode(SENSOR_L, INPUT_PULLUP); //Lichtschranke_L
  pinMode(SENSOR_R, INPUT_PULLUP); //Lichtschranke_R
  pinMode(BLITZER, OUTPUT); // LED-Blitzer

  u8g2.begin();
  u8g2.setContrast(25);
  u8g2.setFont(u8g2_font_t0_11_tn); // choose a suitable font
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setCursor(2, 8);
  u8g2.print("--");
  u8g2.sendBuffer();          // transfer internal memory to the display
}

enum class Schritte {WAIT_R, WAIT_L};

void loop()  {
  static uint16_t speed;
  static uint32_t starttime;
  static Schritte schritt = Schritte::WAIT_R;
  switch (schritt) {
    case Schritte::WAIT_R:
      if (digitalRead(SENSOR_R) == LOW) {
        starttime = millis(); //Sensor Right was activated, start time = system time (ms)
        schritt = Schritte::WAIT_L;
      }
      break;
    case Schritte::WAIT_L:
      if (digitalRead(SENSOR_L) == LOW) {
        speed = scale * distance / (millis() - starttime) * 3.6;
        if (speed > maxspeed) {
          flash(true);
        }
        speed_display(speed, true);
        schritt = Schritte::WAIT_R;
      }
      break;
  }
  flash(false);
  speed_display(speed, false);
}

void flash(bool ein) {
  static uint32_t vorhin = 0;
  if (ein) {
    digitalWrite(BLITZER, HIGH);
    vorhin = millis();
  } else {
    if (millis() - vorhin >= flashintervall) {
      digitalWrite(BLITZER, LOW);
    }
  }
}

void speed_display(uint16_t v, bool ein) {
  static uint32_t vorhin = 0;
  static bool EINaus = true;
  if (ein) {
    EINaus = true;
    anzeige(v, true);
  } else {
    if (v > maxspeed) {
      if (millis() - vorhin >= blinkintervall) {
        vorhin = millis();
        anzeige(v, EINaus);
        EINaus = !EINaus;
      }
    }
  }
}

void anzeige(uint16_t v, bool einaus) {
  u8g2.clearBuffer();          // clear the internal memory
  u8g2.setCursor(2, 8);
  if (einaus) {
    Serial.print("Speed: ");
    Serial.print(v);
    Serial.println(" km/h");
    u8g2.print(v);
  } else {
    Serial.println("----");
    u8g2.print("  ");
  }
  u8g2.sendBuffer();          // transfer internal memory to the display
}

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.