Hi community,
I'm developing a critical code for a high frequency inverter using Pyboard v1.1.
I would like it to run in 50us.
An issue that I'm facing is that I need to read 3 ADCs in high frequency, and I would like it to occur without blocking the main processor and the code execution. I've tried simply using adc.read() and also adc.read_timed_multi(), both without success. In fact "timed multi" version has a worse performance...
Is there a way to do this in the Pyboard?
Some data that I've measured:
Execution time without ADCs: 8us
Execution time with ADCs read: 158us
Execution time with ADCs read + scale and shift ADCs: 205us
Execution time with ADCs read_timed_multi buffer size 1 + scale and shift ADCs: 81us (code) + 283us (MCU blocked by ADC)
Thanks! A section of the code follows:
Vd_ref_buf = array.array('H', (0 for i in range(1)))#bytearray(1)
Vq_ref_buf = array.array('H', (0 for i in range(1)))#bytearray(1)
theta_buf = array.array('H', (0 for i in range(1)))#bytearray(1)
while True:
pyb.ADC.read_timed_multi((p_Vd_ref, p_Vq_ref, p_theta), (Vd_ref_buf, Vq_ref_buf, theta_buf), tim4)
if flag_current_control == True:
p_code_duration.high()
# ADCs:
Vd_ref = Vd_ref_buf[0]
Vq_ref = Vq_ref_buf[0]
theta = theta_buf[0]
# Loop read method:
#Vd_ref = p_Vd_ref.read()
#Vq_ref = p_Vq_ref.read()
#theta = p_theta.read()
# Shift and scale:
Vd_ref = (Vd_ref*0.40293040293)-825 #((Vd_ref/4095*3.3)-1.65)*500
Vq_ref = (Vq_ref*0.40293040293)-825
theta = (theta*0.00168779093)-0.314159265 # ((theta/4095*3.3)-0.15)*(2*pi*pole_pairs)/3/pole_pairs. The last division make it go 0 to 2*pi
# SVPWM duty cicle:
#duty_abc = svpwm(Vd_ref,Vq_ref,theta)
## Duty Cicle set:
#tch_A_upp.pulse_width_percent(duty_abc[0]) # A upper
#tch_B_upp.pulse_width_percent(duty_abc[1]) # B upper
#tch_C_upp.pulse_width_percent(duty_abc[2]) # C upper
flag_current_control = False
p_code_duration.low()
Non-blocking ADC read?
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Non-blocking ADC read?
Nonblocking ADC read is sadly unsupported. The purpose of read_timed_multi (which blocks) is to enable phase measurements which are impossible with read_timed because it blocks for the duration.
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.
Re: Non-blocking ADC read?
You could do low-level programming of the STM32F405 registers with machine.mem32[] statements.
A SWSTART or JSWSTART bit has to be set to start the conversion. And an EOC (End of Conversion) flag could be probed to determine when it is finished. These statements are very fast.
Yury Magda described it with some micropython code in his book:
A SWSTART or JSWSTART bit has to be set to start the conversion. And an EOC (End of Conversion) flag could be probed to determine when it is finished. These statements are very fast.
Yury Magda described it with some micropython code in his book:
.Advanced Programming in MicroPython By Example
by Yury Magda
Paperback, 136 Pages, Published 2019
- pythoncoder
- Posts: 5956
- Joined: Fri Jul 18, 2014 8:01 am
- Location: UK
- Contact:
Re: Non-blocking ADC read?
Good point. Speed could be increased further using the inline assembler to read the three ADC's concurrently and populate an array with the results. It would block, but not for long.
Peter Hinch
Index to my micropython libraries.
Index to my micropython libraries.