Stoppuhr mit Lichtschranken und Ampel für Carrerabahn

Hallo, ich möchte mit und für meinen Sohn eine Stoppuhr mit Lichtschranke für unsere Carrerabahn bauen.

Wir haben die Lichtschranken ausprobiert und wir bekommen eine Test-LED zum leuchten.

Dann haben wir die DMX-Steuerung mit einem MAX485 hinbekommen. Wir würden gerne unseren LED-PAR aus dem Partykeller verwenden.

Jetzt versuchen wir alles unter einen Hut zu bekommen. Das erweist sich gerade als problematisch.

So weit sind wir bis jetzt:

#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int resetPin = 24;            // Pin für Reset

int startButtonstate;                    // variable Start - Lichtschranke Zustand
int lastStartbuttonState;                // variable Start - vorheriger Lichtschranke Zustand

// const int redOn = DmxSimple.write(1, 255);  // DMX Rot-Zustände
// const int redOff = DmxSimple.write(1, 0);

// const int greenOn = DmxSimple.write(2, 255); // DMX Grün-Zustände
// const int greenOff = DmxSimple.write(2, 0);

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (3000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (3000);
    
}

void loop() {
  lcd.clear();
  DmxSimple.write(1, 255);  
  
 startButtonstate = digitalRead(startPin); // Check ob der Button gedrückt wurde
 if (startButtonstate == LOW && lastStartbuttonState == HIGH) {  //falls ja, dann:

 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(1, 255);
 delay (1000);
 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(1, 255);
 delay (1000);
 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(1, 255);
 delay (1000);
 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(1, 255);
 delay (1000);
 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(1, 255);
 delay (1000);
 DmxSimple.write(1, 0);
 delay (500);
 DmxSimple.write(2, 255);
 delay (5000);
 DmxSimple.write(2, 0);
}
}

Wenn ich versuche mit PIN 22 an GND die Ampelsequenz auszulösen, dann passiert nichts!

Vielen dank im voraus für eure Hilfe!

hi,

das ist ein grundsätzliches verständnisproblem von delay.

bei einem delay wartet der arduino nicht auf ein ereignis ubnd tut halt sonst nix, sondern er "steht", wenn man so sagen will. er bekommt also auch nicht mit, ob ein taster gedrückt wird. er weiß auch nicht, ob der taster während des delays gedrückt wurde.

schau Dir das blinkwithoutdelay-beispiel in der IDE an.

gruß stefan

EDIT: ich sehe gerade, daß die delays erst vom setzen des pins auf low ausgelöst werden. versuche bitte, einrückungen zu machen, es wird dann auch für Dich leichter.
aber ich sehe nicht, daß lastStartbuttonState auf HIGH gesetzt wird.

Hallo,

das habe ich mal ausprobiert aber ich bekomme das mit den DMX Zuständen nicht hin!

#include <DmxSimple.h>
// const byte redLedPin = 51;
// const byte orangeLedPin = 52;
// const byte greenLedPin = 53;

int redOn = DmxSimple.write(1, 255);
int redOff = DmxSimple.write(1, 0);

int greenOn = DmxSimple.write(2, 255);
int greenOff = DmxSimple.write(2, 0);


byte flashCount = 0;
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 500;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup()
{
  Serial.begin(115200);
  
  DmxSimple.usePin(53);
  DmxSimple.maxChannel(4);

//  pinMode(redLedPin, OUTPUT);
//  pinMode(orangeLedPin, OUTPUT);
//  pinMode(greenLedPin, OUTPUT);
//  digitalWrite(redLedPin, HIGH);
//  digitalWrite(orangeLedPin, HIGH);  
//  digitalWrite(greenLedPin, HIGH);
  waitStart = millis();
}

void loop()
{
  switch (state)
  {
    case 0:  //flash red led 5 times
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        digitalWrite(redOn, !digitalRead(redLedPin));
        waitStart = currentTime;
        flashCount++;
        if (flashCount == 10)
        {
          state = 1;
          flashCount = 0;
        }
      }
      break;

    case 1:  //flash orange led 5 times
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        digitalWrite(orangeLedPin, !digitalRead(orangeLedPin));
        waitStart = currentTime;
        flashCount++;
        if (flashCount == 11)
        {
          state = 2;
          digitalWrite(orangeLedPin, HIGH);
          digitalWrite(greenLedPin, LOW);
        }
      }
      break;

    case 2:    //green LED on for 5 seconds
      currentTime = millis();
      if (currentTime - waitStart >= longPeriod)
      {
        digitalWrite(greenLedPin, HIGH);
        state = 3;  //no code for state 3 so nothing will happen in this state
      }
      break;
  }
}

ich bin zu faul, DmxSimple.h zu suchen,

glaube aber, dass die Deklaration der globalen Variablen so schonmal gar nicht gehen kann:

int redOn = DmxSimple.write(1, 255);

int redOff = DmxSimple.write(1, 0);

int greenOn = DmxSimple.write(2, 255);
int greenOff = DmxSimple.write(2, 0);

Da du es so verwendest:

digitalWrite(redOn, !digitalRead(redLedPin));

rate ich mal, das sollen Pin Nummern sein ?

Macht alles keinen Sinn.

Hast du sowas vor?

#define greenOn DmxSimple.write(2,255)

void setup(){
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);

//... 

}

int state = 0;

void loop() {
  switch (state)
  {
    case 0:  // demo only
      greenOn;
    break;
  ... 
  }
}

Das wirkt praktisch wie eine Text Ersetzung um den Code evtl. lesbarer zu machen-
Was aber m.E. eher nicht der Fall ist, wenn es hauptsächlich das Verständnis erschwert ... :frowning:

Danke!

Bin schon mal einen Schritt weiter.

Der DMX Strahler gibt jetzt Case 1 und Case 2 hintereinander aus. aber ohne zu blinken.

#include <DmxSimple.h>

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);


byte flashCount = 0;
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 500;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup()
{
  Serial.begin(115200);
  
  DmxSimple.usePin(53);
  DmxSimple.maxChannel(4);

  waitStart = millis();
}

void loop()
{
  switch (state)
  {
    case 0:  //flash red led 5 times
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        greenOn
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 10)
        {
          greenOff
          state = 1;
          flashCount = 0;
        }
      
           }
     
      break;

    case 1:  //flash orange led 5 times
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        redOn
        waitStart = currentTime;
        flashCount++;
        if (flashCount == 11)
        {
          state = 2;
      
        }
      }
      break;

    case 2:    //green LED on for 5 seconds
      currentTime = millis();
      if (currentTime - waitStart >= longPeriod)
      {
        redOn
        state = 3;  //no code for state 3 so nothing will happen in this state
      }
      break;
  }
}

Hallo,
innerhalb von "case 0" steht nur greenOn, da kann nichts Blinken. Erst nach zehn Durchläufen (5 Sekunden) kommt greenOff.

boolean stateGreen = false;
...
        if (stateGreen) {greenOff;} else {greenOn;}
        stateGreen = !stateGreen;
        waitStart = currentTime;
        flashCount++;
...

Danke agmue! Jetzt blinkt es!

Bitte gerne.

Wenn die anderen Dinge funktionieren, hätte ich noch eine Erweiterungsidee zur Anzeige.

Ich habe jetzt noch folgende Probleme:

  1. In "case 0" soll zusätzlich zum Roten Blinken, im Display "Ready" stehen. Tut es aber nicht. Wieso?
  2. Alles funktioniert nur wenn ich den Button gedrückt halte. Wie kann ich denn Zustand speichern bis zum ende des switch Durchlauf.
#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

int startButtonstate;                    // variable Start - Lichtschranke Zustand

int readyButtonstate;                    // variable Neustart - Lichtschranke Zustand

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (3000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (3000);
    
}

void loop() {
  lcd.clear();
  
 readyButtonstate = digitalRead(readyPin); // Check ob der Button gedrückt wurde
 if (readyButtonstate == LOW) {  //falls ja, dann:

switch (state)
  {
    case 0:  //flash red led 5 times
    
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
    
        flashCount++;
        
        
       if (flashCount == 10)
        {
          redOff
          state = 1;
          flashCount = 0;
        }
       }
     
      break;

    case 1:  //flash orange led 5 times
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        greenOn
        waitStart = currentTime;
        flashCount++;
        
        if (flashCount == 11)
        {
          state = 2;
      
        }
      }
      break;

    case 2:    //green LED on for 5 seconds
      currentTime = millis();
      if (currentTime - waitStart >= longPeriod)
      {
        redOn
        state = 3;  //no code for state 3 so nothing will happen in this state
      }
      break;
  }

}
}

Das erste Problem habe ich gelöst:

Jetzt steht "Ready" bei rotem Blinken und "GO" bei Dauergrün!

Ich muss aber immer noch den Button gedrückt halten!

#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

int startButtonstate;                    // variable Start - Lichtschranke Zustand

int readyButtonstate;                    // variable Neustart - Lichtschranke Zustand

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (2000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (2000);
  
  lcd.clear();
}

void loop() {
  
  
 readyButtonstate = digitalRead(readyPin); // Check ob der Button gedrückt wurde
 if (readyButtonstate == LOW) {  //falls ja, dann:

switch (state)
  {
    case 0:  //DMX Rot blinkt 5 mal
        
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 10)
        {
          redOff
          state = 1;
          flashCount = 0;
          lcd.clear();
        }
       }
     
      break;

    case 1:  //Grün bleibt 5 Sekunden an
      
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        lcd.setCursor(7, 0);
        lcd.print("GO"); 
        
        greenOn
        waitStart = currentTime;
        flashCount++;
        
        if (flashCount == 10)
        {
          state = 2;
      
        }
      }
      break;

  }

}
}

agmue:
Bitte gerne.

Wenn die anderen Dinge funktionieren, hätte ich noch eine Erweiterungsidee zur Anzeige.

Sehr gerne! :wink:

Ich würde zunächst bei Problem 1 bleiben wollen: Der Text wird ständig zum Display geschickt, was nicht sein muß. Daher:

    case 0:  // Text ausgeben
        
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        state = 1;
        break;

    case 1:  //DMX Rot blinkt 5 mal

      currentTime = millis();
...

Dasselbe für den Text "GO".

Problem 2: Dein Kommentar sagt es: "//falls ja, dann:" Nur wenn der Button gedrückt ist, soll etwas passieren. Was möchtest Du denn?

    case 0:  // Warten auf Tastendruck
      if (digitalRead(readyPin) == LOW) { // Check ob der Button gedrückt wurde
        state = 1;
      }

Sollte Dich die Umnummerierung von state stören:

enum ZUSTAENDE {WARTEN, TEXT1, ROTE_LED, TEXT2, GRUENE_LED};
byte state = WARTEN;
...
case WARTEN:
...

Was ist mein Fehler mit enum?

#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

// int startButtonstate;                    // variable Start - Lichtschranke Zustand
// int readyButtonstate;                    // variable Neustart - Lichtschranke Zustand

enum ZUSTAENDE {warten, textReady, ampelRot, textGo, ampelGruen};
byte state = warten;
/*byte state = textReady;
byte state = ampelRot;
byte state = textGo;
byte state = ampelGruen;
*/

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (2000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (2000);
  
  lcd.clear();
}

void loop() {
  
  
 //readyButtonstate = digitalRead(readyPin); // Check ob der Button gedrückt wurde
 //if (readyButtonstate == LOW) {  //falls ja, dann:

switch (state)
  {
   case warten:  // Warten auf Tastendruck
      if (digitalRead(readyPin) == LOW) { // Check ob der Button gedrückt wurde
        state = textReady;
      }
    
    case textReady: // Ready auf Display ausgeben
        
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        state = ampelRot;
        break;
    
    case ampelRot: // DMX Rot blinkt 5 mal
    
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 10)
        {
          redOff
          state = textGo;
          flashCount = 0;
          lcd.clear();
        }
       }
     
      break;
    
    case textGo: // "GO" auf Display ausgeben
    
        lcd.setCursor(7, 0);
        lcd.print("GO"); 
        state = ampelGruen;
        break;
        
    case ampelGruen:  //Grün bleibt 5 Sekunden an
      
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        greenOn
        waitStart = currentTime;
        flashCount++;
        
        if (flashCount == 10)
        {
          state = 4;
          lcd.clear();
          greenOff
        }
      }
      break;

  }

}
}

Am Ende von "case warten:" fehlt "break"

So ist jetzt die ganze Ampel mit Ausgabe auf dem Display perfekt!

#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

enum State {warten, textReady, ampelRot, textGo, ampelGruen};

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (2000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (2000);
  
  lcd.clear();
}

void loop() {

switch (state)
  {
   case warten:  // Warten auf Tastendruck
      if (digitalRead(readyPin) == LOW) { // Check ob der Button gedrückt wurde
        state = textReady;
        }
        break;
    
    case textReady: // Ready auf Display ausgeben
        
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        redOn
        state = ampelRot;
        break;
    
    case ampelRot: // DMX Rot blinkt 5 mal
    
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 11)
        {
          redOff
          state = textGo;
          flashCount = 0;
          lcd.clear();
        }
       }
     
      break;
    
    case textGo: // "GO" auf Display ausgeben
    
        lcd.setCursor(7, 0);
        lcd.print("GO"); 
        greenOn
        state = ampelGruen;
        break;
        
    case ampelGruen:  //Grün bleibt 5 Sekunden an
      
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        greenOn
        waitStart = currentTime;
        flashCount++;
        
        if (flashCount == 10)
        {
          state = warten;
          flashCount = 0;
          lcd.clear();
          greenOff
        }
      }
      break;

  }

}

Vielen Dank "agmue"!

Ich habe jetzt in den letzten teil des Switch eine Stoppuhr eingefügt. Diese läuft aber aber nur einmal durch! Wie kann ich veranlassen, das solange Zeit genommen wird bis wieder an der Lichtschranke ein impuls ausgelöst wird?

[

#include <Wire.h>
#include <DmxSimple.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

enum State {warten, textReady, ampelRot, textGo, ampelGruen, rennen, zeitNehmen, ende};

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

int frameRate = 1000;               // the frame rate (frames per second) at which the stopwatch runs
long startTime ;                    // start time for stop watch
long elapsedTime ;                  // elapsed time for stop watch
long interval = 1000;

int fractional;                     // variable used to store fractional part of Frames
int fractionalSecs;                 // variable used to store fractional part of Seconds
int fractionalMins;                 // variable used to store fractional part of Minutes

int elapsedFrames;                  // elapsed frames for stop watch
int elapsedSeconds;                 // elapsed seconds for stop watch
int elapsedMinutes;                 // elapsed Minutes for stop watch

char buf[12];                       // string buffer for itoa function

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (2000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (2000);
  
  lcd.clear();
}

void loop() {

switch (state)
  {
   case warten:  // Warten auf Tastendruck
      lcd.clear(); 
     
      if (digitalRead(readyPin) == LOW) { // Check ob der Button gedrückt wurde
        state = textReady;
        }
        break;
    
    case textReady: // Ready auf Display ausgeben
        
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        redOn
        state = ampelRot;
        break;
    
    case ampelRot: // DMX Rot blinkt 5 mal
    
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 11)
        {
          redOff
          state = textGo;
          flashCount = 0;
          lcd.clear();
        }
       }
     
      break;
    
    case textGo: // "GO" auf Display ausgeben
    
        lcd.setCursor(7, 0);
        lcd.print("GO"); 
        greenOn
        state = rennen;
        break;
        
    case rennen:  // Warten auf Lichtschranke
      if (digitalRead(startPin) == LOW) { // Check ob der Button gedrückt wurde
        state = zeitNehmen;
        }
        break;    
  
    case zeitNehmen: // Stoppuhr ist ausgelöst
    
    lcd.clear();                                         // clear LCD
    lcd.setCursor(0, 1);

    elapsedTime =   millis() - startTime;                // store elapsed time

    elapsedMinutes = (elapsedTime / 60000L);
    elapsedSeconds = (elapsedTime / 1000L);              // divide by 1000 to convert to seconds - then cast to an int to print
    elapsedFrames = (elapsedTime / interval);            // divide by 100 to convert to 1/100 of a second - then cast to an int to print

    fractional = (int)(elapsedFrames % frameRate);       // use modulo operator to get fractional part of 100 Seconds
    fractionalSecs = (int)(elapsedSeconds % 60L);        // use modulo operator to get fractional part of 60 Seconds
    fractionalMins = (int)(elapsedMinutes % 60L);        // use modulo operator to get fractional part of 60 Minutes

    lcd.clear();                                         // clear the LDC
    lcd.setCursor(0, 1);
    lcd.print("Zeit:");

    if (fractionalMins < 10) {                           // pad in leading zeros
      lcd.print("0");                                 // add a zero
    }

    lcd.print(itoa(fractionalMins, buf, 10));       // convert the int to a string and print a fractional part of 60 Minutes to the LCD
    lcd.print(":");                                 //print a colan.

    if (fractionalSecs < 10) {                           // pad in leading zeros
      lcd.print("0");                                 // add a zero
    }

    lcd.print(itoa(fractionalSecs, buf, 10));          // convert the int to a string and print a fractional part of 60 Seconds to the LCD
    lcd.print(":");                                    //print a colan.

    if (fractional < 10) {                               // pad in leading zeros
      lcd.print("0");                                 // add a zero
    }

    lcd.print(itoa(fractional, buf, 10));              // convert the int to a string and print a fractional part of 25 Frames to the LCD
  
      state = warten;
      break;

  }

}

Ich vermute, diese Zeile hat noch keine Berücksichtigung gefunden:

const int stopPin = 23; // Pin für Stop - Lichtschranke

Es soll erstmal nur eine Lichtschranke verwendet werden für Start und Stop. Beim ersten durchfahren, soll die Messung los gehen und bei der zweiten Durchfahrt soll die Zeit stehen bleiben und ausgegeben werden.

Möglicherweise so:

      if (digitalRead(startPin) == LOW) { // Check ob Lichtschranke durchfahren
        state = warten;
        }
        break;

Wobei es besser die Abfrage der Flanke HIGH->LOW sein müßte.

Ich sehe gerade, startTime wird nirgendwo gesetzt.

Ich habe der Einfachheit halber die Stopwatch classe eingebunden. Funktioniert auch soweit. Nur läuft das ganze nur einmal durch und dann ist ende. Ich hätte aber gerne eine Stuppuhr die solange läuft bis wieder die Lichtschranke durchfahren wird.

Kann man das mit "while" lösen?

Vielen Dank!

Im Moment, sieht das Ganze so aus:

#include <Wire.h>
#include <DmxSimple.h>
#include <StopWatch.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE);

const int startPin = 22;            // Pin für Start - Lichtschranke
const int stopPin = 23;            // Pin für Stop - Lichtschranke
const int readyPin = 24;            // Pin für Neustart

enum State {warten, textReady, ampelRot, textGo, ampelGruen, rennen, zeitNehmen, zeit, ende};

#define redOn DmxSimple.write(1, 255);  // DMX Rot-Zustände
#define redOff DmxSimple.write(1, 0);
boolean stateRed = false;

#define greenOn DmxSimple.write(2,255); // DMX Grün-Zustände
#define greenOff DmxSimple.write(2, 0);
boolean stateGreen = false;

byte flashCount = 0;                    // DMX Ampelsequenzen
byte state = 0;
unsigned long waitStart;
unsigned long shortPeriod = 1000;
unsigned long longPeriod = 5000;
unsigned long currentTime;

StopWatch sw_millis;    // MILLIS (default)
StopWatch sw_micros(StopWatch::MICROS);
StopWatch sw_secs(StopWatch::SECONDS);

void setup() {
  
  DmxSimple.usePin(53);            // DMX Setup
  DmxSimple.maxChannel(4);
  
  waitStart = millis();            // DMX Ampel Zähler
  
  sw_millis.start();
    sw_micros.start();
    sw_secs.start();
  
  lcd.begin(16, 2);                 // LCD Setup

  pinMode(startPin, INPUT);         // Startpin Setup
  digitalWrite(startPin, HIGH);     

  pinMode(readyPin, INPUT);         // Neustartpin Setup
  digitalWrite(readyPin, HIGH);     
  
  lcd.setCursor(0, 0);              // LCD Begrüßung
  lcd.print("Rallycrono");


  delay (2000);

  lcd.clear();

  lcd.setCursor(0, 0);
  lcd.print("Gib Gummi!");
  lcd.setCursor(0, 1);
  lcd.print("Viel Spass");
  
  delay (2000);
  
  lcd.clear();
}

void loop() {

switch (state)
  {
   case warten:  // Warten auf Tastendruck
      greenOff
      
      lcd.setCursor(0, 0);
      lcd.print("Wir koennen!");
      
      if (digitalRead(readyPin) == LOW) { // Check ob der Button gedrückt wurde
        lcd.clear();
        state = textReady;
        }
         break;
    
    case textReady: // Ready auf Display ausgeben
        lcd.clear();
        lcd.setCursor(5, 0);
        lcd.print("Ready"); 
        redOn
        state = ampelRot;
        break;
    
    case ampelRot: // DMX Rot blinkt 5 mal
    
      currentTime = millis();
      if (currentTime - waitStart >= shortPeriod)
      {
        if (stateRed) {redOff;} else {redOn;}
        stateRed = !stateRed;
        waitStart = currentTime;
        flashCount++;
        
        
       if (flashCount == 11)
        {
          redOff
          state = textGo;
          flashCount = 0;
          lcd.clear();
        }
       }
     
      break;
    
    case textGo: // "GO" auf Display ausgeben
    
        lcd.setCursor(7, 0);
        lcd.print("GO"); 
        greenOn
        state = rennen;
        break;
        
    case rennen:  // Warten auf Lichtschranke
      if (digitalRead(startPin) == LOW) { // Check ob der Button gedrückt wurde
        state = zeitNehmen;
        }
        break;    
  
    case zeitNehmen: // Stoppuhr ist ausgelöst
    
    lcd.clear();
    lcd.print("s=");
    lcd.print(sw_secs.elapsed());
    lcd.print(" ms=");
    lcd.print(sw_millis.elapsed());
    lcd.setCursor(0, 1);
    lcd.print("us=");
    lcd.print(sw_micros.elapsed());

    
  // case zeit // Zeit wird auf Display ausgegeben 
  
      state = warten;
      break;

  }

}