1

I want to start a relay, have it run for 3 seconds, stop for 10 seconds, repeat.

I can't use delay, because I have a motor driver starting / stopping every 100 milis.

So I put together this code, but it does not work. Any help appreciated.

There's a 500ms delay to stop too much debugging info.

Also for some reason, tenSecondsBool switches to true as soon as you run the code.

unsigned long threeSeconds=3000; // the time we need to wait
unsigned long threeSecondsMillis=0; // millis() returns an unsigned long.
unsigned long fourSeconds=7000; // the time we need to wait
unsigned long fourSecondsMillis=0; // millis() returns an unsigned long.



unsigned long previousMillis=0; // millis() returns an unsigned long.
bool ledState = false; // state variable for the LED
bool led2State = false; // state variable for the LED
unsigned long tenSecondMilis=0; // millis() returns an unsigned long.
unsigned long tenSeconds=10000; // the time we need to wait

unsigned long paliGasiMilis=0; // millis() returns an unsigned long.
unsigned long paliGasi=1000; // the time we need to wait

unsigned long ventMilis=0; // millis() returns an unsigned long.
unsigned long ventInt=100; // the time we need to wait

bool threeSecondBool = false;
bool tenSecondBool = false;

int Fin1 = D7;

#define enA D1
#define in1 D2 
#define in2 D3
#define button 4

int rotDirection = 0;
int pressed = false;

void setup() {
  Serial.begin(9600); // send and receive at 9600 baud
  pinMode(enA, OUTPUT);
  pinMode(in1, OUTPUT);
  pinMode(in2, OUTPUT);
  pinMode(button, INPUT);
  digitalWrite(in1, LOW);
  digitalWrite(in2, HIGH);
  pinMode(Fin1, OUTPUT);
  digitalWrite(Fin1, HIGH);
  threeSecondBool = false;
  tenSecondBool = false;
}

void loop() {


 unsigned long currentMillis = millis(); // grab current time

 if ((unsigned long)(currentMillis - tenSecondMilis) >= tenSeconds) {
    Serial.print("---------------\n");
    Serial.print("10 second end\n");
    Serial.print("---------------\n");
    tenSecondBool = true;
    tenSecondMilis = millis();
} 

Serial.print("10 second bool = ");
Serial.print(tenSecondBool);
Serial.print("\n");
Serial.print("3 second bool = ");
Serial.print(threeSecondBool);
Serial.print("\n");

 if (tenSecondBool) {
  if ((unsigned long)(currentMillis - threeSecondsMillis) >= threeSeconds) {
   Serial.print("---------------\n");
   Serial.print("3 second end\n");
   Serial.print("---------------\n");
   threeSecondBool = true;
   threeSecondsMillis = millis();
  }
 }

if (!tenSecondBool && threeSecondBool){
  Serial.print("Both triggered!\n");
  digitalWrite(Fin1, HIGH);
}

if (!tenSecondBool && !threeSecondBool){
  Serial.print("Both triggered!\n");
  digitalWrite(Fin1, HIGH);
}

if (tenSecondBool && threeSecondBool){
  threeSecondBool = false;
  tenSecondBool = false;
  digitalWrite(Fin1, LOW);
}

delay(500);

  if ((unsigned long)(currentMillis - ventMilis) >= ventInt) {
    digitalWrite(in1, HIGH);
    digitalWrite(in2, LOW);
    ventMilis = millis();
  } else {
    digitalWrite(in1, LOW);
    digitalWrite(in2, HIGH);    
  }


}
2

If you want a timer with millis with different intervals, then you can change the interval.

I use the Blink Without Delay to start with, and I borrow the 'relay_is_on' from the answer by Edgar Bonet.

unsigned long previousMillis;
unsigned long interval;
bool relay_is_on;

void loop() {
  unsigned long currentMillis = millis();

  if (currentMillis - previousMillis >= interval) {
    previousMillis = currentMillis;
    if (relay_is_on) {
      // Relay was on, now turn it off.
      interval = 10000;
      digitalWrite (relayPin, LOW);
      relay_is_on = false;
    } else {
      // Relay was off, now turn it on.
      interval = 3000;
      digitalWrite (relayPin, HIGH);
      relay_is_on = true;
    }
  }
}

The global variables can be set to a value to start with (for example 3000 for the interval) or they can be set in the setup() function. You have to choose what you want to start with. For example one second or one minute delay before it starts is also possible.

|improve this answer|||||
2

Your code is somewhat confusing, probably because it has too many variables. For doing what you describe, the program only needs to remember two things:

  • is the relay in the ON state or in the OFF state?
  • when was the last time the relay changed state?

These can be represented as follows:

bool relay_is_on = false;
unsigned long last_relay_change = 0;

Then, I recommend you use descriptive names for your variables and constants. Calling a constant threeSeconds is not useful. It has no added value over just typing 3000. Having the constant named RELAY_ON_TIME makes it a lot clearer what it is intended for. It is a common convention to name the constants with all caps to make them stand out relative to variables:

const uint8_t RELAY_PIN = ...;
const unsigned long RELAY_ON_TIME  =  3000;  //  3 s ON
const unsigned long RELAY_OFF_TIME = 10000;  // 10 s OFF

With this in place, periodically switching the relay on and off can be achieved as follows:

void loop()
{
    unsigned long now = millis();
    if (relay_is_on && now - last_relay_change >= RELAY_ON_TIME) {
        // Turn off.
        digitalWrite(RELAY_PIN, LOW);
        relay_is_on = false;
        last_relay_change = now;
    }
    if (!relay_is_on && now - last_relay_change >= RELAY_OFF_TIME) {
        // Turn on.
        digitalWrite(RELAY_PIN, HIGH);
        relay_is_on = true;
        last_relay_change = now;
    }
}
|improve this answer|||||

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.