Reactiesnelheid

Hallo,

Ik ben een reactiesnelheidsmeter aan het maken, met twee voetpedalen van zo’n race-setje, een groene en een rode led en een OLED tft schermpje.

Het enige wat ik niet voor elkaar krijg is in te bouwen dat de testpersoon zijn voet niet van het gaspedaal af mag halen voordat het licht op rood springt.

Die voorwaarde (start_status == LOW) mag alleen gecontroleerd worden als het licht op groen staat.
Het leek me niet zo moeilijk, maar ik kom er niet uit. Al op verschillende plekken in de lus proberen te plaatsen, maar elke keer als het licht op rood springt en je haalt je voet van het gaspedaal, zegt ie dat je valsspeelt.

Moet ik daarvoor de code helemaal anders opzetten? Of is het heel simpel op te lossen?

Hieronder de code. Het gaat denk ik vooral om de loop().

Alvast bedankt voor het meekijken.

Gr.
Johan

/*
Reactiesnelheids test met een gas- en een rempedaal.
Gemaakt door Johan Nijsse.
Voor de NLT-Module 'Rijden onder invloed'.
*/


// You can use any (4 or) 5 pins
#define sclk 2
#define mosi 3
#define dc   4
#define cs   5
#define rst  6

// Color definitions
#define	BLACK           0x0000
#define	BLUE            0x001F
#define	RED             0xF800
#define	GREEN           0x07E0
#define CYAN            0x07FF
#define MAGENTA         0xF81F
#define YELLOW          0xFFE0
#define WHITE           0xFFFF

#include <Adafruit_GFX.h>
#include <Adafruit_SSD1351.h>
#include <SPI.h>

int s1 = 8;
int s2 = 9;

int RoodLicht = 2;
int GroenLicht = 3;

unsigned long starttijd1 = 0;
float starttijd2 = 0;
float stoptijd = 0;
float looptijd = 0;

int start_status = 0;
int last_start_status = 0;
int stop_status = 0;
int last_stop_status = 0;

int randomtime;

Adafruit_SSD1351 tft = Adafruit_SSD1351(cs, dc, rst);

void setup() {
  tft.setRotation(2);
  Serial.begin(9600);
  tft.begin();
  pinMode (s1, INPUT);
  pinMode (s2, INPUT);
  pinMode (RoodLicht, OUTPUT);
  pinMode (GroenLicht, OUTPUT);

  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.setTextSize(2);
  tft.println("Reactie");
  tft.print("snelheid");
  tft.setCursor(0, 100);
  tft.setTextSize(1);
  tft.println("       Geef gas");
  tft.print("    om te beginnen");
}

void loop() {

  start_status = digitalRead(s1);    //gaspedaal
  stop_status = digitalRead(s2);      //rempedaal
  if (start_status != last_start_status) {    //als gas ingedrukt is, gaat het groene licht aan (ook op de OLED).
    if (start_status == HIGH) {
      starttijd1 = millis();
      groenlicht();
      digitalWrite(RoodLicht, LOW);
      digitalWrite(GroenLicht, HIGH);
    }
    
    //poging om valsspelen te voorkomen. Voet moet op het gaspedaal blijven staan totdat er rood licht komt.
    else if (start_status == LOW){
      unsigned long valsspelen = millis();
      
      if ((millis() - valsspelen) > 1000){
      tft.fillScreen(BLACK);
      tft.println("Je speelt vals.");
      reset();
    }
    }
    randomtime = random(3000, 15000);
  }
  if (millis() == (starttijd1 + randomtime)) {    //na random tijd springt het op rood.
    starttijd2 = millis();
    roodlicht();
    digitalWrite(GroenLicht, LOW);
    digitalWrite (RoodLicht, HIGH);
  }
  last_start_status = start_status;

  if (stop_status != last_stop_status) {    //rempedaal wordt ingedrukt en de reactietijd gemeten. Met wat tekst op het OLED.
    if (stop_status == HIGH) {
      stoptijd = millis();
      looptijd = (stoptijd - starttijd2) / 1000, 2;
      rapport();
      reactie();
      reset();
    }
    last_stop_status = stop_status;

  }
}

void groenlicht() {
  tft.fillScreen(BLACK);
  tft.drawCircle(60, 40, 20, WHITE);
  tft.drawCircle(60, 90, 20, WHITE);
  tft.fillCircle(60, 90, 20, GREEN);
}

void roodlicht() {
  tft.drawCircle(60, 40, 20, WHITE);
  tft.fillCircle(60, 40, 20, RED);
  tft.fillCircle(60, 90, 20, BLACK);
  tft.drawCircle(60, 90, 20, WHITE);
}

void rapport() {
  tft.fillScreen(BLACK);
  tft.setCursor(0, 0);
  tft.println("   Je reactietijd is:");
  tft.println("");
  tft.setTextSize(2);
  tft.setCursor(40, 30);
  tft.println(looptijd);
  tft.setTextSize(1);
  tft.println("      seconde(n)");
}

void reactie() {
  tft.setCursor(0, 70);
  if (looptijd <= 0.10) {
    tft.println("Ongeloofelijk!");
  }
  if (looptijd > 0.10 && looptijd < 0.20) {
    tft.println("Geweldig!");
  }
  if (looptijd > 0.20 && looptijd < 0.30) {
    tft.println("        Prima!");
  }
  if (looptijd > 0.30 && looptijd < 0.40) {
    tft.println("    Dit moet beter!");
  }
  if (looptijd > 0.40 && looptijd < 0.50) {
    tft.println("   Dit is niet best!");
  }
  if (looptijd > 0.50) {
    tft.println("Eerst nuchter worden!");
  }
}


void reset() // Restarts program from beginning but does not reset the peripherals and registers
{
  delay(2000);
  asm volatile ("  jmp 0");
}

je speelt inderdaad vals, in een regel zet je de valsspelen op millis
en een regel daaronder trek je ze van elkaar af, dan hou je niet veel over.
verder zag ik een == teken en dat is beter een >= teken
zet in de loop alleen maar if statements zoals bij groen en geen gaspedaal doe valsspelen ();
bij groen en rood uit en gaspedaal doe start groentijd
bij einde groentijd zet licht op rood, zet stoptijd
bij roodlicht en stoppedaal toon resultaat, zet rood en groen uit,
dan hoef je ook geen jmp te doen, maar programma wacht dan gewoon op gaspedaal.

alles in functies, maar dat ken je.

@shooter:
Bedankt voor je reactie. Dat geeft me weer een duwtje in de goede richting.

Ik zie mijn fout met die valsspelen = millis(). Dat wordt natuurlijk iedere loop opnieuw gedaan, dus dat komt nooit boven een seconde.

Verder begrijp ik één zin niet van je:

bij groen en rood uit en gaspedaal doe start groentijd

Wat bedoel je daar precies mee?
Bedoel je als beide lampen uit staan en het gaspedaal wordt in gedrukt, dat dan de random tijd tot aan rood begint?

Groet,
Johan

ja dat bedoel ik, en de andere regels ook zo.
dan krijg je een begin van een state machine, maar dat is nog iets te snel voor je.
is een kwestie van correct aanleren, dan gaat het straks allemaal veel sneller met programmeren.