element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Arduino
  • Products
  • More
Arduino
Blog [Christmas Wreath of Things] Internet of Holiday Lights: part 9 - Time and Event Management
  • Blog
  • Forum
  • Documents
  • Quiz
  • Events
  • Polls
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Arduino to participate - click to join for free!
  • Share
  • More
  • Cancel
Group Actions
  • Group RSS
  • More
  • Cancel
Engagement
  • Author Author: Jan Cumps
  • Date Created: 30 Dec 2014 8:24 PM Date Created
  • Views 574 views
  • Likes 1 like
  • Comments 2 comments
  • mqtt
  • wreath_of_things
  • iot_holidaylights
  • internet-of-things
  • iot
  • arduino
Related
Recommended

[Christmas Wreath of Things] Internet of Holiday Lights: part 9 - Time and Event Management

Jan Cumps
Jan Cumps
30 Dec 2014

My entry for the Internet of Holiday Lights is an electro-mechanical wreath.

My first blog post was a brain dump of possibilities.

In my second post I made a paper prototype.

My third post was about getting the Arduino Yun up and running.

In the fourth post I used the Linux part of the Yun to get at the current date and time.

In the fifth post I scavenged a stepper motor from a flatbed scanner.

In post six that motor was running.

Post seven is covering the Infineon RGB LED shield.

My post number eight is an aside on programming the advent calendar logic.

In post nine I'm covering the creative 'Arts & Crafts" part.


This time I'll cover Time and Event handling.


Why Time management


My wreath will be doing several things. A few of them event handled, other repetitive.

  • There are some animations happening (LEDs dimming and flashing)
  • A connection with the Eclipse MQTT broker needs to be kept alive.
  • I'm sending MQTT messages to something for surprise functionality on a regular base.
  • Others.

 

I can handle all of this in the loop() function without real issues (it's not that complex after all). But a timer can handle all of this without me having to worry about it too much.

The ATMega has spare timers, so why not.

 

In my design I need three granularities:

  • things to be done approx each second
  • actions that should be done each minute
  • hourly activities

 

image

 

So I've set up a counter that ticks every second and manages the cadence.

void timerInit() {
  // initialize timer1 for 1 second ticks; ISR(TIMER1_COMPA_vect) will be called as interrupt handler
  noInterrupts();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1  = 0;


  OCR1A = 62500;            // compare match register 16MHz/256/1Hz
  TCCR1B |= (1 << WGM12);   // CTC mode
  TCCR1B |= (1 << CS12);    // 256 prescaler
  TIMSK1 |= (1 << OCIE1A);  // enable timer compare interrupt
  interrupts();             // enable all interrupts
}

 

 

My interrupt handler does nothing more than marking what jobs need to execute:

ISR(TIMER1_COMPA_vect)          // timer compare interrupt service routine
{
  static unsigned int uSeconds = 0;
  uSeconds++; // every call is a second
  bRunSeconds = true; // so yes, flag that the seconds handler should be called
  bRunMinutes = ! (uSeconds % 60); // each 60th second, flag that the minutes handler should be called
  if (uSeconds > 3599) { // every hour
    bRunHours = true; // flag that the hours handler should be called
    uSeconds = 0; // and start over
  }
}

This is a very short routine that is guaranteed to give back control to non-interrupt code fast

 

I have a function that calls the right schedule at the right times. That function is the first call in my 'arduino sketch' loop():

void loop()
{

  timerTasks();

  // non timer related functionality comes here
  // ...

 

void timerTasks() {
  if (bRunSeconds && ! bIsRunningSeconds) { // timer interrupt flagged that seconds handler should be called
    runSeconds(); // but we only run it if it's not active
  }
  if (bRunMinutes && ! bIsRunningMinutes) { // timer interrupt flagged that minutes handler should be called
    runMinutes(); // but we only run it if it's not active
  }
  if (bRunHours && ! bIsRunningHours) { // timer interrupt flagged that hours handler should be called
    runHours(); // but we only run it if it's not active
  }
}

 

As an example, here's some household variables, runSeconds() and the beginning of runMinutes():

boolean bRunSeconds = false;
boolean bIsRunningSeconds = false;
boolean bRunMinutes = false;
boolean bIsRunningMinutes = false;
boolean bRunHours = false;
boolean bIsRunningHours = false;


void runSeconds() {
  bIsRunningSeconds = true;

  Serial.print("s"); // remove when confident


  // task: keep MQTT alive
  client.yield(30); // this takes 30 ms. May reduce the parameter // if you get duplicates, increase

// surprise functionality removed

  bRunSeconds = false;
  bIsRunningSeconds = false;
}


void runMinutes() {
  bIsRunningMinutes = true;

  Serial.println("m"); // remove when confident

  // ..

 

Why Event management


MQTT is event driven for the receiving side. You subscribe to a message, and provide the callback function that will be invoked upon incoming messages.

That is currently the only (non-interrupt) event driven scenario in my design.

 

image

Here's my handler. Some functionality that I'll reveal later is removed.

 

void messageArrived(MQTT::MessageData& md) // this handler is called when a subscribed MQTT message arrives
{
  MQTT::Message &message = md.message;

  // debug code
  sprintf(printbuf, "Message arrived: qos %d, retained %d, dup %d, packetid %d\n",
  message.qos, message.retained, message.dup, message.id);
  Serial.print(printbuf);
  sprintf(printbuf, "Payload %s\n", (char*)message.payload);
  Serial.print(printbuf);
  // end debug code



  // in the real world, I should validate if this is the right topic -- I've only subscribed to one so I'll not bother

  // here be secret codes for surprise functionality

}

 

Other candidates?


I may add an interrupt handler for a button that I plan to use, but since that is only to be used in calibration scenario's, I may just handle that in my loop(). I'm not in the mood to pull out my debounce lib.

I would go full-fledged if I had a keyboard or an end-user button interface. But that's not the case, so a simple check of the pin state in my loop will do.

 

update: execution log of one hour operation

invoking linux date
linux date invoked
20141231


20141231
day: 20141231 checking against: 20141130 checking against: 20141201 checking against: 20141202 checking against: 20141203 checking against: 20141204 checking against: 20141205 checking against: 20141206 checking against: 20141207 checking against: 20141208 checking against: 20141209 checking against: 20141210 checking against: 20141211 checking against: 20141212 checking against: 20141213 checking against: 20141214 checking against: 20141215 checking against: 20141216 checking against: 20141217 checking against: 20141218 checking against: 20141219 checking against: 20141220 checking against: 20141221 checking against: 20141222 checking against: 20141223 checking against: 20141224 checking against: 20141225 checking against: 20141226 checking against: 20141227 checking against: 20141228 checking against: 20141229 checking against: 20141230 checking against: 20141231 found state : 22
0
...
0
Payload secret
119
...
116
motor adjust in seconds: 9
115
motor adjust in seconds: 9
114
motor adjust in seconds: 9
113
motor adjust in seconds: 9
112
motor adjust in seconds: 8
111
motor adjust in seconds: 7
110
motor adjust in seconds: 6
109
motor adjust in seconds: 5
108
motor adjust in seconds: 4
107
motor adjust in seconds: 3
106
motor adjust in seconds: 2
105
motor adjust in seconds: 1
104
motor adjust in seconds: 0
103
motor adjust to advent state
102
...
65
m
64
...
6
5
m
4
3
2
1
0
0
...
0
Payload secret
119
...
106
motor adjust in seconds: 9
105
motor adjust in seconds: 8
104
motor adjust in seconds: 7
103
motor adjust in seconds: 6
102
motor adjust in seconds: 5
101
motor adjust in seconds: 4
100
motor adjust in seconds: 3
99
motor adjust in seconds: 2
98
motor adjust in seconds: 1
97
motor adjust in seconds: 0
96
motor adjust to advent state
95
m
94
93
...
36
35
m
34
33
...
4
3
2
1
0
0
...
0
0
m
0
...
0
m
h
invoking linux date
linux date invoked
20141231


20141231
day: 20141231 checking against: 20141130 checking against: 20141201 checking against: 20141202 checking against: 20141203 checking against: 20141204 checking against: 20141205 checking against: 20141206 checking against: 20141207 checking against: 20141208 checking against: 20141209 checking against: 20141210 checking against: 20141211 checking against: 20141212 checking against: 20141213 checking against: 20141214 checking against: 20141215 checking against: 20141216 checking against: 20141217 checking against: 20141218 checking against: 20141219 checking against: 20141220 checking against: 20141221 checking against: 20141222 checking against: 20141223 checking against: 20141224 checking against: 20141225 checking against: 20141226 checking against: 20141227 checking against: 20141228 checking against: 20141229 checking against: 20141230 checking against: 20141231 found state : 22
0
0
...

 

 

 

 

 


  • Sign in to reply
  • Jan Cumps
    Jan Cumps over 10 years ago in reply to DAB

    I have deliberately chosen a slow timer tick. And even with that slow tick my timing isn't critical. It doesn't matter in this design if I miss a second.

     

    The linux part on our Yun is not deterministic for timing, so I guess timing can be an issue with slower time events too, if it matters for the design.

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
  • DAB
    DAB over 10 years ago

    Timing is always important and a great habit to get into.

     

    I am curious as to how well Linux can support real time events at the sub second level?

    I assume that your longer time events were not critical response issues so you could live with the normal wireless delays.

     

    DAB

    • Cancel
    • Vote Up 0 Vote Down
    • Sign in to reply
    • More
    • Cancel
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube