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 |
--- /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();
+
+
+
+ }
+}
--- /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