Variable speed drive (SPWM) for the STM32F302 Nucleo with the ihm07m1 motor control board
Dependencies: mbed
Revision 0:0e9094f7b28d, committed 2020-03-08
- Comitter:
- f3d
- Date:
- Sun Mar 08 13:51:54 2020 +0000
- Commit message:
- Variable speed drive for the STM32F302 Nucleo with the ihm07m1 motor control board
Changed in this revision
main.cpp | Show annotated file Show diff for this revision Revisions of this file |
mbed.bld | Show annotated file Show diff for this revision Revisions of this file |
diff -r 000000000000 -r 0e9094f7b28d main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/main.cpp Sun Mar 08 13:51:54 2020 +0000 @@ -0,0 +1,179 @@ +// This program allows the user to change the frequency of the three phase SPWM output +// produced by TIM1. The voltage ramps upwards with frequency. +#include <stdint.h> +#include "mbed.h" +DigitalOut myled(LED1); +/* +PA8,9,10 are used to drive the PWM outputs. They are also connected back to TIM_CH1,CH2,CH3 +EN1,2,3 are pulled low and connected back to PC10,11,12 +PC13 = Blue button +PB13 = User LED (I think - if not it is PA5) +*/ + + +PwmOut PhA(PA_8); +PwmOut PhB(PA_9); +PwmOut PhC(PA_10); + + +DigitalOut En1(PC_10); +DigitalOut En2(PC_11); +DigitalOut En3(PC_12); +AnalogIn Pot(PB_1); +Serial pc(USBTX, USBRX); // tx, rx useful for debugging +volatile int CountA,CountB,CountC; + +#define FS 12000 +#define FC 72000000 +#define F_MOD_MIN 10 +#define F_MOD_MAX 100 +#define MAX_PWM_STEPS (FS/F_MOD_MIN) +#define PI 3.141592f +volatile int UpdatePending = 0; +volatile uint32_t NSwitchesPerCycle; +float AngleStep; +float fm = 0; // modulation frequency +float ami = 0; // Amplitude modulation index +volatile uint16_t PWM_length; + +volatile uint16_t *PWM; +volatile uint16_t PWMBuffer1[MAX_PWM_STEPS]; +volatile uint16_t PWMBuffer2[MAX_PWM_STEPS]; + + +void TimerISR(void) +{ + TIM1->CCR1 = PWM[CountA]; + TIM1->CCR2 = PWM[CountB]; + TIM1->CCR3 = PWM[CountC]; + + CountB = (CountB + 1) % PWM_length; + CountC = (CountC + 1) % PWM_length; + TIM1->SR &= ~0x3f; // ack the interrupt + CountA = (CountA + 1) % PWM_length; + if ( (CountA == 0) && UpdatePending ) + { + if (PWM == PWMBuffer1) + PWM = PWMBuffer2; + else + PWM = PWMBuffer1; + CountA = 0; + CountB = PWM_length/3; + CountC = (2*PWM_length)/3; + PWM_length = NSwitchesPerCycle; + UpdatePending = 0; + } + +} +void initTimer1() +{ + + TIM1->CR1 = 0; // make sure Counter is disabled before changing configuration + TIM1->CR2 = 0; + TIM1->PSC = 0; + TIM1->ARR = (FC/FS)-1; + TIM1->CCR1 = 0; // 0% duty + TIM1->CCR2 = 0; // 0% duty + TIM1->CCR3 = 0; // 0% duty + // Enable timer outputs on channels 1,2,3 + TIM1->CCER = (1 << 0) + (1 << 4) + (1 << 8); + TIM1->SR = 0; // Clear flags. + TIM1->CR1 |= 1; // enable counter + + // Set up the interrupt handler + TIM1->DIER = 1; // Want update interrupt + NVIC_SetVector(TIM1_UP_TIM16_IRQn,(uint32_t) TimerISR); + NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); + __enable_irq(); // enable interrupts */ + +} +void start() +{ + + TIM1->CCR1 = 0; // 0% duty + TIM1->CCR2 = 0; // 0% duty + TIM1->CCR3 = 0; // 0% duty + En1 = 1; + En2 = 1; + En3 = 1; + CountA = 0; + PWM_length = 6; + CountB = PWM_length / 3; + CountC = (2 *PWM_length) / 3; + for (int i=0;i<PWM_length;i++) + { + PWMBuffer1[i] = PWMBuffer2[i]= (FC/FS)/2; // set 50% duty for all values + } + PWM = PWMBuffer1; +} +void updatePWM() +{ + float ami = Pot.read(); + float fmi=ami; // maintain V/F = constant + uint16_t * UnusedPWMBuffer; + + if (PWM == PWMBuffer1) + { + UnusedPWMBuffer = (uint16_t *)PWMBuffer2; + } + else + { + UnusedPWMBuffer = (uint16_t *)PWMBuffer1; + } + fm = fmi * F_MOD_MAX; + if (fm < F_MOD_MIN) + { + ami = 0; + for (int i=0;i<PWM_length;i++) + { + UnusedPWMBuffer[i] = UnusedPWMBuffer[i]= (FC/FS)/2; // set 50% duty for all values + } + PWM = UnusedPWMBuffer; + PWM_length = 6; + } + else + { + // Need to provide a voltage boost here to increase torque (motor stalls otherwise) + float amplitude = (1.5f*ami) * (FC/FS)/2; // Scale amplitude to ARR range + // The higher the frequency the greater the angle step size (similar to digital sampling + // The greatest number of steps occurs when we calculate a value for sine + + NSwitchesPerCycle = FS/fm; + + float AngleStep = 2.0f*PI / ((float)NSwitchesPerCycle); + + float Angle = 0; + + for (int i=0;i<NSwitchesPerCycle;i++) + { + float sine = (amplitude * sinf(Angle))+(FC/FS)/2; + if (sine > (FC/FS)) + sine = (FC/FS); + if (sine < 0) + sine = 0; + UnusedPWMBuffer[i] = sine; // set 50% duty for all values + + Angle = Angle + AngleStep; + } + + UpdatePending = 1; + /* pc.printf("NSwitchesPerCycle = %d\r\n",NSwitchesPerCycle); + pc.printf("amplitude = %f\r\n",amplitude); + pc.printf("ARR = %d\r\n",TIM1->ARR); + pc.printf("---------------\r\n"); */ + } + +} +int main() { + initTimer1(); + start(); + updatePWM(); + while(1) { + wait(1); // wait for 200ms + myled = myled ^ 1; // Toggle the LED + updatePWM(); + + + + } +}
diff -r 000000000000 -r 0e9094f7b28d mbed.bld --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mbed.bld Sun Mar 08 13:51:54 2020 +0000 @@ -0,0 +1,1 @@ +https://os.mbed.com/users/mbed_official/code/mbed/builds/65be27845400 \ No newline at end of file