Flash LED using Millis() while relay is activated

Hi All,

I am creating a sketch for an Attiny85 to run a fan for 60 seconds every 30 minutes. While the fan is running (relay connected to Pin 0) I want an LED (connected to Pin 1) to flash.

Although my current sketch isn't set to 60 seconds every 30 minutes, the fan operation is working as expected. (timing set shorter for development / testing purposes)

I cannot get the millis() loop and logic working correctly to flash the LED only while the relay is on.

Can I please have some assistance getting this code right. Currently the LED isn't flashing & it's in reverse. ie: on solid while the fan is off.

const long LED= 1;
const long RELAY= 0;
const long FANINTERVAL= 5000;
const long FANONTIME= 2000;
const long LedonDuration= 250;
const long LedoffDuration= 750;

int ledon = 0;
int fanon = 0;
long ledtime= 0;

void setup(void) {
     pinMode(LED,OUTPUT);
     pinMode(RELAY,OUTPUT);
     digitalWrite(LED,LOW);
     digitalWrite(RELAY,LOW);
}

void loop(){
static uint32_t fanintervaltime= millis();
static uint32_t fanstarttime= millis();

    // FAN START
    if ( (millis()- fanintervaltime) > FANINTERVAL) {
      fanintervaltime= millis();
      fanstarttime= millis();
      ledtime=millis();
      fanon= 1;
      digitalWrite(RELAY,HIGH);
      //digitalWrite(LED,HIGH);
    }

    // FAN STOP
    if ( (millis()- fanstarttime) > FANONTIME) {
      digitalWrite(RELAY,LOW);
      //digitalWrite(LED,LOW);
      fanon= 0;
    }

    // LED FLASH WHILE FAN ON
    if( fanon == 1 ) {
      if( (millis()- ledtime) >= LedonDuration){   
        digitalWrite(LED,LOW);// change the state of LED
        ledtime=millis();// remember Current millis() time
      }
    }
    else {   
      if( (millis()- ledtime) >= LedoffDuration){     
        digitalWrite(LED,HIGH);// change the state of LED
        ledtime=millis();// remember Current millis() time
      }
    }
} 

...so the off part is only in the if( fanon == 1 ) part and the on part is only in the else part where fanon == 1 is not true. Maybe they both belong in the same part.

Thanks for the pointer. You were correct. I have tweaked the code and got it working now. But oddly, it will only work correctly if LedonDuration & LedoffDuration are the same. If I set on to 250 and off to 500 it only flashes once.

const long LED= 1;
const long RELAY= 0;
const long FANINTERVAL= 20000;
const long FANONTIME= 5000;
const long LedonDuration= 250;
const long LedoffDuration= 250;

int ledon = 0;
int fanon = 0;
long ledtime= 0;

void setup(void) {
     pinMode(LED,OUTPUT);
     pinMode(RELAY,OUTPUT);
     digitalWrite(LED,LOW);
     digitalWrite(RELAY,LOW);
}

void loop(){
static uint32_t fanintervaltime= millis();
static uint32_t fanstarttime= millis();

    // FAN START
    if ( (millis()- fanintervaltime) > FANINTERVAL) {
      fanintervaltime= millis();
      fanstarttime= millis();
      digitalWrite(RELAY,HIGH);
      fanon= 1;
      digitalWrite(LED,HIGH);// change the state of LED
      ledtime=millis();
    }

    // FAN STOP
    if ( (millis()- fanstarttime) > FANONTIME) {
      digitalWrite(RELAY,LOW);
      digitalWrite(LED,LOW);
      fanon= 0;
    }

    // LED FLASH WHILE FAN ON
    if( fanon == 1 ) {
      if( (millis()- ledtime) >= LedonDuration){   
        digitalWrite(LED,LOW);// change the state of LED
        ledtime=millis();// remember Current millis() time
      }
      if( (millis()- ledtime) >= LedoffDuration){     
        digitalWrite(LED,HIGH);// change the state of LED
        ledtime=millis();// remember Current millis() time
      }
    }
} 

Ausip,
I have moved your topic from the uncategorised category to a more suitable location.

const byte LED = 1;
const byte RELAY = 0;
const long FANINTERVAL = 5000;
const long FANONTIME = 2000;
const long LedonDuration = 250;
const long LedoffDuration = 750;

int ledon = 0;
int fanon = 0;
long ledtime = 0;

void setup(void) {
  pinMode(LED, OUTPUT);
  pinMode(RELAY, OUTPUT);
  digitalWrite(LED, LOW);
  digitalWrite(RELAY, LOW);
}

void loop() {
  static uint32_t fanintervaltime = millis();

  // FAN START
  if (!digitalRead(RELAY)) {
    if ( (millis() - fanintervaltime) > FANINTERVAL) {
      fanintervaltime = millis();
      fanon = 1;
      digitalWrite(RELAY, HIGH);
    }
  } else {

    // FAN STOP
    if ( (millis() - fanintervaltime) > FANONTIME) {
      fanintervaltime = millis();
      digitalWrite(RELAY, LOW);
      digitalWrite(LED, LOW);
      fanon = 0;
    }
  }

  // LED FLASH WHILE FAN ON
  if ( fanon == 1 ) {
    if (digitalRead(LED)) {
      if ( millis() - ledtime >= LedonDuration) {
        digitalWrite(LED, LOW); // change the state of LED
        ledtime = millis(); // remember Current millis() time
      }
    }
    else {
      if ( (millis() - ledtime) >= LedoffDuration) {
        digitalWrite(LED, HIGH); // change the state of LED
        ledtime = millis(); // remember Current millis() time
      }
    }
  }
}

Here is my solution. I change the interval inside the millis timer.

// Forum: https://forum.arduino.cc/t/flash-led-using-millis-while-relay-is-activated/1289454
// This Wokwi project: https://wokwi.com/projects/405568161981442049

const int ledPin = 1;    // 'int' or 'byte'
const int relayPin = 0;  // 'int' or 'byte'

const unsigned long FANONDURATION  = 5000UL;
const unsigned long FANOFFDURATION = 15000UL;
const unsigned long LEDONDURATION  = 150;
const unsigned long LEDOFFDURATION = 250;

unsigned long previousMillisFan;
unsigned long fanInterval = FANOFFDURATION;
unsigned long previousMillisLed;
unsigned long ledInterval = LEDONDURATION;

bool ledOn = false;
bool fanOn = false;

void setup(void) 
{
  pinMode(ledPin, OUTPUT);     // set output and low
  pinMode(relayPin, OUTPUT);   // set output and low

  digitalWrite(ledPin, LOW);   // not necessary
  digitalWrite(relayPin, LOW); // not necessary
}

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

  // A millis timer for the fan.
  // With different on and off times.
  if(currentMillis - previousMillisFan >= fanInterval) 
  {
    previousMillisFan = currentMillis;

    if(!fanOn)
    {
      digitalWrite(relayPin, HIGH);
      fanInterval = FANONDURATION;
      fanOn = true;
    }
    else
    {
      digitalWrite(relayPin, LOW);
      fanInterval = FANOFFDURATION;
      fanOn = false;
    }
  }

  // A millis timer for the led.
  // Flash led when the fan is on.
  if(fanOn) 
  {
    if(currentMillis - previousMillisLed >= ledInterval)
    {   
      previousMillisLed = currentMillis;

      if(!ledOn)
      {
        digitalWrite(ledPin, HIGH);
        ledInterval = LEDONDURATION;
        ledOn = true;
      }
      else
      {
        digitalWrite(ledPin, LOW);
        ledInterval = LEDOFFDURATION;
        ledOn = false;
      }
    }
  }
}

Try it in Wokwi:

Those inner ifs are too independent. You might want to only test if it is time to turn it off only when it is on, and vice versa.

That's a nice piece of code. Compared to mine anyway. You can tell I am not a programmer.

That worked perfectly on my device. Thanks for your help.

You are programmer enough to get 80% there, and that's more than 80% of people. It's always the last 20% where it gets tricky. And where you learn stuff.

One trick that helps in figuring out what is going on is adding print statements. Like:

const long LED = 1;
const long RELAY = 0;
const long FANINTERVAL = 20000;
const long FANONTIME = 5000;
const long LedonDuration = 250;
const long LedoffDuration = 250;

int ledon = 0;
int fanon = 0;
long ledtime = 0;

void setup(void) {
  pinMode(LED, OUTPUT);
  pinMode(RELAY, OUTPUT);
  digitalWrite(LED, LOW);
  digitalWrite(RELAY, LOW);
  Serial.begin(115200);
}

void loop() {
  static uint32_t fanintervaltime = millis();
  static uint32_t fanstarttime = millis();

  // FAN START
  if ( (millis() - fanintervaltime) > FANINTERVAL) {
    fanintervaltime = millis();
    fanstarttime = millis();
    Serial.print("F");
    digitalWrite(RELAY, HIGH);
    fanon = 1;
    Serial.print("B");
    digitalWrite(LED, HIGH); // change the state of LED
    ledtime = millis();
  }

  // FAN STOP
  if ((millis() - fanstarttime) > FANONTIME) {
    Serial.print("f");
    digitalWrite(RELAY, LOW);
    digitalWrite(LED, LOW);
    fanon = 0;
  }

  // LED FLASH WHILE FAN ON
  if ( fanon == 1 ) {
    if ( (millis() - ledtime) >= LedonDuration) {
      Serial.print("l");
      digitalWrite(LED, LOW); // change the state of LED
      ledtime = millis(); // remember Current millis() time
    }
    if ( (millis() - ledtime) >= LedoffDuration) {
      Serial.print("L");
      digitalWrite(LED, HIGH); // change the state of LED
      ledtime = millis(); // remember Current millis() time
    }
  }
}

Where you could make the output less frantic with:

  // FAN STOP
  if ( fanon == 1 &&  (millis() - fanstarttime) > FANONTIME) {
    Serial.print("f");
    digitalWrite(RELAY, LOW);
    digitalWrite(LED, LOW);
    fanon = 0;
  }

The Wokwi simulator can show debug messages for an ATtiny85. It can help to develop code for an ATtiny85: https://docs.wokwi.com/parts/wokwi-attiny85#debug-prints-with-tinydebug

1 Like