Turning on solenoid that depend on state of LED

musical0714:
I'm guessing the error was at :

where I had to change HIGH --> LOW?

That's right.

musical0714:
Can you explain why
digitalWrite(port_LED, ledState); is inside the if loop?

It's actually within two if blocks.

The rational is this
If the LED is active, there is not need to do anything to the Solenoid. Similarly, if the Solenoid is active, there is no need to do anything with the LED.

The program works fine but I was just wondering because if it is inside the if clause then ledState will be assigned to HIGH state and it would never enter the if (ledState == LOW) clause again?

A couple of lines down from that if statement, we then check to see if the LED has been on for long enough. If the LED has been on for the predetermined amount of time, we turn it off (ie set ledState to LOW).

I'm just asking because I'm curious and want to learn more about the if clause functionality. I've always thought that the Arduino loops around so fast that it's impossible to "trap" a functionality inside an if clause

How fast a system runs has no impact on logic. If a condition is true or false, it will be true or false no matter how quickly or slowly you evaluate the condition.

I'd suggest the you get a piece of paper and run through the logic, line by line.
Put a heading Up top
LOOP 1:
Run through the code, line by line as if you have just turned the Arduino on. Write down the Logical variables and the digital inputs and their values. record each time that changes.
eg

ledState : HIGH -> LOW

led_On_Time: 0 -> 1000 for things like time variables, just start at 1000

Once you have come to the end of loop(), write a line under your output, then put another heading.
LOOP 2:
Run through the code again. This time, however, assume that 1 second (ie 1000 milliseconds) has passed since the last runthrough (don't worry about setup()). Use the values you wrote down for the last pass each time you encounter a variable.
Again, write the variable name out, and record their values.

Repeat this for the next 7 loops, each loop 1 second apart.

Finally, assume that and additional 10 seconds have passed, just to test the case where the solenoid has turned on, then turned off and the delay before the LED turns on again expired.

It does seem a bit tedious, but.. doing the above is an important exercise for a few reasons.

You can get an idea of how the program actually flows.
You can follow the logic
You can catch any logic errors
It really drives home the fact that loop() loops. Once that fact is fully understood, you suddenly 'get' how you can use it to drive your program :wink:

**EDIT
Just a quick addition.
In some functions you'll see a declaration like

static boolean someBool = false;

The keyword static does two things.

  • The variable will get initalised only on the first passthrough
  • The value of the variable will be persistent between calls. In other words: on this passthrough, the variable will have the same value it was at the end of the last passthrough.

Hello darrob,

Thanks so much for your help and suggestions!
I just finished going through the loops on a piece of paper as you suggested.
It really did help me understand better about the nature of loops.

But I think I'm still confused as to the position of this statement: (or any other digitalWrite statements in the code)

digitalWrite(port_LED, ledState);

Wouldn't this need to be outside the second if clause in order for the LED to retain its HIGH value?

Something like this:

void led_operate() {
  
  static unsigned long led_On_Time = 0;
  
  if (solenoid_operate_Active == false) {  // Only do stuff if we're not playing with the solenoid
    // if the LED is OFF, turn it on
    if (ledState == LOW) {
      ledState = HIGH;
      led_On_Time = millis();
    }
      digitalWrite(port_LED, ledState);

    // check to see if the LED has been on for long enough
    if (millis() - led_On_Time > LED_on_duration) {
      // yup, turn it off and update LED_switched_off so that the solenoid can do its thing 
      ledState = LOW;
      LED_switched_off = true;
    }
      digitalWrite(port_LED, ledState) ;
  }
}

I understand that the led_operate function doesn't get executed unless the solenoid_operate_Active boolean is false
(if (solenoid_operate_Active == false)) and will keep looping around this function as long as solenoid_operate_Active is false. (which is until the the LED_on_duration expires and led_State is assigned LOW at which point it enters the solenoid_operate function and toggles the solenoid_operate_Active boolean)

My question is, how can the compiler enter this code the second time when ledState is assigned to HIGH after the first loop?

if (ledState == LOW) {
      ledState = HIGH;
      digitalWrite(port_LED, ledState);
      led_On_Time = millis();
    }

If it can't enter it the second time, how can it digitalWrite the second time?
This is why I thought I needed to put the digitalWrite statement after the if clause, since the first if clause will evaluate to TRUE anyway (if (solenoid_operate_Active == false)) and digitalWrite will remain in the scope (within the first if clause)

Let me know if my logic is wrong (probably is...) or if I'm missing something.
Thanks again for all your time and input darrob!

Let's look at the function again

void led_operate() {
 
  static unsigned long led_On_Time = 0;
 
  if (solenoid_operate_Active == false) {  // Only do stuff if we're not playing with the solenoid
    // if the LED is OFF, turn it on
    if (ledState == LOW) {
      ledState = HIGH;
      digitalWrite(port_LED, ledState);
      led_On_Time = millis();
    }
    // check to see if the LED has been on for long enough
    if (millis() - led_On_Time > LED_on_duration) {
      // yup, turn it off and update LED_switched_off so that the solenoid can do its thing
      ledState = LOW;
      LED_switched_off = true;
      digitalWrite(port_LED, ledState) ;
    }
  }
}

Let us assume that the code has been running happily for some time. At a certain point, the Solenoid delay period expires and it is now time for the LED to turn on again
The variable solenoid_operate_Active is false, and we can enter the block that actually operates the LED.

This line then evaluates as TRUE

if (ledState == LOW) {

and the following lines get executed

  ledState = HIGH;
  digitalWrite(port_LED, ledState);
  led_On_Time = millis();

The important bit is this line

led_On_Time = millis();

So at this point in time, the LED is on, and ledState is set to HIGH, and we know when we turned the LED on

Fast Forwards 5 seconds...

this line is FALSE

if (ledState == LOW) {

but... the next if statement evaluates as TRUE

if (millis() - led_On_Time > LED_on_duration) {

(This is because we recorded when we turned the LED on in the previous if statement)
because it is true, the next lines get executed

  ledState = LOW;
  LED_switched_off = true;
  digitalWrite(port_LED, ledState) ;

so, after 5 seconds, the LED get turned OFF and ledState get set to LOW. This means that the next time the solenoid delay has expired, we enter the block with ledState as LOW

That explains the logic behind the code.

Now the only other thing that I think you may be confused about.
You do not need to perform a digitalWrite each execution of the loop.
One a digital pin gets set to a value, it stays at that value until the next time it gets set.
In other words, once the LED gets turned on, it stays on until it gets turned OFF

darrob:
Now the only other thing that I think you may be confused about.
You do not need to perform a digitalWrite each execution of the loop.
One a digital pin gets set to a value, it stays at that value until the next time it gets set.
In other words, once the LED gets turned on, it stays on until it gets turned OFF

On reflection, I think this may have been what you were asking about.
Writing HIGH or LOW to a digital port is exactly like flipping a light switch. It stays where you left it until you decide to flip it again.
You don't need to continuously turn a light switch on if you want to see in the dark :wink:

Hello Darrob

[/quote]

darrob:
On reflection, I think this may have been what you were asking about.
Writing HIGH or LOW to a digital port is exactly like flipping a light switch. It stays where you left it until you decide to flip it again.
You don't need to continuously turn a light switch on if you want to see in the dark :wink:

Yes Actually this was exactly what I was confused about!
I've always thought that I had to continuously turn the light on instead of toggling (flipping) it
Thanks so much for explaining this to me!