0

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

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 sketch – AbramsM101 Jan 30 '17 at 12:13
  • @AbramsM101, see edit 1 – James Waldby - jwpat7 Jan 30 '17 at 17:55

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.