3

I have a statement:

if(control > 100 && control < 130)
{

  //count time 30 seconds and open pin1 for 3 seconds.

}

How can I count 30 seconds and open a pin for 3 seconds?

  • 1
    Arduino measures time in millis() and delay() and in milliseconds, so to convert counts of time in seconds to milliseconds would be 1000x. – Dave X Feb 21 '16 at 19:39
4

A non-blocking version is often needed as there is often other tasks to be performed during the wait. The "blink-without-delay"-pattern is a solution but unfortunately it becomes tedious to use with several time periods and logic.

The Timemark library helps abstract the pattern and hide a lot of the details. The below sketch uses two timemarks and a simple state-machine to help reduce complexity.

#include <Timemark.h>

Timemark turnOnWait(30000L);
Timemark turnOffWait(3000L);

enum {
  IDLE,
  TURN_ON_WAIT,
  TURN_OFF_WAIT
};
int state = IDLE;

const int pin = 4;
int control = 0;

void setup()
{
  ...
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void loop()
{
  ...
  switch (state) {
  case IDLE:
    if ((control > 100) && (control < 130)) {
      turnOnWait.start();
      state = TURN_ON_WAIT;
    }
    break;
  case TURN_ON_WAIT:
    if (turnOnWait.expired()) {
      digitalWrite(pin, HIGH);
      turnOffWait.start();
      state = TURN_OFF_WAIT;
    }
    break;
  case TURN_OFF_WAIT:
    if (turnOffWait.expired()) {
      digitalWrite(pin, LOW);
      state = IDLE;
    }
    break;
  default:
    ;
  }
  ...
}

Two timemarks are used for clarity. It is possible to use a single timemark and reinitiate it with a new time limit.

#include <Timemark.h>

const uint32_t TURN_ON_TIMEOUT = 30000L;
const uint32_t TURN_OFF_TIMEOUT = 3000L;

Timemark timemark;

enum {
  IDLE,
  TURN_ON_WAIT,
  TURN_OFF_WAIT
};
int state = IDLE;

const int pin = 4;
int control = 0;

void setup()
{
  ...
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void loop()
{
  ...
  switch (state) {
  case IDLE:
    if ((control > 100) && (control < 130)) {
      timemark.limitMillis(TURN_ON_TIMEOUT);
      timemark.start();
      state = TURN_ON_WAIT;
    }
    break;
  case TURN_ON_WAIT:
    if (timemark.expired()) {
      digitalWrite(pin, HIGH);
      timemark.limitMillis(TURN_OFF_TIMEOUT);
      timemark.start();
      state = TURN_OFF_WAIT;
    }
    break;
  case TURN_OFF_WAIT:
    if (timemark.expired()) {
      digitalWrite(pin, LOW);
      state = IDLE;
    }
    break;
  default:
    ;
  }
  ...
}

The Scheduler library allows the blocking version (delay) to be used. Non-blocking is achieved by context switching on yield() or delay(). Below is a rewrite using this style:

#include <Scheduler.h>

const int pin = 4;
int control = 0;

void setup()
{
  ...
  Scheduler.start(setupController, loopController);
}

void loop()
{
  ...
  delay(1000);
}

void setupController()
{
  ...
  pinMode(pin, OUTPUT);
  digitalWrite(pin, LOW);
}

void loopController()
{
  ...
  if ((control > 100) && (control < 130)) {
    delay(30000L);
    digitalWrite(pin, HIGH);
    delay(3000L);
    digitalWrite(pin, LOW);
  }
  else {
    delay(100);
  }
}

Cheers!

2

What you can also use is non-blocking code, where delay() would block for the 30s. My suggesting makes use of millis(), one could say similar to blink without delay code example.

Here is an example of what you could place in the loop:

//declared variable stuff here

if(control > 100 && control < 130 && !toggled_bit){

    toggled_bit = true;     //to control the timing section
    start_time = millis();
}
else if (!(control > 100 && control < 130)){
    toggled_bit = false;
}

if (toggled_bit){
        test1 = millis()
    if(test1 - start_time > 30000){

        digitalWrite(1, HIGH);
            short_wait = millis();
            // wait for 3s after fist time
                if(short_wait - start_time > 33000)
                    digitalWrite(1, LOW);
                    toggled_bit = false;
                }
        }
}

// other code here

The code sets a 'flag', toggled_bit, which is checked by the if() later on in the loop, also it sets start_time. It then checks if 30s has passed and then waits an extra 3s to turn the output off after being turned on. It then resets the toggled_bit.

This will also allow you to check or do other things while waiting.

1

Rearrange the Blink example:

if(control>100 && control<130)
{
  //**count time 30 seconds and open pin1 for 3 seconds.**
  delay(30000);             // wait for 30 seconds
  digitalWrite(1, HIGH);    // turn the LED on (HIGH is the voltage level)
  delay(3000);              // wait for 3 seconds
  digitalWrite(1, LOW);     // turn the LED off by making the voltage LOW
}
1

Well 30s equals 30,000ms and the arduino comes with a native function that counts in Milliseconds so the following code should work:

Time = millis();  //time passed before entering loop…
If((control > 100) && (control < 130))
{ 
While (millis() < Time + 30000) //counts to Thirty seconds 
{
While (millis() < Time + 3000) // counts to three seconds
{
DigitalWrite(1,HIGH);
};};};

This way you can add some code in the while loops if u want to multitask.

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.