0

I want to reboot relay (turn off , waiting 4 seconds and turn ON) it works perfectly if I use delay(4000), but code is blocked while delay (4 seconds) and I cant start relay 2. How can I use Millis instead of delay to reboot relay 1 and start relay 2 same time?

#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <EthernetUdp.h> //Load the Udp Library

//Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; //Assign mac address
IPAddress ip(192, 168, 1, 178); //Assign the IP Adress
unsigned int localPort = 80; // Assign a port to talk over
char packetBuffer[UDP_TX_PACKET_MAX_SIZE]; //dimensian a char array to hold our data packet
String datReq; //String for our data
int packetSize; //Size of the packet
EthernetUDP Udp; // Create a UDP Object                            //server port
String readString;

bool relayState = false;
//define relay pins
int relay_1 = 22;
int relay_2 = 24;

void setup() {
  Serial.begin(9600);
  Ethernet.begin(mac, ip);
  Udp.begin(localPort); //Initialize Udp
  delay(2000);

  //Initial state of the relay
  pinMode(relay_1, OUTPUT); digitalWrite(relay_1, LOW); //relay 1 is On
  pinMode(relay_2, OUTPUT); digitalWrite(relay_2, HIGH);//relay 2 is Off


}

void loop() {

  packetSize = Udp.parsePacket(); //Reads the packet size
  if (packetSize > 0) { //if packetSize is >0, that means someone has sent a request
    Udp.read(packetBuffer, UDP_TX_PACKET_MAX_SIZE); //Read the data request
    String datReq(packetBuffer); //Convert char array packetBuffer into a string called datReq
    //Serial.println(datReq);

    if (datReq == "relay1reboot") { //reboot relay
      digitalWrite(relay_1, HIGH);//relay off
      delay(4000); 
      digitalWrite(relay_1, LOW);//relay on

      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 1 reboot");
      Udp.endPacket(); //End the packet

    }
    if (datReq == "relay2on") {
      digitalWrite(relay_2, LOW);//relay 2 on
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 2 on");
      Udp.endPacket(); //End the packet
    }
    if (datReq == "relay1on") {
      digitalWrite(relay_1, LOW);//relay 2 on
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort()); //Initialize packet send
      Udp.print("relay 1 on");
      Udp.endPacket(); //End the packet
    }
    // Use the snapshot to set track time until next event
    //previousMillis = currentMillis;
  }
}

//}
memset(packetBuffer, 0, UDP_TX_PACKET_MAX_SIZE); //clear out the packetBuffer array

}
1
  • 1
    reboot is a term that is specific to programmable devices, such as computers ... it does not apply to a simple relay ... it would make sense to say I want to cycle a relay
    – jsotola
    Aug 20, 2022 at 18:50

1 Answer 1

2

A general approach to remove a delay() is to replace it by some code that:

  • takes note that some action (whatever follows the delay()) will have to be performed in the future

  • takes note of the current time.

Then, somewhere else in loop(), you check whether that “some action” has to be done right now and, if this is the case, does it.

In this particular case, I would add a global boolean variable named relay1isRebooting. When it is true, that means that the relay has been turned off and will have to be turned on in the near future.

bool relay1isRebooting = false;
unsigned long relay1rebootStarted;

void loop() {
  packetSize = Udp.parsePacket();
  if (packetSize > 0) { //we have received a packet
    // ...
    if (datReq == "relay1reboot") {
      digitalWrite(relay_1, HIGH); //relay off
      relay1isRebooting = true;
      relay1rebootStarted = millis();
    }
    // ...
  }

  // Switch back the relay 1 on if needed.
  if (relay1isRebooting && millis() - relay1rebootStarted >= 4000) {
      digitalWrite(relay_1, LOW); //relay on
      relay1isRebooting = false;
      Udp.beginPacket(Udp.remoteIP(), Udp.remotePort());
      Udp.print("relay 1 reboot");
      Udp.endPacket();
  }
}

Please note that the test for whether the relay 1 should be turned back on is performed outside the if (packetSize > 0) block. Also note that relay1rebootStarted has a valid value only when relay1isRebooting is true.

2
  • for advanced coders: I usually use only the variable for millis. if it is 0 the timer is not running. if (relay1rebootStarted && millis() - relay1rebootStarted >= RELAY_DELAY)
    – Juraj
    Aug 21, 2022 at 6:33
  • 1
    @Juraj: I dislike this approach. Zero is a legitimate return value for millis(), returned every 49.7 days. Aug 21, 2022 at 20:12

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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