Switch LED Off inside several If statements

Hello,

I am trying to avoid using the delay function and make use of the millis function. However, this doesn't seem to work inside several if statements.

Any advise?

unsigned long currentMillis = millis();
buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState) 
        {
            if (buttonState == HIGH) {
            p++;
            Serial.print("Level 1 ");
            Serial.println(p);
    } 
 
  }
  lastButtonState = buttonState;


if (p==1) 
      {
         currentStateCLK = digitalRead(inputCLK);
           if (currentStateCLK != previousStateCLK)
                { 
                   counter ++; 
                   Serial.println(counter);  
                     
                      if (currentMillis - previousMillis >= interval ) 
                      {
                            digitalWrite(3, HIGH);
                      }
                      else   
                       
                      {
                            digitalWrite(3, LOW);
                      }  
                       previousMillis = currentMillis;  
                }
               
                  
   previousStateCLK = currentStateCLK;

You can add ‘print statements’ throughout your code to prove your variables are what you think they should be.

These print statements can also be used to see if code execution is happening.

larryd:
You can add ‘print statements’ throughout your code to prove your variables are what you think they should be.

These print statements can also be used to see if code execution is happening.

I tried that, but my 2 led's remain on.

I would like to switch both leds on, wait a second, switch the first led off, wait another second, and then switch the second led off....and they should remain off until further actions.

It's impossible..

Let’s see your attempt.

Use CTRL T to format your code.
Attach your ‘complete’ sketch between code tags, use the </> icon in the posting menu.
[code]Paste your sketch here[/code] .

//My Rotary Speed Encoder poject

const unsigned long interval_LED = 1000;
const unsigned long interval_Buzzer = 2000;

unsigned long previousTime_1 = 0;
unsigned long previousTime_2 = 0;

#define inputCLK 6
#define inputDT 7
int counter = 0;
int p = 1;
int currentStateCLK;
int previousStateCLK;

const int buttonPin = 2;
int buttonState;
int lastButtonState = 0;

void setup()
{
  pinMode (inputCLK, INPUT);
  pinMode (inputDT, INPUT);
  pinMode (buttonPin, INPUT);
  pinMode (8, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);
  Serial.begin (9600);

  previousStateCLK = digitalRead(inputCLK);

}

void loop()
{
  unsigned long currentTime1 = millis();
  unsigned long currentTime2 = millis();

  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {
    if (buttonState == HIGH) {
      p++;
      Serial.print("Sensitivity Level:  ");
      Serial.println(p);
    }

  }
  lastButtonState = buttonState;


  if (p == 1)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);
      while (millis() < currentTime1 + interval_LED)
      {
        digitalWrite(3, HIGH);
        currentTime1 = millis();
      }
      digitalWrite(3, LOW);

      while (millis() < currentTime2 + interval_Buzzer)
      {
        digitalWrite(4, HIGH);
        currentTime2 = millis();
      }
      digitalWrite(4, LOW);


    }
    previousStateCLK = currentStateCLK;

  }

  if (p == 2)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);


    }
    previousStateCLK = currentStateCLK;

  }

  if (p == 3)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);
      if ((counter % 5) == 0)
      {

      }

    }
    previousStateCLK = currentStateCLK;
  }

  if (p == 4)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;

      if ((counter % 7) == 0)
      {

      }
      Serial.println(counter);
    }
    previousStateCLK = currentStateCLK;
  }

  if (p == 5)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;

      if ((counter % 9) == 0)
      {

      }
      Serial.println(counter);
    }
  }
  previousStateCLK = currentStateCLK;


  if (p == 6)
  {
    p = 0;
  }




}

If you use WHILE like this

 while (millis() < currentTime1 + interval_LED)

the effect will be identical to using delay(). WHILE and FOR are also blocking concepts.

You should be using IF and allowing loop() to do the repetition.

The demo Several Things at a Time illustrates the use of millis() to manage timing without blocking. It may help with understanding the technique.

Have a look at Using millis() for timing. A beginners guide if you need more explanation.

…R

And if you want time comparisons to actually work you must use subtraction:

 if (millis() < currentTime1 + interval_LED)

needs to be

 if (millis() - currentTime1 < interval_LED)

Subtraction makes the code work across wrap-around of time variables, because subtraction always produces the right result even if millis() has just wrapped-back to zero.

Hello, thanks for your help.

I read the tutorials linked in your post, however they refer to blinking leds after a certain interval.
I can’t adjust that to my code. I don’t want blinks. Normally leds should be off. They should switch on only based on an interval I choose.

I’ve used your advise to use subtraction, but I still can’t make it work.

//My Rotary Speed Encoder poject
unsigned long startMillis;
unsigned long currentMillis1;
unsigned long currentMillis2;
const unsigned long interval_LED = 1000;
const unsigned long interval_Buzzer = 2000;

unsigned long previousTime_1 = 0;
unsigned long previousTime_2 = 0;

#define inputCLK 6
#define inputDT 7
int counter = 0;
int p = 1;
int currentStateCLK;
int previousStateCLK;

const int buttonPin = 2;
int buttonState;
int lastButtonState = 0;

void setup()
{
  pinMode (inputCLK, INPUT);
  pinMode (inputDT, INPUT);
  pinMode (buttonPin, INPUT);
  pinMode (8, OUTPUT);
  pinMode (3, OUTPUT);
  pinMode (4, OUTPUT);
  Serial.begin (9600);

  previousStateCLK = digitalRead(inputCLK);
  startMillis = millis();
}

void loop()
{

  currentMillis1 = millis();
  currentMillis2 = millis();

  buttonState = digitalRead(buttonPin);
  if (buttonState != lastButtonState)
  {
    if (buttonState == HIGH) {
      p++;
      Serial.print("Sensitivity Level:  ");
      Serial.println(p);
    }

  }
  lastButtonState = buttonState;


  if (p == 1)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);


      if (currentMillis1 - startMillis <= interval_LED)
      {
        digitalWrite(3, HIGH);
        currentMillis1 = millis();
      }
      else
      {
        digitalWrite(3, LOW);
      }

      if (currentMillis2 - startMillis <= interval_Buzzer)
      {
        digitalWrite(4, HIGH);
        currentMillis2 = millis();
      }
      else
      {
        digitalWrite(4, LOW);
      }

    }
    previousStateCLK = currentStateCLK;

  }

  if (p == 2)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);


    }
    previousStateCLK = currentStateCLK;

  }

  if (p == 3)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;
      Serial.println(counter);
      if ((counter % 5) == 0)
      {

      }

    }
    previousStateCLK = currentStateCLK;
  }

  if (p == 4)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;

      if ((counter % 7) == 0)
      {

      }
      Serial.println(counter);
    }
    previousStateCLK = currentStateCLK;
  }

  if (p == 5)
  {
    currentStateCLK = digitalRead(inputCLK);
    if (currentStateCLK != previousStateCLK)
    {
      counter ++;

      if ((counter % 9) == 0)
      {

      }
      Serial.println(counter);
    }
  }
  previousStateCLK = currentStateCLK;


  if (p == 6)
  {
    p = 0;
  }




}

ionass:
I can't adjust that to my code. I don't want blinks. Normally leds should be off.

An important skill for a programmer is the ability to translate a concept from one specific case to a different one.

They should switch on only based on an interval I choose.

Please describe in English the behaviour you wish to achieve.

...R

I followed the blink without delay tutorial, and I have managed to complete a working sketch on my own.

However, when I try to add a blinking LED to a different sketch, it doesn’t work.

I have a rotary encoder. When the encoder is incremented I would like an LED to blink.

I can’t figure out how to make the code below work:

#define CLK_PIN  2
#define DATA_PIN 7

const int ledPin1 =  9;
int led1State = LOW;
int counter1 = 10;  // count the number of times LED is HIGH.
unsigned long previousMillis1 = 0;
const long interval1 = 50;


////////////////////////////////////////////////////
void setup() {
  pinMode(CLK_PIN, INPUT);
  pinMode(DATA_PIN, INPUT);
  pinMode(ledPin1, OUTPUT);

  Serial.begin(9600);
  Serial.println("Rotary Encoder KY-040");
}

////////////////////////////////////////////////////
void loop() {
  unsigned long currentMillis = millis();

  static uint16_t state = 0, counter = 0;

  delayMicroseconds(100); // Simulate doing somehing else as well.

  state = (state << 1) | digitalRead(CLK_PIN) | 0xe000;

  if (state == 0xf000) {
    state = 0x0000;
    if (digitalRead(DATA_PIN))
    {
      counter++;
      Serial.println(counter);
    }
    else
    {
      counter++;
      Serial.println(counter);
    }

    if (currentMillis - previousMillis1 >= interval1)
    {
      previousMillis1 = currentMillis;
      if (led1State == LOW)
      {
        led1State = HIGH;
        counter1++;
      }
      else
      {
        led1State = LOW;
      }
      digitalWrite(ledPin1, led1State);
    }

    if (counter1 >= 5) {          //If LED binked 5 times, stop the blinking
      digitalWrite(ledPin1, LOW);
    }
  }

ionass:
I have a rotary encoder. When the encoder is incremented I would like an LED to blink.

Do you mean one blink for every pulse of the encoder?

How long should the LED stay on?

Or perhaps one pulse should turn it on and the next should turn it off?

...R

Robin2:
Do you mean one blink for every pulse of the encoder?

How long should the LED stay on?

Or perhaps one pulse should turn it on and the next should turn it off?

...R

Sorry for the poor explanation.

One pulse should turn the blinking on for a certain interval (i.e. 1000ms) at a rate of 50ms.

I was planing to stop the blinks, and keep the LED off until until next pulse.

Please post a link to the datasheet for the encoder - it does not seem to be the simple sort that I thought.

I presume the encoder is being turned by hand?

…R

Robin2:
Please post a link to the datasheet for the encoder - it does not seem to be the simple sort that I thought.

I presume the encoder is being turned by hand?

...R

That is correct, encoder is turned by hand.

Datasheet of the KY040 rotary encoder here: https://www.handsontec.com/dataspecs/module/Rotary%20Encoder.pdf

Much appreciated your help.

Why are you not using the code from the encoder datasheet? - it seems much simpler.

...R

Although it looks simpler, it's not accurate. Every time I turn the knob, the encoder value is incremented by 2 instead of 1.

Is there a way I could introduce the blinking in my sketch?

ionass:
it's not accurate. Every time I turn the knob, the encoder value is incremented by 2 instead of 1.

I'm sure it's totally accurate. The code looks for a change in pinA, without regard for it being a rising or falling change. Then it compares B to the new A, to get the direction; same = one way, different = the other.

So it's seeing 2 changes in A (up and down) when you seem to want only every second one, into the detent.

That code could be easily modified to ask if there's a change on A, AND A is now low (or high, whichever is the right one), then it's going to ignore half of the counts.

ionass:
Although it looks simpler, it's not accurate. Every time I turn the knob, the encoder value is incremented by 2 instead of 1.

If it always increments by 2 then just subtract 1

Making the code very complex is not going in the right direction.

...R

Robin2:
If it always increments by 2 then just subtract 1

That and your edited-away suggestion (which I think was to divide by 2) are both a bit kludgey though.

Subtracting 1 probably wouldn’t work anyway. On it’s way to 2, it goes through 1, which would then be 0 after subtracting 1, and then the second sense would be to 1 which would get subtracted back to 0. (I think, would need to test…)

I’d go for only looking for A to change in one direction up or down but not both, thus only seeing every second count and being inherently correct not fudged.

jubukraa:
That and your edited-away suggestion (which I think was to divide by 2) are both a bit kludgey though.

I can't see how subtracting 1 from 2 in order to get 1 is a kludge.

I deleted the divide-by version because I thought it might be misunderstood.

On it's way to 2, it goes through 1

In that case it does not always produce 2 - which was the premise for my suggestion.

...R