2 years, 5 months ago.

Change the period of a ticker "on the fly"

I am writing a motion controller to run on F401RE. I need to generate pulses on six output pins at six different rates. But let's look at just one pin.

It seems the easy way is use a "ticker". The following should work perfectly

ticker t;
t.attach_us(&flipTheBit(), 105);

The above should make a square wave with 210 uS period. But then I want to change the speed and I want to do it "perfectly" meaning that one wave has a period of 210 and the next has a period of 200.

Can I simply do this (a second attach with no detach first)?

ticker t;
t.attach_us(&flipTheBit(), 105);
wait(1);
t.attach_us(&flipTheBit(), 100);

If not is there a better way?

Next question: How do I find out how many tickers my platform supports? Or is this done in software and it's basically unlimited? I need to have six and I REALLY cannot afford to have glitches when the speed changes.

What I'm afraid of is that I will not be able to use mbed API and will need to find a platform with six free 32-bit timers and then "stuff" the compare registers on the fly to change the rates. If I have to do this which Nucleo has 6 free 32-bit timers?

(Just in case you wonder, this is a robot arm with 6 degrees of freedom that is moving a few Kg of mass around.)

3 Answers

2 years, 5 months ago.

Have you looked into using the PWM feature? The mbed basic library uses Pwmout but you can use the ST HAL libraries for additional features such as what you're looking to do. Also there is a "FastPWM" use library out in the mbed universe which has additional features.

Thanks, it did not occur to me that PWM would run as fast a 1uS period. But I don't see a "FastPWN" in the OS 5 handbook API.

It will be some time be some time before i contest this, need to get setup to measure jitter statistics. May have to record the PWM with my digital scope then figure out how to get data into computer.

Then to figure out how many PWM signals I can output at the same time.

posted by Chris Albertson 02 Apr 2018

Like I said, the FastPWM lib is out in the mbed universe... just use the search function. It's an add-on from one of the contributors https://os.mbed.com/users/Sissors/code/FastPWM/docs/tip/classFastPWM.html

posted by Bill Bellis 03 Apr 2018
2 years, 5 months ago.

To answer your questions in the reverse order:

Tickers, Timers and Timeouts are all done in software. One of the hardware timers is set to generate a 1 us tick (or slower on some of the low end boards) and then all of the tickers etc... are done in software off of that single timer.

So there is a slight performance hit for each additional ticker since it has more to check each clock tick but you can't run out of hardware timers.

On your first question, how to maintain nice clean wave forms, I'd do it something like this:

Ticker output1Tick;
DigitalOut output1Pin(<pinName>);
unsigned int output1Period;

void flipTick1() {
  static unsigned int currentPeriod = 0;
  output1Pin != output1Pin;
  if (currentPeriod != output1Period) 
    if (!output1Pin) {  // only change period when transitioning high to low
      output1Tick.attach_us(&flipTick1,output1Period);
      currentPeriod  = output1Period;
    }
}

main () {
  output1Period = 210;
  output1Tick.attach_us(&flipTick1,output1Period);
  wait(1);
  output1Period = 200;
}

By changing the period in the ticker function you ensure that you'll keep the correct periods at all times. The way your code was working you would get a single pulse at the transition that would be between the new length and the new length plus the old length.

Be careful if you go the PWM route, it may or may not work for you. On many of the platforms 4 or 8 PWMs are generated from a single hardware timer using different match registers. This means that the duty cycle on each can be set independently but changing the period on one changes the period on all of the others. How flexible they are and whether they will do what you want or not will depend on the platfom you use and possibly which PWM output pins you use.

Thanks, I tried PWM and it seems to work but my test platform was Nucleo F446 and it has lots of timers. I want this to run on a much smaller platform like the $2 F103 "blue pill". I'll try it but it has fewer hardware timers.

What I did not know is if attach() could be called twice reliably. The documentation does not say and simply testing it is risky because it might work 10,000 times in a row then fail or as you pointed out work on one platform and fail on another. So I hate to use "try and see if it works" method.

So far I like PWM method because it seems to have very excellent timing (on the F446), the jitter on the pulse is on the order of 50 nS and there is zero software overhead. But it is fails to work on low-end platforms I can't use it. It was good news to hear that you can't run out of tickers but let's see what the uncertainty in interrupt latency does to the timing. Likely it will still be OK.

posted by Chris Albertson 03 Apr 2018
2 years, 5 months ago.

I have written a small "Tickers" for Arduino and mbed where you can change the timing on fly. https://github.com/sstaub/mbedTickers