Go Down

Topic: event is not properly executing when using millis in "else if" statement (Read 603 times) previous topic - next topic

iriseth

I'm working on a simple project pulls up a relay for 5, 30, 90 minutes based on a keypress. (like a simple countdown timer) the goal is to put the relay LOW after the time passed.
I've been adding 3 leds to control what's going on + a single button
For some reason, the led and the relay is not getting to LOW state once the timer reaches the time.
seems that the led on the relay shows that its low, but I can't actually hear that the contactors switch, also the led remains up. any ideas?

I found a ton of issues with my code in the meantime. millis() is not starting only when the program loads (needs to figure out where to reset/start the countdown) (relay will gets pulled down after time pass without keypress...)

also the original problem -> why the led is not pulled down+where to reset states after the end of each cycle....


here's my code:

Code: [Select]
long halfhour = 1800000; // 30 min
long hour = 3600000; // 3600000 milliseconds in an hour
long ninetymin = 5400000; //90 minutes
long fifteenmin = 900000; // 15 min
long fivemin = 300000; // 5 min
long minute = 60000; // 60000 milliseconds in a minute

const int buttonPin = 12;
const int led1 = 9;
const int led2 = 8;
const int led3 = 5;
const int relay1 = 10;
unsigned long currentMillis;
unsigned long startMillis;

int counter = 0;
void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(relay1, OUTPUT);
}


void loop()
{
  int buttonState;
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) // light the LED
  {
    counter++;
    delay(150);
  }

  if (counter == 0)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(relay1, LOW);
  }
  
  else if (counter == 1)
  {
    digitalWrite(led1, HIGH);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (millis() - startMillis >= ninetymin) {
    digitalWrite(led2, HIGH);
    digitalWrite(relay1, LOW);
    startMillis = currentMillis;  
     }
   }
  else if (counter == 2)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, LOW);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (millis() - startMillis >= hour) {
    digitalWrite(relay1, LOW);
    digitalWrite(led2, LOW);
     startMillis = currentMillis;
    }  
  }

  else if (counter == 3)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, HIGH);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (millis() - startMillis >= minute) {
    digitalWrite(relay1, LOW);
    digitalWrite(led3, LOW);
    startMillis = currentMillis;
    }  
  }

  else
  {
    counter = 0;
  }
}

Grumpy_Mike

Can you post the schematic of you setup please.

Note you should be looking for when the buttons BECOMES pressed not when it is pressed.

noiasca

can you try to initialize your longs with a value as long?

and by the way, why long and not unsigned long?

Code: [Select]

unsigned long halfhour = 1800000UL; // 30 min
how to react on postings:
- post helped: provide your final sketch, say thank you & give karma.
- post not understood: Ask as long as you understand the post
- post is off topic (or you think it is): Stay to your topic. Ask again.
- else: Ask again.

iriseth

hi, thanks much for your help / suggestion.
updated to use UL. but this is just a misc thing :)

Code: [Select]
unsigned long halfhour = 1800000UL; // 30 min
unsigned long hour = 3600000UL; // 3600000 milliseconds in an hour
unsigned long ninetymin = 5400000UL; //90 min
unsigned long fifteenmin = 900000UL; // 15 min
unsigned long fivemin = 300000UL; // 5 min
unsigned long minute = 60000UL; // 60000 milliseconds in a minute

const int buttonPin = 12;
const int led1 = 9;
const int led2 = 8;
const int led3 = 5;
const int relay1 = 10;
unsigned long currentMillis;
unsigned long startMillis;

int counter = 0;
void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(relay1, OUTPUT);
}


void loop()
{
  int buttonState;
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) // light the LED
  {
    counter++;
    delay(150);
  }

  if (counter == 0)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(relay1, LOW);
  }
 
  else if (counter == 1)
  {
    digitalWrite(led1, HIGH);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
//    delay (5000);
    digitalWrite(relay1, HIGH);
   
    if (millis() - startMillis >= ninetymin) {
    digitalWrite(led2, HIGH);
    digitalWrite(relay1, LOW); 
     }
    startMillis = currentMillis;
   }
  else if (counter == 2)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, LOW);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (millis() - startMillis >= hour) {
    digitalWrite(relay1, LOW);
    digitalWrite(led2, LOW);
     startMillis = currentMillis;
    } 
  }

  else if (counter == 3)
  {
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, HIGH);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (millis() - startMillis >= minute) {
    digitalWrite(relay1, LOW);
    digitalWrite(relay1, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(led3, LOW);
    startMillis = currentMillis;
//    digitalWrite(relay1, LOW);
//    digitalWrite(led3, LOW);
    } 
  }

  else
  {
    counter = 0;
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(relay1, LOW);
  }
}

iriseth

have no sketch really, but a photo of the current circuit. will check how to control the button to see when it BECOME pressed. not sure at this stage what's the difference. Also the point is that the button switches between the modes, so the appropriate leds are lit up, it starts the cycle to wait (though I have to reset the timer somewhere at the beginning of each else statement because now it starts when the program starts) the problem is that the led is not pulling down.


iriseth

I think I finally made this working. will needs some beautify (to wait a few sec before counter start, etc) but it does what I wanted:
Code: [Select]
unsigned long halfhour = 1800000UL; // 30 min
unsigned long hour = 3600000UL; // 3600000 milliseconds in an hour
unsigned long twohours = 7200000; // two hours
unsigned long ninetymin = 5400000UL; //90 minutes
unsigned long fifteenmin = 900000UL; // 15 min
unsigned long fivemin = 300000UL; // 5 min
unsigned long minute = 60000UL; // 60000 milliseconds in a minute

const int buttonPin = 12;
const int led1 = 9;
const int led2 = 8;
const int led3 = 5;
const int relay1 = 10;

unsigned long startMillis;
unsigned long previousMillis = 0;

int counter = 0;
void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  pinMode(led1, OUTPUT);
  pinMode(led2, OUTPUT);
  pinMode(led3, OUTPUT);
  pinMode(relay1, OUTPUT);
}


void loop()
{
  unsigned long currentMillis = millis();
  int buttonState;
  buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) // light the LED
  {
    counter++;
    delay(150);
  }

  if (counter == 0)
  {
    currentMillis = millis();
    previousMillis = 0;
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
    digitalWrite(relay1, LOW);
  }
 
  else if (counter == 1)
  {
    currentMillis = millis();
    previousMillis = 0;
    digitalWrite(led1, HIGH);
    digitalWrite(led2, LOW);
    digitalWrite(led3, LOW);
//    delay (5000);
    digitalWrite(relay1, HIGH);
    if (currentMillis - previousMillis >= ninetymin) {
    counter = 0;
    previousMillis = currentMillis;
    }
  }
  else if (counter == 2)
  {
    currentMillis = millis();
    previousMillis = 0;
    digitalWrite(led1, LOW);
    digitalWrite(led2, HIGH);
    digitalWrite(led3, LOW);
    digitalWrite(relay1, HIGH);
    if (currentMillis - previousMillis >= fivemin) {
    counter = 0;
    previousMillis = currentMillis;
    } 
  }

  else if (counter == 3)
  {
    currentMillis = millis();
    previousMillis = 0;
    digitalWrite(led1, LOW);
    digitalWrite(led2, LOW);
    digitalWrite(led3, HIGH);
    digitalWrite(relay1, HIGH);
    if (currentMillis - previousMillis >= minute) {
    counter = 0;
    previousMillis = currentMillis;
    } 
  }
  else
  {
    counter = 0;
  }
}

Grumpy_Mike

Quote
will check how to control the button to see when it BECOME pressed. not sure at this stage what's the difference.
The difference is that when the button becomes pressed you can detect it but not detect it when the button is constantly held down. In technical terms is is known as triggering on an edge not a level.

To do this you keep a track of the last state of the button and only trigger the increment in the count when the button is LOW and when the current state is not equal to the last state. There is an example in the IDE called state change detection, look at that and try and understand what is happening.

You should not have to have any delays if you write your code correctly.

Replace that long chain of if ... else if statements with a switch ... case structure.


Go Up