So last Friday we tried generating DShot with an ESP32 DevkitC and starting our motor with it.
After familiarising ourselves with the ESP API reference, we managed to generate a DShot signal on the SPI bus of the ESP32 using DMA. The idea is to send a DShot bit as an 8-bit SPI frame with the first 3 bits high to send a 0 and the 6 first bits high to send a 1, as explained in this post.
The SPI clock frequency we need to generate DShot600 is a 4.8MHz (4.8 MHz = 8 * 600 KHz, keeping in mind that a DShot bit is sent as an 8-bit SPI frame). But it turns out that on the ESP almost all peripherals, including the SPI, derive their clock from an 80 MHz clock. This means (using prescalers) only divisors of 80MHz could be obtained. The closest frequency available was 5 MHz, so we used that.
However when we tried to turn on the motor with this signal, we couldn’t : the motor hiccuped in a jerky way and stopped after a few seconds. With the help of the logic analyser and some maths (that really should have been our first step), we realised that the frequency difference was too big to ever have a chance to work.
We then thought to use the RMT peripheral, but it would have the same clock issues. In fact, there really seems to be no easy way to generate accurate DShot with an ESP32.
Score 1 for STM32 !
Today, we turned ourselves back to the STM32. In order to avoid taking up to much of the CPU time and so achieve higher speeds, we decided to use a DMA transfer as explained here.
The idea is to configure the duty cycle duration of the timer on the fly from one PWM cycle to the next, so as to send the necessary succession of long and short pulses. To do so, we precompute the required duty cycles for each of the 16 bits of the current DShot frame (mainly composed of a throttle value and a checksum). Then, we set up a DMA to transfer the next pre-computed duty cycle directly to the CCRx register (the one where the duty cycle is stored) of the timer at the time the update event of the timer occurs.
After a few attempts, we finally managed to generate a correct DShot signal, with correct timings and frequency, but since the FabLab is closed, we couldn’t test it to turn on our motor :/ We’ll do that first thing tomorrow.
Stay tuned !