Hi there,
Yes, this is the Rtos that handles the WIFi, etc… Even with radios disabled, the ESP32-C6 runs FreeRTOS on a single application core. Unlike the ESP32/ESP32-S3, the C6 has:
- One application core (RISC-V) for user code
- One low-power core for Wi-Fi/BLE and low-level tasks
So even though there are two cores, user code does not run independently from the OS services. That means:
- Periodic tasks (e.g. watchdog, timers, even idle task management) can interrupt fine-grained timing.
- Bit-banging GPIO for step pulses is not timing-guaranteed unless it’s running under a hardware peripheral (LEDC, MCPWM, etc).
That tiny stutter every 2 seconds? Likely a FreeRTOS housekeeping or system tick. I haven’t had my coffee yet to have total recall , let me look and I’ll get back…
HTH
GL PJ
One cup Later and some AI…
Bit-banging via digitalWrite()
or even gpio_set_level()
in a loop is not real-time. Especially when tight pulse spacing is required like:
digitalWrite(STEP, HIGH);
delayMicroseconds(5);
digitalWrite(STEP, LOW);
delayMicroseconds(500); // etc.
Even tiny delays in delayMicroseconds()
caused by interrupts can introduce jitter or pauses.
Options to Consider
Option 1: Use LEDC (again)
Even if the library doesn’t support LEDC out of the box, you can patch AccelStepper to optionally use LEDC or a timer-driven ISR for the step()
routine. It’s been done before with ESP32.
Option 2: Use a timer-based ISR
Use hw_timer_t
(on other ESPs) or esp_timer
on ESP32C6 to schedule a timer interrupt that toggles STEP at fixed intervals, avoiding loop()
entirely.
Option 3: Use taskDISABLE_INTERRUPTS()
block (NOT recommended long-term)
Temporarily disabling interrupts during pulse output might help prove the cause, but is not safe for long durations:
portDISABLE_INTERRUPTS();
digitalWrite(STEP, HIGH);
delayMicroseconds(5);
digitalWrite(STEP, LOW);
portENABLE_INTERRUPTS();
This could stop the stutter, confirming it’s an interrupt issue.
(good to be sure , so a test would be good too)
Option 4: Use a different library
Some variants of FastAccelStepper or custom stepper drivers (written for ESP32) use hardware timers, and may be better suited than AccelStepper on ESP32C6.
Option 5: Add external step pulse generator
If ultra-smooth motion is needed, some projects offload the pulse generation to an external chip (e.g. TMC2209 in stealth mode, or FPGA/CPLD pulse gen), and the MCU just sets direction/speed.
Summary Recommendation
Tell the user:
On the ESP32-C6, bit-banging
digitalWrite()
for stepper pulses isn’t timing-accurate due to the FreeRTOS scheduler—even if radios are off. Because the C6 only has a single application core, periodic OS tasks can cause tiny delays that ruin smooth stepper motion.Either patch AccelStepper to use
LEDC
(hardware PWM), or switch toesp_timer
-based pulse generation. If your application must use bit-banged pulses, it won’t be reliable on the C6 without real-time hardware assistance.
The S3 has two true Cores, it may perform better too.