Recent changes
SerialPC
Creating a program
Downloading a program
Setup guide
Exporting to Code Red
Exporting to uVision
Order
tag order
From the mbed microcontroller Handbook.  

Ticker

The Ticker interface is used to setup a recurring interrupt to repeatedly call a function at a specified rate.

Any number of Ticker objects can be created, allowing multiple outstanding interrupts at the same time. The function can be a static function, or a member function of a particular object.

Hello World!

A simple program to setup a Ticker to invert an LED repeatedly...

Example attaching a static function to a ticker

#include "mbed.h"

Ticker flipper;
DigitalOut led1(LED1);
DigitalOut led2(LED2);

void flip() {
    led2 = !led2;
}

int main() {
    led2 = 1;
    flipper.attach(&flip, 2.0); // the address of the function to be attached (flip) and the interval (2 seconds)

    // spin in a main loop. flipper will interrupt it to call flip
    while(1) {
        led1 = !led1;
        wait(0.2);
    }
}

API

API summary

TickerA Ticker is used to call a function at a recurring interval
Functions
attachAttach a function to be called by the Ticker, specifiying the interval in seconds
attachAttach a member function to be called by the Ticker, specifiying the interval in seconds
attach_usAttach a function to be called by the Ticker, specifiying the interval in micro-seconds
attach_usAttach a member function to be called by the Ticker, specifiying the interval in micro-seconds
detachDetach the function
class Ticker : public TimerEvent
A Ticker is used to call a function at a recurring interval
void attach(void (*fptr)(void),
float t)
Attach a function to be called by the Ticker, specifiying the interval in seconds
void attach_us(void (*fptr)(void),
unsigned int t)
Attach a function to be called by the Ticker, specifiying the interval in micro-seconds
void detach()
Detach the function

Examples

Example attaching a member function to a ticker

#include "mbed.h"

// A class for flip()-ing a DigitalOut 
class Flipper {
public:
    Flipper(PinName pin) : _pin(pin) {
        _pin = 0;
    }
    void flip() {
        _pin = !_pin;
    }
private:
    DigitalOut _pin;
};

DigitalOut led1(LED1);
Flipper f(LED2);
Ticker t;

int main() {
    t.attach(&f, &Flipper::flip, 2.0); // the address of the object, member function, and interval

    // spin in a main loop. flipper will interrupt it to call flip
    while(1) {
        led1 = !led1;
        wait(0.2);
    }
}



calendar Page history
Last modified 21 Jul 2010, by   user Dan Ros   tag No tags | 22 comments      

22 comments on Ticker:

06 Dec 2010

Has anyone used Ticker() to develop a thread scheduler or some other type of preemptive multiprocessor OS?

07 Dec 2010

the function says attach_us where the description says micro-seconds

07 Dec 2010

Hi Stephan,

Yes, that is correct. In general:

  • milli-seconds is shortened to ms
  • micro-seconds is shortened to us

Simon

19 Dec 2010

When I create multiple Ticker objects, are the attached functions executed in parallel? E.g. When I have one ticker updating the first line of a LCD every second, and other ticker updating the second line of the same LCD every 5 second, do I need some form of synchronization (a semaphore) or are these calls executed after each other?

28 Dec 2010

Just a suggestion...

The example code for Ticker in the "mbed" library browser declares the ticker object using the identifier "timer". Would "ticker" be a more appropriate identifier? There's nothing wrong with the code, but this caused me a little confusion between the Timer and Ticker classes for about half an hour. All sorted now :) (P.S. mbed is a superb product)

28 Dec 2010

Hendrick; they don't execute in parallel, as one will get there first and they both have the same priority. So you should be fine

John; thanks for the pointer. I'll note that to be updated at the next natural point.

Simon

11 Jan 2011

how small can I make the wait time?

11 Jan 2011

user shang wang wrote:

how small can I make the wait time?

AFAIK one microsecond (when you use the attach_us methods). But then your callbacks would need to be really fast...

29 Jan 2011

My question is the opposite...how LONG can I make the wait time?

I have two tickers set up, one that goes off every 0.25 seconds, and another that goes off...well, if I set it to every minute, they both work, if I set it to every hour (60.0*60.0) then the shorter one never goes off. And I haven't waited around long enough to see if the longer one does ;)

20 Mar 2011

How do I pass arguments to a function that is to be attached using the Ticker function.

for e.g using the above example if the function flip was something like

void flip (int x) { x= x+1; }

How do I attacn this function with Ticker???

09 Apr 2011

I have the same question as Kunai.

I have the function: void ledpwmonoff(int lednr) {

And the ticker attach attempt: ticker.attach(&ledpwmonoff(1),24.0);

Which gives the error: expression must be an lvalue or a function designator (E158)

tried some (()()())))()()'s around ledpwnonoff in the attach, but didn't work.

09 Apr 2011

Make a small wrapper and attach that.

Code

void ledon()
{
  ledpwmonoff(1);
}
[...]
ticker.attach(ledon, 24.0);
15 Apr 2011

What I mean to accomplish is something like

Code

void ledpwmonoff(int lednr) {
    switch(lednr) {
        case 1: led1=!led1;
        case 2: led2=!led2;
        case 3: led3=!led3;
        case 4: led4=!led4;
    }
}

int main() {
    ticker.attach(&ledpwmonoff(int variable),2.0); //variable = the lednr; 1,2,3 or 4
    wait(0.5);
    ticker.attach(&ledpwmonoff(int variable),2.0); //variable = the lednr; 1,2,3 or 4
    wait(0.5);
    ticker.attach(&ledpwmonoff(int variable),2.0); //variable = the lednr; 1,2,3 or 4
    wait(0.5);
    ticker.attach(&ledpwmonoff(int variable),2.0); //variable = the lednr; 1,2,3 or 4
}

which should create a very simple lightshow ;) The wrapper does solve the error, but not the problem I was having ;)

Regards,

Melchior

15 Apr 2011

Simple solution is probably to make 4 seperate functions :)

15 Apr 2011

You could always use templates to do the work for you if you did want to go down this closure-style route:

Code

#include "mbed.h"

DigitalOut led1(LED1);
DigitalOut led2(LED2);
DigitalOut led3(LED3);
DigitalOut led4(LED4);

void ledpwmonoff(int lednr) {
    switch(lednr) {
        case 1: led1=!led1;
        case 2: led2=!led2;
        case 3: led3=!led3;
        case 4: led4=!led4;
    }
}

template<void (*fptr)(int), int value>
void caller() { 
    fptr(value);
}

Ticker ticker;

int main() {
    ticker.attach(caller<&ledpwmonoff,1>, 2.0);
    wait(0.5);
    ticker.attach(caller<&ledpwmonoff,2>, 2.0);
    wait(0.5);
    ticker.attach(caller<&ledpwmonoff,3>, 2.0);
    wait(0.5);
    ticker.attach(caller<&ledpwmonoff,4>, 2.0);
    wait(0.5);
}

Simon

20 Apr 2011

I'm a novice C++ programmer and I've been playing with the examples above, even though I don't fully understand what I'm doing! That said, it looks like the above example should be using 4 different tickers rather than just 1. When I tried it, only LED4 does anything. I modded the code:

Code

Ticker ticker1;
Ticker ticker2;
Ticker ticker3;
Ticker ticker4;
int main() {
    ticker1.attach(caller<&ledpwmonoff,1>, 2.0);
    wait(0.5);
    ticker2.attach(caller<&ledpwmonoff,2>, 2.0);
    wait(0.5);
    ticker3.attach(caller<&ledpwmonoff,3>, 2.0);
    wait(0.5);
    ticker4.attach(caller<&ledpwmonoff,4>, 2.0);
//  wait(0.5);
}

now all 4 LEDs dance!

Graeme

21 Apr 2011

Ah right, that makes sense Graeme : )

I wrote the example just to explain what I wanted to achieve but I see that it would just overwrite the ticker 4 times, leaving only the last one with LED4. Your solution solves that!

And cheers Simon, I will have a go with the template when I'm at home. Graeme's response is cause for optimism ^^

Thanks,

Melchior

17 Nov 2011

From the http://mbed.org/forum/mbed/topic/1189/?page=1#comment-14619 post:

Quote:

All mbed tickers use the TIMER3 object, so you can create a critical section in your main code to access a buffer being written to by a Ticker handler:

Code

NVIC_DisableIRQ(TIMER3_IRQn);

// critical section
 
NVIC_EnableIRQ(TIMER3_IRQn);

21 Nov 2011

Hello guys, i am new to programming and try to set up a ticker. my code looks like this:

Code

class1.h
#include "mbed.h"

class class1 {
  private:
    Ticker ticker;
  public
    class1();
    void func();
};

Code

class1.cpp
#include "class1.h"

class1::class1() {
  ticker.attach(&class1::func, 2.0);
}

class1::func() {
  //Do something
}

i always get the error: "no instance of overloaded function "mbed::Serial::attach" matches the argument list"

if i put the function func() in a separate .h-file not as a memberfunction and then call:

Code

  ticker.attach(func,2.0);

everything works fine. Can someone help me with the correct syntax?? Thank You.

21 Nov 2011

The member-function version of attach() also needs an instance pointer. Try:

Code

class1::class1() {
  ticker.attach(this, &class1::func, 2.0);
}
21 Nov 2011

user Igor Skochinsky wrote:

The member-function version of attach() also needs an instance pointer. Try:

Code

class1::class1() {
  ticker.attach(this, &class1::func, 2.0);
}

thank you, you saved my day!

27 Nov 2011

Warning!

The mbed compiler will aggressively optimise use of global variables, which may result in changes to a variable in a Ticker attach function not being seen by the base level code. Compiler optimisation is variable, and can be prevented by API calls etc, so this is a difficult bug to diagnose.

Such variables must be declared volatile.

Here is an example which will (likely but not certainly) fail without the use of volatile.

Code

volatile int running = 1;

Ticker tick;

void isr(void)
{
  running = 0;
}

int main(void)
{
   tick.attach(&isr, 10.0); // set up interrupt every 10s
   while (1) {
     printf("Starting test...\n");
     running = 1;
     while (running); // inner while loop is broken by interrupt
     printf("OK.\n");
   }
   return 0;
}



Please login to post comments.