IOT ESP8266 Timer Tutorial – Arduino IDE

This is the second of a multi-part posting on the ESP8266. We are giving an example of how to use the timers on the ESP8266. It was very hard to find a simple example of how to use the timers under the Arduino IDE. We need this for our new IOT project, a pulse meter feeding into the Amazon IOT software. We need a steady 2 millisecond interrupt based timer to do the pulse sampling.

Check out our other ESP8266 Projects and Products

A series of IOT ESP8266 Tutorials

Part 1 IOT ESP8266 Tutorial – Using nodeMCU/LUA

Part 2 IOT ESP8266 Timer Tutorial – Arduino IDE

Part 3 IOT ESP8266 Tutorial – Using the Arduino IDE

Part 4 IOT ESP8266 Tutorial – AT Command Set Firmware

Part 5 IOT ESP8266 Tutorial – Connect to the IBM Bluemix Internet of Things

Part 6 IOT ESP8266 Tutorial – Sending ESP8266 Data to the IBM Bluemix IOT

Part 7 IOT ESP8266 Tutorial – The IOT Application and Source Code

Part 8 IOT ESP8266 Tutorial – Displaying the data on the IBM Bluemix IOT

We are using the Adafruit ESP8266 Huzzah breakout board for these postings.

Why Use Timers to Generate Interrupts?

Often you want an action to be repeated at specific intervals. Timing your loops and adding delay statements to time your loops is difficult, may change and will not port to a faster processor (and there are faster versions of the ESP8266 coming out). The best way of doing this is to use a timer and a callback routine. That is what we are showing in the example below.

Note that it doesn’t have to be a repeatable event. You can schedule one-shots too in the future.

The ESP8266

The ESP8266 is made by a privately held company in China called Espressif. They are a fabless semiconductor company that just came out of nowhere and shook up the whole industry. Now all the major players are working on inexpensive versions of an IOT chip with WiFi connectivity. And they are all struggling to make it as inexpensive as the ESP8266

The Adafruit ESP8266 Huzzah

The Adafruit ESP8266 Huzzah board is a great breakout for the ESP8266. It makes it much easier to use with the Raspberry Pi that the really cheap modules.

Most of the low cost modules are not breadboard friendly, don’t have an onboard 3.3V regulator or level shifting for signals. The Huzzah has all of those features. For more on the ESP8266 Huzzah board see this posting.

The Timers on the ESP8266

There are two types of timers on the ESP8266. There is os_timer, which is a software based interval timer and the os_timer apparently only has capacity to have seven timers set at one time. The second type of timer is a hardware based timer, hw_timer, of which there is apparently only one. We would suggest not to use the hw_timer, as we really don’t know or understand what the ESP8266 libraries are using it for. You could easily screw up the WiFi, for example. The documentation for the hw_timer is sparse, at best. Our example below uses the os_timer.

The above information is not solid. The ESP8266 is a poorly documented system at this point. It will get better. We will update this as more information becomes available.

Update November 13, 2015: We now have found out that the use of the os_timer set to a 2ms interrupt will cause the WiFi to fail. We are investigating the cause, but right now it definitely kills the WiFi connection and will not reconnect.

Note on the use of os_timer

Because it is a software timer, based on the underlying hardware timer, it is “Soft Real Time”. Depending on what the rest of the operating system is doing (WiFi, PWM, etc.), it will interrupt you when triggered, but it isn’t at an exact time. It will be close. Keep that in mind. You may see jitter in the timing. The faster interval you set for the os_timer, the more jitter you may see.

A Simple Timer Example for the ESP8266

We spent quite a bit of time looking for an example of how to use os_timer in the Arduino IDE. Here is our test program. Our pulse monitor is now running on os_timer correctly. Note there is another set of os_timer functions that allow microsecond resolution. Using them will increase your jitter as above.

// // ESP8266 Timer Example // SwitchDoc Labs October 2015 // extern "C" { #include "user_interface.h" } os_timer_t myTimer; bool tickOccured; // start of timerCallback void timerCallback(void *pArg) { tickOccured = true; } // End of timerCallback void user_init(void) { /* os_timer_setfn - Define a function to be called when the timer fires void os_timer_setfn( os_timer_t *pTimer, os_timer_func_t *pFunction, void *pArg) Define the callback function that will be called when the timer reaches zero. The pTimer parameters is a pointer to the timer control structure. The pFunction parameters is a pointer to the callback function. The pArg parameter is a value that will be passed into the called back function. The callback function should have the signature: void (*functionName)(void *pArg) The pArg parameter is the value registered with the callback function. */ os_timer_setfn(&myTimer, timerCallback, NULL); /* os_timer_arm - Enable a millisecond granularity timer. void os_timer_arm( os_timer_t *pTimer, uint32_t milliseconds, bool repeat) Arm a timer such that is starts ticking and fires when the clock reaches zero. The pTimer parameter is a pointed to a timer control structure. The milliseconds parameter is the duration of the timer measured in milliseconds. The repeat parameter is whether or not the timer will restart once it has reached zero. */ os_timer_arm(&myTimer, 1000, true); } // End of user_init void setup() { Serial.begin(115200); Serial.println(); Serial.println(); Serial.println(""); Serial.println("--------------------------"); Serial.println("ESP8266 Timer Test"); Serial.println("--------------------------"); tickOccured = false; user_init(); } void loop() { if (tickOccured == true) { Serial.println("Tick Occurred"); tickOccured = false; } yield(); // or delay(0); }

Compile the code, run it and you will see “Tick Occurred” printed to your serial console on the Arduino IDE every second.

Comments

Here are few pointers about using interrupts in the ESP8266, as well as in any Arduino based system.

– Keep your Interrupt Service Routine (ISR) short. ISR is another name for the callback function.

– Do not use “serial print” commands in an ISR. The serial commands also use interrupts and using them can hang the processor

– It is good practice to disable interrupts in an ISR routine (os_intr_lock();/os_intr_unlock();) and then enable them as you leave. We are not doing that in this routine as we are not sure what the effects would be on the underlying operating system. Our routine is so short, it clearly doesn’t matter here.

– Note that the real work of the interrupt is being done in the main loop. That can affect your timing of your servicing your interrupt.

– You have to put a yield() or a delay(0) in your main loop to allow the underlying operating system to do it’s work.

– There is a watchdog timer in the ESP8266 that will reset the processor if you keep it busy too long. More on that in a future posting. Put lots of yield() or delay(0) statement in your program to keep this from happening. Note, delays with values greater than zero (delay(10) for example) are fine.