From f1e64f7e3823fc0ef214f4c0d81fc4d91ced8edd Mon Sep 17 00:00:00 2001 From: Charlie Smurthwaite Date: Thu, 12 Apr 2018 08:32:44 +0100 Subject: [PATCH] rework for new setup --- main.c | 135 +++++++++++++++++++++++++++---------------------------- system.c | 53 +++++++++++++--------- 2 files changed, 99 insertions(+), 89 deletions(-) diff --git a/main.c b/main.c index 447dcbf..536b359 100644 --- a/main.c +++ b/main.c @@ -18,6 +18,7 @@ void uart_write_string(char* str); void uart_write_int(int32_t i); void uart_write_nl(); + // Phase should rotate from 0 - (2^24)*6-1 // Voltage should be 0 - 2^12-1 void update_svm(uint32_t phase, uint32_t voltage) @@ -79,78 +80,74 @@ void update_svm(uint32_t phase, uint32_t voltage) } } -void TIM1_UP_TIM16_IRQHandler(void) { - // Start ADC conversions. - // TODO: Try to cause these 2 conversions to run for a - // significant portion of the PWM cycle. - ADC1->SQR1 = (1<<6); - ADC2->SQR1 = (2<<6); +uint16_t adc_data[4]; +void DMA1_Channel1_IRQHandler(void) { + // Debug output + uart_write_int(adc_data[0]); + uart_write_string(","); + uart_write_int(adc_data[1]); + uart_write_string(","); + uart_write_int(adc_data[2]); + uart_write_string(","); + uart_write_int(adc_data[3]); + uart_write_nl(); ADC1->CR |= ADC_CR_ADSTART; - ADC2->CR |= ADC_CR_ADSTART; - TIM1->SR = ~TIM_SR_UIF; } -void ADC1_2_IRQHandler(void) { - // Fetch current values - // TODO: Instead of waiting for 2 ADCs, use combined mode and trust the interrupt. - while(ADC1->CR & ADC_CR_ADSTART); - while(ADC2->CR & ADC_CR_ADSTART); - i1 = ((float)ADC1->DR - 31715); - i2 = ((float)ADC2->DR - 31800) * 1.04f; - i3 = 0 - i1 - i2; - - // Fetch the voltages. - v1 = TIM1->CCR1 + TIM1->CCR1 - TIM1->CCR2 - TIM1->CCR3; - v2 = TIM1->CCR2 + TIM1->CCR2 - TIM1->CCR1 - TIM1->CCR3; - v3 = TIM1->CCR3 + TIM1->CCR3 - TIM1->CCR1 - TIM1->CCR2; - - // Calculate the instantaneous current and power. - // TODO optimize compiler, especially here. - current = sqrt(i1 * i1 + i2 * i2 + i3 * i3); - power = (v1 * i1 + v2 * i2 + v3 * i3) >> 14; - - // Adjust voltage to fit calculates power to target power. - if (power > target_power) voltage -= 10; - if (power < target_power) voltage += 10; - if (voltage < 0) voltage = 0; - if (voltage > 4080) voltage = 4080; - - // TODO: We can do better V/Hz control if we measure the - // bus voltage too. - // Work out V/Hz by multiplying the voltage by a Hz constant. - // Subtract some voltage based on current to account for resistive losses. - - // A multiple is 25 here is theoretically correct for my motor at 23V DC supply. - int increment = voltage * 25 - 1000 * 25; - if(increment < 0) increment = 0; - - // Increment the output phase. - sine_angle += increment; - if(sine_angle > 100663295) sine_angle -= 100663296; - if(sine_angle < 0) sine_angle += 100663296; - // Output SVM using PWM. - update_svm(sine_angle, voltage); -} +// void TIM1_UP_TIM16_IRQHandler(void) { +// // Start ADC conversions. +// // TODO: Try to cause these 2 conversions to run for a +// // significant portion of the PWM cycle. +// ADC1->SQR1 = (1<<6); +// ADC2->SQR1 = (2<<6); +// ADC1->CR |= ADC_CR_ADSTART; +// ADC2->CR |= ADC_CR_ADSTART; +// TIM1->SR = ~TIM_SR_UIF; +// } + +// void ADC1_2_IRQHandler(void) { +// // Fetch current values +// // TODO: Instead of waiting for 2 ADCs, use combined mode and trust the interrupt. +// while(ADC1->CR & ADC_CR_ADSTART); +// while(ADC2->CR & ADC_CR_ADSTART); +// i1 = ((float)ADC1->DR - 31715); +// i2 = ((float)ADC2->DR - 31800) * 1.04f; +// i3 = 0 - i1 - i2; + +// // Fetch the voltages. +// v1 = TIM1->CCR1 + TIM1->CCR1 - TIM1->CCR2 - TIM1->CCR3; +// v2 = TIM1->CCR2 + TIM1->CCR2 - TIM1->CCR1 - TIM1->CCR3; +// v3 = TIM1->CCR3 + TIM1->CCR3 - TIM1->CCR1 - TIM1->CCR2; + +// // Calculate the instantaneous current and power. +// // TODO optimize compiler, especially here. +// current = sqrt(i1 * i1 + i2 * i2 + i3 * i3); +// power = (v1 * i1 + v2 * i2 + v3 * i3) >> 14; + +// // Adjust voltage to fit calculates power to target power. +// if (power > target_power) voltage -= 10; +// if (power < target_power) voltage += 10; +// if (voltage < 0) voltage = 0; +// if (voltage > 4080) voltage = 4080; + +// // TODO: We can do better V/Hz control if we measure the +// // bus voltage too. +// // Work out V/Hz by multiplying the voltage by a Hz constant. +// // Subtract some voltage based on current to account for resistive losses. + +// // A multiple is 25 here is theoretically correct for my motor at 23V DC supply. +// int increment = voltage * 25 - 1000 * 25; +// if(increment < 0) increment = 0; + +// // Increment the output phase. +// sine_angle += increment; +// if(sine_angle > 100663295) sine_angle -= 100663296; +// if(sine_angle < 0) sine_angle += 100663296; +// // Output SVM using PWM. +// update_svm(sine_angle, voltage); +// } int main() { - ADC3->SQR1 = (4<<6); - while (1) { - // Fetch throttle input. - ADC3->CR |= ADC_CR_ADSTART; - while(ADC3->CR & ADC_CR_ADSTART); - throttle = ADC3->DR; - target_power = throttle; - - // Debug output. - int n; for(n=0;n<20000;n++) nop(); - uart_write_int(target_power); - uart_write_string(","); - uart_write_int(power); - uart_write_string(","); - uart_write_int(voltage); - uart_write_string(","); - uart_write_int(current); - uart_write_nl(); - } - return(0); + ADC1->CR |= ADC_CR_ADSTART; + while(1); } diff --git a/system.c b/system.c index 0375696..1df7324 100644 --- a/system.c +++ b/system.c @@ -6,6 +6,8 @@ void SystemInitError(uint8_t error_source) { while(1); } +extern uint32_t adc_data[]; + void SystemInit() { // Enable FPU @@ -56,16 +58,14 @@ void SystemInit() { // B13,B14,B15 -> TIM1 GPIOB->AFR[1] &= ~(GPIO_AFRH_AFSEL13_Msk|GPIO_AFRH_AFSEL14_Msk|GPIO_AFRH_AFSEL15_Msk); GPIOB->AFR[1] |= GPIO_AFRH_AFSEL13_0 | GPIO_AFRH_AFSEL14_0 | GPIO_AFRH_AFSEL15_0; - // C0,C1,C2,C3 -> ADC1 - GPIOC->AFR[0] &= ~(GPIO_AFRL_AFSEL0_Msk|GPIO_AFRL_AFSEL1_Msk|GPIO_AFRL_AFSEL2_Msk|GPIO_AFRL_AFSEL3_Msk); - GPIOC->AFR[0] |= GPIO_AFRH_AFSEL13_0 | GPIO_AFRH_AFSEL14_0 | GPIO_AFRH_AFSEL15_0; // PORTA Modes GPIOA->MODER = 0xABEAFFEF; + GPIOA->ASCR = 0x3; // ADC // PORTB Modes GPIOB->MODER = 0xABFFFFFF; // PORTC Modes GPIOC->MODER = 0xFFFFFFFF; - GPIOC->ASCR = 0xF; + GPIOC->ASCR = 0xF; // ADC // Enable USART2 clock RCC->APB1ENR1 |= RCC_APB1ENR1_USART2EN; @@ -79,28 +79,44 @@ void SystemInit() { // Enable transmit USART2->CR1 |= USART_CR1_TE; + // DMA for ADC1 + RCC->AHB1ENR |= RCC_AHB1ENR_DMA1EN; // DMA1 + // Wait a bit + nop(); nop(); nop(); nop(); nop(); nop(); + DMA1_Channel1->CPAR = (uint32_t)&(ADC123_COMMON->CDR); + DMA1_Channel1->CMAR = (uint32_t)&adc_data; + DMA1_Channel1->CNDTR = 2; + DMA1_Channel1->CCR = DMA_CCR_MSIZE_1 | DMA_CCR_PSIZE_1 | DMA_CCR_MINC | + DMA_CCR_CIRC | DMA_CCR_TCIE | DMA_CCR_EN; + // ADC123 RCC->AHB2ENR |= RCC_AHB2ENR_ADCEN; // Connect to system clock RCC->CCIPR |= RCC_CCIPR_ADCSEL_0 | RCC_CCIPR_ADCSEL_1; // Divide clock (/8) - ADC123_COMMON->CCR |= (4<<18); + ADC123_COMMON->CCR |= ADC_CCR_PRESC_2; + // Dual mode + ADC123_COMMON->CCR |= ADC_CCR_DUAL_1 | ADC_CCR_DUAL_2; + // MDMA + ADC123_COMMON->CCR |= ADC_CCR_MDMA_1; - // ADC1+2+3 + // ADC1+2 // Disable DEEPPWD, enable ADVREGEN ADC1->CR = ADC_CR_ADVREGEN; ADC2->CR = ADC_CR_ADVREGEN; - ADC3->CR = ADC_CR_ADVREGEN; + // Wait a bit int n; for(n=0;n<100000;n++) nop(); + // Configure ADC1/2 IN5 for differential input + ADC1->DIFSEL |= (1<<5); + ADC2->DIFSEL |= (1<<5); + // Calibrate // ADC1->CR |= ADC_CR_ADCAL; // ADC2->CR |= ADC_CR_ADCAL; - // ADC3->CR |= ADC_CR_ADCAL; // while(ADC1->CR & ADC_CR_ADCAL); // while(ADC2->CR & ADC_CR_ADCAL); - // while(ADC3->CR & ADC_CR_ADCAL); // // Wait a bit // for(n=0;n<100000;n++) nop(); @@ -109,20 +125,16 @@ void SystemInit() { ADC1->CR |= ADC_CR_ADEN; ADC2->ISR |= ADC_ISR_ADRDY; ADC2->CR |= ADC_CR_ADEN; - ADC3->ISR |= ADC_ISR_ADRDY; - ADC3->CR |= ADC_CR_ADEN; while(!(ADC1->ISR & ADC_ISR_ADRDY)); while(!(ADC2->ISR & ADC_ISR_ADRDY)); - while(!(ADC3->ISR & ADC_ISR_ADRDY)); - // Interrupts - ADC1->IER = ADC_IER_EOCIE; + + // Sequence + ADC1->SQR1 = (1<<6) | (5<<12) | 1; + ADC2->SQR1 = (2<<6) | (4<<12) | 1; // Oversampling (16x) - ADC1->CFGR2 = (3<<2) | 1; - ADC2->CFGR2 = (3<<2) | 1; - // ADC1->CFGR2 = (4<<5) | (3<<2) | 1; - // ADC2->CFGR2 = (4<<5) | (3<<2) | 1; - // ADC3->CFGR2 = (4<<5) | (3<<2) | 1; + // ADC1->CFGR2 = (3<<2) | 1; + // ADC2->CFGR2 = (3<<2) | 1; // TIM1 RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; @@ -143,6 +155,7 @@ void SystemInit() { TIM1->CR1 |= 1; // Global interrupt config - NVIC->ISER[0] = (1 << TIM1_UP_TIM16_IRQn) | (1 << ADC1_2_IRQn); + //NVIC->ISER[0] = (1 << TIM1_UP_TIM16_IRQn); + NVIC->ISER[0] = (1 << DMA1_Channel1_IRQn); }