Hello all,
I'm hoping for some help on using a for loop, among other things. I'm making a test fixture at work that will automate a valve switching between drawing ambient pressure air, and drawing air through a constricted tube, producing reduced pressure. Eventually, I would also like to incorporate a pressure sensor into the system so I utilized the millis() function rather than delay(). The digital output of the Arduino will go through a relay that's connected to a power supply that will deliver the 12V required to open the valve, as I test I just have an LED where the relay would go, just to have something to turn on and off.
Here is the code:
const int valvePin = 12; // number of the pin switching the valve
int valveState = LOW; // valveState will be used to set the valve
unsigned long previousMillis = 0; // store last time valve was updated
long ReducedPressureTime = 40000; // time of reduced pressure intervals
long AmbientPressureTime = 20000; // time of ambient pressure intervals
void setup() {
pinMode(valvePin, OUTPUT); // pin switching the valve is an output
delay (10000); // Intitial pause before first reduced pressure interval
digitalWrite(valvePin, HIGH); // Start initial reduced inlet pressure interval after 10 second delay
for(int x = 0; x < 3; x++){
unsigned long currentMillis = millis(); // Start timing
if((valveState == HIGH) && (currentMillis - previousMillis >= ReducedPressureTime))
{
valveState = LOW; // Close valve, return to ambient pressure
previousMillis = currentMillis; // remember the time of switch
digitalWrite(valvePin, valveState); // switch valve closed
}
else if ((valveState == LOW) && (currentMillis - previousMillis >= AmbientPressureTime))
{
valveState = HIGH; // Open valve, reduce inlet pressure
previousMillis = currentMillis; // remember the time of switch
digitalWrite(valvePin, valveState); // switch valve open to reduce inlet pressure
}
}
}
void loop() {
}
If working properly it should wait 10 seconds, then turn the LED on for 40 seconds, off for 20 seconds, on for 40, off for 20, on for 40, then turn off and stay off.
Currently, it waits 10 seconds, turns the LED on for 50 seconds, off for 20 seconds, then endlessly cycles the LED on for 40, off for 20 instead of stopping after 3 cycles. Is there something wrong with my for loop? Also curious if anybody knows why that initial "on" cycle of the LED is 50 seconds. I'm rather new to Arduino and this is probably my biggest undertaking so I'm sure I have probably missed more than a few basics, but upon doing Google research on the matter I couldn't find anything that gave more insight to my situation.
Thank you for any and all suggestions!
-Anders
The code you have posted will not give the results you have described. Which one is correct? Did you mean to have the for loop in the loop() function?
Something to have a look at...
The initial value of valveState is LOW and the initial value of previousMillis is zero, so what happens when you get to the if/else statements? (hint: look at the else part). Imagine you are the Arduino and read through your code keeping a track of the variables and most importantly the time.
If you ran this code in the loop() function, where do you tell the valve to finally switch off forever?
I agree with Martin - I can't see how the code you posted could possibly give the results you describe.
You 'for' loop will iterate three times, then everything will stop because 'setup()' only executes once.
You must have changed your code after testing and before posting it.
I had a similar weird thing happen, where the arduino would loop through an impossible set of states. It was caused by my LEDs drawing so much power that they reset the arduino.
The digital output of the Arduino will go through a relay
Not sure this is a great idea - a relay is a heavy inductive load. Be sure to include a flashback diode. I have used a darlington array chip to switch 12v, and it worked fine.
In any case, I would expect your sketch to wait 10 seconds, open the valve, then do nothing.
Try this: (kindly excuse typos, I am just typing this in)
enum State {
START = 0,
INITIAL_DELAY = 1,
CYCLING = 2,
DONE = 3
} state = START;
int cyclesDone = 0;
unsigned long previousMillis = 0; // store last time valve was updated
const long InitialDelayTime = 10000; // initial delay
const long ReducedPressureTime = 40000; // time of reduced pressure intervals
const long AmbientPressureTime = 20000; // time of ambient pressure intervals
const int TARGET_CYCLES = 3;
void setup() {
pinMode(valvePin, OUTPUT); // pin switching the valve is an output
}
void loop() {
unsigned long currentMillis = millis();
switch(state) {
case START:
// this could go in the setup, but I prefer to do all work related to
// state transitions in the loop, so it's in one place, and to just do pinout stuff in the setup
digitalWrite(valvePin, HIGH); // Start initial reduced inlet pressure interval after 10 second delay
previousMillis = currentMillis;
state = INIIAL_DELAY;
break;
case INITIAL_DELAY:
if(currentMillis - previousMillis >= InitialDelayTime) {
digitalWrite(valvePin, HIGH);
previousMillis = currentMillis;
state = CYCLING;
}
break;
case CYCLING:
if((valveState == HIGH) && (currentMillis - previousMillis >= ReducedPressureTime))
{
valveState = LOW; // Close valve, return to ambient pressure
digitalWrite(valvePin, valveState); // switch valve closed
previousMillis = currentMillis; // remember the time of switch
}
else if ((valveState == LOW) && (currentMillis - previousMillis >= AmbientPressureTime))
{
valveState = HIGH; // Open valve, reduce inlet pressure
digitalWrite(valvePin, valveState); // switch valve open to reduce inlet pressure
previousMillis = currentMillis; // remember the time of switch
cyclesDone++;
if(cyclesDone >= TARGET_CYCLES) {
state = DONE;
}
}
break;
case DONE:
// do nothing
break;
}
}
Martin-x, OldSteve, and Delta_G,
Apologies, I posted at the end of my workday after staring at my code onscreen for a good hour or two and mistakenly copied and pasted a second version of the sketch that works exactly as you described (on after 10 seconds, then remains on for as long as I cared to time).
I put the for loop up in setup because I do just want it to run through those cycles three times and then be done. This will be used to supply air to one of our instruments during calibration as it is taking data, I would like the cycling to stop so the technician can then take the data given and put it into a spreadsheet for analysis once the test is done. Thank you Martin, I see why it was doing what it was doing too, and I hadn't yet written the code that would get it to stop looping, mostly because I wasn't quite sure how that is done (sorry!)
PaulMurray, the relay+pwr supply is temporary. Just used them for this initial build to prove it could be done to by manager, then planned to refine it and make it a bit more compact. Will look into the array chip you mentioned too. Thank you for taking the time to type out and give some descriptions to your sketch, I will try it out when I have a free couple of moments today.