servodisc goodness

Dependencies:   mbed-dev-f303

Revision:
3:2e9713c61c2d
Parent:
1:27b535673eed
Child:
4:6e290eb553cd
--- a/main.cpp	Fri Oct 27 19:34:31 2017 +0000
+++ b/main.cpp	Wed Dec 13 05:04:38 2017 +0000
@@ -4,15 +4,15 @@
 #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 J               0.000065f            // Inertia
+#define KT              0.0678f              // 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_IN            20.0f               // DC input voltage
+#define K_SAT           22000.0f               // Controller saturation gain
+#define DTC_MAX         0.97f               // Max duty cycle (limited by bootstrapping)
 #define V               V_IN*DTC_MAX        // Max useable voltage
 
-#define TICKSTORAD(x)           x*2*PI/CPR  
+#define TICKSTORAD(x)           (float)x*2.0f*PI/CPR  
 #define CONSTRAIN(x,min,max)    ((x)<(min)?(min):((x)>(max)?(max):(x)))
 
 Serial pc (PA_2, PA_3);                     // Serial to programming header
@@ -31,64 +31,182 @@
 void InitGPIO();
 void WriteVoltage( float v);
 int GetID();
+void SerialISR(void);
 
 
 
 /* Control Variables */
 int id;
-int q_raw;
-float q, q_old, dq, u, e, q_ref;
-int count = 0;
+int q_raw, dir, dq_raw = 0;
+float q, q_old, dq, u, e, q_ref, dqdebug = 0;
+int count, count2;
+int controlmode =0;
+
+/* Kalman Filter Variables */
+float q_est[2] = {0.0f};
+float q_meas[2] = {0.0f};
+float F[2][2] = {{1.0f, DT},{0.0f, 1.0f}};
+float B[2] = {0.0f, DT/J};
+float P[2][2] = {0};
+float Q[2] = {1.0f, 0.01f};
+float Rk[2] = {0.01, 10};
+float S[2][2] = {0};
+float Y[2] = {0};
+float K[2][2] = {0};
+float U;
+
+
+int16_t log_vec[2500] = {0};
+//int16_t log_vec_2[1250] = {0};
+
 
 /* PWM Timer Interrupt */
 extern "C" void TIM1_UP_TIM16_IRQHandler(void) {    
   if (TIM1->SR & TIM_SR_UIF ) {
       }
       count++;
+    
+    if(count>1000 && count<2000){
+        q_ref = 1.57f;
+        //ref = 18000.0f;
+        }
+         
+    if(count>2000 && count<3000){
+        q_ref = 0.0f;
+        //ref = 0;
+        //count = 0;
+        }
+    if(count>3000 && count<4000){
+        q_ref = -1.57f;
+        }
+        
+    if(count>4500){
+        controlmode = 1;
+    }
+    if(count<5000){
+            //log_vec_2[count/4] = (int)(q_est[1]*10.0f);
+            log_vec[count/2] = (int)(q*1000.0f);
+            }
+    
+    if(count>20000 && count<22500){
+        //printf("%d\n\r", log_vec[count2]);
+        //wait_us(200);
+        //printf("%d\n\r", log_vec_2[count2]);
+        //wait_us(200);
+        count2++;
+        }
+        
+        
       Control();
+      /*
       if(count > 5000){
-          io.printf("derp\n\r");
-          pc.printf("derp\n\r");
-          led = !led;
-          d_out = !d_out;
+          //io.printf("derp\n\r");
+          //pc.printf("derp\n\r");
+          //pc.printf("%d   %f\n\r", q_raw, e);
+          printf("%f   %f\n\r", dq, dqdebug);
+          //d_out = !d_out;
           count = 0;
           }
+          */
   TIM1->SR = 0x0; // reset the status register
 }
 
+
 /* Main Loop */
 int main() {
-    pc.printf("\n\r Rubix Controller\n\r");
-    id = GetID();
-    pc.printf(" Motor ID:  %d\n\r", id);
     
+    pc.baud(921600);
     io.baud(921600);
-    
+
+    //pc.printf("\n\r Rubix Controller\n\r");
     id_1.mode(PullUp);
     id_2.mode(PullUp);
     id_3.mode(PullUp);
-    d_in.mode(PullDown);
+    id = GetID();
+    pc.printf(" Motor ID:  %d\n\r", id);
+    
+    //d_in.mode(PullDown);
     led = 1;
     d_out = 1;
+    //wait(.1);
     
-    InitEncoder();
     InitPWM();
-    wait(.1);
-
+    InitEncoder();
+    //pc.printf("Initializing Encoder\n\r");
+    //pc.printf("Initializing PWM\n\r");
+    //wait(.1);
     while(1) {
     }
 }
 
 /* Position Control */
 void Control(void){
-    q_raw = TIM2->CNT;
+    
+    // Sample Position and Velocity //
+    q_raw = TIM2->CNT;    
+    dir = -2*(((TIM2->CR1)>>4)&1)+1; 
+    dq_raw = dir*(TIM15->CCR1);
     q = TICKSTORAD(q_raw);
-    dq = (q - q_old)/DT;
+    //dq = (q - q_old)/DT;
+    dq = (18000000.0f*4.0f*2.0f*PI/CPR)/((float)dq_raw);
+    if(isinf(dq)){ dq = 0.0f;}
     q_old = q;
-    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
+    
+    q_meas[0] = q;
+    q_meas[1] = dq;
+    
+    // Kalman Filter //
+    // Update Model //
+    
+    q_est[0] += q_est[1]*F[0][1];
+    q_est[1] += B[1]*U;
+    
+    
+    P[0][0] += Q[0] + DT*P[1][0] + DT*(P[0][1] + DT*P[1][1]);
+    P[0][1] += DT*P[1][1];
+    P[1][0] += DT*P[1][1];
+    P[1][1] += Q[1];
+    
+    //Calculate Kalman Gains//
+    S[0][0] = P[0][0] + Rk[0];
+    S[0][1] = P[0][1];
+    S[1][0] = P[1][0];
+    S[1][1] = P[1][1] + Rk[1];
+    float denom = (S[0][0]*S[1][1] - S[0][1]*S[1][0]);
+    K[0][0] = (P[0][0]*S[1][1])/denom - (P[0][1]*S[1][0])/denom;
+    K[0][1] = (P[0][1]*S[0][0])/denom - (P[0][0]*S[0][1])/denom;
+    K[1][0] = (P[1][0]*S[1][1])/(S[0][0]*S[1][1] - S[0][1]*S[1][0]) - (P[1][1]*S[1][0])/denom;
+    K[1][1] = (P[1][1]*S[0][0])/(S[0][0]*S[1][1] - S[0][1]*S[1][0]) - (P[1][0]*S[0][1])/denom;
+    
+    Y[0] = q_meas[0] - q_est[0];
+    Y[1] = q_meas[1] - q_est[1];
+    
+    // Update Estimate //
+    q_est[0] += K[0][0]*Y[0] + K[0][1]*Y[1];
+    q_est[1] += K[1][0]*Y[0] + K[1][1]*Y[1];
+    
+    P[0][0] = -K[0][1]*P[1][0] - P[0][0]*(K[0][0] - 1.0f);
+    P[0][1] = -K[0][1]*P[1][1] - P[0][1]*(K[0][0] - 1.0f);
+    P[1][0] = -K[1][0]*P[0][0] - P[1][0]*(K[1][1] - 1.0f);
+    P[1][1] = -K[1][0]*P[0][1] - P[1][1]*(K[1][1] - 1.0f);
+    
+   
+    
+    // Control Law //
+    if(controlmode == 0){
+       e = K_SAT*((q_ref - q) + (abs(dq)*dq*1.3f*R*J)/(2.0f*KT*(-V - KT*abs(dq))));   // Bullshit sliding mode control with nonlinear sliding surface, for minimum-time response
+        //e = K_SAT*((q_ref - q) + (abs(q_est[1])*q_est[1]*1.3f*R*J)/(2.0f*KT*(-V - 1.0f*KT*abs(q_est[1]))));   // Bullshit sliding mode control with nonlinear sliding surface, for minimum-time response
+
+    }
+    //q_ref = 0.0f;
+    if(controlmode == 1){
+        e = 0;
+        //e = 40.0f*(q_ref - q) + .2f*(0.0f-dq);
+        }
     u = CONSTRAIN(e, -V, V);
-    //WriteVoltage(u);
-    WriteVoltage(10.0f);
+    WriteVoltage(u);
+    U = KT*(u - KT*dq)/R;
+    //WriteVoltage(-10.0f);
     }
     
 /* Set motor voltage */
@@ -97,12 +215,19 @@
         TIM1->CCR1 = 0;
         TIM1->CCR2 = (int) (PWM_ARR*(v/V));
         }
-    else if(v<0){
+    else if(v<=0){
         TIM1->CCR2 = 0;
-        TIM1->CCR1 = (int) (PWM_ARR*(v/V));
+        TIM1->CCR1 = (int) (PWM_ARR*(abs(v)/V));
         }
     }
 
+void SerialISR(void){
+    // PC Serial Interrupt //
+    
+    
+    }
+    
+    
 /* Read ID Jumpers */
 int GetID(void){
     int i1 = !id_1.read();
@@ -113,17 +238,20 @@
 
 /* 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->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->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
+    TIM2->DIER = 0x00;
+    TIM2->EGR = 0x0;
+    NVIC_DisableIRQ(TIM2_IRQn);
+    
     RCC->APB1ENR |= 0x00000001;                             // Enable clock for TIM2
     TIM2->CR1   = 0x0001;                                   // CEN(Counter Enable)='1'   
     TIM2->SMCR  = 0x0003;                                   // SMS='011' (Encoder mode 3)   
@@ -132,11 +260,21 @@
     TIM2->CCER  = 0x0011;                                   // CC1P CC2P                    
     TIM2->PSC   = 0x0000;                                   // Prescaler = (0+1)            
     TIM2->CNT = 0x0000;                                     //reset the counter before we use it  
+    
+    TIM2->CR2 = 0x030;  //MMS = 101
+    __TIM15_CLK_ENABLE();
+    TIM15->PSC = 0x03;
+    TIM15->SMCR = 0x4; //TS = 010 for ITR2, SMS = 100
+    TIM15->CCMR1 = 0x3;// CC1S = 11, IC1 mapped on TRC
+    TIM15->CCER |= TIM_CCER_CC1P;
+    TIM15->CCER |= TIM_CCER_CC1E;
+    TIM15->CR1 = 0x1;
+
 }
 
+
 /* Initialize PWM */
 void InitPWM(void){
-    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
@@ -156,10 +294,12 @@
     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;                                
-    }
\ No newline at end of file
+    TIM1->EGR |= TIM_EGR_UG;       
+                             
+    }
+    
\ No newline at end of file