Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: mbed
main.cpp
00001 // This program allows the user to change the frequency of the three phase SPWM output 00002 // produced by TIM1. The voltage ramps upwards with frequency. 00003 #include <stdint.h> 00004 #include "mbed.h" 00005 DigitalOut myled(LED1); 00006 /* 00007 PA8,9,10 are used to drive the PWM outputs. They are also connected back to TIM_CH1,CH2,CH3 00008 EN1,2,3 are pulled low and connected back to PC10,11,12 00009 PC13 = Blue button 00010 PB13 = User LED (I think - if not it is PA5) 00011 */ 00012 00013 00014 PwmOut PhA(PA_8); 00015 PwmOut PhB(PA_9); 00016 PwmOut PhC(PA_10); 00017 00018 00019 DigitalOut En1(PC_10); 00020 DigitalOut En2(PC_11); 00021 DigitalOut En3(PC_12); 00022 AnalogIn Pot(PB_1); 00023 Serial pc(USBTX, USBRX); // tx, rx useful for debugging 00024 volatile int CountA,CountB,CountC; 00025 00026 #define FS 12000 00027 #define FC 72000000 00028 #define F_MOD_MIN 10 00029 #define F_MOD_MAX 100 00030 #define MAX_PWM_STEPS (FS/F_MOD_MIN) 00031 #define PI 3.141592f 00032 volatile int UpdatePending = 0; 00033 volatile uint32_t NSwitchesPerCycle; 00034 float AngleStep; 00035 float fm = 0; // modulation frequency 00036 float ami = 0; // Amplitude modulation index 00037 volatile uint16_t PWM_length; 00038 00039 volatile uint16_t *PWM; 00040 volatile uint16_t PWMBuffer1[MAX_PWM_STEPS]; 00041 volatile uint16_t PWMBuffer2[MAX_PWM_STEPS]; 00042 00043 00044 void TimerISR(void) 00045 { 00046 TIM1->CCR1 = PWM[CountA]; 00047 TIM1->CCR2 = PWM[CountB]; 00048 TIM1->CCR3 = PWM[CountC]; 00049 00050 CountB = (CountB + 1) % PWM_length; 00051 CountC = (CountC + 1) % PWM_length; 00052 TIM1->SR &= ~0x3f; // ack the interrupt 00053 CountA = (CountA + 1) % PWM_length; 00054 if ( (CountA == 0) && UpdatePending ) 00055 { 00056 if (PWM == PWMBuffer1) 00057 PWM = PWMBuffer2; 00058 else 00059 PWM = PWMBuffer1; 00060 CountA = 0; 00061 CountB = PWM_length/3; 00062 CountC = (2*PWM_length)/3; 00063 PWM_length = NSwitchesPerCycle; 00064 UpdatePending = 0; 00065 } 00066 00067 } 00068 void initTimer1() 00069 { 00070 00071 TIM1->CR1 = 0; // make sure Counter is disabled before changing configuration 00072 TIM1->CR2 = 0; 00073 TIM1->PSC = 0; 00074 TIM1->ARR = (FC/FS)-1; 00075 TIM1->CCR1 = 0; // 0% duty 00076 TIM1->CCR2 = 0; // 0% duty 00077 TIM1->CCR3 = 0; // 0% duty 00078 // Enable timer outputs on channels 1,2,3 00079 TIM1->CCER = (1 << 0) + (1 << 4) + (1 << 8); 00080 TIM1->SR = 0; // Clear flags. 00081 TIM1->CR1 |= 1; // enable counter 00082 00083 // Set up the interrupt handler 00084 TIM1->DIER = 1; // Want update interrupt 00085 NVIC_SetVector(TIM1_UP_TIM16_IRQn,(uint32_t) TimerISR); 00086 NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); 00087 __enable_irq(); // enable interrupts */ 00088 00089 } 00090 void start() 00091 { 00092 00093 TIM1->CCR1 = 0; // 0% duty 00094 TIM1->CCR2 = 0; // 0% duty 00095 TIM1->CCR3 = 0; // 0% duty 00096 En1 = 1; 00097 En2 = 1; 00098 En3 = 1; 00099 CountA = 0; 00100 PWM_length = 6; 00101 CountB = PWM_length / 3; 00102 CountC = (2 *PWM_length) / 3; 00103 for (int i=0;i<PWM_length;i++) 00104 { 00105 PWMBuffer1[i] = PWMBuffer2[i]= (FC/FS)/2; // set 50% duty for all values 00106 } 00107 PWM = PWMBuffer1; 00108 } 00109 void updatePWM() 00110 { 00111 float ami = Pot.read(); 00112 float fmi=ami; // maintain V/F = constant 00113 uint16_t * UnusedPWMBuffer; 00114 00115 if (PWM == PWMBuffer1) 00116 { 00117 UnusedPWMBuffer = (uint16_t *)PWMBuffer2; 00118 } 00119 else 00120 { 00121 UnusedPWMBuffer = (uint16_t *)PWMBuffer1; 00122 } 00123 fm = fmi * F_MOD_MAX; 00124 if (fm < F_MOD_MIN) 00125 { 00126 ami = 0; 00127 for (int i=0;i<PWM_length;i++) 00128 { 00129 UnusedPWMBuffer[i] = UnusedPWMBuffer[i]= (FC/FS)/2; // set 50% duty for all values 00130 } 00131 PWM = UnusedPWMBuffer; 00132 PWM_length = 6; 00133 } 00134 else 00135 { 00136 // Need to provide a voltage boost here to increase torque (motor stalls otherwise) 00137 float amplitude = (1.5f*ami) * (FC/FS)/2; // Scale amplitude to ARR range 00138 // The higher the frequency the greater the angle step size (similar to digital sampling 00139 // The greatest number of steps occurs when we calculate a value for sine 00140 00141 NSwitchesPerCycle = FS/fm; 00142 00143 float AngleStep = 2.0f*PI / ((float)NSwitchesPerCycle); 00144 00145 float Angle = 0; 00146 00147 for (int i=0;i<NSwitchesPerCycle;i++) 00148 { 00149 float sine = (amplitude * sinf(Angle))+(FC/FS)/2; 00150 if (sine > (FC/FS)) 00151 sine = (FC/FS); 00152 if (sine < 0) 00153 sine = 0; 00154 UnusedPWMBuffer[i] = sine; // set 50% duty for all values 00155 00156 Angle = Angle + AngleStep; 00157 } 00158 00159 UpdatePending = 1; 00160 /* pc.printf("NSwitchesPerCycle = %d\r\n",NSwitchesPerCycle); 00161 pc.printf("amplitude = %f\r\n",amplitude); 00162 pc.printf("ARR = %d\r\n",TIM1->ARR); 00163 pc.printf("---------------\r\n"); */ 00164 } 00165 00166 } 00167 int main() { 00168 initTimer1(); 00169 start(); 00170 updatePWM(); 00171 while(1) { 00172 wait(1); // wait for 200ms 00173 myled = myled ^ 1; // Toggle the LED 00174 updatePWM(); 00175 00176 00177 00178 } 00179 }
Generated on Tue Aug 16 2022 04:11:13 by
1.7.2