Skip to content

Conversation

@thomasfla
Copy link

Current Sense for RP2350

warning Work in progress

Implementation of current sensing on RP2350 using the PIO to read SPI based ADCs.
Wiring:

  • SCK_PIN -> Clock pin shared with 3 ADCs
  • CSB_PIN -> Chip Select pin shared with 3 ADCs
  • D0, D1 D2 -> The 3 data output from the ADCs. Needs to be contigus (D1=D0+1 D2=D1+1)

Temporarly, for this to work, we need to add a PWM chanell in Arduino-FOC rp2040 hardware specific files. The duty cyctle needs to be computed to trigger the ADC at the right-time.

TODO:

  • Init a the DMA or IRQ to read samples from PIO.
  • Activate the push of adc data in PIO program (disabled for tests)
  • Find a way to setup the trigger PWM from the driver, or change the arduino-foc lib.

@runger1101001 runger1101001 marked this pull request as draft September 3, 2025 14:52
@runger1101001
Copy link
Member

I changed it into draft mode - that way it can’t be merged by accident…

@github-actions
Copy link

github-actions bot commented Sep 3, 2025

Memory usage change @ 4aa83b6

Board flash % RAM for global variables %
rp2040:rp2040:rpipico 🔺 +20 - +20 0.0 - 0.0 🔺 +16 - +24 +0.01 - +0.01
Click for full report table
Board examples/drivers/drv8316/drv8316_3pwm
flash
% examples/drivers/drv8316/drv8316_3pwm
RAM for global variables
% examples/drivers/drv8316/drv8316_6pwm
flash
% examples/drivers/drv8316/drv8316_6pwm
RAM for global variables
% examples/encoders/calibrated_sensor/calibration_save
flash
% examples/encoders/calibrated_sensor/calibration_save
RAM for global variables
% examples/encoders/linearhall
flash
% examples/encoders/linearhall
RAM for global variables
% examples/encoders/mt6816/mt6816_spi
flash
% examples/encoders/mt6816/mt6816_spi
RAM for global variables
%
rp2040:rp2040:rpipico 20 0.0 16 0.01 20 0.0 16 0.01 20 0.0 16 0.01 20 0.0 24 0.01 20 0.0 24 0.01
Click for full report CSV
Board,examples/drivers/drv8316/drv8316_3pwm<br>flash,%,examples/drivers/drv8316/drv8316_3pwm<br>RAM for global variables,%,examples/drivers/drv8316/drv8316_6pwm<br>flash,%,examples/drivers/drv8316/drv8316_6pwm<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibration_save<br>flash,%,examples/encoders/calibrated_sensor/calibration_save<br>RAM for global variables,%,examples/encoders/linearhall<br>flash,%,examples/encoders/linearhall<br>RAM for global variables,%,examples/encoders/mt6816/mt6816_spi<br>flash,%,examples/encoders/mt6816/mt6816_spi<br>RAM for global variables,%
rp2040:rp2040:rpipico,20,0.0,16,0.01,20,0.0,16,0.01,20,0.0,16,0.01,20,0.0,24,0.01,20,0.0,24,0.01

…sing the same PIO with different state machine, ans also be compatible with other library that uses other PIOs (encoder for example)
@github-actions
Copy link

Memory usage change @ ff1108c

Board flash % RAM for global variables %
rp2040:rp2040:rpipico 🔺 +20 - +20 0.0 - 0.0 🔺 +16 - +24 +0.01 - +0.01
Click for full report table
Board examples/drivers/drv8316/drv8316_3pwm
flash
% examples/drivers/drv8316/drv8316_3pwm
RAM for global variables
% examples/drivers/drv8316/drv8316_6pwm
flash
% examples/drivers/drv8316/drv8316_6pwm
RAM for global variables
% examples/encoders/calibrated_sensor/calibration_save
flash
% examples/encoders/calibrated_sensor/calibration_save
RAM for global variables
% examples/encoders/linearhall
flash
% examples/encoders/linearhall
RAM for global variables
% examples/encoders/mt6816/mt6816_spi
flash
% examples/encoders/mt6816/mt6816_spi
RAM for global variables
%
rp2040:rp2040:rpipico 20 0.0 16 0.01 20 0.0 16 0.01 20 0.0 24 0.01 20 0.0 16 0.01 20 0.0 16 0.01
Click for full report CSV
Board,examples/drivers/drv8316/drv8316_3pwm<br>flash,%,examples/drivers/drv8316/drv8316_3pwm<br>RAM for global variables,%,examples/drivers/drv8316/drv8316_6pwm<br>flash,%,examples/drivers/drv8316/drv8316_6pwm<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibration_save<br>flash,%,examples/encoders/calibrated_sensor/calibration_save<br>RAM for global variables,%,examples/encoders/linearhall<br>flash,%,examples/encoders/linearhall<br>RAM for global variables,%,examples/encoders/mt6816/mt6816_spi<br>flash,%,examples/encoders/mt6816/mt6816_spi<br>RAM for global variables,%
rp2040:rp2040:rpipico,20,0.0,16,0.01,20,0.0,16,0.01,20,0.0,24,0.01,20,0.0,16,0.01,20,0.0,16,0.01

@runger1101001
Copy link
Member

I was just about to ask you for the #if conditional compilation :-) thanks so much!

Thanks for all your amazing effort on this!

@github-actions
Copy link

Memory usage change @ 488eff6

Board flash % RAM for global variables %
adafruit:samd:adafruit_metro_m4 0 - 0 0.0 - 0.0 N/A N/A
arduino:avr:nano 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
rp2040:rp2040:rpipico 🔺 +20 - +20 0.0 - 0.0 🔺 +16 - +24 +0.01 - +0.01
arduino:sam:arduino_due_x 0 - 0 0.0 - 0.0 N/A N/A
arduino:samd:nano_33_iot 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
esp32:esp32:esp32 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
esp32:esp32:esp32s2 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE 0 - 0 0.0 - 0.0 0 - 0 0.0 - 0.0
Click for full report table
Board examples/drivers/drv8316/drv8316_3pwm
flash
% examples/drivers/drv8316/drv8316_3pwm
RAM for global variables
% examples/drivers/drv8316/drv8316_6pwm
flash
% examples/drivers/drv8316/drv8316_6pwm
RAM for global variables
% examples/encoders/calibrated_sensor/calibration_save
flash
% examples/encoders/calibrated_sensor/calibration_save
RAM for global variables
% examples/encoders/linearhall
flash
% examples/encoders/linearhall
RAM for global variables
% examples/encoders/mt6816/mt6816_spi
flash
% examples/encoders/mt6816/mt6816_spi
RAM for global variables
% examples/drivers/simplefocnano/simplefocnano_atmega
flash
% examples/drivers/simplefocnano/simplefocnano_atmega
RAM for global variables
% examples/encoders/calibrated_sensor/calibrated
flash
% examples/encoders/calibrated_sensor/calibrated
RAM for global variables
%
adafruit:samd:adafruit_metro_m4 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A
arduino:avr:nano 0 0.0 0 0.0 0 0.0 0 0.0
rp2040:rp2040:rpipico 20 0.0 16 0.01 20 0.0 16 0.01 20 0.0 24 0.01 20 0.0 16 0.01 20 0.0 16 0.01
arduino:sam:arduino_due_x 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A 0 0.0 N/A N/A
arduino:samd:nano_33_iot 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0
esp32:esp32:esp32 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0
esp32:esp32:esp32s2 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0
STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0
STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0 0 0.0
Click for full report CSV
Board,examples/drivers/drv8316/drv8316_3pwm<br>flash,%,examples/drivers/drv8316/drv8316_3pwm<br>RAM for global variables,%,examples/drivers/drv8316/drv8316_6pwm<br>flash,%,examples/drivers/drv8316/drv8316_6pwm<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibration_save<br>flash,%,examples/encoders/calibrated_sensor/calibration_save<br>RAM for global variables,%,examples/encoders/linearhall<br>flash,%,examples/encoders/linearhall<br>RAM for global variables,%,examples/encoders/mt6816/mt6816_spi<br>flash,%,examples/encoders/mt6816/mt6816_spi<br>RAM for global variables,%,examples/drivers/simplefocnano/simplefocnano_atmega<br>flash,%,examples/drivers/simplefocnano/simplefocnano_atmega<br>RAM for global variables,%,examples/encoders/calibrated_sensor/calibrated<br>flash,%,examples/encoders/calibrated_sensor/calibrated<br>RAM for global variables,%
adafruit:samd:adafruit_metro_m4,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A
arduino:avr:nano,,,,,,,,,,,,,0,0.0,0,0.0,,,,,0,0.0,0,0.0
rp2040:rp2040:rpipico,20,0.0,16,0.01,20,0.0,16,0.01,20,0.0,24,0.01,20,0.0,16,0.01,20,0.0,16,0.01,,,,
arduino:sam:arduino_due_x,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A,0,0.0,N/A,N/A,,,,
arduino:samd:nano_33_iot,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,,,,
esp32:esp32:esp32,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,,,,,0,0.0,0,0.0,,,,
esp32:esp32:esp32s2,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,,,,
STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,,,,,,,,
STMicroelectronics:stm32:Nucleo_64:pnum=NUCLEO_F411RE,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,0,0.0,,,,,0,0.0,0,0.0

@runger1101001 runger1101001 self-assigned this Sep 24, 2025
@runger1101001 runger1101001 added the enhancement New feature or request label Sep 24, 2025
@runger1101001
Copy link
Member

I have a board in development that will hopefully allow me to test this out :-)

the way I see it there is still the todo to make the trigger from the timer to the PIO.

  • your code uses a GPIO to trigger the PIO. So for this we would need a function to reserve an additional channel matching the driver, and a parameter to set its phase in relation to the PWM timings
  • An alternative might be to use WAIT IRQ to wait on the timer interrupt. This occurs on the timer wrap, which should be the middle of the low-side on-time. So for some setups not needing dummy reads this could work too. For this we would need a method to switch on the irq for one of the PWM timer channels.

@runger1101001
Copy link
Member

runger1101001 commented Oct 21, 2025

Looking at this a bit more, I am not sure there is any TODO for the ArduinoFOC code...

In the RP2350PIOCurrentSense we can do the following:

#include "drivers/hardware_api.h"

// get the driver params
RP2040DriverParams* params = (RP2040DriverParams*)driver->params;
// create a 1PWM timer on the trigger pin using the same frequency
RP2040DriverParams* paramsTrigger = (RP2040DriverParams*)_configure1PWM(params->pwm_frequency, pinTRIG);
// set the correct duty cycle for the desired trigger point, we could provide a convenience function for that
_writeDutyCycle1PWM(0.29f, paramsTrigger);

and for IRQ based triggering with WAIT IRQ in the PIO:

#include "hardware/pwm.h"

RP2040DriverParams* params = (RP2040DriverParams*)driver->params;
pwm_set_irq_enabled(params->slice[0], true); // using PWM_IRQ_WRAP_0
// TODO check the IRQ isn't being used on the interrupt controller, because then it can't be used for PIO
irq_set_enabled(PWM_IRQ_WRAP_0, true);

// for the PIO code we will probably have to make an alternate version that uses WAIT IRQ PWM_IRQ_WRAP_0 1
// instead of the two WAIT GPIO instructions?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants