Austin Brown
/
ESCmk2_Inductance
Inductance Testing Code
Fork of CurrentModeSine by
Inverter/Inverter.cpp
- Committer:
- austinbrown124
- Date:
- 2018-10-11
- Revision:
- 1:64b881306f6f
- Parent:
- 0:9edd6ec0f56a
File content as of revision 1:64b881306f6f:
#include "Inverter.h" //Condensing all hardware related variables into just this file. //This includes all the register diddling, assigning duty cycles, etc. //should probably have a class called "inverter" but thats a lot of effort Inverter::Inverter(){ } void Inverter::Init_PWM(void){ printf("\nStarting Hardware PWM\n\r"); RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // enable the clock to GPIOA //RCC->AHBENR |= RCC_AHBENR_IOPAEN; // the above line is supposed to be this but mbed is borked RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable TIM1 clock //PWM Setup TIM1->CCMR1 |= 0x7070; // Enable output compare 1 and 2 in PWM mode 2 (inverted for low side shunts) TIM1->CCMR2 |= 0x70; // Enable output compare 3 in PWM mode 2 (inverted for low side shunts) TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC2E | TIM_CCER_CC3E; // enable outputs 1, 2, 3 //no inverting outputs. PWM mode opposite of Jaredtroller because CH1N is on high side, effectively inverts input //no dead time needed! TIM1->BDTR |= TIM_BDTR_MOE; //main output enable = 1 TIM1->PSC = 0x0; // no prescaler TIM1->ARR = PWM_ARR; // set auto reload, 20 khz TIM1->CR1 |= TIM_CR1_ARPE; // autoreload on, RCC->CFGR3 |= RCC_CFGR3_TIM1SW; // bump tim1 up to 144MHz //hardware pin setup GPIOA->MODER |= GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1 | GPIO_MODER_MODER10_1; GPIOA->AFR[1] |= 0x00000666; // PA8,9,10 to alternate function 6 //interrupt generation NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); //Enable TIM1 IRQ //dafuq is this TIM16 BS? TIM1->DIER |= TIM_DIER_UIE; // enable update interrupt TIM1->CR1 |= 0x40; //CMS = 10, interrupt only when counting up TIM1->RCR |= 0x001; // update event once per up/down count of tim1 TIM1->EGR |= TIM_EGR_UG; TIM1->CR1 |= TIM_CR1_CEN; //go! //sync with ADCs //nvm changed to Update as trgo2 //TIM1->CR2 |= 0x200000; } void Inverter::Init_ADC(void){ // ADC Setup RCC->AHBENR |= RCC_AHBENR_GPIOAEN; RCC->AHBENR |= RCC_AHBENR_GPIOBEN; RCC->AHBENR |= RCC_AHBENR_ADC12EN; // clock for ADC1 and 2 enable //RCC->AHBENR |= RCC_AHBENR_GPIOAEN; //page 149 on the ref manual ADC12_COMMON->CCR |= 0x20006; // Regular simultaneous mode only, sync clock? /* //for board 1 //PA_0 is horrendously noisy! ADC1->SQR1 = 0x80; // use PA_1 as input, ADC1 in2 ADC2->SQR1 = 0x40; // use PA_4 as input, ADC2 in1 GPIOA->MODER |= 0x0000030C; // Alternate function, PA_1, PA_4 are analog inputs ADC1->SMPR1 = 256; //19.5 adc cock cycles for sample ADC2->SMPR1 = 32; //19.5 adc cock cycles for sample. Found it works better without this ADC2->CR |= ADC_CR_ADEN; ADC1->CR |= ADC_CR_ADEN; */ //for board 3 ADC1->SQR1 = 0x40; // use PA_0 as input, ADC1 in1 ADC2->SQR1 = 0x40; // use PA_4 as input, ADC2 in1 GPIOA->MODER |= 0x00000303; // Alternate function, PA_0, PA_4 are analog inputs ADC1->SMPR1 = 32; //19.5 adc cock cycles for sample ADC2->SMPR1 = 32; //19.5 adc cock cycles for sample. Found it works better without this ADC2->CR |= ADC_CR_ADEN; ADC1->CR |= ADC_CR_ADEN; //may try the sync clock later } void Inverter::Init(){ wait_ms(100); Init_ADC(); wait(0.1); Init_PWM(); } void Inverter::zero_current(){ int adc1_offset_s = 0; int adc2_offset_s = 0; int n = 1024; for (int i = 0; i<n; i++){ ADC1->CR |= ADC_CR_ADSTART; //wait_us(5); for (volatile int t = 0; t < 16; t++) {} adc2_offset_s += ADC2->DR; adc1_offset_s += ADC1->DR; } adc1_offset = adc1_offset_s/n; adc2_offset = adc2_offset_s/n; } void Inverter::ADCsync() { //EXTEN[1:0] = 01 //EXTSEL[3:0] = 1010 //this code works to slave to center of TIM1 update ADC1->CFGR |= ADC_CFGR_EXTEN_0 | ADC_CFGR_EXTEN_1; ADC1->CFGR |= ADC_CFGR_EXTSEL_3 | ADC_CFGR_EXTSEL_1; TIM1->CR2 |= TIM_CR2_MMS2_1; ADC1->CR |= ADC_CR_ADSTART; } //below is inverter- specific. May have to rearrange i_a and stuff depending on board /* void Inverter::GetCurrents(FocStruct *focc){ if (!INVERT_MOTOR_DIR) { focc->i_b = I_SCALE*(float)(adc1_raw - adc1_offset); focc->i_a = I_SCALE*(float)(adc2_raw - adc2_offset); focc->i_c = -focc->i_a - focc->i_b; } else { focc->i_c = I_SCALE*(float)(adc1_raw - adc1_offset); focc->i_a = I_SCALE*(float)(adc2_raw - adc2_offset); focc->i_b = -focc->i_a - focc->i_c; } } void Inverter::SetDutyCycles (FocStruct *focc) { if (!INVERT_MOTOR_DIR) { TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_u); TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v); TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_w); } else { TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_u); TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v); TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_w); } }*/ void Inverter::GetCurrents(FocStruct *focc){ if (!INVERT_MOTOR_DIR) { focc->i_a = I_SCALE*(float)(adc1_raw - adc1_offset); focc->i_b = I_SCALE*(float)(adc2_raw - adc2_offset); focc->i_c = -focc->i_a - focc->i_b; } else { focc->i_c = I_SCALE*(float)(adc1_raw - adc1_offset); focc->i_b = I_SCALE*(float)(adc2_raw - adc2_offset); focc->i_a = -focc->i_b - focc->i_c; } } void Inverter::SetDutyCycles (FocStruct *focc) { if (!INVERT_MOTOR_DIR) { TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_u); TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v); TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_w); } else { TIM1->CCR1 = PWM_ARR*(1.0f - focc->dtc_u); TIM1->CCR2 = PWM_ARR*(1.0f - focc->dtc_v); TIM1->CCR3 = PWM_ARR*(1.0f - focc->dtc_w); } } /*for board 3: CCR3 -> phase C so if non inverted, U in FW is A on gd. V is CCR2 so A is ADC1 */