Scheduling LED shop sign to turn on and off

Hi there,

I have a D1 mini and mosfet dc switch module ( RobotDyn® Transistor MOSFET DC Switch Module 5V Logic DC 24V 30A With Optocouplers ) and I would like to set up some code as a timer so that it turns on some 12v strip LEDS at 6pm and off at 9:30pm based on the time retrieved from the wifi connection.
I've spent plenty of time trying to get the code but there always seems to be something different about the tutorial and I end up having trouble adapting it to my needs. Any help with coding would be greatly appreciated.

Thanks,

Mike

A wild guess. Check the code near line 125.

2 Likes

Can you show us the code that you was working with?

So what are you able to do?

Get the time from wifi?

Switch the light on and off?

Do you have code you wrote at least part of?
If so, do you understand it?

Hi there,

Thanks for the response! This is the last one I've tried. Sorry I couldn't get it to inset into the response properly

M

'
#include <ESP8266WiFi.h>
#include <time.h>

const char* ssid = "";
const char* password = "";

int ledPin = 13;

int timezone = 7 * 3600;
int dst = 0;

void setup() {

pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,LOW);

Serial.begin(115200);
Serial.println();
Serial.print("Wifi connecting to ");
Serial.println( ssid );

WiFi.begin(ssid,password);

Serial.println();

Serial.print("Connecting");

while( WiFi.status() != WL_CONNECTED ){
delay(500);
Serial.print(".");
}

Serial.println();

Serial.println("Wifi Connected Success!");
Serial.print("NodeMCU IP Address : ");
Serial.println(WiFi.localIP() );

configTime(timezone, dst, "pool.ntp.org","time.nist.gov");
Serial.println("\nWaiting for Internet time");

while(!time(nullptr)){
Serial.print("*");
delay(1000);
}
Serial.println("\nTime response....OK");
}

void loop() {

time_t now = time(nullptr);
struct tm* p_tm = localtime(&now);

// TURN LED ON

if( (p_tm->tm_hour == 18) && (p_tm->tm_min == 00)){
digitalWrite(ledPin,HIGH);
}

// TURN LED OFF

if( (p_tm->tm_hour == 21) && (p_tm->tm_min == 30)){
digitalWrite(ledPin,LOW);
}

delay(1000);

}

'

code

#include <ESP8266WiFi.h>
#include <time.h>

const char* ssid = "";
const char* password = "";

int ledPin = 13;

int timezone = 7 * 3600;
int dst = 0;

void setup() {

pinMode(ledPin,OUTPUT);
digitalWrite(ledPin,LOW);

Serial.begin(115200);
Serial.println();
Serial.print("Wifi connecting to ");
Serial.println( ssid );

WiFi.begin(ssid,password);

Serial.println();

Serial.print("Connecting");

while( WiFi.status() != WL_CONNECTED ){
delay(500);
Serial.print(".");
}

Serial.println();

Serial.println("Wifi Connected Success!");
Serial.print("NodeMCU IP Address : ");
Serial.println(WiFi.localIP() );

configTime(timezone, dst, "pool.ntp.org","time.nist.gov");
Serial.println("\nWaiting for Internet time");

while(!time(nullptr)){
Serial.print("*");
delay(1000);
}
Serial.println("\nTime response....OK");
}

void loop() {

time_t now = time(nullptr);
struct tm* p_tm = localtime(&now);

// TURN LED ON

if( (p_tm->tm_hour == 18) && (p_ttm->tm_min == 30)){
digitalWrite(ledPin,LOW);
}

delay(1000);

}

Hi there,

Thanks for reply.
Yep I want the time from wifi, (I've actually got that clock battery thing but that seems even harder to set up and I don't think it works with daylight saving etc)

And I basically want to turn it on at 6:30pm and turn it of at 9:30pm everyday.

I vaguely understand the code but tbh I am relying heavily on cut and paste, was using blynk before but don't like this subscription stuff they're doing now.

Thanks again,

M

#include <ESP8266WiFi.h>
#include <time.h>

const char* ssid = "<your wifi ssid>";
const char* password = "<your wifi password>";

int ledPin = 13;

int timezone = 7 * 3600;
int dst = 0;

void setup() {
  
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW);

  Serial.begin(115200);
  Serial.println();
  Serial.print("Wifi connecting to ");
  Serial.println( ssid );

  WiFi.begin(ssid,password);

  Serial.println();
  
  Serial.print("Connecting");

  while( WiFi.status() != WL_CONNECTED ){
      delay(500);
      Serial.print(".");        
  }

  
  Serial.println();

  Serial.println("Wifi Connected Success!");
  Serial.print("NodeMCU IP Address : ");
  Serial.println(WiFi.localIP() );

  configTime(timezone, dst, "pool.ntp.org","time.nist.gov");
  Serial.println("\nWaiting for Internet time");

  while(!time(nullptr)){
     Serial.print("*");
     delay(1000);
  }
  Serial.println("\nTime response....OK");   
}

void loop() {
  
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);
   
  // TURN LED ON

  if( (p_tm->tm_hour == 18) && (p_tm->tm_min == 00)){
      digitalWrite(ledPin,HIGH);
  }
  

  // TURN LED OFF

  if( (p_tm->tm_hour == 21) && (p_tm->tm_min == 30)){
      digitalWrite(ledPin,LOW);
  }
  
  delay(1000);

  

}

I see the time data declared in void loop() that should be global.
I see in setup the time is supposed to be read but nowhere in loop(), also known as Later is the wifi time updated.

Me mysellf if the D1 has a crystal is get wifi time of day turned into millis and stored once a day along with Arduino millis() as start time to get elapsed time to add to the wifi time and see if it's 6:00PM to 9:30PM --- since the Arduino millis clock is always updating.

Using unsigned longs, Arduino millis can track elapsed time almost 50 days long to +/- 1 ms. Yes the value rolls over but with unsigned math it is the round clock at 12=0 and to the signed vale line segment that sign-switch wraps when you go off either end.

Elapsed time = end time - start time ... works across rollover, no if() necessary.

1 Like

Hey @Idahowalker thanks for sending this through. Couldn't get this to work, do you think it could be to do with timezone? I'm in the UK fwiw

Thanks,

M

Thanks for the reply @GoForSmoke . I think your understanding of the code is a much higher level than mine and I don't understand anything that you've suggested. Sorry.

Helpful?

#include <ESP8266WiFi.h>
#include <time.h>

const char* ssid = "<your wifi ssid>";
const char* password = "<your wifi password>";

int ledPin = 13;

int timezone = 7 * 3600;
int dst = 0;

void setup() {
  
  pinMode(ledPin,OUTPUT);
  digitalWrite(ledPin,LOW);

  Serial.begin(115200);
  Serial.println();
  Serial.print("Wifi connecting to ");
  Serial.println( ssid );

  WiFi.begin(ssid,password);

  Serial.println();
  
  Serial.print("Connecting");

  while( WiFi.status() != WL_CONNECTED ){
      delay(500);
      Serial.print(".");        
  }

  
  Serial.println();

  Serial.println("Wifi Connected Success!");
  Serial.print("NodeMCU IP Address : ");
  Serial.println(WiFi.localIP() );

  configTime(timezone, dst, "pool.ntp.org","time.nist.gov");
  Serial.println("\nWaiting for Internet time");

  while(!time(nullptr)){
     Serial.print("*");
     delay(1000);
  }
  Serial.println("\nTime response....OK");   
}

void loop() {
  
  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);
   
  // TURN LED ON

  if( (p_tm->tm_hour == 18) && (p_tm->tm_min == 00)){
      digitalWrite(ledPin,HIGH);
  }
  

  // TURN LED OFF

  if( (p_tm->tm_hour == 21) && (p_tm->tm_min == 30)){
      digitalWrite(ledPin,LOW);
  }
  
  delay(1000);

  

}

Global variables can be used by any function in the sketch.
Global variables are declared outside of all functions usually before them.

Variables declared inside of a function, only that function can use them.

So if I want to read wifi time in setup() and use that data in loop(), I want it to be global.

You STILL do not read the wifi time in loop(), time goes on and your code does not check the time in any way so how can it see when 6 comes along?

The code looks plausible.

For testing to not take days, temporarily replace the on/off stuff with something that plays out much faster.

You can also simplify time logic sometimes by using a minutes since midnight number.

And to make the device a bit more robust, don't expect to always be available at exactly the right time. Instead use a range, viz:

  // TURN LED ON or... 

  int theHour = p_tm->tm_hour;   // maybe use tm_min during testing
  int theMinute = p_tm->tm_min;  // maybe use tm_sec during testing

  int minutesSince00 = 60 * theHour + theMinute;

  if (minutesSince00 >= (18 * 60) and minutesSince00 <= (21 * 60 + 30)
      digitalWrite(ledPin,HIGH);
  else 
      digitalWrite(ledPin,LOW);

I can't run this from under the umbrella here, so it is untested. But the idea is sound. I think. It is so hot, feels good actually, but the brain, ya know.

a7

1 Like

Oh, I assumed this did get the time and put it into a tm struct.

  time_t now = time(nullptr);
  struct tm* p_tm = localtime(&now);

a7

I didn't catch that time library call also checked wifi.
I foolishly thought that it just looks at the same data over and over.
Sorry.

Yes!

int timezone = 7 * 3600;
If you are GMT then change that to 0 (0 * 3600, 3600sec / hr offset)

Is it supposed to be a clock, showing the time too? If not, it could be set up to wake up before 6pm, get the NTP, turn on the light, go to sleep till just before turn off time, get then NTP, turn off the light, go back to sleep till before 6pm the following evening, . . .

Thanks @runaway_pancake
There is no timer it's just a lightbox that's meant to turn on. I've adjusted the timezone but it's still not working. The serial monitor says that it's connected to the wifi as well.
I like the idea of it sleeping/waking up but want to get the basics done first. Any other ideas?

M

Thanks for your input @alto777 would you be able to adjust the code so that I could test something? My knowledge of this is VERY basic.
I don't understand why testing should take days with my current code. It's now 7:15pm here and I if I were to adjust the code so that it turns on at 7:20pm it doesn't. Serial monitor states time fetched and connected to wifi so that part is working..

Do you see anything glaringly obvious that could be causing problems with the code I'd provided?