Probleme beim Code eines Reaktionstester

Hey,
Ich code einen Reaktionstester, jedoch habe ich Probleme damit.
Das erste Problem wäre, dass entweder der Lautsprecher einen Ton abgibt oder die LED blinkt. Dies soll zufällig laufen.
Das zweite Problem wäre die Zeitmessung. Ich möchte die Zeit messen ab dem Zeitpunkt, ab dem ein blinken oder ein Ton wiedergegeben werden. Daraufhin soll der Spieler den Schalter betätigen. Der Kontext:
"Der Reaktionstester misst die Zeit wie schnell man bei entweder blinken der LED oder einem bestimmten Ton aus dem Lautsprecher reagiert. Reagiert wird indem der Knopf gedrückt wird. Sobald der Knopf gedrückt wurde wird die Zeit gemessen und auf dem Display angezeigt. "

Ich habe es versucht umzusetzen. Jedoch hat es nicht geklappt. Woraufhin ich hier gelandet bin. Ich hoffe ihr könnt mir weiterhelfen.
Der Code:
Lg
Mikail

> long randNumber; //settings
>  #include <Wire.h>
>  #include <LiquidCrystal_I2C.h>
>  LiquidCrystal_I2C Lcd(0x27,16,2);
>  unsigned long myTime1;
>  unsigned long myTime2;
>  const int LED_PIN = 6; 
>  const int TASTER_PIN = 3;
>  int PIEZO_PIN = 5; 
>  int a = 5;
>  int b = 2;
>  int c = 1;
> void setup() {//setup
>   Lcd.backlight();
>   pinMode(LED_PIN, OUTPUT);
>   pinMode(TASTER_PIN, INPUT_PULLUP);
>   Serial.begin(9600);
>   Lcd.init();
>   randomSeed(analogRead(A0));
>   Lcd.print("NWT Projekt Game");
>   delay(200);
>   Serial.println("Void setup finish");
>  }
> void loop() { //loop
>   Lcd.clear();
>   Serial.println("Void loop start");  
>   int tasterValue = digitalRead(TASTER_PIN);
>   randNumber = random (1,7);
> 
> Lcd.print("START"); //rolling display
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   delay(50);
>   Lcd.scrollDisplayRight();
>   Lcd.clear();
>   Lcd.setCursor(0,0);
>   delay(50);
>   Lcd.clear();
>   Lcd.setCursor(11,4);
>   Lcd.print("START");
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.scrollDisplayLeft();
>   delay(50);
>   Lcd.setCursor(0,0);
>   Lcd.clear();
>   Serial.println("Zeile 82");
>   Lcd.print("Press Button");
>   delay(350);
>   Lcd.clear();
> 
> if (randNumber == b)  { //if clause LED
>   pinMode(LED_PIN, HIGH);
>   myTime1 = millis();
>   Serial.println("if clause 1 starting LED");
>   }
>   else {
>   pinMode(LED_PIN,LOW);
>   }
> if (randNumber == a)  { //if clause PIEZO
>   myTime1=millis();
>   tone(PIEZO_PIN,523);
>   Serial.println("if clause 2 starting Piezo");
>   }
> else { //else clause for 1&2
>   delay(50);
>   noTone(PIEZO_PIN);
> 
>  }
> if (tasterValue == 1) { //if clause for c
>  c=c+1;
>  myTime2=millis();
> 
>  } 
> 
> while (c==1) { //while clause for Display
>   Serial.println(c);
>   Lcd.println("Reaktionszeit: ");
>   delay(1000);
>   Lcd.clear();
>   Lcd.println(myTime1-myTime2);
>   Lcd.print("s");
>   Serial.println("Zeit: ");
>   Serial.print(myTime1);
>   Serial.print("s");
>   Serial.print("-");
>   Serial.print(myTime2);
>   Serial.print("=");
>   Serial.print(myTime2-myTime1);
>   Serial.print("s");
>   delay(1000); 
>   c=c-1; 
>  }
>  }

Und ich tippe mal drauf, dass die zahlreichen Delays dein Vorhaben stört.
Die solltes du besser entfernen und mit der Funktion millis() arbeiten, genau nach dem Beispiel "BlinkWithoutDelay".

Las den ganzen Quatsch weg, den Du da als Spielerchen drin hast und mach erstmal die Grundfunktion.
Und teile das in Funktionen auf.
Dann findest Du evtl, selber was.

Ich bin mit dem rumscrollen nicht warm geworden.

Wie nutzt ich den Befehl am besten? bzw. wo genau?

> long randNumber; //settings
>  #include <Wire.h>
>  #include <LiquidCrystal_I2C.h>
>  LiquidCrystal_I2C Lcd(0x27,16,2);
>  unsigned long myTime1;
>  unsigned long myTime2;
>  const int LED_PIN = 6; 
>  const int TASTER_PIN = 3;
>  int PIEZO_PIN = 5; 
>  int a = 5;
>  int b = 2;
>  int c = 1;
> void setup() {//setup
>   Lcd.backlight();
>   pinMode(LED_PIN, OUTPUT);
>   pinMode(TASTER_PIN, INPUT_PULLUP);
>   Serial.begin(9600);
>   Lcd.init();
>   randomSeed(analogRead(A0));
>   Lcd.print("NWT Projekt Game");
>   delay(200);
>   Serial.println("Void setup finish");
>  }
> void loop() { //loop
>   Lcd.clear();
>   Serial.println("Void loop start");  
>   int tasterValue = digitalRead(TASTER_PIN);
>   randNumber = random (1,7);
> 
> 
> 
> if (randNumber == b)  { //if clause LED
>   pinMode(LED_PIN, HIGH);
>   myTime1 = millis();
>   Serial.println("if clause 1 starting LED");
>   }
>   else {
>   pinMode(LED_PIN,LOW);
>   }
> if (randNumber == a)  { //if clause PIEZO
>   myTime1=millis();
>   tone(PIEZO_PIN,523);
>   Serial.println("if clause 2 starting Piezo");
>   }
> else { //else clause for 1&2
>   delay(50);
>   noTone(PIEZO_PIN);
> 
>  }
> if (tasterValue == 1) { //if clause for c
>  c=c+1;
>  myTime2=millis();
> 
>  } 
> 
> while (c==1) { //while clause for Display
>   Serial.println(c);
>   Lcd.println("Reaktionszeit: ");
>   delay(1000);
>   Lcd.clear();
>   Lcd.println(myTime1-myTime2);
>   Lcd.print("s");
>   Serial.println("Zeit: ");
>   Serial.print(myTime1);
>   Serial.print("s");
>   Serial.print("-");
>   Serial.print(myTime2);
>   Serial.print("=");
>   Serial.print(myTime2-myTime1);
>   Serial.print("s");
>   delay(1000); 
>   c=c-1; 
>  }
>  }

Hier bitte. Ohne die Details bzw. verschönerungen.
Die Serialen angaben hab ich hinzugefügt um den Fehler usw. zu finden

Den schicke ich im laufe des Tages hier rein...

Moin,
Bitte beim nächsten Mal das </> Symbol und nicht das Blockzitat, dann kan man den Code auch übernehmen.

ALSO:

Du willst da einen PIN beschreiben, aktivierst aber den internen PULLUP...

Dann werde ich aus Deinem Ablauf nicht schlau.
Eigentlich ist ein Reaktionstester doch ein einfacher Ablauf.
Starten, irgendwann kommt ein Auslöser, auf den muss reagiert werden, dann wird die Zeit ausgegeben, und alles von vorn.
Eine typische Schrittkette oder auch als Suchbegriff Statemachine.

Dafür gibt es das eine odere fertige Stück Code auch mit der Suchfunktion...

Hä, hab ich doch im Setup?

Und was macht das im loop()?

Ups...xd

So ich habe Problem 2 gelöst aber Problem 1 nicht.
Das hier :"Das erste Problem wäre, dass entweder der Lautsprecher einen Ton abgibt oder die LED blinkt. Dies soll zufällig laufen."
Joa ich hab das mal so versucht, aber jedoch blinken und geben einen Ton wieder und dies zusammen. Mein Ziel: das nicht beide Sachen (Ton/blinken) auf einmal erfüllt werden(zufällig) Ich hoffe es ist jetzt verständlich @my_xy_projekt

long randNumber; //settings
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C Lcd(0x27,16,2);
unsigned long myTime1;
unsigned long myTime2;
const int LED_PIN = 6;
const int TASTER_PIN = 3;
int PIEZO_PIN = 5;
void setup() {//setup
Lcd.backlight();
pinMode(LED_PIN, OUTPUT);
pinMode(TASTER_PIN, INPUT_PULLUP);
Serial.begin(9600);
Lcd.init();
Lcd.print("NWT Projekt Game");
delay(200);
}
void loop() { //loop
int zahl = random(0,2);
int tasterValue = digitalRead(TASTER_PIN);
while (tasterValue == 1) {
tasterValue = digitalRead(TASTER_PIN);
}
Lcd.clear();
Lcd.print("START"); //rolling display
for (int i = 0; i < 10; i++) {
Lcd.scrollDisplayRight();
delay(50);
}
Lcd.scrollDisplayRight();
Lcd.clear();
Lcd.setCursor(0,0);
delay(50);
Lcd.clear();
Lcd.setCursor(11,4);
Lcd.print("START");
for (int i = 0; i < 12; i++) {
Lcd.scrollDisplayLeft();
delay(50);
}
Lcd.setCursor(0,0);
Lcd.clear();
Lcd.print("Press Button");
delay(350);
Lcd.clear();
tasterValue = digitalRead(TASTER_PIN);
if (tasterValue == 0) { //if statement LED&PIEZO
if (zahl == 1) {
digitalWrite(LED_PIN, HIGH);
Serial.println("if clause 1 starting LED");
}
else {
tone(PIEZO_PIN,523);
}
myTime1 = millis();
while (tasterValue == 0) {
tasterValue = digitalRead(TASTER_PIN);
}
myTime2 = millis();

digitalWrite(LED_PIN, LOW);
Lcd.println("Reaktionszeit: ");
delay(1000);
Lcd.clear();
Lcd.println(myTime2-myTime1);
delay(1000);
Lcd.print("ms");
}
else {
Lcd.print("Nicht schummeln!");
delay(1000);
}
}

Das dazugehörige if(...) {
ist wo ?

Moins,
aehm.. mir ist schon klar, was Du willst, ich versteh nur noch nicht, wie Du das realisieren willst.

Also: Du hast einen Taster.
Mit dem willst Du den Test starten und gleichzeitig beenden.

Wie willst Du verhindern, das einfach doppelt auf den Taster gedrückt wird?
Also muss nach dem Start eine zufällige Zeit vergehen, bis die LED anfängt zu blinken - wobei mit dem aufleuchten begonnen werden sollte, damit nicht die AUS-Zeit schon mitzählt -, bzw. der piezo anfängt zu tröten.
Dann muss auf den Taster reagiert werden.

Die zufällige Auswahl, ob LED oder Piezo, ist dabei das geringste Übel.
Ist ein Zweizeiler.
Und @michael_x hats geschrieben... Codetags!

Dafür hab ich mir das ja mit dem nicht schummeln ausgedacht

Wenn dar taster vor dem Signal(Blinken/Ton) gedrückt wird zeigt es nicht schummeln an. War jetzt meine Idee.

Okay danke für den tipp. Dann würd ich ne neue Variable festlegen die zufällig variiert und das vor dem Ton/LED packen in einer Delay.

Der^. Da ich werd mich gleich an den rechner setzen und alles taggen

Na dann werd ich mal zusehen, ob ich das gebaut kriege.

Da erleichtere ich dich mal :smiley:

hab eine Simulation in der das schon läuft

Nicht wirklich.
Da ich da nicht ran komme, nutzt mir das nix.
Aber ich stell mal was zur Diskussion.

#include <Wire.h>
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C Lcd(0x27, 16, 2);
unsigned long startZeit, stopZeit;
const byte LED_PIN = 6;
const byte TASTER_PIN = 3;
const byte PIEZO_PIN = 5;


void setup()  //setup
{
  Lcd.backlight();
  pinMode(LED_PIN, OUTPUT);
  pinMode(TASTER_PIN, INPUT_PULLUP);
  Serial.begin(9600);
  Serial.println(F("Start..:"));
  //  Lcd.init();
  Lcd.print("NWT Projekt Game");
  delay(200);
  while (!digitalRead(TASTER_PIN))
  {
    Serial.println(F("Loslassen!"));
  }
}
//
void loop()
{
  findReaktion();
}

void findReaktion()
{
  enum {start, warten, ausgeloest, reaktion,  auswertung};
  byte zustand = start;
  switch (zustand)
  {
    case start:
      /*
           Lcd.clear();
           Lcd.print(F("START")); //rolling display
           for (int i = 0; i < 10; i++)
           {
             Lcd.scrollDisplayRight();
             delay(50);
           }
           Lcd.clear();
           Lcd.print(F("Press Button"));
      */
      digitalWrite(LED_PIN, LOW);
      noTone(PIEZO_PIN);
      Serial.println(F("Bitte Taste zum Start drücken!"));
      break;
    case warten:
      if (!digitalRead(TASTER_PIN))                                  // Taste gedrückt
      {
        Serial.println(F("Taste wieder loslassen!"));
        startZeit = millis();
      }
      if (digitalRead(TASTER_PIN))                                   // losgelassen und
      {
        if (millis() - startZeit > 60)                               // prellzeit um
        {
          zustand = ausgeloest;
          stopZeit = random(1000, 5000);
          startZeit = millis();
        }
      }
      else if (millis() - startZeit > 1000)                          // nicht losgelassen??
      {
        Serial.println(F("Nicht schummeln!"));
        startZeit = millis();                                        // Wartezeit neu starten
      }
      break;
    case ausgeloest:
      if (!digitalRead(TASTER_PIN))                                  // Vorzeitig Taste gedrückt?
      {
        zustand = warten;
      }
      else if (millis() - startZeit > stopZeit)                           // random Wartezeit abgelaufen
      {
        byte zahl = random(0, 2);                                    // random auslöser ...
        zahl ? digitalWrite(LED_PIN, HIGH) : tone(PIEZO_PIN, 523);   // auswählen
        startZeit = millis();                                        // auslösezeit merken
        zustand = reaktion;
      }
      break;
    case reaktion:
      if (!digitalRead(TASTER_PIN))                                  // Auf taste reagieren
      {
        stopZeit = millis();                                         // Zeit merken
        noTone(PIEZO_PIN);                                           // alles aus
        digitalWrite(LED_PIN, LOW);
        zustand = auswertung;
      }
      break;
    case auswertung:
      Serial.print(F("Reaktionszeit: "));
      Serial.print(stopZeit - startZeit);
      Serial.println(F(" Millisekunden"));
      delay(2000);
      Serial.println(F("Neustart!"));
      zustand = start;
      break;
  }
}

Fürs LCD musst dann noch einarbeiten.
Das LED las ich noch nicht blinken, die geht nur an.
Aber füs komplette neuschreiben war ich dann doch zu faul.

hmm okay viele neue begriffe xd
Ja alles gut ich zwing dich zu nix xD

Drei?
Na dann happy learning.

1 Like