Jared DiCarlo
/
george
motor controller
Diff: io.cpp
- Revision:
- 2:7312ac02785d
- Parent:
- 1:2acd7dfc4b1b
- Child:
- 3:08746709f023
--- a/io.cpp Mon Oct 03 05:57:20 2016 +0000 +++ b/io.cpp Sun Oct 30 19:37:46 2016 +0000 @@ -2,46 +2,33 @@ #include "config.h" #include "io.h" #include "foc.h" - -Serial pc_ser(USBTX, USBRX); -Serial debug_ser(PC_10, PC_11); -Serial panel_ser(PC_6, PC_7); - -float tick_const = SystemCoreClock/1000000.0f; +#include "pwm_in.h" -volatile bool enabled = false; -volatile bool error_ = false; -bool arduino_connected = false; +Serial pc_ser(USBTX, USBRX); +DigitalOut dout(PC_9); +PwmOut a(PA_9); +PwmOut b(PA_8); +PwmOut c(PA_10); +PWM_IN p_in(PB_8, 1100, 1900); +InterruptIn *index_interrupt; +DigitalIn *index_in; -bool getError() +void handle_index(); + +float get_throttle() { - return error_; + return p_in.get_throttle(); } -void setError() -{ - error_ = true; -} - -bool getEnabled() -{ - return enabled; -} - -void setEnabled(bool _enabled) -{ - enabled = _enabled; -} void setup() { - getSerial(0)->baud(SERIAL_BAUD); //set serial baud - getSerial(1)->baud(SERIAL_BAUD); //set serial baud - getSerial(2)->baud(SERIAL_BAUD); //set serial baud + //set serial baud + get_serial(0)->baud(K_SERIAL_BAUD); - getSerial(0)->printf("GEORGE\n"); - getSerial(0)->printf("*******INITIALIZING**********\n"); + get_serial(0)->printf("GEORGE\n\r"); + get_serial(0)->printf("*******INITIALIZING**********\n\r"); - getSerial(0)->printf("Setting up clocks...\n"); + get_serial(0)->printf("Setting up clocks...\n\r"); /************************************* CLOCKS **************************************/ @@ -53,20 +40,23 @@ RCC->APB2ENR |= RCC_APB2ENR_ADC2EN; //adc2 RCC->APB1ENR |= RCC_APB1ENR_DACEN; //dac - getSerial(0)->printf("Setting up interrupts...\n"); + get_serial(0)->printf("Setting up interrupts...\n\r"); /************************************* INTERRUPTS **************************************/ NVIC_EnableIRQ(TIM1_UP_TIM10_IRQn); //setup interrupt controller TIM1->DIER |= TIM_DIER_UIE; //enable timer interrupts - getSerial(0)->printf("Setting up PWM...\n"); + get_serial(0)->printf("Setting up PWM...\n\r"); /************************************ PWM CONFIGURATION *************************************/ //set center aligned mode bits to 10 (might be 01 though). - TIM1->CR1 |= TIM_CR1_CMS_1; //counts up and down, but only interrupts when counting up. - TIM1->EGR |= TIM_EGR_UG; //reference manual says I need to go this. + TIM1->CR1 |= TIM_CR1_CMS_1; //counts up and down, but only interrupts when counting up. + TIM1->CR1 = 0x40; + TIM1->CR1 |= TIM_CR1_ARPE; + TIM1->RCR |= 0x01; //repetition counter set for 2 repetitions + TIM1->EGR |= TIM_EGR_UG; //reference manual says I need to go this. //enable and set polarity of output compares (using 1, 2, 3) TIM1->CCER |= TIM_CCER_CC3E; TIM1->CCER |= TIM_CCER_CC3P; @@ -75,20 +65,19 @@ TIM1->CCER |= TIM_CCER_CC1E; TIM1->CCER |= TIM_CCER_CC1P; - getSerial(0)->printf("Setting up Timers...\n"); + get_serial(0)->printf("Setting up Timers...\n\r"); /************************************ TIMER CONFIGURATION *************************************/ //buffer the auto reload register (ARR) to update only on update event - TIM1->CR1 |= TIM_CR1_ARPE; - TIM1->RCR |= 0x01; //repetition counter set for 2 repetitions + TIM1->PSC = 0x0; //no prescaler. - //set counter maximum to value for 10 kHz PWM - TIM1->ARR = 0x2328; //this is for 20 kHz, which is think is a needed correction. + //set counter maximum to value for 5 kHz PWM + TIM1->ARR = 0x4650; //5khz for prius inverter //counter needs to do two cycles for 1 full pwm cycle I think. //this is due to the center aligned mode. - getSerial(0)->printf("Setting up ADC...\n"); + get_serial(0)->printf("Setting up ADC...\n"); /************************************ ADC CONFIG *************************************/ @@ -96,21 +85,19 @@ ADC1->SQR3 |= 0x4; //on ADC1, sample ADC12_IN channel 4 (PA4) ADC2->SQR3 |= 0x8; //on ADC2, sample ADC12_IN channel 8 (PB0) - getSerial(0)->printf("Setting up GPIO...\n"); - getSerial(0)->printf("PWM pins are set up as 'alternate function'...\n"); - getSerial(0)->printf("May eventually need to set speed, pullup...\n"); + get_serial(0)->printf("Setting up GPIO...\n"); /************************************ GPIO CONFIG *************************************/ //pwm outs //0x2A0000 = 0b 10 10 10 00 00 00 00 00 00 00 00 - GPIOA->MODER |= 0x2A0000; + GPIOA->MODER |= 0x2AA000; // 109876543210 GPIOA->MODER |= 0b001100000000; //PA4 as analog. GPIOB->MODER |= 0b000000000011; //PB0 as analog. GPIOA->MODER |= 0b110000000000; //PA5 as analog. - getSerial(0)->printf("Turning on ADC/DAC...\n"); + get_serial(0)->printf("Turning on ADC/DAC...\n"); /************************************ ADC/DAC START *************************************/ @@ -118,7 +105,7 @@ ADC2->CR2 |= ADC_CR2_ADON; //adc 2 on DAC->CR |= DAC_CR_EN2; //dac 2 (PA5) on - getSerial(0)->printf("Turning on TIMER\n"); + get_serial(0)->printf("Turning on TIMER\n"); /************************************ TIMER START *************************************/ @@ -126,84 +113,99 @@ wait_us(100000); /************************************ - ZERO CURRENT + INIT CONTROL *************************************/ - + init_control(); /************************************ ENCODER *************************************/ + //from ben's encoder code + GPIOB->MODER |= GPIO_MODER_MODER3_1; + GPIOB->OTYPER |= GPIO_OTYPER_OT_3 | GPIO_OTYPER_OT_10 ; + GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR3 | GPIO_OSPEEDER_OSPEEDR10 ; + GPIOB->AFR[0] |= 0x00001000 ; - /************************************ - FRONT PANEL BOARD - *************************************/ - char front_panel_init_value = 236; - getSerial(0)->printf("Sending init command to arduino..\n"); - ser_send(getSerial(2), &front_panel_init_value, 1); - wait_us(100000); - getSerial(0)->printf("Waiting for response...\n"); - char response = 0; - if(ser_read(getSerial(2), &response, 1) < 1) getSerial(0)->printf("Got nothing from arduino. Is it on?\n"); - if(response == 118) - { - getSerial(0)->printf("Got a good response from arduino.\n"); - arduino_connected = true; - } - else - { - getSerial(0)->printf("Got a bad response from arduino.\n"); - } - + GPIOA->MODER |= GPIO_MODER_MODER15_1; + GPIOA->OTYPER |= GPIO_OTYPER_OT_15; + GPIOA->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR15; + GPIOA->AFR[1] |= 0x10000000 ; + + __TIM2_CLK_ENABLE(); + + TIM2->CR1 = 0x0001; + TIM2->SMCR = TIM_ENCODERMODE_TI12; + TIM2->CCMR1 = 0xf1f1; + TIM2->CCMR2 = 0x0000; + TIM2->CCER = 0x0011; + TIM2->PSC = 0x0000; + TIM2->ARR = 0xffffffff; + + TIM2->CNT = 0; + index_interrupt = new InterruptIn(PB_12); + index_in = new DigitalIn(PB_12); + index_interrupt-> enable_irq(); + index_interrupt-> rise(&handle_index); + index_interrupt-> mode(PullDown); + } -Serial *getSerial(int port) +Serial *get_serial(int port) { switch(port) { case 0: return &pc_ser; case 1: - return &debug_ser; + //return &debug_ser; case 2: - return &panel_ser; + // return &panel_ser; + break; } return &pc_ser; } +//timer interrupt handler extern "C" void TIM1_UP_TIM10_IRQHandler(void) { + //check to see if timer1 caused the interrupt if(TIM1->SR & TIM_SR_UIF) { - if(getEnabled() && !getError()) sampleCurrent(); - //else go turn off enabled pin. + //togle debugging pin + dout = !dout; + //run control loop + motor_control(); } + //reset timer 1 interrupt flag TIM1->SR = 0; } - +//convert phase voltage to timer ticks uint32_t volts_to_ticks(float volts) { float duty_cycle = volts/K_V_BUS + .5f; - duty_cycle = fmaxf(.04f, duty_cycle); - duty_cycle = fminf(.96f, duty_cycle); - float width_us = 50.0f*duty_cycle; //this needs to change if I slow down from 20 kHz! - return(width_us * tick_const + 0.5f); //add .5 to avoid ever setting zero. + //for prius brick, we don't need to limit duty cycle! + //duty_cycle = fmaxf(.04f, duty_cycle); + //duty_cycle = fminf(.96f, duty_cycle); + return (uint32_t)(duty_cycle * 0x4650); } -void set_inverter(Inverter* invt) +void set_inverter(float v_a, float v_b, float v_c) { - TIM1->CCR1 = volts_to_ticks(invt->v_a); - TIM1->CCR2 = volts_to_ticks(invt->v_b); - TIM1->CCR3 = volts_to_ticks(invt->v_c); + TIM1->CCR1 = volts_to_ticks(v_a); + TIM1->CCR2 = volts_to_ticks(v_b); + TIM1->CCR3 = volts_to_ticks(v_c); } -//why doesn't mbed have something like this.... -//not everybody wants asynchronous serial reads/writes and callbacks.... void ser_send(Serial *ser, const void* start, size_t size) { const char* data_ptr = (const char*)start; //ptr to beginning of buffer const char* end = data_ptr + size; //ptr to end of buffer while (data_ptr != end) //if we haven't reached the end { - ser->putc(*data_ptr++);//go write to the serial port and move the buffer ptr forward + //if(ser->writable()) + if(true) + ser->putc(*data_ptr++);//go write to the serial port and move the buffer ptr forward + else + return; //need to go implement return codes. } } @@ -216,4 +218,47 @@ else return i; //otherwise, break from loop and return bytes read. } return size; //we finished the loop so buffer is full, all bytes read. +} + +//interrupt handler for encoder index +void handle_index() +{ + if (index_in->read()) + { + if(index_in->read()) + TIM2->CNT=0; + } +} + +float get_position() +{ + int raw = TIM2->CNT; + if (raw < 0) raw += CPR; + if (raw >= CPR) raw -= CPR; + float signed_elec = fmod((POLE_PAIRS / RESOLVER_LOBES * (6.28318530718f * (raw) / (float)CPR)), 6.28318530718f); + if (signed_elec < 0) + { + return signed_elec + 6.28318530718f; + } + else + { + return signed_elec; + } +} + + +float position_last; +Timer vel_timer; + +float get_velocity() +{ + int usecs = vel_timer.read_us(); + float dx = get_position() - position_last; + if(dx > M_PI) dx -= 2 * M_PI; + if(dx < -M_PI) dx += 2 * M_PI; + vel_timer.stop(); + vel_timer.reset(); + vel_timer.start(); + position_last = get_position(); + return 1000000*dx/usecs; } \ No newline at end of file