Comment by topspin
5 days ago
From the blog: "Not surprising once you understand that slewing to a target significantly increases the number of pulses per second sent to the motors, and everything became just too much to handle for our little ESP32."
A hobby application of mine involves driving multiple steppers at high-ish frequencies, following sigmoid curves precisely and no tolerance for glitches, because the mass and the cost of the device(s) is too great to risk any failure in pulse output, and there is no feedback, so I must not suffer "missed" steps, glitches, etc. The big hammer that solves this is obviating the MCU core (ARM or otherwise,) in motion control and using timer peripherals with DMA.
Ultimately, I ended up turning to STM32G4 MCUs because of the ACT (advanced control timer) peripheral. These timers can generate arbitrary waveforms using DMA in a relatively simple manner: the ARM core and its code/RTOS/whatever can suffer whatever overload, priority inversion, sleep mode, etc. happens to emerge, and the timers are unaffected.
Today I would consider using RP2350 and the PIO peripheral, which is also capable of achieving this, I believe.
ESP32 has its MCPWM peripheral, but I determined that with MCPWM you can't do the sort of arbitrary acceleration/deceleration profiles I needed in a 100% "core-free" manner without either a.) cascading timers or b.) using interrupts. The former is, comparatively speaking, complex[1], and the later gets you back into the MCU core, and possible glitches[2]. With the ST ACT peripheral, the problem is self contained to one timer per motor: simple and straightforward. At least one of their MCUs has three of those timers (G474, in larger packages, for example.)
The other way to go is specialized motor driver ICs. Analog Devices, by way of their Trimanic line of devices and low cost breakout boards, has great products there, widely used with 3D printers, CNC and similar. The driver software is much more complex than my simple ACT peripheral solution, however.
[1] I know it's possible and others have done it. The ST peripheral is far easier to get working and get right, if you can deal with CMSIS and the ST reference manual.
[2] I know about interrupt priorities. I also know about code evolution, bugs and other ways that dealing in interrupt priorities can get fragile.
OnStepX is very much pulse based as far as I understand it. I haven't encountered offloading techniques like you mentioned yet. Since both motors support (multiturn) positon modes, it should be possible to completely forego the pulsebased approach and only drive the motors using regular (and less frequent in comparison to pulses) position instructions over CANBUS. I spent some time reading the code in OnStepX to understand how to implement it in this way but hooking it up in pulsemode was just too easy to get started.
> it should be possible to completely forego the pulsebased approach and only drive the motors using regular (and less frequent in comparison to pulses) position instructions
Since that capability is present, it's probably worth your while to apply it. Good motion control is hard, but important. Unnecessary vibration due to phase noise in the pulse train is an example of the subtleties that matter at high frequency. Excessive force generated when moving large masses can prematurely wear drive components and, over time, backlash increases and you get precision and repeatability problems. Well managed motion control will mitigate these things.
When I was doing stepper control on rp2040 I looked into using PIO but the 5 bit counters and 32 instruction limit made it too awkward to use. What worked better for my needs was dedicating 2nd core for just motion control and bit-banging the step/dir signals- simple to implement and good enough for the modest needs I had (just trapezoidal velocity profile for single axis motion).
> but the 5 bit counters
5 bit shift register, I believe you mean. Have a look at this. 16 instructions. Completely untested. I qualified my comment about RP2350 as "I believe," because I haven't actually done this: only investigated it via ChatGPT and Gemini. But it appears sound. Precision bit banging. PIO is pretty cool.
For anyone wondering how much they can push their MCU controlling stepper, take a look at Merlin 3D printer FW, they used to run on a little 8 bit AVR MCU and do complex math(for delta printer)
I think the ESP32 also has an RMT, did you also exclude that as an option?
Good question, and yes, I did. RMT can work, but ACT has a key advantage. Motion curves are naturally segmented into phases. With ACT, the Repeat Count Register (RCR) defines how many cycles to hold a given frequency and duty, so each phase is exactly 64 bits: PSC, ARR, CCR, and RCR. A full curve reduces to a compact precomputed table that can be hardcoded, generated once, or streamed with negligible core load for continuous motion.
With RMT, you either need a large table of individual level/duration symbols or involve the core to manage phase pulses.
It’s entirely feasible to do this with ESP32 using MCPWM, RMT, etc. Its been done and has worked well. But I value the dead-simple, hard-to-get-wrong invariants of ST's timers.