Comportamiento errático en Arduino

Hola a todos!

Hace tiempo empece con un nuevo proyecto, un Drag racing Tree, su función es mostrar la “reacción” que tarda una persona en soltar un botón al ver aparecer la luz verde, existen ya algunos contadores de marca, pero como todo en el hobby de las carreras es carisimo, así que me motivo a realizarlo, de hecho ya esta montado en un enclosure de acrílico y la presentación quedo muy bien, solo que al paso del tiempo usandolo para ver si tenia errores, pues si, les comento.

Al prenderlo todo va bien, al presionar el botón, aparece en la pantalla el mensaje correspondiente al tiempo, el problema es que al soltar el botón AVECES, no siempre se va al caso de “FAIL” (ya lo verán en el código) cuando la reacción es menor a 500ms, inclusive pasa que cuando la reacción es mayor a los 500ms y debe irse a “green light” no lo hace, se va a “FAIL”, el problema persiste aun cambiando de placa (ya probé en UNO, MEGA, DUE, NANO, MINI).

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

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

const int button = 2;

double reaction = 0;
unsigned long time = 0;

const int stage = 9;
const int prestage = 8;
const int amber1 = 7;
const int amber2 = 6;
const int amber3 = 5;
const int green = 4;
const int red = 3;
const int stagel = 10;
const int prestagel = 11;
const int amber1l = 12;
const int amber2l = 13;
const int amber3l = 14;
const int greenl = 15;
const int redl = 16;
const int blue = 17;
int buzz = 1;

int toneVal;

void Start();

void setup()
{
  randomSeed(analogRead(analogRead(0)));
  lcd.begin(16, 2);
  pinMode(button, INPUT);
  pinMode(stage, OUTPUT);
  pinMode(prestage, OUTPUT);
  pinMode(amber1, OUTPUT);
  pinMode(amber2, OUTPUT);
  pinMode(amber3, OUTPUT);
  pinMode(green, OUTPUT);
  pinMode(red, OUTPUT);
  pinMode(stagel, OUTPUT);
  pinMode(prestagel, OUTPUT);
  pinMode(amber1l, OUTPUT);
  pinMode(amber2l, OUTPUT);
  pinMode(amber3l, OUTPUT);
  pinMode(greenl, OUTPUT);
  pinMode(redl, OUTPUT);
  pinMode(blue, OUTPUT);
}

void loop() 
{
  lcd.setCursor(1, 0);
  if(digitalRead(button)==LOW)
  {
    lcd.print(" BracketTree    ");
    digitalWrite(stage, HIGH);
    digitalWrite(prestage, HIGH);
    digitalWrite(amber1, HIGH);
    digitalWrite(amber2, HIGH);
    digitalWrite(amber3, HIGH);
    digitalWrite(green, HIGH);
    digitalWrite(red, HIGH);
    digitalWrite(stagel, HIGH);
    digitalWrite(prestagel, HIGH);
    digitalWrite(amber1l, HIGH);
    digitalWrite(amber2l, HIGH);
    digitalWrite(amber3l, HIGH);
    digitalWrite(greenl, HIGH);
    digitalWrite(redl, HIGH);
    digitalWrite(blue, HIGH);
  }
  
  lcd.setCursor(0, 1);
  
  if(digitalRead(button)== HIGH)
    {
   
      delay(random(500,1000));
      digitalWrite(stage, LOW);
      delay(random(200,900));
      digitalWrite(stagel, LOW);
      lcd.clear();
      lcd.setCursor(1, 0);
      lcd.print("   Pre-Stage    ");
      delay(random(500,2000));
      lcd.setCursor(0, 1);
      lcd.print("     Stage      ");
      digitalWrite(prestage, LOW);
      delay(random(300,800));  
      digitalWrite(prestagel, LOW);
      delay(random(200,900));    
      lcd.print("               ");
      Start();
    }
}

void Start()
{
  digitalWrite(stage, LOW);
  digitalWrite(prestage, LOW);
  digitalWrite(amber1, LOW);
  digitalWrite(amber2, HIGH);
  digitalWrite(amber3, HIGH);
  digitalWrite(green, HIGH);
  digitalWrite(red, HIGH);
  digitalWrite(stagel, LOW);
  digitalWrite(prestagel, LOW);
  digitalWrite(amber1l, LOW);
  digitalWrite(amber2l, HIGH);
  digitalWrite(amber3l, HIGH);
  digitalWrite(greenl, HIGH);
  digitalWrite(redl, HIGH);
  tone(buzz, 500, 300);
  delay(500);
  digitalWrite(stage, LOW);
  digitalWrite(prestage, LOW);
  digitalWrite(amber1, HIGH);
  digitalWrite(amber2, LOW);
  digitalWrite(amber3, HIGH);
  digitalWrite(green, HIGH);
  digitalWrite(red, HIGH);
  digitalWrite(stagel, LOW);
  digitalWrite(prestagel, LOW);
  digitalWrite(amber1l, HIGH);
  digitalWrite(amber2l, LOW);
  digitalWrite(amber3l, HIGH);
  digitalWrite(greenl, HIGH);
  digitalWrite(redl, HIGH);
  tone(buzz, 500, 300);
  delay(500);
  digitalWrite(stage, LOW);
  digitalWrite(prestage, LOW);
  digitalWrite(amber1, HIGH);
  digitalWrite(amber2, HIGH);
  digitalWrite(amber3, LOW); time = millis(); // comienza conteo
  digitalWrite(green, HIGH);
  digitalWrite(red, HIGH);
  digitalWrite(stagel, LOW);
  digitalWrite(prestagel, LOW);
  digitalWrite(amber1l, HIGH);
  digitalWrite(amber2l, HIGH);
  digitalWrite(amber3l, LOW);
  digitalWrite(greenl, HIGH);
  digitalWrite(redl, HIGH);
  tone(buzz, 500, 300);
  
  while( ((millis() - time)<499)&&(digitalRead(button) == HIGH))
  {
    }
  if(digitalRead(button) == LOW )
  {
    lcd.clear();
    lcd.setCursor(1,0);
    lcd.print("Reaction");
    digitalWrite(stage, HIGH);
    digitalWrite(prestage, HIGH);
    digitalWrite(amber1, HIGH);
    digitalWrite(amber2, HIGH);
    digitalWrite(amber3, HIGH);
    digitalWrite(green, HIGH);
    digitalWrite(red, LOW);
    digitalWrite(stagel, HIGH);
    digitalWrite(prestagel, HIGH);
    digitalWrite(amber1l, HIGH);
    digitalWrite(amber2l, HIGH);
    digitalWrite(amber3l, HIGH);
    digitalWrite(greenl, LOW);
    digitalWrite(redl, HIGH);
    tone(buzz, 150, 500);
    lcd.setCursor(0,1);
    reaction = ((millis() - time));
    reaction = reaction * .001;
    lcd.print(reaction,3);
    lcd.print(" sec. FAIL");
    delay(2000);
    lcd.clear();
  }
  
  if(digitalRead(button) == HIGH )
  {
    digitalWrite(stage, HIGH);
    digitalWrite(prestage, HIGH);
    digitalWrite(amber1, HIGH);
    digitalWrite(amber2, HIGH);
    digitalWrite(amber3, HIGH);
    digitalWrite(green, LOW);
    digitalWrite(red, HIGH);
    digitalWrite(stagel, HIGH);
    digitalWrite(prestagel, HIGH);
    digitalWrite(amber1l, HIGH);
    digitalWrite(amber2l, HIGH);
    digitalWrite(amber3l, HIGH);
    digitalWrite(greenl, LOW);
    digitalWrite(redl, HIGH);
    tone(buzz, 700, 600);
    while(digitalRead(button) == HIGH )
    {lcd.clear();
    lcd.setCursor(1,0);
    lcd.print("Reaction");
    lcd.setCursor(0,1);
      if(digitalRead(button) == LOW )
      {
      reaction = ((millis() - time));
      reaction = reaction * .001;
      lcd.print(reaction,3);
      lcd.print(" sec.");
     }
     }
    delay(4000);
    lcd.clear();
   
  }
}

Agradezco su apoyo!

Saludos

Eso ocurre porque tu código no tiene debouce y tu pulsador esta rebotando.
Por eso se va a FAIL.
debes agregar una rutina de debounce.

Busca arduino debounce

Perfecto, lo checo!