Turning on solenoid that depend on state of LED

Hello everyone,

I've been trying to design a system with LEDs / solenoids / and IR photo-interrupters where an LED turns off after being on for 5 seconds and the solenoid is turned on to dispense water right after LED turns off. After that, I would like the LEDs to wait in an idle position and wait for the next signal which would be waiting for 10 seconds.
Ultimately, I would like to vary the wait time by setting some values within an array.

ex)
int wait_interval[5] = {10, 15, 7, 25, 13}

I also want an IR detector which records IR beams breaking on and off in the background, independent of the LEDs and solenoids.

So basically, the schematic is:

LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 10s -->
LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 15s -->
LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 7s -->

etc.

These are some codes I have written down but I can't seem to combine the two sketches in a working fashion / make the solenoid operation dependent on LED turning off. (Right now, I have the led blinking, but that's not what I intend to do...)

I've been looking around and thought using state machines would be useful but I was wondering if I could just code this using state variables.

Any help would be appreciated! :frowning:
I've been stuck on this for weeks now and it's getting depressing...

// Arduino Sketch 11/5/18
// solenoids / LEDs / IRs

int port_sol = 6;
int port_LED = 3;
int port_IR = 4;

int LED_on_duration = 5000;

unsigned long IRBreakTime;
unsigned long IROffTime;
unsigned long led_previous_time = 0;

boolean previous_State = HIGH;
boolean ledState = LOW;

void setup() {

  pinMode(port_LED, OUTPUT);
  pinMode(port_IR, INPUT);
  pinMode(port_sol, OUTPUT);
  Serial.begin(9600);
  delay(2000); // wait 2 seconds until program starts
  Serial.println(" Hello ");

}

void loop() {
  led_operate();
  record_IR();
}

void led_operate() {
  if (millis() - led_previous_time > LED_on_duration) {
    led_previous_time = millis();

    if (ledState == LOW) {
      ledState = HIGH;
    }

    else {
      ledState = LOW;
    }

    digitalWrite(port_LED, ledState) ;
  }
}

void record_IR() {

  int read_Gate = digitalRead(port_IR);

  if (read_Gate != previous_State) {
    if (read_Gate == LOW) { // IR Broken
      // portNum = 1; 
      IRBreakTime = millis();
      Serial.print("IRBreakTime: ");
      Serial.println(IRBreakTime);
    }
    if (read_Gate == HIGH) {
      IROffTime = millis();
      Serial.print("IROffTime: ");
      Serial.println(IROffTime);
    }
  }
  previous_State = read_Gate;
}

The first thing you need to do is add a setup() function and move the code that's meant to be there into it.

Please always do a Tools > Auto Format on your code before posting it. This will make it easier for you to spot bugs and make it easier for us to read. If you're using the Arduino Web Editor you will not have access to this useful tool but it's still unacceptable to post poorly formatted code. I recommend you to use the standard IDE instead.

Are you looking to pay someone to help you with this code? The reason I ask is because the "Gigs & Collaborations" forum section where you posted this is used for people to offer paid work.

The people on this forum are happy to help you learn for free. It's usually only when someone just wants code or hardware design done for them that we expect payment. If you only want help then we can ask the moderator to move this thread to a more appropriate section where the people who can help are more likely to see it.

Thanks pert for the reply!

I've edited my code so that it includes the setup function
I must have missed it when I was copying and pasting it...

And yes actually I would like it if we could ask the moderator to move the post where it will get more views!
It's my first time posting it so I didn't really know which channel to use....

musical0714:
I've edited my code so that it includes the setup function
I must have missed it when I was copying and pasting it...

Great, but you forgot the auto format. And while you're at it, please remove unnecessary blank lines from your code. One or two to separate code into logical sections is fine but large spaces for no reason or random blank lines just make for more scrolling when we're trying to read your code.

musical0714:
And yes actually I would like it if we could ask the moderator to move the post where it will get more views!

OK, I have done so.

Thanks pert.
I've fixed the blank lines and did autoformat!

Hopefully the code is more readable now

And thank you for requesting to move it to a different forum!
I appreciate it!

Hello everyone,

/
I've originally posted this post on "Gigs and Collaboration" but realized that's not the actual forum I wanted.
Reposting the same content below to get more help / wider exposure.
/

I've been trying to design a system with LEDs / solenoids / and IR photo-interrupters where an LED turns off after being on for 5 seconds and the solenoid is turned on to dispense water right after LED turns off. After that, I would like the LEDs to wait in an idle position and wait for the next signal which would be waiting for 10 seconds.
Ultimately, I would like to vary the wait time by setting some values within an array.

ex)
int wait_interval[5] = {10, 15, 7, 25, 13}

I also want an IR detector which records IR beams breaking on and off in the background, independent of the LEDs and solenoids.

So basically, the schematic is:

LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 10s -->
LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 15s -->
LED ON (5s) ---> LED OFF --(True)--> Solenoid On (1s) ---> Solenoid Off --(True) --> WAIT for 7s -->

etc.

These are some codes I have written down but I can't seem to combine the two sketches in a working fashion / make the solenoid operation dependent on LED turning off. (Right now, I have the led blinking, but that's not what I intend to do...)

I've been looking around and thought using state machines would be useful but I was wondering if I could just code this using state variables.

Any help would be appreciated! :frowning:
I've been stuck on this for weeks now and it's getting depressing...

// Arduino Sketch 11/5/18
// solenoids / LEDs / IRs

int port_sol = 6;
int port_LED = 3;
int port_IR = 4;

int LED_on_duration = 5000;

unsigned long IRBreakTime;
unsigned long IROffTime;
unsigned long led_previous_time = 0;

boolean previous_State = HIGH;
boolean ledState = LOW;

void setup() {

  pinMode(port_LED, OUTPUT);
  pinMode(port_IR, INPUT);
  pinMode(port_sol, OUTPUT);
  Serial.begin(9600);
  delay(2000); // wait 2 seconds until program starts
  Serial.println(" Hello ");

}

void loop() {
  led_operate();
  record_IR();
}

void led_operate() {
  if (millis() - led_previous_time > LED_on_duration) {
    led_previous_time = millis();

    if (ledState == LOW) {
      ledState = HIGH;
    }

    else {
      ledState = LOW;
    }

    digitalWrite(port_LED, ledState) ;
  }
}

void record_IR() {

  int read_Gate = digitalRead(port_IR);

  if (read_Gate != previous_State) {
    if (read_Gate == LOW) { // IR Broken
      // portNum = 1; 
      IRBreakTime = millis();
      Serial.print("IRBreakTime: ");
      Serial.println(IRBreakTime);
    }
    if (read_Gate == HIGH) {
      IROffTime = millis();
      Serial.print("IROffTime: ");
      Serial.println(IROffTime);
    }
  }
  previous_State = read_Gate;
}

musical0714:
Reposting the same content below to get more help / wider exposure.

Please do not cross-post.

I've originally posted this post on "Gigs and Collaboration" but realized that's not the actual forum I wanted.

Next time click Report to moderator then ask for the thread to be moved.

Thread moved. Threads merged.

Thank you!
This is my first time using the forum so I wasn't sure of the customary practices.
Won't do it in the future!

musical0714:
I've been looking around and thought using state machines would be useful but I was wondering if I could just code this using state variables.

You are using a different set of words to describe essentially the same concept.

How are your object oriented skills?

Not good at all....

I recently stumbled upon PaulMurray's github code on OOP on Arduino and reading through it right now to get more insights and hints.
http://paulmurraycbr.github.io/ArduinoTheOOWay.html

But other than that I have no programming background whatsoever...

// Arduino Sketch 11/5/18
// solenoids / LEDs / IRs

int port_sol = 6;
int port_LED = 3;
int port_IR = 4;

// int LED_on_duration = 5000;
#define LED_on_duration 5000L

unsigned long IRBreakTime;
unsigned long IROffTime;

boolean previous_State = HIGH;
boolean ledState = LOW;
boolean LED_switched_off = false;   // Did we just turn the LED off?
boolean solenoid_operate_Active = false;

#define Solenoid_On_Period 1000L // how long the solenoid will be on for
#define NUM_TIMES 5
int wait_interval[NUM_TIMES] = {10000, 15000, 7000, 25000, 13000};


void setup() {

  pinMode(port_LED, OUTPUT);
  pinMode(port_IR, INPUT);
  pinMode(port_sol, OUTPUT);
  Serial.begin(9600);
  delay(2000); // wait 2 seconds until program starts
  Serial.println(" Hello ");

}

void loop() {
  led_operate();
  solenoid_operate();
  record_IR();
}

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) ;
    }
  }
}

void record_IR() {

  int read_Gate = digitalRead(port_IR);

  if (read_Gate != previous_State) {
    if (read_Gate == LOW) { // IR Broken
      // portNum = 1;
      IRBreakTime = millis();
      Serial.print("IRBreakTime: ");
      Serial.println(IRBreakTime);
    }
    if (read_Gate == HIGH) {
      IROffTime = millis();
      Serial.print("IROffTime: ");
      Serial.println(IROffTime);
    }
  }
  previous_State = read_Gate;
}

void solenoid_operate() {

  static unsigned long solenoid_On_Time = 0;
  static unsigned long solenoid_Off_Time = 0;
  static boolean solenoidStatus = LOW;
  static int time_index = 0;
  
  if (ledState == HIGH) {       // Only do stuff if the LED is off
    // check the LED_switch_off status. if it is TRUE, turn on the solenoid, and record the time.
    
    if (LED_switched_off) {
      LED_switched_off = false;
      solenoidStatus = HIGH;
      digitalWrite(port_sol, solenoidStatus);
      solenoid_On_Time = millis();
      solenoid_operate_Active = true;
    }
    
    // check the solenoid is turned on, and if the on period has expired.
    // NOTE. The second part of the if expression below only gets executed if solenoidStatus is TRUE.
    if ((solenoidStatus == HIGH) && ((millis() - solenoid_On_Time) >= Solenoid_On_Period)) {
      solenoidStatus = LOW;
      digitalWrite(port_sol, solenoidStatus);
      solenoid_Off_Time = millis();
    }
    
    // Check to see if the Solenoid is off and if the off period has expired
    if ((solenoidStatus == LOW) && ((millis() - solenoid_Off_Time) >= wait_interval[time_index])) {
      
      // the solenoid off period has expired. update solenoid_operate_Active so that led_Operate can turn the LED on again
      // and update the array index in preparation for the next solenoid activation phase
      solenoid_operate_Active = false;
      time_index += 1;
      if (time_index >= NUM_TIMES)
        time_index = 0;            // just to ensure that we do not go out of bounds on the delay times array
    }
  }
}

So, the above should (I think) pretty well do what you want.
HOWEVER, there is a (pretty obvious) error in there which will definitely make it not work unless you find it. (As I say, it is pretty obvious)

But I put it in there so that you could look through and figure out how the code works.

Another however, (however) I have not debugged it other than to ensure that it compiles :wink:
So test it out pretty thoroughly.

musical0714:
I've been trying to design a system with LEDs...

How many?

...solenoids...

How many?

...IR photo-interrupters...

Ditto.

My guess is they are ganged: for every LED there is a solenoid and a photo-interrupter.

Thank you darrob!

I've been testing it and it seems to work as I intended.
I'm guessing the error was at :

if (ledState == HIGH) { // Only do stuff if the LED is off
// check the LED_switch_off status. if it is TRUE, turn on the solenoid, and record the time.}

where I had to change HIGH --> LOW?

I do have a few questions though.

In this function:

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) ;
    }
  }
}

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

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?

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

Thanks so much!

Hi codingbadly,

Thanks for the reply

So right now, I'm just working with one LED, one solenoid, and one photo-interrupter to test things out but eventually I want to expand this project so that I have 6 LEDs, 1 solenoids, and 6 photo-interrupters.

And yes the solenoids and photo-interrupters will be paired because I am planning to record each time I break the photogate to receive water from solenoid. (Solenoid and photogate will be located in the same port, and 5 LEDs and 5 photogates will be in their 5 respective ports. (6 ports in total))

But state-wise, the solenoid and photointerrupter will be independent; the solenoid will dispense water only after the correct LED goes off (out of the 5 LEDs) and the photogate senses that a response has been made in the same port with the correct LED.

So basically the photogate is there just to record signals, nothing more.

musical0714:
Not good at all....

If you have an interest in applying such things to your project just say.

Otherwise I am going to assume @darrob has set you on the right path.

@CodingBadly

Oh I am very interested in learning how to code Arduino in an OOP way

I've been looking at some tutorials / websites (like adafruit) on OOP (A classy solution | Multi-tasking the Arduino - Part 1 | Adafruit Learning System) on Arduino but if you can give me more pointers / guidelines / examples that would be better!

Thanks so much!

Step 1: Identify the things. Using the description you provided what are the things in your system?

I'm assuming I would need three different classes: solenoid class, LED class, IR class
I'll try coming up with a code and post it here soon!

Is "solenoid" a class? Or is "solenoid interface" a class? Aren't those two separate things?

Is "LED" a class? Or is "LED manager" a class? Are those two things?

Ditto for "IR class".

I recall you mentioning, directly or indirectly, "timer". That seems like a thing.

I also recall something about a "state machine". That also seems like a thing.

You mentioned breaking a light beam. Whatever does that is a thing.

musical0714:
I'm assuming I would need three different classes

Maybe. Some things will be classes. Some things will be instances. Some will be properties. Some will be external. Some will be entirely conceptual. Some may not fit well anywhere. (In a complete model, even you, the developer, is included.)

The next step is to decide how your things interact with each other. That will help you put your things into appropriate boxes (class, instance, property, external, trash).