Skip to content
dniklaus edited this page Oct 14, 2014 · 24 revisions

Go back Home - Go back to the previous step: Project Repository and Workspace Preparations


With the just cloned skeleton project you get an empty Sketch with the typical Arduino stub functions setup() and loop(). Additionally the Timer library component is made ready to be used:

blink-skel-app

You will add some functionality to the Blink Sketch now in order to create a blinking LED application. The following class diagram depicts the application design:

blink-skel-app

Implement the Sketch

In the Eclipse IDE open the file arduino_blink.cpp, this is our Blink Sketch where we add our code.

  • let's start with including the Timer library, add the following line just after the existing #include line.

    #include "Timer.h"
  • copy the Event Processing function into the Sketch right after the include lines:

    void toggleLed(int ledPin)
    {
      bool isLedOn = digitalRead(ledPin);
      digitalWrite(ledPin, !isLedOn);
    }

    This function reads the LED pin's state using the Arduino's built in digitalRead() and writes the inverse state back with the Arduino's function digitalWrite().

  • declare a blinkTimer instance variable and initialize it to zero (NULL pointer):

    Timer* blinkTimer = 0;
  • define the interval time

    const unsigned int BLINK_TIME_MILLIS = 500;
  • define and implement the Timer Event callback adapter, calling the Event Processing function:

    class BlinkTimerAdapter : public TimerAdapter
    {
    public:
      void timeExpired()
      {
        toggleLed(LED_BUILTIN);
      }
    };
  • in the setup() function (this gets called once after startup):

    • configure the LED pin as output (LED_BUILTIN is an Arduino constant, for most Arduino board types this is set to 13)

    • instantiate a Timer object, inject a BlinkTimerAdapter object, make the Timer recurring and set the interval

      void setup()
      {
        pinMode(LED_BUILTIN, OUTPUT);
        blinkTimer = new Timer(new BlinkTimerAdapter(), Timer:: IS_RECURRING, BLINK_TIME_MILLIS);
      }
  • in the loop() function (this gets repeatedly called forever right after setup() has finished):

    • trigger the scheduler by calling the yield() function:

      void loop()
      {
        yield();
      }

Please find the example Sketch source implementation here: https://github.com/ERNICommunity/arduino-blink/blob/example/src/arduino_blink.cpp

Discussion

The following sequence diagram shows the principle of how the application works:

In the setup() the BlinkTimerAdapter and the blinkTimer are created, and the BlinkTimerAdapter object gets injected into the blinkTimer object. On creation of the Timer this fetches an instance of the TimerContext singleton and attaches itself to it.

The first time the loop() function runs after setup() is finished, the yield() function implemented by the Timer library runs and the TimerContext instance is fetchted in order to run handleTick() on it. This calls tick() on the first attached Timer object in the list of TimerContext. With this the blinkTimer object's time expiration event will be evaluated. This time the event is not yet due, so nothing happens. The linked list of timers has no more elements, so the handleTick() method terminates and the control is given back to the loop() function.

The second time the loop() function runs, the expiry time has been reached and the blinkTimer calls out the adapter's timeExpired() method which finally toggles the LED.

So all in all making a fuss of toggling a dull LED!? you might say. Well, this is an embedded Hello World program (these all just blink a LED), being a simple example to demonstrate the concept with the Timer library, which will help you to build much more complex applications with different timed and other events from outside the system, triggering multiple processes running in parallel.

Imagine the case where you will have more recurring events, all with different intervals triggering several processes. With the Timer library you can abstract all the time evaluations and the organisation of the several different timers. You just have to focus on your processing code and you can create loosely coupled components.

And: with this Timer library you are even able to use the Arduino's built-in delay() function. While the caller gets kept busy waiting, the yield() function will be steadily called (as it is implemented by the Arduino environment) and the timers get evaluated in the meanwhile.

Make the Timer Interval controllable

In order to demonstrate how you can get two processes work in paralell, the Blink with Timer example shall be enhanced. The interval of the timer shall be made controllable by certain characters received on the serial interface with the help from a new BlinkTimerControl class:

  • beside the toggleLed() action, the time expired event also triggers the blink timer interval control process
  • after each timer expired event, the timer shall be restarted with the new interval, if changed
  • the interval can be altered by certain received characters on the serial interface:
    • on an 'i', the timer interval shall be incremented
    • on a 'd', the timer interval shall be decremented

blink-skel-app

Copy the class files BlinkTimerControl.{h|cpp} from here:

.. into the folder C:\git\arduino-projects\arduino-blink\src

In the Eclipse IDE select the arduino_blink project and press F5. This will refresh the source file list in the project tree and the new class will appear.

In the Blink Sketch file arduino_blink.cpp, add the following code fragments:

  • start with adding the BlinkTimerControl dependency inclusion:

    #include "BlinkTimerControl.h"
  • go ahead with adding the global variable definition for the BlinkTimerControl object instance:

    // global variable definition
    BlinkTimerControl* blinkTimerControl = 0;
  • within the existing BlinkTimerAdapter timeExpired() method, add the following call out after the one for toggleLed():

    if (0 != blinkTimerControl)
    {
      blinkTimerControl->timeExpired();
    }
  • insert the new function serialEvent():

    /*
      SerialEvent occurs whenever new data comes in from the
      hardware serial RX. This routine is run between each
      time loop() runs, so using delay inside loop can delay
      response. Multiple bytes of data may be available.
    */
    void serialEvent()
    {
      while (Serial.available())
      {
        // get the new byte:
        char inChar = ( char)Serial.read();
        if (0 != blinkTimerControl)
        {
          if ('d' == inChar)
          {
            blinkTimerControl->decrementBlinkTime();
          }
          else if ('i' == inChar)
          {
            blinkTimerControl->incrementBlinkTime();
          }
        }
      }
    }
  • replace the existing setup() function implementation by the following one:

    void setup()
    {
      pinMode(LED_BUILTIN, OUTPUT);
      Serial.begin(115200);
      BlinkTimerAdapter* blinkTimerAdapter = new BlinkTimerAdapter ();
      blinkTimerControl = new BlinkTimerControl(blinkTimerAdapter, BLINK_TIME_MILLIS);
      //blinkTimer = new Timer(new BlinkTimerAdapter(), Timer::IS_RECURRING, BLINK_TIME_MILLIS);
    }

Please find the example code with the controllable Timer: https://github.com/ERNICommunity/arduino-blink/blob/example2/src/arduino_blink.cpp


Go to Top - Go back Home - Go back to the previous step: Project Repository and Workspace Preparations

Clone this wiki locally