Go Down

Topic: Arduino MEGA + OneShot125 (Read 1 time) previous topic - next topic


Hello everyone!

I'm building a quadcopter drone, meant to be autonomous. And I'm having some ESC (electronic speed controller) issues.

The ESCs used to control brushless motors have a lot of protocols, some slower and some faster. The standard PWM protocol can be controlled using the servo library, but offers a narrow range and slow response. Today some newer ESCs even have a digital protocol ("DShot"), but I'm not that far, my EMAX 20A ESCs doesn't support digital protocols.

Using PWM protocol + servo library I can use the motors. But now I want to use the faster "OneShot125" protocol, and the servo library doesn't seems to support it because of the higher frequency and shorter pulses. OneShot125 pulses have a 125µs - 250µs duration, and the original PWM protocol uses a 1ms - 2ms duration. The duration of the pulse is equal to the motor acceleration, shorter pulse (125µs) means stop and longer pulse (250µs) means full power.

Does anyone have experience making OneShot125 work with Arduino Mega? Some examples would be very welcome.

There's almost no documentation regarding use of Arduino with such protocol, people usually control ESCs with dedicated flight controllers, not Arduinos.

Thanks in advance!


Jan 03, 2018, 07:15 pm Last Edit: Jan 03, 2018, 07:17 pm by MartinL
Hi ZeroDrop,

Unfortunately, there isn't a simple solution to implementing Oneshot PWM on the Mega.

The issue is that in order to have control over the PWM frequency, you have to use phase and frequency correct mode, but the timers' hardware is really geared up for just continuous PWM.

(DShot also isn't possible with the Mega, as it doesn't have a Direct Memory Access Controller (DMAC)).

Oneshot125 PWM is however possible with both the Arduino Due and Zero. The Zero supports it, the Due doesn't, but there's a workaround to make it function.

However, the Mega can support 490Hz standard hardware PWM for ESCs.

Here's some example code that runs 12 servos at 50Hz, 14-bit resolution: https://forum.arduino.cc/index.php?topic=444373.0.

To adapt this for ESC use at 490Hz, just change the ICRx regsiters from 20000 to 2040. Load the OCRxx registers with 1000: minimum throttle, 1500: mid throttle and 2000: max throttle.

Warning: Please remove the propellers if you're testing this code with brushless motors.


Jan 03, 2018, 11:29 pm Last Edit: Jan 03, 2018, 11:55 pm by MartinL
Hi ZeroDrop,

Actually, here's a solution for Oneshot125 on the Mega.

After giving it some thought, I realised I might be able to get it going by using the timers' interrupt service routines (ISRs). I wouldn't say it's a natural fit with the Mega's timers, but it works, producing a characteristic Oneshot125 pulsewidth from 125us to 250us.

The sketch sets up 12 timer channels on the 16-bit timers 1, 3, 4 and 5. It uses the timers' overflow (OVF) ISRs to load the OCRxx registers with the pulsewidth values on the first pass, and reset the PWM output back to 0V on the second.

There are 12 counter compare "cc" variables one for each timer channel. To generate a Oneshot125 pulse on a timer channel, just load the corresponding cc[] array with 1000 for minimum throttle, 1500 for mid throttle and 2000 for maximum, then enable the timer's overflow interrupt. Once the pulse has been sent the ISR disables itself.

The sketch outputs a Oneshot125 pulse set to trigger every second on all 12 channels. The pulse widths cycle from 125us, 187us, 250us then back to 125us and so on...

Please find the attached sketch as a zip file...

Go Up