2 CH Relay On/Off timer Help

Good Day,

I'm having a problem with a 2 channel relay running from a nodeMCU,

The relay acts like i want it to in the way that it turns on and off for the amounts of time stated, But when turning on the external 5V supply that powers the node and the relay externally. The Coil initially remains LOW/Off for the first off timer count and only then energizes.
Where i Would like the Coil to immediately switch ON/High state from the start and only turn off once the on timer count has been reached.
Hence Restarting it would turn on the relays straight away and not have to wait 30 minutes for an off counter to finish before turning on device.

I Have adapted this code to suit my needs and have tried changing around the logic in the if statements, setting the pin as HIGH in the setup, putting delays on the setup, moving the switch case below the setup thinking it was not setting the pin before the update statement started.. but not managing to get it right,

If anyone is able to point me in the right direction or spot any errors in code, it would be a great help. Thanks

class Switcher
{
// class member variables
  byte relayPin; // number of pin for relay
  long OnTime; 
  long OffTime;
  int relayState; // set relay state (active HIGH)
  unsigned long previousMillis; // set time since last update
public:
Switcher(byte pin, long on, long off)
{
  relayPin = pin;
  pinMode(relayPin, OUTPUT);
  OnTime = on;
  OffTime = off;
  relayState = HIGH;
  previousMillis = 0; 
}
void Update()
{
 // check the time to see if relays need to be turned on
 // or off
  unsigned long currentMillis = millis();

  if ((relayState == HIGH) && (currentMillis - previousMillis>= OffTime))
  {
   relayState = LOW; // Turn it off
   previousMillis = currentMillis; // Remember the time
   digitalWrite(relayPin, relayState); //update the relay
   }
   else if ((relayState == LOW) && (currentMillis - previousMillis >= OnTime))
   {
   relayState = HIGH; // turn it on
   previousMillis = currentMillis;
   digitalWrite(relayPin, relayState);
   }
 }
 };
 Switcher waterpump(14, 60000, 300000);
 Switcher vortexpump(12, 600000, 1800000);

void setup() {
  // put your setup code here, to run once:
  digitalWrite(14, OUTPUT);
  digitalWrite(12, OUTPUT);
   }
  
void loop() {
  // put your main code here, to run repeatedly:
  waterpump.Update();
  vortexpump.Update();
  }

If you declare a global object, the constructor function gets called before the Arduino runtime library is initialized. Calling Arduino functions such as pinMode() or digitalWrite() from the constructor is not a good idea. That is why so many library objects have a .begin() function: to call any Arduino runtime functions needed to initialize the object.

Move any Arduino functions out of your constructor and into a .begin() function, then call that function in setup().

johnwasser:
If you declare a global object, the constructor function gets called before the Arduino runtime library is initialized. Calling Arduino functions such as pinMode() or digitalWrite() from the constructor is not a good idea. That is why so many library objects have a .begin() function: to call any Arduino runtime functions needed to initialize the object.

Move any Arduino functions out of your constructor and into a .begin() function, then call that function in setup().

Thank you for the reply, Unfortunately my coding knowledge is not great and i had just used another code and modified the varaibles needed so what you said did kinda go over my head a bit, I think i understand what you saying but not sure about the part of calling the function in setup.
Anyway i have been doing more research and trying to change what you recommend.

I've changed the class variables out of the switch, and taken the pinmode object to setup so my code looks like this now below.

byte relayPin; // number of pin for relay
  long OnTime;
  long OffTime;
  int relayState; // set relay state (active HIGH)
  unsigned long previousMillis; // set time since last update
  
class Switcher{
  public:
Switcher(byte pin, long on, long off)
{
  relayPin = pin;
  OnTime = on;
  OffTime = off;
  relayState = HIGH;
  previousMillis = 0;
}
void Update()
{
 // check the time to see if relays need to be turned on
 // or off
  unsigned long currentMillis = millis();

  if ((relayState == HIGH) && (currentMillis - previousMillis>= OffTime))
  {
   relayState = LOW; // Turn it off
   previousMillis = currentMillis; // Remember the time
   digitalWrite(relayPin, relayState); //update the relay
   }
   else if ((relayState == LOW) && (currentMillis - previousMillis >= OnTime))
   {
   relayState = HIGH; // turn it on
   previousMillis = currentMillis;
   digitalWrite(relayPin, relayState);
   }
 }
 };
 Switcher waterpump(14, 10000, 5000);
 Switcher vortexpump(12, 10000, 5000);

void setup() {
  // put your setup code here, to run once:
  pinMode(14, OUTPUT);
  pinMode(12, OUTPUT);
  
   }
 
void loop() {
  // put your main code here, to run repeatedly:
  waterpump.Update();
  vortexpump.Update();
  }

But only one relay turns off and on correctly and the other stays on,

Changing the setup to the following, only the one relay is turning on, the other stays off.

...
void setup() {
  // put your setup code here, to run once:
  pinMode(relayPin, OUTPUT);
  
   }

Hi, I've just gone back to the original code in first post and had to use it as it is,

Unfortunately i had fish die on me last night and at least that is keeping the pumps going until i can figure it out even if its not 100% the way i want it (relays off timers start first after a reboot and after the off count do they only activate, I'm wanting after a reset to activate relays for ontime first, I presume this is because the code is trying to run before Node has finished its boot).
My brother was the one who used to do these things for me but have had to change the micro-controller since his passing.
I started with the delay option which was easy did work for a couple weeks but would often freeze up and would only see it when checking the pond. The script i found for the millis with a class seemed to suit my needs perfectly and made it so much easier to just add in another relay if needed.

If anyone is able to assist me in simpler terms or point me in the right direction of learning what needs to be changed it will be extremely helpful. I Am also willing to compensate anyone that can change it for me to the correct working code .

Thanks again

The suggestion was not to put the pinMode() in setup() but to put a begin() function in the class that sets the pinMode() for the object pin to OUTPUT and call that function from setup() with the appropriate relay pin as its parameter.

Hi,

Sorry, as i said my coding knowledge is very limited apart from some html and CSS, even my english language comprehension is not great at best so even the jargons and fancier words often confuse me. I understand the script as far as which variables are being used but when it comes to writing code and structure i get so lost.

I did spend a couple hours last night researching .begin() functions which took me into in depth c++ tutourials and things about vectors and everything was just way over my head. I also was looking at arduino site examples of creating libraries but find there examples are so limited and that they go back to using delays ect.

Could you be as kind as to show me an syntax example or point to me to a easy to understand tutourial about creating a .begin() function and how to call the function,

Thanks

  public:
    Switcher(byte pin)
    {
      relayPin = pin;
    }

    void begin(long on, long off)
    {
      pinMode(relayPin, OUTPUT);
      OnTime = on;
      OffTime = off;
      relayState = HIGH;
      previousMillis = 0;
    }

Call the constructor like this

Switcher waterpump(14);
Switcher vortexpump(12);

Call the begin() function from setup() like this

waterpump.begin(60000, 300000);
vortexpump.begin(600000, 1800000);

UKHeliBob:

  public:

Switcher(byte pin)
    {
      relayPin = pin;
    }

void begin(long on, long off)
    {
      pinMode(relayPin, OUTPUT);
      OnTime = on;
      OffTime = off;
      relayState = HIGH;
      previousMillis = 0;
    }




Call the constructor like this


Switcher waterpump(14);
Switcher vortexpump(12);




Call the begin() function from setup() like this


waterpump.begin(60000, 300000);
vortexpump.begin(600000, 1800000);

Ok, Thank you that does seem to compile and i’ll test it out bit later and give feedback. I was busy trying to add the function before i saw your reply but seems i was on the wrong track with not adding the long off and long on in the begin void.

So just to understand correctly, the constructor was changed to only provide the pin number in the class,
and all the variables for the update function if statement were moved to a separate void begin function which we call from the setup?

So just to understand correctly, the constructor was changed to only provide the pin number in the class,
and all the variables for the update function if statement were moved to a separate void begin function which we call from the setup?

Correct. The on and off parameters could be put in the constructor but to me it makes more sense to put them in the begin() function

UKHeliBob:

  public:

Switcher(byte pin)
   {
     relayPin = pin;
   }

void begin(long on, long off)
   {
     pinMode(relayPin, OUTPUT);
     OnTime = on;
     OffTime = off;
     relayState = HIGH;
     previousMillis = 0;
   }





Call the constructor like this


Switcher waterpump(14);
Switcher vortexpump(12);




Call the begin() function from setup() like this


waterpump.begin(60000, 300000);
vortexpump.begin(600000, 1800000);

Thank you that works perfectly as needed and helped me understand better where i was going wrong, UKHeliBob please Private message me so i can get your details to send you some beer money or order your something small off amazon as a thanks.

Here is the working code with relays activating at reboot, hopefully it will help others looking for a simple working on/off timer for relays.

class Switcher
{
// class member variables
  byte relayPin; // number of pin for relay
  long OnTime;
  long OffTime;
  int relayState; // set relay state (active HIGH)
  unsigned long previousMillis; // set time since last update
 public:
    Switcher(byte pin)
    {
      relayPin = pin;
    }

    void begin(long on, long off)
    {
      pinMode(relayPin, OUTPUT);
      OnTime = on;
      OffTime = off;
      relayState = HIGH;
      previousMillis = 0;
    }
void Update()
{
 // check the time to see if relays need to be turned on
 // or off
  unsigned long currentMillis = millis();

  if ((relayState == HIGH) && (currentMillis - previousMillis>= OffTime))
  {
   relayState = LOW; // Turn it off
   previousMillis = currentMillis; // Remember the time
   digitalWrite(relayPin, relayState); //update the relay
   }
   else if ((relayState == LOW) && (currentMillis - previousMillis >= OnTime))
   {
   relayState = HIGH; // turn it on
   previousMillis = currentMillis;
   digitalWrite(relayPin, relayState);
   }
 }
 };
 Switcher waterpump(14);
 Switcher vortexpump(12);

void setup() {
  // put your setup code here, to run once:

  waterpump.begin(60000, 600000);
  vortexpump.begin(600000, 1800000);
   }
 
void loop() {
  // put your main code here, to run repeatedly:
  waterpump.Update();
  vortexpump.Update();
  }