BlinkWithoutDelay

Hallo miteinander,

Ich hoffe einer von euch da draußen kann mir helfen :-)!

Funktion des Programmes: beide Leds leuchten random auf, von dort weg wird der Zähler gestartet und sobald ich gedrückt habe wird die Zeit angehalten und die Zeit dann auf dem Serial Monitor ausgegeben.

ich habe folgendes Problem: Er misst zwar die richtige Zeit, allerdings springt er immer in die if Abfrage, nach der vorgegebenen Zeitspanne (siehe Random Funktion) hinein und beginnt wieder von neu zählen. Wie kann ich nun sagen, dass er nach der vorgegebenen Zeitspanne nicht mehr in die If Abfrage reingehen soll und den Timer weiterzählen lässt?

MfG
Alm8090

int ledState = LOW;

int button1 = 53;
int button2 = 3;

int led1 = 52;
int led2 = 2;

long randomTime1;
long randomTime2;

long startTime1;
long startTime2;

long endTime1;
long endTime2;

float elapsedTime1;
float elapsedTime2;

boolean lastButton1 = LOW;
boolean lastButton2 = LOW;

boolean currentButton1 = LOW;
boolean currentButton2 = LOW;

boolean Started1 = true;
boolean Started2 = true;

boolean timer1 = true;
boolean timer2 = true;

unsigned long prevMillis1 = 0;
unsigned long prevMillis2 = 0;

boolean test = true;
boolean test2 = true;



void setup()
{
  pinMode(button1, INPUT);
  pinMode(button2, INPUT);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  Serial.begin(9600);



  //Random1();
  //Random2();
  timer1 = true;
  timer2 = true;

  

}

boolean debounce(boolean last, int pin) //Entprellen des Tasters
{
  boolean current = digitalRead(pin);
  if(last != current)
  {
    delay(5);
    current = digitalRead(pin);
  }
  return current;
}

void loop()
{
  Random2();
  Random1();
  Funktion2();
  Funktion1();
}

void Funktion1()
{

  currentButton1 = debounce(lastButton1, button1);  

  if(lastButton1 == LOW && currentButton1 == HIGH) 
  {
    Started1 = !Started1;
  }

  lastButton1 = currentButton1;

  if(Started1 == false && timer1 == true)
  {
    Stop1();
    timer1 = false;
  }
}

void Funktion2()
{
  currentButton2 = debounce(lastButton2, button2); 

  if(lastButton2 == LOW && currentButton2 == HIGH) 
  {
    Started2 = !Started2;
  }

  lastButton2 = currentButton2;

  if(Started2 == false && timer2 == true)
  {
    Stop2();
    timer2 = false;
  }
}

void Random1()
{
  unsigned long ms = millis();
  randomTime1 = random(2,8);
  randomTime1 = randomTime1*1000;

  if((ms-prevMillis2) >= randomTime1)
  {
    prevMillis2 = ms;
    if(ledState == LOW && test2)
    {
       Start1();
    }
  } 
 
}

void Random2()
{
  unsigned long ms = millis();
  randomTime2 = random(4,7);
  randomTime2 = randomTime2*1000;
  int i;

  //while(i =1)
  //{
  
  if((ms - prevMillis1) >= randomTime2)
  {
    prevMillis1 = ms;
    if(ledState == LOW && test == true)
    {
     Start2();
    }
  }
  //}
}

void Start1()
{
  startTime1 = millis();
  digitalWrite(led1, HIGH);
}


void Start2()
{
  Serial.println("Start 2");
  startTime2 = millis();
  Serial.println(startTime2);
  digitalWrite(led2, HIGH);
}

void Stop1()
{
  endTime1 = millis();
  elapsedTime1 = (endTime1-startTime1);
  elapsedTime1 = elapsedTime1/1000;
  test2 = false;
  Serial.println(elapsedTime1);
  digitalWrite(led1, LOW);
}

void Stop2()
{
  Serial.println("stop2");
  endTime2 = millis();
  elapsedTime2 = (endTime2-startTime2);
  elapsedTime2 = elapsedTime2/1000;
  test = false;
  Serial.println(elapsedTime2);
  digitalWrite(led2, LOW);
}

Hallo,

ich hab nur Bahnhof verstanden , und was hat das mit BlinkWithoutDelay zu tun ?.

Soll das Ganze eine Stopuhr werden , was machen die beiden Taster, was die LED´s. Er spring in welche If Abfrage ?

Heinz

ich hab nur Bahnhof verstanden

Ein Reaktionstest-Spiel.
2 LED, 2 Taster.
Die LED leuchten zufallsgesteuert auf. 
Die Zeit bis zum Drücken des dazugehörigen Tasters wird gemessen und angezeigt.

So ungefähr ?
Meine Verständnis-Fragen:
Soll die zweite LED auch losgehen können schon während auf die erste Reaktion gewartet wird?
Gehen die LED auch wieder aus, bevor der Taster gedrückt wird?
Was passiert bei Fehleingaben (Taste gedrückt ohne dass LED leuchtet)?

was hat das mit BlinkWithoutDelay zu tun

Es blinkt, und delay() kann man nicht wirklich brauchen :slight_smile:

Hallo,

@Michael_x ich habe es schon mehrfach geahnt , Du hast telepatische Fähigkeiten :wink:

Gruß Heinz

Nein, keine Telepathie. Meine Glaskugel ist aus Super-Gleitsichtglas.

Die Kombination aus Erfahrung und trotzdem noch was sehen im Alter bringt 's eben.

Ein Reaktionstest-Spiel.
2 LED, 2 Taster.
Die LED leuchten zufallsgesteuert auf. 
Die Zeit bis zum Drücken des dazugehörigen Tasters wird gemessen und angezeigt.

Also genau so, wie du es gerade erklärt hast soll es funktionieren.

Bei einer Fehleingabe passiert nichts, also da wird auch nichts bestätigt bzw. angezeigt!

Die LEDs sollen nicht gleichzeitig angehen (daher auch random), sind allerdings unabhängig voneinander!

Gruß

Hi

Ich blick's nicht :wink:

Ich hatte schon (in einem anderen Thread) gefragt, wofür ich hier einen entprellten Taster brauchen können soll.
BEIM ERSTEN DRUCK soll auf den Druck reagiert werden - Reaktionszeitmessung und so, oder?
Wie oft der Kram dann noch prellt, ist doch wumpe - wir reagieren doch eh nicht mehr!!

Was ich noch nicht verstanden habe: Die beiden Taster und LEDs haben NICHTS miteinander zu tun, LED1 und Button1 sind eine Einheit, wie auch LED2 und Button2.
LED1 und Button2 wie auch gekreuzt gemischt hat NICHTS miteinander zu tun?

Wie Dem auch sei: Du machst 2x exakt das Gleiche - nur mit verschiedenen Pins - für mich riecht (nein, es stinkt sogar schon) Das nach einer Funktion für LED und BUTTON.

Doppelter Code ist meist ein Zeichen dafür, daß man etwas zusammenfassen kann.

MfG

PS: Gerade das random könnte Dir öfter in die Suppe spucken - bei JEDEM Aufruf ziehst Du neue Zufallszahlen und prüfst auch mit Diesen, ob Zeiten um sind - ich sehe Da Probleme auf Dich zukommen.

postmaster-ino:
Hi

Ich blick's nicht :wink:

Ich hatte schon (in einem anderen Thread) gefragt, wofür ich hier einen entprellten Taster brauchen können soll.
BEIM ERSTEN DRUCK soll auf den Druck reagiert werden - Reaktionszeitmessung und so, oder?
Wie oft der Kram dann noch prellt, ist doch wumpe - wir reagieren doch eh nicht mehr!!

Was ich noch nicht verstanden habe: Die beiden Taster und LEDs haben NICHTS miteinander zu tun, LED1 und Button1 sind eine Einheit, wie auch LED2 und Button2.
LED1 und Button2 wie auch gekreuzt gemischt hat NICHTS miteinander zu tun?

Wie Dem auch sei: Du machst 2x exakt das Gleiche - nur mit verschiedenen Pins - für mich riecht (nein, es stinkt sogar schon) Das nach einer Funktion für LED und BUTTON.

Doppelter Code ist meist ein Zeichen dafür, daß man etwas zusammenfassen kann.

MfG

PS: Gerade das random könnte Dir öfter in die Suppe spucken - bei JEDEM Aufruf ziehst Du neue Zufallszahlen und prüfst auch mit Diesen, ob Zeiten um sind - ich sehe Da Probleme auf Dich zukommen.

Das Problem ich brauche diese Random Funktionen, ich schreibe das Programm für meine Diplomarbeit (Schule), es wird also nicht nur ein Reaktionstester, sondern in Summe insgesamt 4 Stück, nur das Problem sind halt eben wie du gesagt die Random Funktionen.

Die Vereinfachung mache ich dann, wenn das ganze Programm erstmal so funktioniert, da ichs so bis jz nur verstehe (bin nicht wirklich talentiert).

MfG

Hi

Dann ziehe doch nur neue Zufalls-Zahlen, wenn Du 'Neue' brauchst?
Z.B. beim ersten Aufruf Deiner Funktion ziehst Du Diese.
Beim 2.ten Aufruf wartest Du, bis die Zeit um ist, BEVOR die LED an geht.
... jetzt vergehen tausende Aufrufe ... wir zählen aber nur bei 'erfolgreichen' Aufrufen weiter :wink:

Beim 3.ten Aufruf schaltest Du die LED an (dieses Mal zählen wir direkt +1 - LED anschalten dauert nicht so lange he)

Beim 4.ten Aufruf prüfst Du, ob der Button betätigt ist
(Auch Das wird tausende Male erfolglos passieren)
Hier kann ggf. noch ein Time-Out integriert werden, wenn der Proband doch eher den Test nicht bestanden hat :wink:

Beim 5.ten Aufruf zeigst Du die Zeit an

Beim 6.ten Aufruf prüfst Du, ob 5 Sekunden um sind (Wartezeit, bis wieder auf Button reagiert wird)
(auch hier tausende Aufrufe, bis die 5 Sekunden um sind)

Beim 7.ten Aufruf prüfst Du, ob der Button erneut gedrückt ist

Beim 8.ten Aufruf prüfst Du, ob der Button seit einer Sekunde nicht mehr gedrückt wurde

Beim 9.ten Aufruf stellst Du die STATUS-Variable wieder auf 0 und unser Programm beginnt von Neuem.

Da wir verschiedene STATUS abklappern - jupp, Das ist eine State-Maschine.
Denke, So kann man Das machen.
Ich habe hier die LED noch nicht wieder abgeschaltet - solltest Du dann integrieren :wink:

MfG

Beim Start werden die Zufälle gezogen, dann geht (irgendwann) eine LED an, jetzt drückt der Proband den Button, die Zeit wird angezeigt (und für 5 Sekunden der Button gesperrt).
Danach wird wieder auf den Button reagiert, der Button muß erneut betätigt werden und dann für eine Sekunde unbetätigt bleiben.
Vll. hier die LED abschalten, daß in der Zeit auch was passiert ...

Ich würde hier mit einer Struktur arbeiten, z.B.

struct satz {
  const byte ledPin;
  const byte TasterPin;
  uint32_t startVerzoegerung;
  uint32_t startMillis;
  uint32_t leuchtDauer;
  uint32_t endMillis;
  bool leuchtet = false;
}

Dann ein Array draus, die Werte startVerzoegerung und leuchtDauer mit Zufallswerten füllen.
Entweder dann gleich starten oder ein Spielleiter gibt über einen weiteren Taster das Startkommando.
Nach der Verzöegerung die LED anschalten und startMillis merken und leuchtet auf true.
Nach LeuchtDauer LED aus und leuchtet auf false.

Beim Tastendruck prüfen, ob leuchtet true ist, sonst Fehler. Am Ende auswerten.

Gruß Tommy

Ich blick’s nicht

Wieso, du hast es doch richtig erkannt.
Dass debounce nicht gebraucht wird, ist richtig.
Dass der Code so wie er zur Zeit ist, noch Fehler hat und nicht nur vereinfachungsfähig ist, sollte auch klar sein.
Was für ein Problem alm8090 mit random() sieht, verstehe ich nicht. Sollte eigentlich einfach sein. Tommys struct wäre ein erster Ansatz, wenn man nicht gleich der struct Methoden hinzufügen will.

Sehe es sogar noch einfacher als Tommy:
Solange die LED nicht “quittiert” ist, bleibt sie eben an. leuchtDauer kann dann raus.
Da das Drücken auf Ausgeschaltete ignoriert werden soll, braucht man auch bool leuchtet nicht. Das kann aber für alle, die gern überall endliche Automaten sehen, die Logik vereinfachen.

PseudoCode:

if (leuchtet && Taste neu gedrückt) {
   LED aus;
   leuchtet=false;
   Reaktionszeit (= jetzt - Start ) ausgeben;
   neue Startverzögerung setzen (random), Start = jetzt ;
}
if (!leuchtet && Startverzögerung abgelaufen) {  
    LED an;
    leuchtet = true;
    Start = jetzt;
}
Taste losgelassen merken (um neu gedrückt erkennen zu können);

Das Ganze mit

            /* led,taste */
struct satz A {52, 2, 0, 0, 0, 0, 0 };
struct satz B {53, 3, 0, 0, 0, 0, 0 };

void setup() {
  A.startVerzoegerung = random (50, 5000);
  B.startVerzoegerung = random (50, 5000);
  Serial.begin(9600);
} 

void loop () {
 run (A);
 run (B);
}

aufrufen. Fertig.
Statt der vielen ... 0,0 bei der Definition könnte man auch c++ - mäßig einen Konstruktor definieren…
Evtl. vorher noch ein randomSeed an den Zeitpunkt des ersten Tasterbetätigung oder so hängen, oder absichtlich nicht, damit man ein bisschen den Ablauf trainieren kann :slight_smile:

Ich halte leuchtet für sinnvoll. Weil bevor leuchtet ist Fehler und danach auch.
Klar sollte man noch Methoden einbauen (z.B. Konstruktoren). Aber der TO will ja eine Arbeit abgeben, da sollte er auch eigene Leistungen haben.

Gruß Tommy

Richtig, Tommy.

Tommy56:
der TO will ja eine Arbeit abgeben …

… die soll er mindestens verstehen. :slight_smile:
Ich halte mich auch etwas zurück. PseudoCode und Andeutungen sind eher als Anregung gedacht.