Spark Core Time Based Event

I’m quiet new to Spark Core. How can I create a time based event on my Spark Core? For instance, if I want to digitalWrite 7,HIGH at 8:30AM every morning for 30 seconds. Any help would be highly appreciated.

I would suggest you start here: http://docs.spark.io/firmware/#libraries-time

Something along the lines of:

bool hasHappenedToday = false;

void loop()
{
    if((Time.hour() == 8) && (Time.isAM() == true) && (Time.minute() == 30) && (hasHappenedToday == false))
    {
        digitalWrite(D7, HIGH);
        hasHappenedToday = true;
        delay(30000);
    }

    if(Time.hour() > 9)
    {
        hasHappenedToday = false;
    }
}
1 Like

Thanks @harrisonhjones. I’ve looked at the time library and I’m guessing that the above snippet has to have a Spark Time sync upon connection? I tried the above snippet with my existing time and it didn’t work. My time zone is GMT+8. Should I add any other lines of code so that my spark core knows my time zone and syncs with some online service to constantly update the time?

@harrisonhjones, this is the modified version of your snippet I tried just now and it didn’t work. I’m a beginner and I’m not sure where I’m going wrong. Please help.

bool hasHappenedToday = false;


#define ONE_DAY_MILLIS (24 * 60 * 60 * 1000)
unsigned long lastSync = millis();


void setup()
{
Spark.syncTime();  
Time.zone(+8);
Serial.begin(115200);
}


void loop()
{
    
    if (millis() - lastSync > ONE_DAY_MILLIS)
    {
        // Request time sync from Spark Cloud
        Spark.syncTime();
        lastSync = millis();
        Serial.print(Time.now());
    }
    
    if((Time.hour() == 3) && (Time.isPM() == true) && (hasHappenedToday == false))
    //if((Time.hour() == 2) && (Time.isPM() == true) && (Time.minute() == 45) && (hasHappenedToday == false))
    {
        digitalWrite(D7, HIGH);
        hasHappenedToday = true;
        delay(30000);
    }

}

I’ve edited your post to properly format the code. Please check out this post, so you know how to do this yourself in the future. Thanks in advance! ~Jordy

There are some things you could improve there.

  • Spark.syncTime() is called internally on boot-up, so you don’t really need it in setup() - but it doesn’t harm :wink:
  • Rather than doing it every 86 400 000 milliseconds (24h) you could do it at a given time - e.g. 00:00:00
  • You don’t actually need to check for AM/PM since Time.hour() returns 0…23 (this will also be the cause that it didn’t work - 3:00PM = 15:00)
  • Instead of testing hours and minutes seperatly I’d calculate the number of minute (h*60 + m) once per minute (60 000 ms) and then test against this (or for higher resolution incorporate seconds too) . This makes testing ‘between’ times a lot easier.
  • You need to reset hasHappenedToday - e.g. along with the 00:00:00 resync
  • You need to reset your D7 pin
  • Try to avoid delay(30000) if you want your Core to do some other jobs too

And if you want a full fledged alarming system, there is a TimeAlarms library available on the Web IDE or on GitHub (https://github.com/bkobkobko/SparkTimeAlarms)

5 Likes

@ScruffR, thanks for the wonderful headsup. Let me try out your suggestions and will update soon. Cheers!

1 Like

Depending on how accurate you want it to be, IFTTT might also work. It allows you to set times and days on which functions will be called. You could create a function to execute your action.
This would require the least amount of work, although the timeAlarms library offers more flexibility. Depending on your user scenario, both options could be considered.

2 Likes

Yes, I agree with all of @ScruffR’s points. Go with his suggestion over mine!

do you use Daylight Savings Time where you are? (GMT+8 maybe not)

but for anyone who comes across this post, an easy way to adjust (this is USA eastern time example)…

void loop()
{
  Time.zone(IsDST(Time.day(), Time.month(), Time.weekday())? -4 : -5);
}
bool IsDST(int dayOfMonth, int month, int dayOfWeek)
{
  if (month < 3 || month > 11)
  {
    return false;
  }
  if (month > 3 && month < 11)
  {
    return true;
  }
  int previousSunday = dayOfMonth - dayOfWeek;
  //In march, we are DST if our previous sunday was on or after the 8th.
  if (month == 3)
  {
    return previousSunday >= 8;
  }
  //In november we must be before the first sunday to be dst.
  //That means the previous sunday must be before the 1st.
  return previousSunday <= 0;
}

you can certainly work to get it to exact, if you want.

1 Like

@BulldogLowell, I’m on GMT+8 timezone. Thanks for the snippet anyways.

@Moors7, I’ve tried IFTTT. However, it is not accurate. There is some delay in triggering the functions.

@ScruffR, I’ve tried the SparkTimeAlarms library example. It is perfect for my scenario. However, I noticed that my functions are not working with this library. For instance, in the given example .ino file, I’m trying to use digitalwrite(D7,HIGH) for the Morning Alarm. When i use spark serial monitor in my terminal window, I can see that the Print statement works, however, the digitalwrite function doesn’t work. I’m assuming that the default Tinker app which is responsible for the digitalread/write, analogread/write is being overwritten when I flash the example code. Usually when I perform spark list, I used to see my spark ID, spark name and the available functions. Now (after flashing the example .ino file), I no longer see those functions available. Hence, I assume the script is not triggering my digitalwrite(D7,HIGH) function too. How can I fix this problem? Should I include the TimeAlarms library to my default tinker and flash it?

Here is the script that I’m trying to use and unable to get the digitalWrite(D7,HIGH) to work when the alarm triggers:

#include "TimeAlarms/TimeAlarms.h"

void setup()
{
  Time.zone(+8);
  Serial.begin(9600);
  // create the alarms 
  Alarm.alarmRepeat(9,20,0, MorningAlarm);  // 8:30am every day
  Alarm.alarmRepeat(22,00,0,EveningAlarm);  // 5:45pm every day 
  Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm);  // 8:30:30 every Saturday 
 
  Alarm.timerRepeat(15, Repeats);            // timer for every 15 seconds    
  Alarm.timerOnce(10, OnceOnly);             // called once after 10 seconds 
}

void  loop(){  
  digitalClockDisplay();
  Alarm.delay(1000); // wait one second between clock display
}

// functions to be called when an alarm triggers:
void MorningAlarm(){
  Serial.println("Alarm: - turn lights off"); 
  digitalWrite(D7,HIGH);
  delay(5000);
  digitalWrite(D7,LOW);
}

void EveningAlarm(){
  Serial.println("Alarm: - turn lights on");
  //digitalWrite(D7,HIGH);
}

void WeeklyAlarm(){
  Serial.println("Alarm: - its Monday Morning");      
}

void ExplicitAlarm(){
  Serial.println("Alarm: - this triggers only at the given date and time");       
}

void Repeats(){
  Serial.println("15 second timer");         
}

void OnceOnly(){
  Serial.println("This timer only triggers once");  
}

void digitalClockDisplay()
{
  // digital clock display of the time
  Serial.print(Time.hour());
  printDigits(Time.minute());
  printDigits(Time.second());
  Serial.println(); 
}

void printDigits(int digits)
{
  Serial.print(":");
  if(digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

you need to designate D7 to be an output. At the beginning of your setup function (right after the { bracket) add the following line: pinMode(D7, OUTPUT); and you should be good to go

3 Likes

@harrisonhjones, Awesome! It worked finally. Thank you so much everybody for helping me out. Cheers!

2 Likes