I am trying to use the millis()
function to start a countdown of 3 seconds when I turn my potentiometer to high travel. My code so far starts the timer at the beginning of the loop or when reset is hit or when the sketch is uploaded to the board. I need the countdown to start when the potentiometer reaches high travel.
The goal of the program is that when the potentiometer reaches high travel, PumpOne starts (HIGH) and if the potentiometer does not reach low travel before 3 seconds, PumpTwo will come on (HIGH). I am trying to simulate a water tank with two pumps (LEDs in this case) and the potentiometer high and low travel representing the high and low levels of the tank respectively.
I've updated the code since the original post but the timer still starts from the beginning of the program and not when L> Plim1.
Here's the code:
int Pump1 = 3; // Declare Blue LED in pin 3 to simulate Pump 1
int Pump2 = 4; // Declare Green LED in pin 4 to simulate Pump 2
int Alarm = 2; //Delcare Red LED in pin 2 to simulate Alarm
int TDCRPot = A0; // Declare Potentiometer(TDCRPot) an int and assign to pin A0
int L; //Declare L a variable to read the High and Low
//travel of the potentiometer
float Plim1 = 1000; // pot reading for pump 1 turn on
float Plim2 = 1000; // pot reading for pump 2 turn on
float Llim = 100; //pot reading to turn both pumps off
unsigned long T; // current time
unsigned long T1 = 0; // P1 on time
boolean P1 = false;
boolean P2 = false;
boolean Alarmstate = false;
unsigned long Tlim = 3000;
void setup() {
Serial.begin(9600); //Turn on Serial monitor for troubleshooting
//purposes and set to 9600 baud
pinMode(Pump1, OUTPUT); //Declare Blue LED(PumpOne) an output
pinMode(Pump2, OUTPUT); //Declare Green LED(PumpTwo) an output
pinMode(Alarm, OUTPUT); //Declare Red LED(Alarm) an output
pinMode(TDCRPot, INPUT); //Declare Potentiometer(TDCRPot) an input
}
void loop() {
L = analogRead(TDCRPot); //Read the voltage from the Potentiometer pin
if (!P1 && L > Plim1) {
T = millis();
digitalWrite(Pump1, !P1);
}
if (Pump1 != P1 && T - T1 > Tlim && L > Plim2) {
digitalWrite(Pump2, !P2);
}
if (Pump1 != P1 && L < Llim ) {
digitalWrite(Pump1, P1);
digitalWrite(Pump2, P2);
}
}
1 Answer 1
The statement TDCRLevel = analogRead(TDCRPot);
will almost always set TDCRLevel
to a non-zero value; hence the && TDCRLevel
term of your last if
statement almost always is satisfied. The only time it won't be satisfied is when TDCRLevel
is exactly zero.
When TDCRLevel >= 1000
is first satisfied, it's likely to be true for some while; during that time, each pass through loop()
will toggle Bluestate
and set previousMillisBlue = currentMillis
. This happens many times per millisecond while TDCRLevel
has a high value. Whether Bluestate
is on or off when TDCRLevel
goes below 1000 is a fairly random outcome.
To handle the process properly, set up a state machine, using either one state-number variable or several variables to maintain state. Change states when conditions tied to state, TDCRLevel
, and time are met.
More simply, something like the following might work.
loop:
if !P1 and L > Plim1:
Set P1; record T1
if P1 and T-T1 > Tlim and L > Plim2:
Set P2
if (P1 or P2) and L < Llim:
Turn off pumps, clear P1 and P2
where P1, P2 represent pump states; T represents current time and T1 represents time that P1 most recently turned on; L = analogRead(TDCRPot); Plim1 and 2 are pot levels for pump turnons; Llim = low level for pump turnoffs; Tlim = desired time delay before pump 2 comes on.
Edit 1: The above is pseudocode, rather than any simulacrum of valid C or C++. As such, you may need to add sets of parentheses and brackets, substitute meaningful variable names, etc.
Note that the constants Plim1, Plim2, Tlim, Llim
should be declared via either const int
declarations, or via enum {}
constructs (enum
declares only integer constants), if they are integers rather than floats. For example, do like either of
const int Plim1 = 1000; // level for pump1 turnon
const int Plim2 = 1000; // level for pump2 turnon
//etc
or
enum { Plim1=1000, Plim2=1000, Tlim=3000, Llim=100};
The phrase "Set P1; record T1" corresponds to code like
P1 = true;
digitalWrite(Pump1, HIGH);
T1 = millis();
in braces. If you don't set P1 and record T1 as current time, the process won't work. P1 and P2 represent state variables, not constants.
The phrase "if P1 and T-T1> Tlim and L> Plim2: Set P2" corresponds to code like
if (P1 && (T - T1 > Tlim) && (L > Plim2)) {
P2 = true;
digitalWrite(Pump2, HIGH);
}
The phrase "if (P1 or P2) and L < Llim: Turn off pumps, clear P1 and P2" corresponds to code like
if((P1 || P2) && (L < Llim)) {
P1 = P2 = false;
digitalWrite(Pump1, LOW);
digitalWrite(Pump2, LOW);
}
-
I've re-edited the question, The timer should start after Plim 1* but starts at the beginning of the sketchAbramsM101– AbramsM1012017年01月30日 12:13:11 +00:00Commented Jan 30, 2017 at 12:13
-
@AbramsM101, see edit 1James Waldby - jwpat7– James Waldby - jwpat72017年01月30日 17:55:06 +00:00Commented Jan 30, 2017 at 17:55