servodisc goodness
main.cpp
- Committer:
- benkatz
- Date:
- 2017-10-09
- Revision:
- 0:92d18e011d98
- Child:
- 1:27b535673eed
File content as of revision 0:92d18e011d98:
#include "mbed.h" #define PWM_ARR 0x3E8 #define DT 0.05f #define TICKS 8000.0f #define J 0.00015f #define KT 0.087f #define R 0.85f #define V 40.0f #define K_SAT 40.0f #define DTC_MAX #define TICKSTORAD(x) TICKS*x #define CONSTRAIN(x,min,max) ((x)<(min)?(min):((x)>(max)?(max):(x))) Serial motorDriver(PB_6, PB_7); //Ticker loop; void Control(); void InitEncoder(); void InitPWM(); void WriteVoltage( float v); /* Control Variables */ int q_raw; float q, q_old, dq, u, e, q_ref; int count = 0; extern "C" void TIM1_UP_TIM16_IRQHandler(void) { if (TIM1->SR & TIM_SR_UIF ) { } count++; Control(); if(count > 1000){ printf("%d\n\r", TIM2->CNT); count = 0; } TIM1->SR = 0x0; // reset the status register } /* Main Loop */ int main() { InitEncoder(); InitPWM(); while(1) { } } void Control(void){ // control loop goes here // q_raw = TIM2->CNT; //printf("%d\n\r", q_raw); q = TICKSTORAD(q_raw); dq = (q - q_old)/DT; q_old = q; e = K_SAT*((q_ref - q) + (-abs(dq)*dq*1.0f*R*J)/(2.0f*KT*(-V - KT*abs(dq)))); u = CONSTRAIN(e, -V, V); WriteVoltage(u); TIM1->CCR1 = TIM2->CNT>>9; TIM1->CCR2 = (TIM2->CNT)>>8; } void WriteVoltage(float v){ } void InitEncoder(void) { // configure GPIO PA0 & PA1 as inputs for Encoder RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // enable the clock to GPIOA //RCC->APB1ENR |= 0x00000001; // Enable clock for GPIOA GPIOA->MODER |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ; //PA0 & PA1 as Alternate Function /*!< GPIO port mode register, Address offset: 0x00 */ GPIOA->OTYPER |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ; //PA0 & PA1 as Inputs /*!< GPIO port output type register, Address offset: 0x04 */ GPIOA->OSPEEDR |= 0x00000011;//|= GPIO_OSPEEDER_OSPEEDR0 | GPIO_OSPEEDER_OSPEEDR1 ; // Low speed /*!< GPIO port output speed register, Address offset: 0x08 */ GPIOA->PUPDR |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ; // Pull Down /*!< GPIO port pull-up/pull-down register, Address offset: 0x0C */ GPIOA->AFR[0] |= 0x00000011 ; // AF01 for PA0 & PA1 /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ GPIOA->AFR[1] |= 0x00000000 ; // /*!< GPIO alternate function registers, Address offset: 0x20-0x24 */ // configure TIM2 as Encoder input RCC->APB1ENR |= 0x00000001; // Enable clock for TIM2 TIM2->CR1 = 0x0001; // CEN(Counter Enable)='1' < TIM control register 1 TIM2->SMCR = 0x0003; // SMS='011' (Encoder mode 3) < TIM slave mode control register TIM2->CCMR1 = 0x5151; // CC1S='01' CC2S='01' < TIM capture/compare mode register 1 TIM2->CCMR2 = 0x0000; // < TIM capture/compare mode register 2 TIM2->CCER = 0x0011; // CC1P CC2P < TIM capture/compare enable register TIM2->PSC = 0x0000; // Prescaler = (0+1) < TIM prescaler TIM2->CNT = 0x0000; //reset the counter before we use it } void InitPWM(void){ RCC->AHBENR |= RCC_AHBENR_GPIOAEN; // enable the clock to GPIOA RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // enable the clock to GPIOB RCC->APB2ENR |= RCC_APB2ENR_TIM1EN; // enable TIM1 clock GPIOA->MODER |= GPIO_MODER_MODER7_1 | GPIO_MODER_MODER8_1 | GPIO_MODER_MODER9_1 ; //PA_7, PA_8, PA_9 to alternate funtion mode GPIOB->MODER |= GPIO_MODER_MODER0_1; // PB_0 to alternate function mode GPIOA->AFR[0] |= 0x60000000; // PA_7 to alternate function 6 GPIOA->AFR[1] |= 0x00000066; // PA_8, PA_9 to alternate function 6 GPIOB->AFR[0] |= 0x00000006; // PB_0 to alternate function 6 //PWM Setup TIM1->CCMR1 |= 0x6060; // Enable output compare 1 and 2 TIM1->CCER |= TIM_CCER_CC1E | TIM_CCER_CC1NE | TIM_CCER_CC2NE | TIM_CCER_CC2E; // enable outputs 1, 2, and complementary outputs TIM1->BDTR |= TIM_BDTR_MOE | 0xF; // MOE = 1 | set dead-time TIM1->PSC = 0x0; // no prescaler, timer counts up in sync with the peripheral clock TIM1->ARR = PWM_ARR; // set auto reload, 40 khz TIM1->CR1 |= TIM_CR1_ARPE; // autoreload on, TIM1->CR1 |= TIM_CR1_CEN; // enable TIM1 NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn); //Enable TIM1 IRQ 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; }