gin66 / FastAccelStepper

A high speed stepper library for Atmega 168/328p (nano), Atmega32u4, Atmega 2560, ESP32, ESP32S2, ESP32S3, ESP32C3, ESP32C6 and Atmel SAM Due
MIT License
308 stars 70 forks source link

ESP-IDF support without Arduino libraries #94

Closed Jkallus closed 2 years ago

Jkallus commented 3 years ago

Is it possible to use this with ESP-IDF without the Arduino libraries? It seems the ESP32 implementation uses an API exposed in the arduino-esp32 library which is different from the main ESP-IDF interfaces for MCPWM and PCNT. When I tried compiling this in an ESP-IDF project that was using arduino-esp32 as a component it failed because of several "has no member" errors. When I looked at the structs that were the problem they were mostly in mcpwm_struct.h and the main ESP-IDF library has different names than the copy in arduino-esp32.

gin66 commented 3 years ago

As I do not use esp-idf, could you please provide the compile error log ?

Jkallus commented 3 years ago

../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp: In function 'void apply_command(StepperQueue, const queue_entry)': ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:110:27: error: 'volatile struct mcpwm_timer_regs_t' has no member named 'status'; did you mean 'timer_status'? if (mcpwm->timer[timer].status.value <= 1) { // mcpwm Timer is stopped ? ^~ timer_status ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:111:25: error: 'volatile struct mcpwm_timer_regs_t' has no member named 'period' mcpwm->timer[timer].period.upmethod = 0; // 0 = immediate update, 1 = TEZ ^~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:113:25: error: 'volatile struct mcpwm_timer_regs_t' has no member named 'period' mcpwm->timer[timer].period.upmethod = 1; // 0 = immediate update, 1 = TEZ ^~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:115:23: error: 'volatile struct mcpwm_timer_regs_t' has no member named 'period' mcpwm->timer[timer].period.period = ticks; ^~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:118:12: error: 'struct mcpwm_dev_t' has no member named 'channel' mcpwm->channel[timer].generator[0].utea = 1; ^~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:170:12: error: 'struct mcpwm_dev_t' has no member named 'channel' mcpwm->channel[timer].generator[0].utea = 2; ^~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp: In function 'void init_stop(StepperQueue)': ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:182:23: error: 'volatile struct mcpwm_timer_regs_t' has no member named 'mode' mcpwm->timer[timer].mode.start = 0; // 0: stop at TEZ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp: In function 'void mcpwm0_isr_service(void)': ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr0_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:233:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM0, 0, 0); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr1_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:234:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM0, 1, 1); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr2_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:235:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM0, 2, 2); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp: In function 'void mcpwm1_isr_service(void*)': ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr0_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:238:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM1, 0, 3); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr1_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:239:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM1, 1, 4); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:223:20: error: 'volatile union mcpwm_int_st_reg_t' has no member named 'cmpr2_tea_int_st' if (mcpwm.int_st.cmpr##TIMER##_tea_int_st != 0) { \ ^~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:240:3: note: in expansion of macro 'MCPWM_SERVICE' MCPWM_SERVICE(MCPWM1, 2, 5); ^~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp: In member function 'void StepperQueue::init(uint8_t, uint8_t)': ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:288:55: error: 'PERIPH_PWM0_MODULE' was not declared in this scope periph_module_enable(mcpwm_unit == MCPWM_UNIT_0 ? PERIPH_PWM0_MODULE ^~~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:288:55: note: suggested alternative: 'PERIPHS_IO_MUX_MTDO_U' periph_module_enable(mcpwm_unit == MCPWM_UNIT_0 ? PERIPH_PWM0_MODULE ^~~~~~ PERIPHS_IO_MUX_MTDO_U ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:289:55: error: 'PERIPH_PWM1_MODULE' was not declared in this scope : PERIPH_PWM1_MODULE); ^~~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:289:55: note: suggested alternative: 'PERIPHS_IO_MUX_MTDO_U' : PERIPH_PWM1_MODULE); ^~~~~~ PERIPHS_IO_MUX_MTDO_U ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:288:5: error: 'periph_module_enable' was not declared in this scope periph_module_enable(mcpwm_unit == MCPWM_UNIT_0 ? PERIPH_PWM0_MODULE ^~~~~~~~ ../../../components/FastAccelStepper-master/src/StepperISR_esp32.cpp:288:5: note: suggested alternative: 'esp_intr_enable' periph_module_enable(mcpwm_unit == MCPWM_UNIT_0 ? PERIPH_PWM0_MODULE ^~~~~~~~ esp_intr_enable

Jkallus commented 3 years ago

FYI I am using ESP-IDF 4.3.1 with VisualGDB.

gin66 commented 3 years ago

espressif apparently changed the register definition with commit:

new old

The change should be straightforward to be implemented - only some detailed work. Just wonder how to distinguish between esp-idf and arduino build system.

gin66 commented 3 years ago

Have not checked situation for pcnt module

Jkallus commented 3 years ago

I've made the necessary changes to make it compile with ESP-IDF 4.3.1 commit 3e370c4296. When running it I'm getting runtime errors that the watchdog was triggered.

18:10:52.787 -> V (2360) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args 18:10:52.787 -> V (2360) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0x502 18:10:52.787 -> D (2360) intr_alloc: Connected src 48 to int 13 (cpu 0) 18:10:52.787 -> V (2370) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): checking args 18:10:52.787 -> V (2370) intr_alloc: esp_intr_alloc_intrstatus (cpu 0): Args okay. Resulting flags 0x502 18:10:52.787 -> D (2380) intr_alloc: Connected src 39 to int 13 (cpu 0)

:12:28.304 -> E (7360) task_wdt: Task watchdog got triggered. The following tasks did not reset the watchdog in time: 18:12:28.304 -> E (7360) task_wdt: - IDLE (CPU 1) 18:12:28.304 -> E (7360) task_wdt: Tasks currently running: 18:12:28.352 -> E (7360) task_wdt: CPU 0: IDLE 18:12:28.352 -> E (7360) task_wdt: CPU 1: StepperTask 18:12:28.352 -> E (7360) task_wdt: Print CPU 0 (current core) backtrace 18:12:28.352 -> 18:12:28.352 -> 18:12:28.352 -> Backtrace:0x400DCF47:0x3FFB0B800x40082751:0x3FFB0BA0 0x400EB4E7:0x3FFB71A0 0x400D1F63:0x3FFB71C0 0x40086E62:0x3FFB71E0 0x4008854D:0x3FFB7200 18:12:28.352 -> 18:12:28.352 -> E (7360) task_wdt: Print CPU 1 backtrace 18:12:28.352 -> 18:12:28.352 -> 18:12:28.352 -> Backtrace:0x40084BF9:0x3FFB11800x40082751:0x3FFB11A0 0x400D62F7:0x3FFAF680 0x400D6546:0x3FFAF6D0 0x400D661D:0x3FFAF700 0x4008854D:0x3FFAF720 18:12:28.352 ->

Stepping through the code I believe this is happening around the point IOMUX is connecting MCPWM module to PCNT module

Changes

gin66 commented 3 years ago

Your changes look good from reviewing your code.

So here are some questions:

gin66 commented 3 years ago

Could you please fork the repo and put your code in your repo ?

gagank1 commented 3 years ago

I'm currently facing the same watchdog issue. I see this this TODO to disable interrupts in FastAccelStepperEngine::manageSteppers(). Could this have something to do with the issue? If this is related to the PCNT as @Jkallus mentioned, it could be why I'm seeing some drift when continuously rotating between two positions.

gin66 commented 3 years ago

@gagank1 Thanks for digging into this. The TODO was just a reminder to check this code again. Long time ago I had the interrupts disabled there, but the execution of that "agreement" code is pretty slow and not acceptable for high speed operation. So I have chosen to not disable the interrupts. Just that time I was not sure, if there could be a race condition between manageSteppers() and starting a stepper. And no, I am still not 100% sure.

If you have a drift during continuously rotation and no watchdog reset, then I doubt any relation to the mentioned issue.

In order to investigate the drift I would propose to use attachToPulseCounter(7) and check using readPulseCounter(), if the independently counted pulses are drifting, too.

Another possibility would be to check, if your driver needs a delay on the direction pin. The current master overload setDirectionPin() to

  // For slow driver hardware the first step after any polarity change of the
  // direction pin can be delayed by the value dir_change_delay_us. The allowed
  // range is MIN_DIR_DELAY_US and MAX_DIR_DELAY_US. The special value of 0
  // means, that no delay is added. Values 1 up to MIN_DIR_DELAY_US will be
  // clamped to MIN_DIR_DELAY_US. Values above MAX_DIR_DELAY_US will be clamped
  // to MAX_DIR_DELAY_US.
  void setDirectionPin(uint8_t dirPin, bool dirHighCountsUp = true,
                       uint16_t dir_change_delay_us = 0);

For the esp32 watchdog reset, this can have many causes. And without digging into the root cause, cannot decide if/how the FastAccelStepper need to change

gagank1 commented 3 years ago

@gin66 Just to clarify, I am getting the same watchdog reset error, and also seeing slight drift during continuous rotation. I'll take a look at the rest of your comment when I have some more time.

gagank1 commented 3 years ago

At first glance the drift might be caused by the direction pin delay. My driver (TMC2209) says it requires I hold dir for 20 ns before and after a full step pulse, so 40 ns in total. Seems small but maybe it's missing a step or two on either side and it's adding up. I'll try setting dir_change_delay_us=1 and report back.

gin66 commented 3 years ago

dir_change_delay_us=1 will be clamped to 50us for esp32.

scottmudge commented 2 years ago

So what is the status on this? I've updated to the ESP32 Arduino implementation of IDF 4.4, and I'm running into the same issues during compilation. I do not see any of the proposed fixes on the Network Graph or on any forks.

Can someone push their local version to a feature/fix branch? Or post a patch file? I can try to debug the watchdog issue, but I just want to be on the same page code-wise for the sake of clarity.

gin66 commented 2 years ago

Installing espressif using platformio platform_packages = framework-espidf@~3.40301.0 apparently only gets up to espidf 4.3.1 and this version compiles quite well

No idea, how to install any 4.4 version with platformio. Any hint ?

scottmudge commented 2 years ago

You can follow this guide here -- I am using the new arduino-esp32 package, version 2.0.1, which includes IDF version 4.4:

https://docs.espressif.com/projects/arduino-esp32/en/latest/installing.html

The version of the ESP32 Arduino package which generally comes with Arduino is quite old (v1.0.6) and is equivalent to 3.4, as you've found. Espressif has since changed the location/link allowing the Arduino software package to update the arduino-esp32 package via the Board Manager.

This is the new link to paste into the Arduino preferences/settings.

https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

Once you've done that, restart the Arduino software, uninstall the old esp32 arduino boards package (probably 1.0.6) from the Board Manager, and reinstall with the new 2.0.1 version.

gin66 commented 2 years ago

Thanks for the hint. Has worked with Arduino-IDE and I can see the compile errors. Any idea, how to install the IDF 4.4 with platformio ? Platformio can be used on github quite well and helps to set up a ci-workflow with github actions

scottmudge commented 2 years ago

Any idea, how to install the IDF 4.4 with platformio ?

That I'm not sure about, but it would certainly be useful.

gin66 commented 2 years ago

I have started a branch espidf4.4 to support idf-4.4. Now there are two esp32 stepper files in the lib, which are selected by the "api version". Means, the definition of a preprocessor variable of the old api is used to distinguish between old and new. This should ensure, that code using the old api is not broken.

New api is still broken though.....

gin66 commented 2 years ago

API is adapted (not perfect) and a deprecation warning is popping up for using mcpwm_isr_register. Nevertheless it works on the bench and the tests/esp32_hw_based tests are working. No watchdog reset observed

scottmudge commented 2 years ago

Great, I'll test it soon! Was getting tired of the lower performance of FlexyStepper

gin66 commented 2 years ago

For the deprecation warning have filed an issue in the esp-idf github repository

scottmudge commented 2 years ago

I used the master branch since it is ahead of the idf-4.4 branch, but everything seems to work great, excluding the deprecation warning. No watchdog warnings/panics.

Thanks!

gin66 commented 2 years ago

@Jkallus Please check the branch espidf. I have modified it, that it compiles under platformio without arduino component. Just the MakeLists.txt in the root directory does not fit. I have copied the sources into the project directory for now as test

Jkallus commented 2 years ago

@gin66 I have done more research since I opened the issue and I've realized I need a solution more like Marlin/GRBL for what I'm doing. I'm now trying FluidNC for my motion control problem. Thank you for the efforts in bringing this library to ESP-IDF. I hope to use it in the future for a more appropriate job.