cancel
Showing results for 
Search instead for 
Did you mean: 

Elegant way to generate 6 variable frequency GPIOs with STM32F446RE.

MFick.1
Associate II

Hello forum, my goal is to emulate a DC motor family with some electronics and an STM32F446RE.

The current setup is, an ECU to control 6 of these motors, 6 coils of the motor family as load, 6 current sensors, running in the STM32, and from there i need 6 frequency modulations back to the ECU. The frequency goes from 5or1Hz up to 5or10kHz.

The STM will do current measurement conversion from cur. to freq. and some state machine for testing different behaviers/errors that these motors have. And later on some communication with the PC for better testing.

My first approach will be a 100kHz timer decrementing a counter variable for a defined high and low time. Lets say count from 10 to 6 with GPIO high and from 5 to 1 with GPIO low. If counter reaches 0 get new high and low times calculated in the main loop.

So my question are: Can i get this leaner? Especially for the processor. I allready use the DMA for ADC conversion so maybe its good for the GPIO as well?

Is a 100kHz time interrupt ok/feasible? Can i go even higher or is 20kHz with 1 up 1 down the way to go for a task like this?

I'm also open for other experience in frequency modulation with the STM32.

1 ACCEPTED SOLUTION

Accepted Solutions
berendi
Principal

Application note AN4776 General-purpose timer cookbook for STM32 microcontrollers might give you a few ideas, esp. chapter 5, which is about updating timer period and duty cycle with DMA.

View solution in original post

5 REPLIES 5
S.Ma
Principal

My undestanding for motor control (which is covered by secific X-NUCLEO and motor libraries) brushless is basically to use TIM1 or TIM8 (the advanced ones) per motor. Then CH1/2/3 and their complement goes to power switch to drive the coils, and 3 ADC channels are the feedback loop.

TIM.BKIN is a safety feedback for motor malfunctions and reacts faster than SW. My understanding is the code is quite optimized as time critical.

Maybe dig the ST MC code/app note to check which motor type is being adressed and if it matches.

Consider the interrupt process to take roughly 30 cycles (push fetch ... pop from stack) and multiple interrupts / priority, durations and latencies.

Generally speaking, 100kHz interrupt is major strain if the code runs at 100-200MHz. If you have USB or higher priority interrupts to manage too, it might be a sweat job. I would guess that you would need all the DMA HW assist possible, double buffering, use RAM interrupt vectors, put interrupt routines in CCM.

my 2 cents.

Thx for the response. I don't want to drive the motors with the STM. I need a fix ECU to control them and the STM to deliver pulses back to the ECU to close the control loop of the ECU. PWM encoded signals were no challange. But the frequency modulation, where the STM basically needs to simulate an encoder for the ECU Sens In are tricky. The hole setup is more about testing the ECU without a prototype and without physically changing the motors.

On top of that it would be nice to simulate a broken cable, offset the frequency, run out of spec duty cycles with serial/usb/CAN commands but thats nice to have right now.

berendi
Principal

Application note AN4776 General-purpose timer cookbook for STM32 microcontrollers might give you a few ideas, esp. chapter 5, which is about updating timer period and duty cycle with DMA.

MFick.1
Associate II

AN4776 was really helpfull. I tried a view things out:

Implementation of one fast Interrupt as a Time Manager is doable but really sweaty. It will affect communication interrupts, debug features and requires 32bit if you want to slow down to 1Hz/5Hz.

The Timer - DMA combination is really sweet but highly focused on PWM. So you can manage 4x4 = 20 PWM signals. But i need to generate 6 freq. signals.

My finals Implementation uses 6 of the simple timers the 446RE has to offer. Each interrupt toggles one pin and read its next reload value. Also a control loop can reduce the reload value if a new calc. period is vastly shorter. Worst case are 6x10kHz of interrupts with one atomic read and write.

A single load and store in an interrupt handler could take maybe 50 to 100 cycles (wild guess with a lot of flash wait states taken into account), so worst case is 6M (100*6*10k) cycles out of 180M in a second. Not exactly negligible, but I wouldn't call it a major strain.

But you perhaps don't even need these interrupt handlers at all. You can enable the auto-reload preload bit (TIM_CR1_ARPE), and write the ARR register directly from the control loop. Preloaded means that it will be taken into account first when the current cycle is finished (at the update event). You can still force a reload by setting TIM_EGR_UG. You'd need timers with an actual output channel, and set channel output mode (OCxM) to 011 toggle mode.