Inductance Testing Code

Dependencies:   mbed

Fork of CurrentModeSine by Austin Brown

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers Inverter.cpp Source File

Inverter.cpp

00001 #include "Inverter.h"
00002 
00003 
00004 
00005 //Condensing all hardware related variables into just this file.
00006 //This includes all the register diddling, assigning duty cycles, etc. 
00007 //should probably have a class called "inverter" but thats a lot of effort
00008 
00009 Inverter::Inverter(){
00010 
00011     
00012     }
00013 
00014 void Inverter::Init_PWM(void){
00015     
00016     printf("\nStarting Hardware PWM\n\r");
00017     
00018     RCC->AHBENR |= RCC_AHBENR_GPIOAEN;                 // enable the clock to GPIOA
00019     //RCC->AHBENR |= RCC_AHBENR_IOPAEN;                // the above line is supposed to be this but mbed is borked
00020     RCC->APB2ENR |= RCC_APB2ENR_TIM1EN;                // enable TIM1 clock
00021 
00022     
00023     //PWM Setup
00024     TIM1->CCMR1 |= 0x7070;                             // Enable output compare 1 and 2 in PWM mode 2 (inverted for low side shunts)
00025     TIM1->CCMR2 |= 0x70;                               // Enable output compare 3 in PWM mode 2 (inverted for low side shunts)
00026     TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E;  // enable outputs 1, 2, 3
00027     //no inverting outputs. PWM mode opposite of Jaredtroller because CH1N is on high side, effectively inverts input
00028     //no dead time needed!
00029     TIM1->BDTR |= TIM_BDTR_MOE;                         //main output enable = 1
00030     TIM1->PSC = 0x0;                                   // no prescaler
00031     TIM1->ARR = PWM_ARR;                               // set auto reload, 20 khz
00032     TIM1->CR1 |= TIM_CR1_ARPE;                         // autoreload on, 
00033     RCC->CFGR3 |= RCC_CFGR3_TIM1SW;                    // bump tim1 up to 144MHz
00034     
00035     //hardware pin setup
00036     GPIOA->MODER   |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1;
00037     GPIOA->AFR[1]    |= 0x00000666;                    // PA8,9,10 to alternate function 6
00038     
00039     //interrupt generation
00040     NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);   //Enable TIM1 IRQ                     //dafuq is this TIM16 BS?
00041     TIM1->DIER |= TIM_DIER_UIE;           // enable update interrupt
00042     TIM1->CR1 |= 0x40;                    //CMS = 10, interrupt only when counting up
00043     TIM1->RCR |= 0x001;                   // update event once per up/down count of tim1 
00044     TIM1->EGR |= TIM_EGR_UG;
00045     
00046     TIM1->CR1 |= TIM_CR1_CEN;   //go!
00047     
00048     //sync with ADCs
00049     
00050     //nvm changed to Update as trgo2
00051     //TIM1->CR2 |= 0x200000;  
00052     
00053     
00054     }
00055 
00056 void Inverter::Init_ADC(void){
00057         // ADC Setup
00058     RCC->AHBENR |= RCC_AHBENR_GPIOAEN; 
00059     RCC->AHBENR |= RCC_AHBENR_GPIOBEN;
00060     RCC->AHBENR |= RCC_AHBENR_ADC12EN;                        // clock for ADC1 and 2 enable 
00061     //RCC->AHBENR |= RCC_AHBENR_GPIOAEN;     //page 149 on the ref manual
00062     
00063     ADC12_COMMON->CCR |= 0x20006;                 // Regular simultaneous mode only, sync clock?
00064     
00065     
00066     /*
00067     //for board 1
00068     //PA_0 is horrendously noisy!
00069     ADC1->SQR1 = 0x80;                            // use PA_1 as input, ADC1 in2
00070     ADC2->SQR1 = 0x40;                            // use PA_4 as input, ADC2 in1
00071     GPIOA->MODER |= 0x0000030C;                   // Alternate function, PA_1, PA_4 are analog inputs 
00072 
00073     ADC1->SMPR1 = 256;     //19.5 adc cock cycles for sample
00074     ADC2->SMPR1 = 32;     //19.5 adc cock cycles for sample. Found it works better without this
00075     
00076     ADC2->CR |= ADC_CR_ADEN;
00077     ADC1->CR |= ADC_CR_ADEN;
00078     */
00079 
00080     //for board 3
00081     ADC1->SQR1 = 0x40;                            // use PA_0 as input, ADC1 in1
00082     ADC2->SQR1 = 0x40;                            // use PA_4 as input, ADC2 in1
00083     GPIOA->MODER |= 0x00000303;                   // Alternate function, PA_0, PA_4 are analog inputs 
00084 
00085     ADC1->SMPR1 = 32;     //19.5 adc cock cycles for sample
00086     ADC2->SMPR1 = 32;     //19.5 adc cock cycles for sample. Found it works better without this
00087     
00088     ADC2->CR |= ADC_CR_ADEN;
00089     ADC1->CR |= ADC_CR_ADEN;
00090     
00091     //may try the sync clock later
00092 
00093 }
00094 
00095 
00096 
00097 
00098 void Inverter::Init(){
00099     wait_ms(100);
00100     Init_ADC();
00101     wait(0.1);         
00102     Init_PWM();
00103     
00104     }
00105     
00106 void Inverter::zero_current(){
00107     int adc1_offset_s = 0;
00108     int adc2_offset_s = 0;
00109     int n = 1024;
00110     for (int i = 0; i<n; i++){
00111         ADC1->CR  |= ADC_CR_ADSTART;  
00112         //wait_us(5);
00113         for (volatile int t = 0; t < 16; t++) {}
00114         adc2_offset_s += ADC2->DR;
00115         adc1_offset_s += ADC1->DR;
00116         }
00117     adc1_offset = adc1_offset_s/n;
00118     adc2_offset = adc2_offset_s/n;
00119 
00120     }
00121     
00122 void Inverter::ADCsync() {
00123     //EXTEN[1:0] = 01
00124     //EXTSEL[3:0] = 1010
00125     
00126     //this code works to slave to center of TIM1 update
00127     ADC1->CFGR |= ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTEN_1;
00128     ADC1->CFGR |= ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1;
00129     TIM1->CR2 |= TIM_CR2_MMS2_1;
00130     ADC1->CR  |= ADC_CR_ADSTART; 
00131 }
00132 
00133 //below is inverter- specific. May have to rearrange i_a and stuff depending on board
00134 /*
00135 void Inverter::GetCurrents(FocStruct *focc){
00136 
00137     if (!INVERT_MOTOR_DIR) {
00138         focc->i_b = I_SCALE*(float)(adc1_raw - adc1_offset);
00139         focc->i_a = I_SCALE*(float)(adc2_raw - adc2_offset);
00140         focc->i_c = -focc->i_a - focc->i_b;
00141     }
00142     else {
00143         focc->i_c = I_SCALE*(float)(adc1_raw - adc1_offset);
00144         focc->i_a = I_SCALE*(float)(adc2_raw - adc2_offset);
00145         focc->i_b = -focc->i_a - focc->i_c;
00146     }
00147     
00148 }
00149 
00150 void Inverter::SetDutyCycles (FocStruct *focc) {
00151     
00152     if (!INVERT_MOTOR_DIR) {
00153         TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_u); 
00154         TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v);
00155         TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_w);  
00156     }
00157     else {
00158         TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_u); 
00159         TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v);
00160         TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_w);  
00161     }
00162     
00163     
00164 }*/
00165 
00166 
00167 
00168 void Inverter::GetCurrents(FocStruct *focc){
00169 
00170     if (!INVERT_MOTOR_DIR) {
00171         focc->i_a = I_SCALE*(float)(adc1_raw - adc1_offset);
00172         focc->i_b = I_SCALE*(float)(adc2_raw - adc2_offset);
00173         focc->i_c = -focc->i_a - focc->i_b;
00174     }
00175     else {
00176         focc->i_c = I_SCALE*(float)(adc1_raw - adc1_offset);
00177         focc->i_b = I_SCALE*(float)(adc2_raw - adc2_offset);
00178         focc->i_a = -focc->i_b - focc->i_c;
00179     }
00180     
00181 }
00182 
00183 void Inverter::SetDutyCycles (FocStruct *focc) {
00184     
00185     if (!INVERT_MOTOR_DIR) {
00186         TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_u); 
00187         TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v);
00188         TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_w);  
00189     }
00190     else {
00191         TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_u); 
00192         TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v);
00193         TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_w);  
00194     }
00195     
00196     
00197 }
00198     
00199 
00200 /*for board 3:
00201 
00202 CCR3 -> phase C
00203 so if non inverted, U in FW is A on gd.
00204 V is CCR2
00205 so A is ADC1
00206 
00207 
00208 
00209 
00210 
00211 */  
00212     
00213     
00214     
00215     
00216     
00217       
00218