A fork of foc-ed_in_the_bot_compact modified to test motors using bayleyw's prius inverter ECU
Fork of foc-ed_in_the_bot_compact by
main.cpp
- Committer:
- nki
- Date:
- 2016-06-15
- Revision:
- 12:264e942f904f
- Parent:
- 10:6829abb438fc
File content as of revision 12:264e942f904f:
#include "mbed.h" #include "math.h" #include "PositionSensor.h" #include "FastPWM.h" #include "Transforms.h" #include "config.h" #include "filters.h" FastPWM *a; FastPWM *b; FastPWM *c; DigitalOut en(EN); DigitalOut toggle(PC_10); AnalogIn pot1(PC_5); AnalogIn pot2(PC_4); //PositionSensorEncoder pos(CPR, 0); Serial pc(USBTX, USBRX); int state = 0; int adval1, adval2; float ia, ib, ic, alpha, beta, d, q, vd, vq, p, flux_cmd, speed_cmd, flux_cmd_raw, speed_cmd_raw, volt_cmd; float ia_supp_offset = 0.0f, ib_supp_offset = 0.0f; //current sensor offset due to bias resistor inaccuracies, etc (mV) float d_integral = 0.0f, q_integral = 0.0f; float last_d = 0.0f, last_q = 0.0f; float d_ref = -0.0f, q_ref = -50.0f; MeanFilter filter_speed_cmd(0.999f); MeanFilter filter_flux_cmd(0.999f); void commutate(); void zero_current(); void config_globals(); void startup_msg(); extern "C" void TIM1_UP_TIM10_IRQHandler(void) { if (TIM1->SR & TIM_SR_UIF ) { toggle = 1; ADC1->CR2 |= 0x40000000; volatile int delay; for (delay = 0; delay < 35; delay++); toggle = 0; adval1 = ADC1->DR; adval2 = ADC2->DR; commutate(); } TIM1->SR = 0x00; } void zero_current(){ for (int i = 0; i < 1000; i++){ ia_supp_offset += (float) (ADC1->DR); ib_supp_offset += (float) (ADC2->DR); ADC1->CR2 |= 0x40000000; wait_us(100); } ia_supp_offset /= 1000.0f; ib_supp_offset /= 1000.0f; ia_supp_offset = ia_supp_offset / 4096.0f * AVDD - I_OFFSET; ib_supp_offset = ib_supp_offset / 4096.0f * AVDD - I_OFFSET; } void config_globals() { pc.baud(115200); //Enable clocks for GPIOs RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOBEN; RCC->AHB1ENR |= RCC_AHB1ENR_GPIOCEN; RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; //enable TIM1 clock a = new FastPWM(PWMA); b = new FastPWM(PWMB); c = new FastPWM(PWMC); NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); //Enable TIM1 IRQ TIM1->DIER |= TIM_DIER_UIE; //enable update interrupt TIM1->CR1 = 0x40; //CMS = 10, interrupt only when counting up TIM1->CR1 |= TIM_CR1_ARPE; //autoreload on, TIM1->RCR |= 0x01; //update event once per up/down count of tim1 TIM1->EGR |= TIM_EGR_UG; TIM1->PSC = 0x00; //no prescaler, timer counts up in sync with the peripheral clock TIM1->ARR = 0x4650; //5 Khz TIM1->CCER |= ~(TIM_CCER_CC1NP); //Interupt when low side is on. TIM1->CR1 |= TIM_CR1_CEN; //ADC Setup RCC->APB2ENR |= RCC_APB2ENR_ADC1EN; // clock for ADC1 RCC->APB2ENR |= RCC_APB2ENR_ADC2EN; // clock for ADC2 ADC->CCR = 0x00000006; //Regular simultaneous mode, 3 channels ADC1->CR2 |= ADC_CR2_ADON; //ADC1 on ADC1->SQR3 = 0x0000004; //PA_4 as ADC1, sequence 0 ADC2->CR2 |= ADC_CR2_ADON; //ADC2 ON ADC2->SQR3 = 0x00000008; //PB_0 as ADC2, sequence 1 GPIOA->MODER |= (1 << 8); GPIOA->MODER |= (1 << 9); GPIOA->MODER |= (1 << 2); GPIOA->MODER |= (1 << 3); GPIOA->MODER |= (1 << 0); GPIOA->MODER |= (1 << 1); GPIOB->MODER |= (1 << 0); GPIOB->MODER |= (1 << 1); GPIOC->MODER |= (1 << 2); GPIOC->MODER |= (1 << 3); //DAC setup RCC->APB1ENR |= 0x20000000; DAC->CR |= DAC_CR_EN2; GPIOA->MODER |= (1 << 10); GPIOA->MODER |= (1 << 11); //Zero duty cycles set_dtc(a, 0.0f); set_dtc(b, 0.0f); set_dtc(c, 0.0f); wait_ms(250); zero_current(); en = 1; } void startup_msg() { pc.printf("%s\n\r\n\r", "Serial Begin"); pc.printf("\n\r"); } void commutate() { //p = pos.GetElecPosition() - POS_OFFSET; p+=1.0f*speed_cmd; //top speed 800 electrical hz if (p < 0) p += 2 * PI; float sin_p = sinf(p); float cos_p = cosf(p); //DAC->DHR12R2 = (unsigned int) (speed_cmd * 4096); DAC->DHR12R2 = (unsigned int) ((((sin_p + 1.0f)/2.0f)*volt_cmd) * 3000); ia = ((float) adval1 / 4096.0f * AVDD - I_OFFSET - ia_supp_offset) / I_SCALE; ib = ((float) adval2 / 4096.0f * AVDD - I_OFFSET - ib_supp_offset) / I_SCALE; ic = -ia - ib; vd = volt_cmd; vq = 0.0f; if (vd < -1.0f) vd = -1.0f; if (vd > 1.0f) vd = 1.0f; if (vq < -1.0f) vq = -1.0f; if (vq > 1.0f) vq = 1.0f; float valpha = vd * cos_p - vq * sin_p; float vbeta = vd * sin_p + vq * cos_p; float va = valpha; float vb = -0.5f * valpha - sqrtf(3) / 2.0f * vbeta; float vc = -0.5f * valpha + sqrtf(3) / 2.0f * vbeta; set_dtc(a, 0.5f + 0.5f * va); set_dtc(b, 0.5f + 0.5f * vb); set_dtc(c, 0.5f + 0.5f * vc); } int main() { config_globals(); startup_msg(); for (;;) { flux_cmd_raw = pot1.read(); speed_cmd_raw = pot2.read(); speed_cmd = filter_speed_cmd.Update(speed_cmd_raw); flux_cmd = filter_flux_cmd.Update(flux_cmd_raw); volt_cmd = flux_cmd * speed_cmd; // both values range from 0-1. speed corresponds to 0-x, where x is defined at the top of commutate(). //increase the coefficient of flux_cmd and cap volt_cmd from 0-1 to adjust location of the transition to constant voltage:frequency volt_cmd *= 2.0f; if(volt_cmd > 1.0f) {volt_cmd = 1.0f;} //pc.printf("%f\t%f\r\n", flux_cmd, speed_cmd); //wait_ms(50); } } /* if commutate() runs at 5kHz, assume a 4 pole motor running at 6000RPM. 100RPS mechanical. 400Hz electrical. speed_cmd(0:1) should map from 0 to 400Hz. since commutate() runs at 5kHz, position+= x*speed_cmd(0:1) in a second, position should be 400*2pi. the increment per loop is 400*2pi/5000 8*pi/50 or 4*pi/25, or about 0.5 */ /* float u = ia; float v = ib; alpha = u; beta = 1 / sqrtf(3.0f) * u + 2 / sqrtf(3.0f) * v; d = alpha * cos_p - beta * sin_p; q = -alpha * sin_p - beta * cos_p; float d_err = d_ref - d; float q_err = q_ref - q; d_integral += d_err * KI; q_integral += q_err * KI; if (q_integral > INTEGRAL_MAX) q_integral = INTEGRAL_MAX; if (d_integral > INTEGRAL_MAX) d_integral = INTEGRAL_MAX; if (q_integral < -INTEGRAL_MAX) q_integral = -INTEGRAL_MAX; if (d_integral < -INTEGRAL_MAX) d_integral = -INTEGRAL_MAX; vd = KP * d_err + d_integral; vq = KP * q_err + q_integral; */