[SOLVED]Checking multiple variables for "states" and then lighting an led

Hello

Say I have four led lights that i want to light depending on different states.

each LED light is controlled individually

the states are:

  1. OFF
  2. Blinking
  3. ON

the states are dependent upon where the user is at in the program. Are arrays useful here, or should i just do something like

if LED1state1
digitalWrite(1, low);
if LED1state2
blink
if LEDstate3
digitalWrite(1,high);

if LED2state1
digitalWrite(2, low);
if LED2state2
blink2
if LED2state3
digitalWrite(2, high);

if LED3state1
digitalWrite(3, low);
if LED3state2
blink3
if LED3state3
digitalWrite(3, high);

if LED4state1
digitalWrite(4, low);
if LED4state2
blink4
if LED4state3
digitalWrite4(4, high);

it would work, but it seems highly inefficient to me?

use an enum or #defines - both will work fine and store your state in as an integer (or enum).

typedef enum state {ON, BLINK, OFF} state; 

state LED1state, LED2state, LED3state, LED4state;

...
{
  if (LED1state == BLINK)
  {
    // blink
  }
  else
    digitalWrite(1, (LED1state == ON) ? HIGH : LOW);

  if (LED2state == BLINK)
  {
    // blink
  }
  else
    digitalWrite(2, (LED2state == ON) ? HIGH : LOW);

  if (LED3state == BLINK)
  {
    // blink
  }
  else
    digitalWrite(3, (LED3state == ON) ? HIGH : LOW);

  if (LED4state == BLINK)
  {
    // blink
  }
  else
    digitalWrite(4, (LED4state == ON) ? HIGH : LOW);
}

you are of course missing some logic as to how you'll do blinking - but you didn't include this in your original question so i've left that as an exercise for you. this is more of a basic C/C++ language question regarding the use of variables, statements and work-flow constructs more than an arduino specific question.

thank you, that does seem more simple.

can you explain to me why the ? is there

Is that syntax or a question?

a nice explanation of enum's in C. you could just use #define and an int - but, it is up to you.

Qdeathstar:
can you explain to me why the ? is there

it is a tertiary operator Ternary conditional operator - Wikipedia - which is a shorthand if-then-else in a single command

variable = (conditional query) ? (value_if_true) : (value_if_false)

you may want to start with an "introduction to C" type tutorial to teach you some of the basics of how to program in C, then move onto C++ (which is used in Arduino libraries). Introduction to C - Cprogramming.com

Thanks!

FIXED: You can't use OFF or ON as variables.

When i try to create the enum, it gives me an error:

LEDbox3_ino:79: error: expected identifier before numeric constant
LEDbox3_ino:79: error: expected `}' before numeric constant
LEDbox3_ino:79: error: expected unqualified-id before numeric constant
LEDbox3_ino:79: error: expected declaration before '}' token

relevant part of the code:

long int setpDo;
//variables 
typedef enum state {ON, BLINK, OFF} state; 

state zone1state, zone2state, zone3state, zone4state;

const int interval = 900;

I did try to look up some examples, but none of the examples i saw for enums have that second line (state zone1state....)

I would be inclined to attack the problem differently - something like this

void updateLED() {
  for (byte n = 0; n < numLeds; n++) {
    digitalWrite(ledPin[n], ledState[n]);
    if (ledBlink[n] == true && millis() - ledPrevMillis[n] >= ledInterval[n]) }
      ledPrevMillis[n] += ledInterval[n];
      ledState[n] = ! ledState[n];
    }
  }
}

It assumes there is a variable (an array) called ledBlink[] which is either true or false depending on whether you want blinking. When it is true it overrides the setting of ledState[]. When it is false the value in ledState[] determines whether the led is on.

...R

I figured out the problem with the code, you can't use LOW or HIGH as variables, they are reserved for arduino. I changed them to ISON and ISOFF and now it works.

@Robin, i am looking for the optimal way of doing this, so, in your example though wouldn't that cause all the LED's to become a group, eg, they can ALL either be blinking, or they ALL can be OFF, or they ALL can be OFF.

I need to be able to separate them,

for instance.

Zone one and four is on, so their LED is on
zone two is in set up, so it's LED is blinking
Zone three is off, so it's led is off.

ardiri:

Qdeathstar:
can you explain to me why the ? is there

it is a tertiary operator Ternary conditional operator - Wikipedia - which is a shorthand if-then-else in a single command

Its a conditional expression, which isn't really an operator because its two operators!
? :
Its very handy for keeping code clear and concise at the same time. If you ever
see something like:

  if (condition)
  {
    return alpha ;
  }
  else
  { 
    return beta ;
  }

then your sense of coding elegance should be offended and you should
feel the need to replace it with:

  return condition ? alpha : beta ;

For long expressions format it indented like a conditional statement:

  return condition ?
    some-long-expression :
    some-other-long-expression ;

Qdeathstar:
in your example though wouldn't that cause all the LED's to become a group, eg, they can ALL either be blinking, or they ALL can be OFF, or they ALL can be OFF.

No. There is a separate control for each - for example ledBlink[n] can have as many elements as needed - one for each LED. Likewise there can be different blink intervals for each. I have assumed equal off and on times - but you could extend the idea to have separate off and on intervals.

You could probably tidy up the code by using a struct to define all the data for one LED and then just have an array of structs. But that may actually be more verbose.

...R

Robin, I tried using your suggestion:

int long ledPrevMillis[] = {0,0,0,0};
  int ledInterval[] = {700,700,700,700};
   
   for (byte n = 0; n < 4; n++) {
    digitalWrite(buttonPin[n], ledState[n]);
    if (buttonArray[n] == 2 | 3 && millis() - ledPrevMillis[n] >= ledInterval[n]){
      ledPrevMillis[n] += ledInterval[n];
      Serial.println(ledPrevMillis[n]);
      ledState[n] = ! ledState[n];
    }
    if (buttonArray[n] == 0) {
       digitalWrite(buttonPin[n], LOW);
    }
    
    if (buttonArray[n] == 1) {
       digitalWrite(buttonPin[n], HIGH);
    }
   }

but ledPrevMillis doens't increment, it stays at 700 :frowning: and my LED blinks super fast.

EDIT:

I changed this:

int long ledPrevMillis[] = {0,0,0,0};

to

byte ledPrevMillis[4];
byte ledInterval[] = {700,700,700,700};

it changes values now, but the lights still blink fast.

Also, if i set it up as

if (buttonArray[n] == 1) {
digitalWrite(buttonPin[n], HIGH);
}

the LED is dim (but not apparently blinking as far as i can tell)

LEDbox3_ino.ino (8.92 KB)

All variables associated with millis() should be define as unsigned long.

The maximum value you can have in a byte is 255 - how do expect to store 700 in a byte?

The problem with ledPrevMillis[] not updating is due to the way you have declared the variable. You have it declared inside your function

void blinker(){
  long timer = millis();
  byte ledPrevMillis[4];
  byte ledInterval[] = {10000,10000,10000,10000};

which means that new variables are created every time blinker() is called. You can do one of 2 things - add the word static before the definition static unsigned long ledPrevMillis[4]; or move the declarations to the top of your code so they are global variables (which would be my personal preference).

Also, I don't understand why you are using a time test before you call blinker(). It should be called in every iteration of loop().

...R

    if (buttonArray[n] == 2 | 3 && millis() - ledPrevMillis[n] >= ledInterval[n]){

Please explain, in English, what you think this test is doing. It almost certainly isn't doing that, but fixing it to do what you think it is supposed to do depends on what you think it is supposed to do.

also; use brackets to clearly identify your conditions and the logical operations between them. - || (logial or) is not the same as | (binary or), like && (logical and) is not the same as & (binary and) - i suspect you mean to write:

if (((buttonArray[n] == 2) || (buttonArray[n] == 3)) && ((millis() - ledPrevMillis[n]) >= ledInterval[n])) {

notice the change of | (binary or) to || (logical or) and the brackets (not required, but help) to make it clearer to read.

So many good responses! Thanks.

Robin, I moved the arrays to the top of my sketch, and changed "byte ledInterval" to long int, but it still didn't have how fast the buttons were blinking.

PaulS:

    if (buttonArray[n] == 2 | 3 && millis() - ledPrevMillis[n] >= ledInterval[n]){

Please explain, in English, what you think this test is doing. It almost certainly isn't doing that, but fixing it to do what you think it is supposed to do depends on what you think it is supposed to do.

For each value in buttonArray, if that value equals 2 or 3, and if it is time, blink the lights.

It appeared to be working (but the blinking was fast). I've updated it to ardiri's suggest, as that seems to make more since

LEDbox3_ino.ino (9.19 KB)

For each value in buttonArray, if that value equals 2 or 3, and if it is time, blink the lights.

That is NOT what it is doing. You can't invent shortcuts like that.

ardiri's code is doing what you describe above.

What was my code doing? Causing problems :roll_eyes: ?

It apparently worked but I didn't do a lot of in depth testing

What was my code doing?

Bitwise ORing the true or false returned by (buttonArray[n] == 2) with 3.

(true | 3) or (false | 3) are nowhere near the same as (true || buttonArray[n] == 3) or (false || buttonArray[n] == 3).

Bitwise OR (|) and Logical OR (||) do two completely different things.