servodisc goodness

Dependencies:   mbed-dev-f303

Revision:
1:27b535673eed
Parent:
0:92d18e011d98
Child:
3:2e9713c61c2d
--- a/main.cpp	Mon Oct 09 22:35:15 2017 +0000
+++ b/main.cpp	Fri Oct 27 19:21:20 2017 +0000
@@ -1,43 +1,56 @@
 #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 PI              3.14159265f
+#define PWM_ARR         0x2E8               // PWM timer auto-reload 
+#define DT              0.00002067f         // PWM_ARR/36 MHz
+#define CPR             8000.0f             // Encoder counts/revolution
+#define J               0.00015f            // Inertia
+#define KT              0.087f              // Torque Constant
+#define R               0.85f               // Resistance
+#define V_IN            40.0f               // DC input voltage
+#define K_SAT           40.0f               // Controller saturation gain
+#define DTC_MAX         0.95f               // Max duty cycle (limited by bootstrapping)
+#define V               V_IN*DTC_MAX        // Max useable voltage
 
-#define TICKSTORAD(x)           TICKS*x
+#define TICKSTORAD(x)           x*2*PI/CPR  
 #define CONSTRAIN(x,min,max)    ((x)<(min)?(min):((x)>(max)?(max):(x)))
 
-
-Serial motorDriver(PB_6, PB_7);
-//Ticker loop;
-
+Serial pc (PA_2, PA_3);                     // Serial to programming header
+Serial io(PB_6, PB_7);                      // Differential Serial to JST Header
+DigitalIn id_1(PB_3);                       // ID Setting Jumpers
+DigitalIn id_2(PB_4);
+DigitalIn id_3(PB_5);
+DigitalOut led(PA_15);                      // Debug LED
+DigitalIn d_in(PA_4);                       // LED on input from AND Board
+DigitalOut d_out(PA_5);                     // LED on output to AND Board
 
 
 void Control();
 void InitEncoder();
 void InitPWM();
+void InitGPIO();
 void WriteVoltage( float v);
+int GetID();
 
 
 
 /* Control Variables */
+int id;
 int q_raw;
 float q, q_old, dq, u, e, q_ref;
 int count = 0;
 
-extern "C" void TIM1_UP_TIM16_IRQHandler(void) {
+/* PWM Timer Interrupt */
+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);
+      if(count > 5000){
+          io.printf("derp\n\r");
+          pc.printf("derp\n\r");
+          led = !led;
+          d_out = !d_out;
           count = 0;
           }
   TIM1->SR = 0x0; // reset the status register
@@ -45,56 +58,88 @@
 
 /* Main Loop */
 int main() {
+    pc.printf("\n\r Rubix Controller\n\r");
+    id = GetID();
+    pc.printf(" Motor ID:  %d\n\r", id);
+    
+    io.baud(921600);
+    
+    id_1.mode(PullUp);
+    id_2.mode(PullUp);
+    id_3.mode(PullUp);
+    d_in.mode(PullDown);
+    led = 1;
+    d_out = 1;
+    
     InitEncoder();
     InitPWM();
+    wait(.1);
+
     while(1) {
     }
 }
 
+/* Position Control */
 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))));
+    e = K_SAT*((q_ref - q) + (-abs(dq)*dq*1.0f*R*J)/(2.0f*KT*(-V - KT*abs(dq))));   // Bullshit sliding mode control with nonlinear sliding surface, for minimum-time response
     u = CONSTRAIN(e, -V, V);
-    WriteVoltage(u);
-    TIM1->CCR1 = TIM2->CNT>>9;
-    TIM1->CCR2 = (TIM2->CNT)>>8;
+    //WriteVoltage(u);
+    WriteVoltage(10.0f);
+    }
+    
+/* Set motor voltage */
+void WriteVoltage(float v){
+    if(v>0){
+        TIM1->CCR1 = 0;
+        TIM1->CCR2 = (int) (PWM_ARR*(v/V));
+        }
+    else if(v<0){
+        TIM1->CCR2 = 0;
+        TIM1->CCR1 = (int) (PWM_ARR*(v/V));
+        }
     }
 
-void WriteVoltage(float v){
-    
+/* Read ID Jumpers */
+int GetID(void){
+    int i1 = !id_1.read();
+    int i2 = !id_2.read();
+    int i3 = !id_3.read();
+    return (i1<<2) | (i2<<1) | i3;
     }
 
+/* Initialize Encoder */
 void InitEncoder(void) {
+    pc.printf("Initializing Encoder\n\r");
     // 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 */
+    RCC->AHBENR |= RCC_AHBENR_GPIOAEN;                                      // enable the clock to GPIOA
+    GPIOA->MODER   |= GPIO_MODER_MODER0_1 | GPIO_MODER_MODER1_1 ;           // PA0 & PA1 as Alternate Function 
+    GPIOA->OTYPER  |= GPIO_OTYPER_OT_0 | GPIO_OTYPER_OT_1 ;                 // PA0 & PA1 as Inputs 
+    GPIOA->OSPEEDR |= 0x00000011;                                           // GPIO Speed
+    GPIOA->PUPDR   |= GPIO_PUPDR_PUPDR0_1 | GPIO_PUPDR_PUPDR1_1 ;           // Pull Down   
+    GPIOA->AFR[0]  |= 0x00000011 ;                                          //  AF01 for PA0 & PA1 
+    GPIOA->AFR[1]  |= 0x00000000 ;                                          //                                  
+    
     // 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  
+    RCC->APB1ENR |= 0x00000001;                             // Enable clock for TIM2
+    TIM2->CR1   = 0x0001;                                   // CEN(Counter Enable)='1'   
+    TIM2->SMCR  = 0x0003;                                   // SMS='011' (Encoder mode 3)   
+    TIM2->CCMR1 = 0x5151;                                   // CC1S='01' CC2S='01'          
+    TIM2->CCMR2 = 0x0000;                                                                 
+    TIM2->CCER  = 0x0011;                                   // CC1P CC2P                    
+    TIM2->PSC   = 0x0000;                                   // Prescaler = (0+1)            
+    TIM2->CNT = 0x0000;                                     //reset the counter before we use it  
 }
 
+/* Initialize PWM */
 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
+    pc.printf("Initializing PWM\n\r");
+    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
@@ -105,16 +150,16 @@
     //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
+    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
+    TIM1->CR1 |= TIM_CR1_ARPE;                              // autoreload on, 
+    TIM1->CR1 |= TIM_CR1_CEN;                               // enable TIM1
     
-    NVIC_EnableIRQ(TIM1_UP_TIM16_IRQn);   //Enable TIM1 IRQ
+    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;
+    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;                                
     }
\ No newline at end of file