Verifying an if statement outside a loop, helperino ;_;

I had done this with buttons and a double input nor gate where I used the blink function to verify these parameters outside a loop.

However, I'm forced to use some analogical piezzos sensors and I'm not able to verify the if outside the loop.

Here's the code:

const int ledR = 12;    
const int ledG = 11;  
const int knockSensor1 = A1;
const int knockSensor2 = A2;
const int threshold1 = 1000; 
const int threshold = 200;  // threshold value to decide when the detected sound is a knock or not
int RTI;
int TI;



// these variables will change:

int sensorReading1 = 0;
int sensorReading2 = 0;

int Random;

void setup() {
pinMode(ledR, OUTPUT);
pinMode(ledG, OUTPUT);
digitalWrite(ledR, HIGH);
digitalWrite(ledG, LOW);
RTI=random(5000,10000);
TI=random(2000,3000);
}   

void loop() {

sensorReading1 = analogRead(knockSensor1); 
sensorReading2 = analogRead(knockSensor2); 
 Serial.println(sensorReading2);
  delay(100);
  
 if (digitalRead(ledR) == HIGH && sensorReading1 > threshold )  {
    digitalWrite(ledR, LOW);
    delay(RTI);
    digitalWrite(ledG, HIGH);
     
    delay(TI);
     
  
    digitalWrite(ledG,LOW);
    delay(100);
    Serial.println('b');
    delay(100);
    digitalWrite(ledR, HIGH);
  }
  if (digitalRead(ledG) == HIGH && sensorReading2 > threshold){
   Serial.println('a');//k
  delay(100); 
  }
  
}

What happens is, the first led goes up (which is the standby); After I click the first sensor, the first led goes down, meaning all leds are down; Then, in a random interval, the second led goes HIGH only for brief seconds, and I wanted it to output me a "b" or whatever if I clicked it while it was high.

Thanks in advance

Your code won't reach the line

if (digitalRead(ledG) == HIGH && sensorReading2 > threshold){

until all of the earlier delay()s have completed.

If you want to be able to check things while the LED is on you need to stop using delay() and use millis() to manage timing as illustrated in several things at a time.

...R

Thank you so much for the reply!

I understand what are you saying, basicly the delay halts the code until it reaches the end.

I watched your tutorial and I'm afraid I learnt nothing at all.

I'm not a good programmer, and I'm failing to understand how should I use millis() instead of the Delays() i use already.

Sorry mate.

I have the same problem but i didn't understand Robin's tutorial either :slightly_frowning_face: :slightly_frowning_face: Could someone help?

I've tried creating the variable using milis, but I fail to understand how to use it as a parameter for my if statement.

And even if I have no errors in compiling, it still fails to output me the desired "a". :'(

Try Nick's tutorial: http://www.gammon.com.au/blink

It explains timing very well, but i’m still struggling to make the led go HIGH, wait like 1,5 seconds, go down, and in this time if I click the piezzo to output me whatever.

Hi MiguelSilva -

You are aware, that the Arduino processor can not do ANyTHING, when you tell it to DELAY in your code ?
Arduino will wait (like sleeping) until the delay time is over, and then it starts working again.

Thats why you have the example in the Arduino sketch library called “BlinkWithoutDelay”.
Here you learn how to blink the LED, not using the delay() function.

Yes, I am AWARE of which was said 1 hour ago, I can read, thank you.

const int ledR = 12;    
const int ledG = 11;  
const int knockSensor1 = A1;
const int knockSensor2 = A2;
const int threshold1 = 1000; 
const int threshold = 200;  // threshold value to decide when the detected sound is a knock or not
// these variables will change:

int sensorReading1 = 0;
int sensorReading2 = 0;

unsigned long   previousMillis = 0;        // 
const long interval = 2000; 
const long interval2 = random (3000,5000); 

unsigned long TimeInterval;
unsigned long RandomTimeInterval;


int Random;

void setup() {

pinMode(ledR, OUTPUT);
pinMode(ledG, OUTPUT);
digitalWrite(ledR, HIGH);
digitalWrite(ledG, LOW);
RandomTimeInterval = millis ();
TimeInterval = millis ();
//RTI=random(5000,10000);

}   

void Prepare(){
    unsigned long currentMillis = millis();
     digitalWrite (ledG, LOW);
     if ( (currentMillis - previousMillis) >= interval){
           previousMillis = currentMillis;  
       digitalWrite (ledG, HIGH);
       
     }
     if ( (currentMillis - previousMillis) >= interval2) {
           previousMillis = currentMillis;  
       digitalWrite (ledG, LOW);
       
       Serial.println ("b");
       digitalWrite (ledR, HIGH);
     }
     
     RandomTimeInterval = millis ();   
     TimeInterval = millis();
}


void loop() {


sensorReading1 = analogRead(knockSensor1); 
sensorReading2 = analogRead(knockSensor2); 
 Serial.println(sensorReading2);
  delay(100);
  
 if (digitalRead(ledR) == HIGH && sensorReading1 > threshold )  {
   Prepare();
   }
  if (digitalRead(ledG) == HIGH && sensorReading2 > threshold){
   Serial.println('a');//k
 delay(100);
  }
  
}

This is what I wrote, Of Course it's not even near of what I wanted it to do.

I wanted the second led to go high after a random time, for a brief instance.

Arrg, I'm asking the same questions over and over, I'm not good at working with deadlines :angry:

MiguelSilva: It explains timing very well, but i'm still struggling to make the led go HIGH, wait like 1,5 seconds, go down, and in this time if I click the piezzo to output me whatever.

Try this

const byte ledPin = 13;
const byte buttonPin = 8;
unsigned long startTime = 0;
unsigned long currentTime = 0;
unsigned long period = 5000;
byte currentButtonState;
byte previousButtonState;

void setup()
{
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop()
{
  currentTime = millis();
  if (currentTime - startTime >= period)  //period has elapsed - turn off the LED
  {
    digitalWrite(ledPin, LOW);
  }
  
  currentButtonState = digitalRead(buttonPin);
  if (currentButtonState != previousButtonState && currentButtonState == LOW) //button has become pressed
  {
    startTime = millis();    //save the time the button was pressed
    digitalWrite(ledPin, HIGH);  //turn on the LED
  }
  previousButtonState = currentButtonState;  //save the button state for the next check
}

When you take the button pin LOW the LED will come on and if you do nothing it will go off 5 seconds later. During the 5 seconds period if you take the button pin LOW again a new 5 second period will start and the LED will stay on.

The principle is simple. Save the time when something happens and check each time through loop() whether the required period has elapsed. If not, go round again, check inputs, do whatever, and when the time has elapsed take the appropriate actions.

MiguelSilva:
(…)

What happens is, the first led goes up (which is the standby);
After I click the first sensor, the first led goes down, meaning all leds are down;
Then, in a random interval, the second led goes HIGH only for brief seconds, and I wanted it to output me a “b” or whatever if I clicked it while it was high.
(…)

What do you mean with “brief seconds”?

When you say “if I clicked it while it was high”, you mean the second LED, right?

luisilva: What do you mean with "brief seconds"?

1, 2 Seconds, imagine it has a action reaction game.

Game Starts with the first led on. You click the first piezzo to start the game. First led goes off, meaning all leds are off. Second led will come up in a random time of let's say 5 to 10 seconds. it stays up for 1,2 seconds. If you managed to click the second piezzo in time, it outputs whatever. Either you clicked or you didn't, at the end of the second led timespan, it outputs another thing.

(it doesn't matter for me that it always output after the second led goes off since in my game[the one I need the hardware for] it will take the first thing that I give him.

Obrigado, thank you.

Anyone struggling to get their minds round Blink Without Delay may find this YouTube video useful, just as an alternative way of explaining.

MiguelSilva: I watched your tutorial and I'm afraid I learnt nothing at all.

versacechainz: I have the same problem but i didn't understand Robin's tutorial either

If you can be more specific about what you don't understand I will try to help.

The general concept is like cooking a chicken + put the chicken in the oven and note the time + periodically check the clock + when enough time has elapsed take the chicken out and turn off the oven

...R

Hey Robin,

I believe I got the hang of it, a little bit.

I'm noticing I need two timers for this.

One that turns the led on after some time, and another to turn it back off after 2 seconds.

So I wrote this :

const byte ledPin = 12;
const byte led2pin = 11;
const byte knockSensor1 = A1;
const byte knockSensor2 = A2;
const int threshold = 200;
unsigned long startTime = 0;
unsigned long currentTime = 0;
unsigned long startTime2 = 0;
unsigned long currentTime2 = 0;
unsigned long period = 5000;
unsigned long period2 = 7000;

byte sensorReading = 0;


void setup()
{
  Serial.begin(115200);
  pinMode(ledPin, OUTPUT);
  pinMode(led2pin, OUTPUT);
  digitalWrite (ledPin, HIGH);
   digitalWrite (led2pin, LOW);
  
  
}

void loop()

{
  
  currentTime = millis();
  currentTime2 = millis();
  if (currentTime - startTime >= period )  //period has elapsed - turn off the LED
  {
    digitalWrite(led2pin, HIGH);
  }
 if (currentTime - startTime >= period2 )  //period has elapsed - turn off the LED
  {
    digitalWrite(led2pin, LOW);
  }


  
  sensorReading = analogRead(knockSensor1);
  if (sensorReading > threshold) //button has become pressed
  {
    startTime = millis();

        //save the time the button was pressed
    digitalWrite(led2pin, LOW);  //turn on the LED
    digitalWrite(ledPin, LOW);
  }
    //save the button state for the next check
}

Problem is, the second timer conflicts with the first one making the led go medium, instead of HIGH / LOW.

That is definitely going in the right direction. You don't need (and have not used) currentTime2. Obviously there can only be one value of currentTime.

If you want the LED to stay on for a specific time you may want to record the time it goes on and use that to figure out the OFF moment

 if (currentTime - startTime >= period )  //period has elapsed - turn off the LED
  {
       digitalWrite(led2pin, HIGH);
      ledOnMillis = currentTime;
  }
 if (currentTime - ledOnMillis >= period2 )  //period has elapsed - turn off the LED
  {
    digitalWrite(led2pin, LOW);
  }

...R

I did what you just said and it doesn't work.

I've done Serial.println(currentTime - ledOnMillis); to debug the value and after the led goes up it doesn't leave 100,101.

I believe it is subtracting itself (?)

thank you so much for your time Robin.

Try a state machine.

Here is an example with 2 LEDS, but it can be any event or any number events, if you add more global variables and functions.

/* 
  State Machine.
  
  This is a piece of code that constitutes a state machine.
  It is used to start an event, then keeping an eye on that event to see if its time slot has elapsed.
  The state machine is what you need to avoid using the "sleep-mode" function delay().
  Note that the code relies on global variables to store the STATE of the events.
  If you try calling the event functions with these variables as parameters, it wont work, as the
  parameters then will be considered local variables in the scope of the functions.
     
  In this code two events controls two blinking LEDs with individual blink intervals, using an event function for each LED.

  The code is written and explained by :
  Jasmine2501
  In this youtube video :
  https://www.youtube.com/watch?v=3VZgaJBrZD8 
  
  Modified 29-03-15 by Anders53
  
*/

// Constants defines pin numbers
const int greenLedPin = 11;           // the number of the green LED pin
const int redLedPin = 12;             // the number of the green LED pin

// Variables will change
int greenLedState = HIGH;             // ledState for green LED
int redLedState = HIGH;               // ledState for red LED
long previousMillisRed = 0;           // last time Red LED was updated
long previousMillisGreen = 0;         // last time Green LED was updated

// Must be long integers to prevent overflow
long greenLedInterval = 1100;         // interval to blink green LED (milliseconds)
long redLedInterval = 1110;           // interval to blink red LED (milliseconds)
unsigned long currentMillis = 0;      // Current time (milliseconds)

void setup()
{  // Set the pins to output mode
  pinMode(greenLedPin, OUTPUT);
  pinMode(redLedPin, OUTPUT);
  digitalWrite(redLedPin, redLedState);
  digitalWrite(greenLedPin, greenLedState);
}

void loop()
{ 
  currentMillis = millis(); // Capture the current time
  manageRedLed();
  manageGreenLed();
}

void manageRedLed()  // function : check if it's time to change state of the Red LED yet
{
  if (currentMillis - previousMillisRed > redLedInterval) // state change condition
  {
    previousMillisRed = currentMillis;  //store the time of this state change
    // next 2 lines is the event controlled
    redLedState = (redLedState == HIGH) ? LOW : HIGH;
    digitalWrite(redLedPin, redLedState);
  }
}

void manageGreenLed() // function : check if it's time to change state of the green LED yet
{
  if (currentMillis - previousMillisGreen > greenLedInterval) // state change condition
  {
    previousMillisGreen = currentMillis; //store the time of this state change
    // next 2 lines is the event controlled
    greenLedState = (greenLedState == HIGH) ? LOW : HIGH;
    digitalWrite(greenLedPin, greenLedState);
  }
}

MiguelSilva: I did what you just said and it doesn't work.

You have to tell me what it does do. "Doesn't work" tells me nothing that enables me to help you.

Also, post the code that "doesn't work"

Because I did not test the code my suggestion may well have had a silly error.

...R

 if (currentTime - startTime >= period )  //period has elapsed - turn off the LED
  {
       digitalWrite(led2pin, HIGH);
      ledOnMillis = currentTime;
  }
 if (currentTime - ledOnMillis >= period2 )  //period has elapsed - turn off the LED
  {
    digitalWrite(led2pin, LOW);
  }

This doesn't work, I have also :

  Serial.println(currentTime - ledOnMillis );

And it doesn't leave 100~101; Since my period2 is a range between 1 and 2 seconds, it never reaches that value.

Btw, the currentTime is initialized in the beggining of the loop. And startTime starts when I touch the piezzo.

Once again thank you Robin.