TimerOne - slow 1 Hz pulses works on Uno, but not on Teensy 3.2?

Status
Not open for further replies.

kd5byb

Member
Good evening!

I'm in the process of creating a controller for a diesel-fired heater. It uses a metering pump to inject a known amount of fuel into the burner. I need to inject fairly low duty cycle pulses into the metering pump at fairly slow rates for this to work properly. (from about 1 Hz to a maximum of 6 Hz, at a duty cycle of 10% to 20%)

I tried the code below on an Arduino Uno using an LED and 1k resistor connected to Pin 9. Works perfectly! I get a 1 Hz pulse train for 5 seconds, then 2 Hz, then 4 Hz, then 5 Hz. :D

However, when I try it on a Teensy 3.2, adjusting the code to reflect that Teensy 3.2 has PWM on pin 3 (or pin 4), it doesn't work. Instead of getting 1 Hz pulses increasing to 5 Hz, I get a much faster pulse train (10 Hz maybe?) that doesn't change in frequency. :confused:

I suspect that perhaps due to the higher clock frequency on the Teensy 3.2 vice the Uno, TimerOne cannot go as slow as I need it to go?

Any help / advice is greatly appreciated!

Code:
#include <TimerOne.h>

void setup(void)
{
  pinMode(9, OUTPUT);
  Timer1.initialize(10000000);  // 1 Hertz
  Timer1.pwm(9, 100);
  Serial.begin(115200);
}


void loop(void)
{
Serial.println(millis());
delay(5000);
Serial.println(millis());
Timer1.setPeriod(500000);  // 2 Hertz
delay(5000);
Serial.println(millis());
Timer1.setPeriod(250000);  // 4 Hertz
delay(5000);
Serial.println(millis());
Timer1.setPeriod(200000);  // 5 Hertz
}

Thanks much and 73,
Ben, KD5BYB
 
That's 10 million, not 1 million.
Indeed! Looks like I injected a typo into my code. :( I just corrected that down to 1 million and tried it again on the Teensy 3.2... And I still get a flash rate between 4 and 5 Hz (put it on the counter to see what it was).

Since I had the counter out, I decided to experiment. Tried 10 thru 50 Hz as in the code block below and this works fine on the Teensy 3.2. I'm thinking 4 to 5 Hz may be the slowest Teensy 3.2 can go?

Code:
#include <TimerOne.h>

void setup(void)
{
  pinMode(3, OUTPUT);
  Timer1.initialize(100000);  // 10 Hertz
  Timer1.pwm(3, 100);
  Serial.begin(115200);
}


void loop(void)
{
Timer1.initialize(100000);  // 10 Hertz
Serial.println(millis());
delay(20000);
Serial.println(millis());
Timer1.setPeriod(50000);  // 20 Hertz
delay(20000);
Serial.println(millis());
Timer1.setPeriod(25000);  // 40 Hertz
delay(20000);
Serial.println(millis());
Timer1.setPeriod(20000);  // 50 Hertz
delay(20000);
}

Thanks much and 73,
Ben, KD5BYB
 
For the Teensy 3.2, the lowest frequency possible with TimerOne is a function of F_BUS/2. The maximum timer count is 32768 * 128 = 4,194,304.

If CPU Speed is the default 96 MHz, F_BUS is 48 MHz, so the minimum frequency is 48/2 MHz / 4,194,304 = 5.7 Hz.

F_BUS can be reduced by reducing the CPU Speed. Above 24 MHz CPU Speed, F_BUS = F_CPU/2. At 24 MHz and below, F_BUS = F_CPU.

At 24 MHz CPU Speed (slowest that still has USB), F_BUS is 24 MHz, so min freq = 2.9 Hz.

If you don't need USB, then at 2 MHz CPU Speed, min freq = 0.2 Hz.
 
For the Teensy 3.2, the lowest frequency possible with TimerOne is a function of F_BUS/2. The maximum timer count is 32768 * 128 = 4,194,304.
...
If you don't need USB, then at 2 MHz CPU Speed, min freq = 0.2 Hz.

Awesome, thanks much for the reply! I actually tried downshifting the clock frequency in the Arduino IDE board options, but did not go low enough in frequency to get where I needed. :)

For my diesel heater controller, I need two channels of PWM. One for the fuel metering pump...and the other for the combustion air blower (to keep the airflow somewhat matched to the fuel flow). Thinking about my approach some more, what I think I'm going to do is use the TimerOne library for the combustion air blower, as the PWM frequency will be in the range where TimerOne can handle it on a Teensy 3.2 with a stock clock. For the fuel metering pump, I think I'll go back to my hand-coded routine that manually generated the pulse output by checking millis() against the start and stop times of the pulse. That should work great at the stock clock speeds of the Teensy 3.2!

I'll admit...I'm tempted by the Teensy 4.1. An ethernet-connected heater with SDCard logging sounds rather neat... ;)

Thanks much and 73,
ben, kd5byb
 
A better solution instead of TimerOne would be to use analogWriteFrequency. The Teensy 3.2 allows up to 3 different frequencies (FTM0,1,2).

You could use pins 3 and 5, for example, as follows:

Code:
analogWriteFrequency (3, 1.0);   // 1 Hz
analogWrite (3, 26);             // 10% duty cycle

analogWriteFrequency (5, 2.0);   // 2 Hz
analogWrite (5, 128);            // 50% duty cycle

See https://www.pjrc.com/teensy/td_pulse.html for more details.
 
A better solution instead of TimerOne would be to use analogWriteFrequency. The Teensy 3.2 allows up to 3 different frequencies (FTM0,1,2).
...
See https://www.pjrc.com/teensy/td_pulse.html for more details.

WOW!!!
That's absolutely awesome! Exactly what I need! Very many thanks for pointing me to this! I searched around quite a bit and can't believe I didn't stumble across this during my searches! Absolutely fantastic. :)

Thanks much again!
-ben
 
I've updated the 6 main product pages to have the word "analogWriteFrequency" (in the Digital Pins > PWM section) link directly to the part of the PWM page about controlling the frequency and which pins are associated with which timers. Hopefully those links will help others to find this more easily in the future.
 
I've updated the 6 main product pages to have the word "analogWriteFrequency" (in the Digital Pins > PWM section) link directly to the part of the PWM page about controlling the frequency and which pins are associated with which timers. Hopefully those links will help others to find this more easily in the future.

Fantastic! I'm pretty sure that would have helped me find it. :)

Thanks much and 73,
ben, kd5byb
 
Status
Not open for further replies.
Back
Top