3 LED blinking randomly using millis got reversed for some reason

Your guess is pretty wild, last night i randomly removed the smoothing progress, somehow it worked.

I changed alpha to 1.0, it worked. But i need to use 0.01 so how can i deal with this

Why do you believe you need to smooth with alpha = 0.01? It seems like it smooths your peaks down below your thresholdForce so you get all zeros for lastPeakForce. I'd try alpha=0.5 or alpha=0.2 for a more responsive but less smooth level of smoothing, and then tune it from there

1 Like

so heres how things getting weird, well when i put the thresholdForce = 0.0, last time i separated my code, the alpha was 0.01, and the results were about like 8 - 40 m/s^2. But this time, after i switch thesholdForce to 0.0, i found that the results were bellow 4.0, thats so weird (also alpha is 0.01)

Can you explain what is tune in this situation?

Oh, I'm sorry--change the line:

to:

static float smoothForce = 0;

...otherwise it won't remember the smoothing history between measurements, and will zero out the results each invocation and give results as you have seen.

As for tuning, did you see this graph:

The smoothing averages a set of observations together to help manage noisy data. In the graph the noisy data are the circles, and the three lines are stronger/wider smoothings of the data. The line with the 0.01 smoothing weights the most recent observation as 1/100 of the average, and smooths out most of the peak. The 0.2 smoothing weights the most recent observation as 1/5 of the resultant average, and is much more responsive to the noisy data. If you used an alpha of 1.0, it would weight the most recent observation as 100% of the average and does no smoothing, connecting the dots to make a jagged line.

Without the static on the smoothForce declaration, the weight of the past values in the average is zero, and instead of smoothing the math merely scales it by alpha.

Tuning would be choosing an alpha that makes an acceptable tradeoff between responsiveness and noise reduction.

Hold up, i changed that, its static at the beginning.

In the beginning of the my smoothing discussion (post#169) I posted it as static:

...but it wasn't static in your final code posted in #190:

Yeah, because i changed it, just in case of that was the problem, ill put it back later

'static' versus dynamically allocated can be very important. Especially if you want to smooth across multiple observations across time.

1 Like

so heres the thing, i changed alpha to 0.1, its decent but when the mpu6050 bounces back, it also reads that value so i cant just increase the thresholdForce value. 0.2 on the other hand, it doesnt read the bounce back values, but should i trust 0.2 because the values are kinda big actually.

It is not clear what you want. What are "results" in terms of accelTotal, smoothForce, myForce, peakForce, or lastPeakForce? What is results 0.2 and what was the 261? What are their units?

Maybe draw some diagram of what you think is happening and identify what you want to happen.

Without any data, I'm imagining you want something like this:

Where the main line is accelTotal, dashed line is peakForce, and light line is lastPeakForce.

...and you hit something and the MPU6050's accelTotal force bounces around and you want to determine and display the lastPeakForce of a hit, ignore the bounces, and reset for the next hits. All the while displaying something like the lastPeakForce= "50" -> "75" -> "25" changes along the bottom timeline of my scribble.

If you want something different, or something like this but it isn't working as expected, you need to describe what you want better, and what is happening better.

2 Likes

Ok so after i took a look at your graph, and also my results, i realized one thing, that is the bounce normally 1/2 times the size of lastPeakForce, sometimes its smaller, and they never get bigger. So heres my idea, ill try to make thresholdForce = 1/2 lastPeakForce

What does your data look like? Can you draw a sketch of a graph of your data?

I intended thresholdForce to filter out the low-level non-hit noise with a low number and for the resetInterval / forceChecker.Time thing to mask a peak's subsequent bounces and then reset the peak detector to look for the next peak.

Without data I'd wild-guess threshold at 2g or 20m/s^2 to and if you are detecting bounces after forceChecker.Interval = 500ms, lengthen the interval to 1000ms or so.

Dynamically setting the threshold up above a bounce acceleration would work too, and might handle fast hits quicker than inhbiting peak detection past the peak time for a longer time window.

Without good data out here, it is hard to guess.

1 Like

Hey @DaveX and @LarryD, i got qualified for the province competition!!

1 Like

hey there Larry, do you remember that i asked you how to make a stopwatch? I have a problem right here, so im trying to make a new mode, it will check your sensibility when you punch, heres how it works: If an LED is on, and you punch, it will say "On time", if you punch slower (like when and LED is off then you punch) it will start the time (when LED is off) and then stop when you hit, and then print out "Slow: ... ms". I use a button to replace a sensor that can detect a punch when you hit it

Heres a code that i tried to make:

#define EXPIRED                    true
#define stillTIMING                false

#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   HIGH

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH

#define ENABLED                    true
#define DISABLED                   false

#define YES                        true
#define NO                         false

//************************************************
const byte LEDpin1               = 3;
const byte LEDpin2               = 4;
const byte LEDpin3               = 5;  
const byte heartbeatLED          = 13;
const byte button                = 8;


byte lastIncSwitch               = RELEASED;

int s = 0;

byte randNumber;
byte LEDselected;

//                          m i l l i s ( )   B a s e d   T I M E R S
//********************************************^************************************************
//TIMER definitions
//Two ways to define a new TIMER
//The first, we will call it a manual method:        example: heartbeat TIMER
//The second, we will call it the structure method:  example: scanSwitches TIMER

//****************************************
//manual method:
//heartbeat TIMER
unsigned long heartbeatTime      = 0;
unsigned long heartbeatInterval  = 500ul;
bool heartbeatTimerFlag          = ENABLED;
bool heartbeatRestart            = YES;

//****************************************
//structure method:
struct makeTIMER
{
//#define ENABLED       true
//#define DISABLED      false

//#define YES           true
//#define NO            false

//#define EXPIRED       true
//#define stillTIMING   false

  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time in ms which we are looking for
  bool          timerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //restart this TIMER ? YES/NO

  //****************************************
  //fuction to check if the TIMER is enabled and check if the TIMER has expired
  bool checkTIMER()
  {
    //*********************
    //is this TIMER enabled and has this TIMER expired ?
    if (timerFlag == ENABLED && millis() - Time >= Interval)
    {
      //*********************
      //should this TIMER restart again?
      if (Restart == YES)
      {
        //restart this TIMER
        Time = millis();
      }

      //this TIMER is enabled and has expired
      return EXPIRED;
    }

    //this TIMER is disabled and/or has not expired
    return stillTIMING;

  } //END of   checkTime()

}; //END of   struct makeTIMER

//********************************************^************************************************
/*example
  // *******************
  makeTIMER toggleLED =
  {
  0, 500ul, ENABLED/DISABLED, YES/NO  //Time, Interval, timerFlag, Restart
  };
*/


makeTIMER checkSwitchesTimer =
{
  0, 50ul, ENABLED, YES      //Time, Interval, timerFlag, Restart
};

//*******************
makeTIMER LEDonTimer =
{
  0, 1000ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************
makeTIMER LEDoffTimer =
{
  0, 1000ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(LEDpin1, OUTPUT);
  pinMode(LEDpin2, OUTPUT);
  pinMode(LEDpin3, OUTPUT);

  pinMode(button, INPUT);

  randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//********************************************^************************************************
void loop()
{

  scoreCheck();

  //************************************************              T I M E R  heartbeatLED
  //when enabled, is it time to toggle the heartbeat LED ?
  if (heartbeatTimerFlag == ENABLED && millis() - heartbeatTime >= heartbeatInterval)
  {
    //restart this TIMER ?
    if (heartbeatRestart == YES)
    {
      heartbeatTime = millis();
    }

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //************************************************              T I M E R  LEDon
  //is the TIMER enabled and is it time to turn OFF this LED ?
  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //LED selected goes OFF
    digitalWrite(LEDselected, LEDoff);

    //disabled this TIMER
    LEDonTimer.timerFlag = DISABLED;

    //enable the OFF TIMER
    LEDoffTimer.timerFlag = ENABLED;

    //restart the OFF TIMER
    LEDoffTimer.Time = millis();    
  }

  //************************************************              T I M E R  LEDoff
  //is the TIMER enabled and is it time to turn ON the next LED ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //disabled this TIMER
    LEDoffTimer.timerFlag = DISABLED;
  }

  //************************************************              Next random LED
  //has LED timing stopped ?
  if (LEDonTimer.timerFlag == DISABLED && LEDoffTimer.timerFlag == DISABLED)
  {
    randomly();
  }

  //************************************************
  //other non blocking code goes here
  //************************************************

} //END of   loop()


//                                    r a n d o m l y ( )
//********************************************^************************************************
void randomly()
{
  //select a LED connected to pin 2,3 or 4
  LEDselected = random(3,6);

  //LED goes ON
  digitalWrite(LEDselected, LEDon);

  //enable the LEDon TIMER
  LEDonTimer.timerFlag = ENABLED;

  //restart this TIMER
  LEDonTimer.Time = millis();

} //END of   randomly()

void scoreCheck()
{
  if(LEDonTimer.timerFlag == ENABLED && LEDoffTimer.timerFlag == DISABLED){
    byte state;
    state = digitalRead(button);
    if (checkSwitchesTimer.checkTIMER() == EXPIRED)
    {
      if (lastIncSwitch != state)
      {
        lastIncSwitch = state;

        //*************************************
        if (state == PUSHED)
        {
          Serial.println("On time");
        }
      }
    }
  }
}
//********************************************^************************************************

Thanks!!

While the LED is ON a hit print “On Time”

After the LED is turn OFF and there is a hit, print "Slow: XYZ ms"

?

1 Like

i made this yesterday, please take a look at it!

//************************************************
#define EXPIRED                    true
#define stillTIMING                false

#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   HIGH

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH

#define ENABLED                    true
#define DISABLED                   false

#define YES                        true
#define NO                         false

unsigned long stopWatch;
unsigned long timerStart;

//************************************************
const byte LEDpin1               = 3;
const byte LEDpin2               = 4;
const byte LEDpin3               = 5;
const byte heartbeatLED          = 13;
const byte button                = 8;

int statusOn = 0;
int statusOff = 0;
int doNothing = 0;
int t = 0;
int n = 0;

byte lastIncSwitch               = RELEASED;

byte lastOn                        = DISABLED;

byte punched = 0;
byte Nopunched = 0;


byte randNumber;
byte LEDselected;

//                          m i l l i s ( )   B a s e d   T I M E R S
//********************************************^************************************************
//TIMER definitions
//Two ways to define a new TIMER
//The first, we will call it a manual method:        example: heartbeat TIMER
//The second, we will call it the structure method:  example: scanSwitches TIMER

//****************************************
//manual method:
//heartbeat TIMER
unsigned long heartbeatTime      = 0;
unsigned long heartbeatInterval  = 500ul;
bool heartbeatTimerFlag          = ENABLED;
bool heartbeatRestart            = YES;

//****************************************
//structure method:
struct makeTIMER
{
//#define ENABLED       true
//#define DISABLED      false

//#define YES           true
//#define NO            false

//#define EXPIRED       true
//#define stillTIMING   false

  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time in ms which we are looking for
  bool          timerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //restart this TIMER ? YES/NO

  //****************************************
  //fuction to check if the TIMER is enabled and check if the TIMER has expired
  bool checkTIMER()
  {
    //*********************
    //is this TIMER enabled and has this TIMER expired ?
    if (timerFlag == ENABLED && millis() - Time >= Interval)
    {
      //*********************
      //should this TIMER restart again?
      if (Restart == YES)
      {
        //restart this TIMER
        Time = millis();
      }

      //this TIMER is enabled and has expired
      return EXPIRED;
    }

    //this TIMER is disabled and/or has not expired
    return stillTIMING;

  } //END of   checkTime()

}; //END of   struct makeTIMER

//********************************************^************************************************
/*example
  // *******************
  makeTIMER toggleLED =
  {
  0, 500ul, ENABLED/DISABLED, YES/NO  //Time, Interval, timerFlag, Restart
  };
*/


makeTIMER checkSwitchesTimer =
{
  0, 50ul, ENABLED, YES      //Time, Interval, timerFlag, Restart
};

//*******************
makeTIMER LEDonTimer =
{
  0, 1000ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************
makeTIMER LEDoffTimer =
{
  0, 1000ul, DISABLED, NO      //Time, Interval, timerFlag, Restart
};
//*******************


//                                       s e t u p ( )
//********************************************^************************************************
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(LEDpin1, OUTPUT);
  pinMode(LEDpin2, OUTPUT);
  pinMode(LEDpin3, OUTPUT);

  pinMode(button, INPUT);

  randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//********************************************^************************************************
void loop()
{

  if (checkSwitchesTimer.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }

  checkSlowTime();
  checkNoPunch();

  //************************************************              T I M E R  heartbeatLED
  //when enabled, is it time to toggle the heartbeat LED ?
  if (heartbeatTimerFlag == ENABLED && millis() - heartbeatTime >= heartbeatInterval)
  {
    //restart this TIMER ?
    if (heartbeatRestart == YES)
    {
      heartbeatTime = millis();
    }

    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //************************************************              T I M E R  LEDon
  //is the TIMER enabled and is it time to turn OFF this LED ?
  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //LED selected goes OFF
    digitalWrite(LEDselected, LEDoff);

    //disabled this TIMER
    LEDonTimer.timerFlag = DISABLED;

    //enable the OFF TIMER
    LEDoffTimer.timerFlag = ENABLED;

    //restart the OFF TIMER
    LEDoffTimer.Time = millis();    
  }

  //************************************************              T I M E R  LEDoff
  //is the TIMER enabled and is it time to turn ON the next LED ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //disabled this TIMER
    LEDoffTimer.timerFlag = DISABLED;
  }

  //************************************************              Next random LED
  //has LED timing stopped ?
  if (LEDonTimer.timerFlag == DISABLED && LEDoffTimer.timerFlag == DISABLED)
  {
    randomly();
  }

  if (LEDonTimer.timerFlag == DISABLED && LEDoffTimer.timerFlag == ENABLED){
    statusOn = 0;
  }

  if (LEDonTimer.timerFlag == ENABLED && LEDoffTimer.timerFlag == DISABLED){
    statusOff = 0;
  }

  //************************************************
  //other non blocking code goes here
  //************************************************

} //END of   loop()


//                                    r a n d o m l y ( )
//********************************************^************************************************
void randomly()
{
  //select a LED connected to pin 2,3 or 4
  LEDselected = random(3,6);

  //LED goes ON
  digitalWrite(LEDselected, LEDon);

  //enable the LEDon TIMER
  LEDonTimer.timerFlag = ENABLED;

  //restart this TIMER
  LEDonTimer.Time = millis();

} //END of   randomly()

void checkSwitches()
{
  int p = 0;
  byte state;
  state = digitalRead(button);

  if (lastIncSwitch != state)
  {
    lastIncSwitch = state;

    //*************************************
    if (state == PUSHED)
    {
      if (LEDonTimer.timerFlag == ENABLED && LEDoffTimer.timerFlag == DISABLED){
        
        statusOn++;
        if(statusOn == 1){
          Serial.println("Fast");
          punched += 1;
        }
        if(statusOn > 1){
          p++;
        }
      }

      if (LEDonTimer.timerFlag == DISABLED && LEDoffTimer.timerFlag == ENABLED){
        stopWatch = millis() - timerStart;
        statusOff++;
        int p = 0;
        if(statusOff == 1){
          Serial.print("Slow: ");
          Serial.println(stopWatch);
          punched += 1;
        }
        if(statusOff > 1){
          p++;
        }
      }
    }
  } 
} 


void checkSlowTime(){
  byte status;
  status = LEDoffTimer.timerFlag;

  if(lastOn != status){
    lastOn = status;
    if(status == ENABLED){
      timerStart = millis();
    }
  }
}

void checkNoPunch(){
  if(punched == 0){
    if(millis() - timerStart == LEDoffTimer.Interval){
      Serial.println("No punch");
    }
  }
}
  //*************************************

well please dont mind that my code is pretty stupid, so heres how it works
Case 1: If LED is on and you hit the button (or punch), it will tell you that you're fast enough.
Case 2: If LED is on but you cant respond fast enough, lead to LED turn off then you punch it, so it will tell you that you're slower for about xyz ms.
Case 3 (the one that is pretty easy to solve but i still can't figure out): If LED turn on, you don't punch, then turn off, you don't punch (technically you don't do anything) and then when it change to another LED, it will say "You haven't punched" (which is "No punch" in my code)
One last thing, i'm still struggling with a buzzer, like every time i press a button it will beep for like maybe 100ms i supposed and a count down from 3 2 1, it sounds like "beep", "beep", "beeeep".

  • How are you wiring/connecting the push button switch ?

  • What kind of buzzer are you going to use ?

1 Like

This should be close:


//================================================
#define LEDon                      HIGH   //PIN---[220R]---A[LED]K---GND
#define LEDoff                     LOW

#define PUSHED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND
#define RELEASED                   HIGH

#define CLOSED                     LOW    //+5V---[Internal 50k]---PIN---[switch]---GND 
#define OPEN                       HIGH


//============================================^================================================
//                     millis() / micros()   B a s e d   T I M E R S
//============================================^================================================
//To keep the sketch tidy, you can put this structure in a different tab in the IDE
//
//These TIMER objects are non-blocking
struct makeTIMER
{
#define MILLIS             1
#define MICROS             1000  //we can use this value to divide into a variable to get milliseconds

#define ENABLED            true
#define DISABLED           false

#define YES                true
#define NO                 false

#define STILLtiming        0
#define EXPIRED            1
#define TIMERdisabled      2

  //these are the bare minimum "members" needed when defining a TIMER
  int           TimerType;      //what kind of TIMER is this? MILLIS/MICROS
  unsigned long Time;           //when the TIMER started
  unsigned long Interval;       //delay time which we are looking for
  bool          TimerFlag;      //is the TIMER enabled ? ENABLED/DISABLED
  bool          Restart;        //do we restart this TIMER   ? YES/NO

  //================================================
  //condition returned: STILLtiming (0), EXPIRED (1) or TIMERdisabled (2)
  //function to check the state of our TIMER  ex: if(myTimer.checkTIMER() == EXPIRED);
  byte checkTIMER()
  {
    //=====================
    //is this TIMER enabled ?
    if (TimerFlag == ENABLED)
    {
      //=====================
      //has this TIMER expired ?
      if (getTime() - Time >= Interval)
      {
        //=====================
        //should this TIMER restart again?
        if (Restart == YES)
        {
          //restart this TIMER
          Time = getTime();
        }

        //this TIMER has expired
        return EXPIRED;
      }

      //=====================
      else
      {
        //this TIMER has not expired
        return STILLtiming;
      }

    } //END of   if (TimerFlag == ENABLED)

    //=====================
    else
    {
      //this TIMER is disabled
      return TIMERdisabled;
    }

  } //END of   checkTime()

  //================================================
  //function to enable and restart this TIMER  ex: myTimer.enableRestartTIMER();
  void enableRestartTIMER()
  {
    TimerFlag = ENABLED;

    //restart this TIMER
    Time = getTime();

  } //END of   enableRestartTIMER()

  //================================================
  //function to disable this TIMER  ex: myTimer.disableTIMER();
  void disableTIMER()
  {
    TimerFlag = DISABLED;

  } //END of    disableTIMER()

  //================================================
  //function to restart this TIMER  ex: myTimer.restartTIMER();
  void restartTIMER()
  {
    Time = getTime();

  } //END of    restartTIMER()

  //================================================
  //function to force this TIMER to expire ex: myTimer.expireTimer();
  void expireTimer()
  {
    //force this TIMER to expire
    Time = getTime() - Interval;

  } //END of   expireTimer()

  //================================================
  //function to set the Interval for this TIMER ex: myTimer.setInterval(100);
  void setInterval(unsigned long value)
  {
    //set the Interval
    Interval = value;

  } //END of   setInterval()

  //================================================
  //function to return the current time
  unsigned long getTime()
  {
    //return the time             i.e. millis() or micros()
    //=====================
    if (TimerType == MILLIS)
    {
      return millis();
    }

    //=====================
    else
    {
      return micros();
    }

  } //END of   getTime()

}; //END of   struct makeTIMER


//                        D e f i n e   a l l   a r e   T I M E R S
//============================================^================================================
/*example
  //=====================
  makeTIMER toggleLED =
  {
     MILLIS/MICROS, 0, 500ul, ENABLED/DISABLED, YES/NO  //.TimerType, .Time, .Interval, .TimerFlag, .Restart
  };

  Function examples:
  toggleLED.checkTIMER();
  toggleLED.enableRestartTIMER();
  toggleLED.disableTIMER();
  toggleLED.expireTimer();
  toggleLED.setInterval(100ul);
*/

//=====================
makeTIMER heartbeatTIMER =
{
  MILLIS, 0, 500ul, ENABLED, YES      //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER checkSwitchesTimer =
{
  MILLIS, 0, 50ul, ENABLED, YES       //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER LEDonTimer =
{
  MILLIS, 0, 1000ul, DISABLED, NO     //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER LEDoffTimer =
{
  MILLIS, 0, 1000ul, DISABLED, NO     //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER stopWatchTimer =
{
  MICROS, 0, 1000ul, ENABLED, YES    //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER commonTimer =
{
  MILLIS, 0, 150ul, ENABLED, YES     //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};

//=====================
makeTIMER machineTIMER =
{
  MICROS, 0, 1000ul, ENABLED, YES   //.TimerType, .Time, .Interval, .TimerFlag, .Restart
};


//                           B E E P   S t a t e   M a c h i n e
//============================================^================================================
//the states in our machine
enum STATES : byte
{
  STARTUP, BEEP1, BEEP2, BEEP3, FINISHED
};
STATES beepState = STARTUP;


//                                        G P I O s
//============================================^================================================
const byte LEDpin1               = 3;
const byte LEDpin2               = 4;
const byte LEDpin3               = 5;
const byte speakerPin            = 6;
const byte button                = 8;
const byte heartbeatLED          = 13;

//variables
int beepDuration                 = 50ul;
int frequency0                   = 0;
int frequency1                   = 4500ul;  //fast hit frequency
int frequency2                   = 4000ul;  //slow hit frequency

int elapsedMilliseconds;
byte randNumber;
byte LEDselected;
byte lastButtonSwitch            = RELEASED;


//                                       s e t u p ( )
//============================================^================================================
void setup()
{
  Serial.begin(9600);

  pinMode(heartbeatLED, OUTPUT);
  pinMode(LEDpin1, OUTPUT);
  pinMode(LEDpin2, OUTPUT);
  pinMode(LEDpin3, OUTPUT);

  pinMode(button, INPUT_PULLUP);

  randomSeed(analogRead(A0));

} //END of   setup()


//                                        l o o p ( )
//============================================^================================================
void loop()
{
  //================================================              T I M E R  heartbeatLED
  //condition returned: STILLtiming, EXPIRED or TIMERdisabled
  //is it time to toggle the heartbeat LED ?
  if (heartbeatTIMER.checkTIMER() == EXPIRED)
  {
    //toggle the LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));
  }

  //================================================              T I M E R  checkSwitches
  //is it time to check the switches ?
  if (checkSwitchesTimer.checkTIMER() == EXPIRED)
  {
    checkSwitches();
  }

  //================================================              T I M E R  machine
  //is it time to service our State Machine ?
  if (machineTIMER.checkTIMER() == EXPIRED)
  {
    checkMachine();
  }

  //================================================              T I M E R  stopWatch
  //is the TIMER enabled and is it time to add 1ms to the counter ?
  if (stopWatchTimer.checkTIMER() == EXPIRED)
  {
    //one more millisecond has gone by
    elapsedMilliseconds++;
  }

  //================================================              T I M E R  LEDon
  //is the TIMER enabled and is it time to turn OFF this LED ?
  if (LEDonTimer.checkTIMER() == EXPIRED)
  {
    //LED selected goes OFF
    digitalWrite(LEDselected, LEDoff);

    //disabled this TIMER
    LEDonTimer.TimerFlag = DISABLED;

    LEDoffTimer.enableRestartTIMER();
  }

  //================================================              T I M E R  LEDoff
  //is the TIMER enabled and is it time to turn ON the next LED ?
  if (LEDoffTimer.checkTIMER() == EXPIRED)
  {
    //disabled this TIMER
    LEDoffTimer.TimerFlag = DISABLED;
  }

  //================================================              Next random LED
  //has LED timing stopped ?
  if (LEDonTimer.TimerFlag == DISABLED && LEDoffTimer.TimerFlag == DISABLED)
  {
    randomly();
  }

  //================================================
  //other non blocking code goes here
  //================================================

} //END of   loop()


//                                    r a n d o m l y ( )
//============================================^================================================
void randomly()
{
  //select a LED connected to pin 3,4 or 5
  LEDselected = random(3, 6);

  //LED goes ON
  digitalWrite(LEDselected, LEDon);

  LEDonTimer.enableRestartTIMER();

  stopWatchTimer.enableRestartTIMER();

  //start our counter
  elapsedMilliseconds = 0;

} //END of   randomly()


//                                c h e c k M a c h i n e ( )
//============================================^================================================
void checkMachine()
{
  //================================================
  //service the current "state"
  switch (beepState)
  {
    //=====================
    case STARTUP:
      {
        //do startup stuff
      }
      break;

    //=====================
    case BEEP1:
      {
        //is the common TIMER expired ?
        if (commonTimer.checkTIMER() == EXPIRED)
        {
          tone(speakerPin, frequency0, beepDuration);
          commonTimer.enableRestartTIMER();
          beepState = BEEP2;
        }
      }
      break;

    //=====================
    case BEEP2:
      {
        //is the common TIMER expired ?
        if (commonTimer.checkTIMER() == EXPIRED)
        {
          //make next beep
          tone(speakerPin, frequency0, beepDuration * 2);
          commonTimer.enableRestartTIMER();
          beepState = BEEP3;
        }
      }
      break;

    //=====================
    case BEEP3:
      {
        beepState = STARTUP;
      }
      break;

    //=====================
    case FINISHED:
      {
      }
      break;

  } //END of  switch/case

} //END of   checkMachine()


//                              c h e c k S w i t c h e s ( )
//============================================^================================================
void checkSwitches()
{
  byte state;

  //================================================              button
  state = digitalRead(button);

  //was there a change in the switches state ?
  if (lastButtonSwitch != state)
  {
    //update to this new state
    lastButtonSwitch = state;

    //========================
    if (state == PUSHED)       //+5V---[Internal 50k]---PIN---[switch]---GND
    {
      if (LEDonTimer.TimerFlag == ENABLED && LEDoffTimer.TimerFlag == DISABLED)
      {
        //Start beep sequence
        frequency0 = frequency1;
        tone(speakerPin, frequency0, beepDuration);
        commonTimer.enableRestartTIMER();
        beepState = BEEP1;

        Serial.print("\nYou are Fast only ");
        Serial.print(elapsedMilliseconds);
        Serial.println("ms");
      }

      else if (LEDonTimer.TimerFlag == DISABLED && LEDoffTimer.TimerFlag == ENABLED)
      {
        //Start beep sequence
        frequency0 = frequency2;
        tone(speakerPin, frequency0, beepDuration);
        commonTimer.enableRestartTIMER();
        beepState = BEEP1;

        Serial.print("\nYou are Sloooow ");
        Serial.print(elapsedMilliseconds);
        Serial.println("ms");
      }
    }
  }

} //END of   checkSwitches()


2 Likes