ArmfulKST / Mbed 2 deprecated DT704_5_3

Dependencies:   mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

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 }