Biorobotics10 / Mbed 2 deprecated Samenvoegen6

Dependencies:   HIDScope MODSERIAL QEI biquadFilter mbed

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers main.cpp Source File

main.cpp

00001 //================================================================  Script: Ball-E ==================================================================
00002 // Author: Ewoud Velu, Lisa Verhoeven, Robert van der Wal, Thijs van der Wal, Emily Zoetbrood
00003 /* This is the script of a EMG measurment moving robot. The purpose of the robot is to amuse people with the disease of Ducenne.
00004  The robot is designed to throw a ball in to a certain chosen pocket. In order to achieve this movement we use a ‘shoulder’ that can turn in the vertical plane
00005 */
00006 
00007 //******************************************** Library DECLARATION **************************************
00008 #include "mbed.h"
00009 #include "QEI.h"
00010 #include "MODSERIAL.h"
00011 #include "HIDScope.h"
00012 #include "biquadFilter.h"
00013 #include <cmath>
00014 #include <stdio.h>
00015 
00016 //******************************************* FUNCTION DECLA *******************************************
00017 //**************** INPUTS *****************
00018 AnalogIn  EMG1(A0);                                            // Input EMG
00019 AnalogIn  EMG2(A1);                                            // Input EMG
00020 //AnalogIn pot(A2);
00021 //AnalogIn pot1(A3);
00022 
00023 QEI wheel2 (D10, D11, NC, 64,QEI::X4_ENCODING);          // Function for Encoder1 on the motor1 to the Microcontroller
00024 QEI wheel1 (D12, D13, NC, 64,QEI::X4_ENCODING);          // Function for Encoder2 on the motor2 to the Microcontroller
00025 
00026 //**************** OUTPUTS ****************
00027 DigitalOut red(LED_RED);                                        // LED declared for calibration
00028 DigitalOut green(LED_GREEN);                                    // LED declared for sampling      
00029 
00030 DigitalOut magnet(D2);
00031                       
00032 DigitalOut motor2direction(D4);                                 // D4 en D5 zijn motor 2 (op het motorshield)
00033 PwmOut motor2speed(D5);
00034 DigitalOut motor1direction(D7);                                 // D6 en D7 zijn motor 1 (op het motorshield)
00035 PwmOut motor1speed(D6);
00036 
00037 //**************** FUNCTIONS **************
00038 /* HIDScope    scope(4);          */                              // HIDScope declared with 4 scopes
00039 MODSERIAL pc(USBTX, USBRX);                                     // Function for Serial communication with the Microcontroller to the pc.
00040 
00041 //******************************* GLOBAL VARIABLES DECLARATION ************************************
00042 const int       led_on             = 0;                         // Needed for the LEDs to turn on and off
00043 const int       led_off            = 1;
00044 const int       relax              = 0;
00045 const int       graden             = 360; 
00046 
00047 int             games_played       = -1;                                    // -1 omdat het spel daar eerst loopt voor het spelen om alles na te checken
00048 int             games_played1       = 0;
00049 bool            flag_calibration   = true;
00050 
00051 //********* VARIABLES FOR MOTOR CONTROL ********                      
00052 const float     cw                 = 1;                          // The number if: motor1 moves clock wise motor2 moves counterclockwise
00053 const float     ccw                = 0;                          // The number if: motor1 moves counterclock wise motor2 moves clockwise
00054 bool            flag_s             = false;                      // Var flag_s sensor ticker
00055 bool            flag_m             = false;                      // Var flag_m motor ticker
00056 float           ain                = 0;
00057 
00058 //********* VARIABLES FOR CONTROL 1 ************
00059 volatile bool   sample_go;                                       // Ticker EMG function
00060 int             Fs                 = 512;                        // Sampling frequency
00061 
00062 const double    low_b1             = 1.480219865318266e-04;                        //Filter coefficients
00063 const double    low_b2             = 2.960439730636533e-04;
00064 const double    low_b3             = 1.480219865318266e-04;
00065 const double    low_a2             = -1.965293372622690e+00;                       // a1 is normalized to 1
00066 const double    low_a3             = 9.658854605688177e-01;
00067 const double    high_b1            = 8.047897937631126e-01;
00068 const double    high_b2            = -1.609579587526225e+00;
00069 const double    high_b3            = 8.047897937631126e-01;
00070 const double    high_a2            = -1.571102440190402e+00;                      // a1 is normalized to 1
00071 const double    high_a3            = 6.480567348620491e-01;
00072 
00073 double u1; double y1;                                            // Declaring the input variables
00074 double u2; double y2;
00075 
00076 int calibratie_metingen = 0;
00077 
00078 //********* VARIABLES FOR FASE SWITCH **********
00079 bool            begin               = true;                                              
00080 int             fase                = 3;                                   // To switch between different phases and begins with the reset phase
00081 const float     fasecontract        = 0.7;                                 // The value the EMG signal must be for fase change
00082 float           rightbiceps         = y2;
00083 float           leftbiceps          = ain;
00084 int             reset               = 0;
00085 int             button_pressed      = 0;
00086 int             j                   = 1;
00087 int             N                   = 200;
00088 bool            fase_switch_wait    = true;
00089 
00090 //********* VARIABLES FOR CONTROL 2 ************
00091 const float     contract            = 0.2;                                 // The minimum value for which the motor moves
00092 const float     maxleft             = -1000;                               // With this angle the motor should stop moving
00093 const float     maxright            = 1000;                                // With this angle the motor should stop moving
00094 const float     speed_plate_1       = 0.4;                                 // The speed of the plate in control 2
00095 bool            flag_left           = true;
00096 bool            flag_right          = true;
00097 float           pos_board           = 0;                                   // The position of the board begins at zero                                 
00098 float           Encoderread2        = 0;
00099 
00100 
00101 //********* VARIABLES FOR CONTROL 3 ************
00102 const float     minimum_contract    = 0.2;                                 // Certain levels for muscle activity to activate motor
00103 const float     medium_contract     = 0.5;                                 // "Medium contract muscle"
00104 const float     maximum_leftbiceps  = 0.8;                                 // "Maximum contract muscle"
00105 const float     on                  = 1.0;
00106 const float     off                 = 0.0;
00107 const float     minimum_throw_angle = -5;
00108 const float     maximum_throw_angle = 110;
00109 float           pos_arm             = 0;
00110 int             pos_arm1            = 0;
00111 float           Encoderread1        = 0;
00112 int             switch_rondjes      = 2;
00113 int             rondjes             = 0;
00114 
00115 //********* VARIABLES FOR CONTROL 4 ************    
00116 
00117 float           reset_positie       = 0;      // Belangrijk
00118 float           reset_board         = 0;
00119 float           speedcompensation;
00120 float           speedcompensation2;
00121 int             t                   = 5;                           // aftellen naar nieuw spel
00122 int             switch_reset        = 1;
00123 bool            arm                 = false;
00124 bool            board1              = false;
00125 
00126 
00127 // **************************************** Tickers *****************************************
00128 Ticker Sensor_control;                                          // Adds ticker function for the variable function : Sensors
00129 Ticker Motor_control; 
00130 Ticker EMG_Control;
00131 
00132 //=============================================================================================== SUB LOOPS ==================================================================================================================
00133 //**************************** CONTROL 1-EMG CALIBRATION ***********************************
00134 
00135 biquadFilter highpass1(high_a2, high_a3, high_b1, high_b2, high_b3);    // Different objects for different inputs, otherwise the v1 and v2 variables get fucked up
00136 biquadFilter highpass2(high_a2, high_a3, high_b1, high_b2, high_b3);
00137 biquadFilter lowpass1(low_a2, low_a3, low_b1, low_b2, low_b3);
00138 biquadFilter lowpass2(low_a2, low_a3, low_b1, low_b2, low_b3);
00139 
00140                                 
00141 double cali_fact1 = 0.9;                                          // calibration factor to normalize filter output to a scale of 0 - 1
00142 double cali_fact2 = 0.9;
00143 double cali_array1[2560] = {};                                  // array to store values in
00144 double cali_array2[2560] = {};                                 
00145 
00146 void hoog_laag_filter() 
00147 {
00148     u1 = EMG1; 
00149     u2 = EMG2;
00150     y1 = highpass1.step(u1); 
00151     y2 = highpass2.step(u2);                                // filter order is: high-pass --> rectify --> low-pass
00152     y1 = fabs(y1); 
00153     y2 = fabs(y2); 
00154     y1 = lowpass1.step(y1)*cali_fact1;
00155     y2 = lowpass2.step(y2)*cali_fact2;                      // roughly normalize to a scale of 0 - 1, where 0 is minimum and 1 is roughly the maximum output.
00156 }
00157  
00158 
00159 //======================================= TICKER LOOPS ==========================================
00160 void SENSOR_LOOP()
00161 {
00162     flag_s = true;
00163 }
00164 
00165 void MOTOR_LOOP()
00166 {
00167     flag_m = true;
00168 }
00169 
00170 void samplego() {                                     // ticker function, set flag to true every sample interval
00171     sample_go = 1;
00172 }
00173 
00174 
00175 //================================================================================================== HEAD LOOP ================================================================================================================
00176 int main() 
00177 {
00178     
00179     pc.baud(115200);
00180     Sensor_control.attach(&SENSOR_LOOP, 0.01);                              // TICKER FUNCTION
00181     Motor_control.attach(&MOTOR_LOOP, 0.01);
00182     EMG_Control.attach(&samplego, (float)1/Fs);
00183     
00184     pc.printf("===============================================================\n");
00185     pc.printf(" \t\t\t Ball-E\n");
00186     pc.printf("In the module Biorobotics on the University of Twente is this script created\n");
00187     pc.printf("Autors:\tE. Velu, L. Verhoeven, R. v/d Wal, T. v/d Wal, E. Zoetbrood\n\n");
00188     wait(3);
00189     pc.printf("The script will begin with a short calibration\n\n");
00190     wait(2.5);
00191     pc.printf("===============================================================\n");
00192     //************************* CONTROL 1-EMG CALIBRATION ****************************
00193     while(1) 
00194     {   
00195     
00196      if(sample_go) 
00197         {            
00198             red.write(led_off);                     // Toggles red calibration LED off
00199             green.write(led_on);                    // Toggles green sampling LED on
00200             hoog_laag_filter();
00201             sample_go = 0;
00202         } 
00203     
00204     if (flag_calibration)
00205         {                                                                   // function to calibrate the emg signals from the user. It takes 5 seconds of measurements of maximum output, then takes the max and normalizes to that.
00206                     calibratie_metingen ++;
00207                     green.write(led_off);                                   // Toggles green sampling LED off
00208                     red.write(led_on);                                      //Toggles red calibration LED on
00209                     cali_fact1 = 0.9;                                          // calibration factor to normalize filter output to a scale of 0 - 1
00210                     cali_fact2 = 0.9;
00211                     double cali_max1 = 0;                                   // declare max y1
00212                     double cali_max2 = 0;                                   //declare max y2
00213                     pc.printf(" \n\n EMG Signal starting up Calibration measurement........... \n");
00214                     wait(2);
00215                     pc.printf("\t.....Calibrating Signal of EMG 1 and 2 .......\n");
00216                     wait(0.5);
00217                     pc.printf("\t......contract muscles..... \n");
00218                 
00219                 for(int cali_index1 = 0; cali_index1 < 2560; cali_index1++)  // Records 5 seconds of y1
00220                 {
00221                     hoog_laag_filter();
00222                     cali_array1[cali_index1] = y1;
00223                     wait((float)1/Fs);
00224                 }
00225                 for(int cali_index2 = 0; cali_index2 < 2560; cali_index2++)  // Records 5 seconds of y2
00226                 {
00227                     hoog_laag_filter();
00228                     cali_array2[cali_index2] = y2;
00229                     wait((float)1/Fs);
00230                 }
00231                 for(int cali_index3 = 0; cali_index3 < 2560; cali_index3++)   // Scales y1
00232                 { 
00233                     if(cali_array1[cali_index3] > cali_max1)
00234                     {
00235                         cali_max1 = cali_array1[cali_index3];
00236                     }
00237                  }
00238                  for(int cali_index4 = 0; cali_index4 < 2560; cali_index4++)  // Scales y2
00239                  {
00240                     if(cali_array2[cali_index4] > cali_max2)
00241                     {
00242                         cali_max2 = cali_array2[cali_index4];
00243                     }
00244                  }
00245                  cali_fact1 = (double)1/cali_max1;                              // Calibration factor for y1
00246                  cali_fact2 = (double)1/cali_max2;                              // Calibration factor for y2
00247                  
00248                                                     // Toggles green sampling LED off
00249                  red.write(led_off);
00250                  green.write(led_on);
00251                  pc.printf(" \t....... Calibration has been completed!\n");
00252                  wait(0.2);
00253                  green.write(led_off);
00254                  wait(0.2);
00255                  green.write(led_on);
00256                  wait(0.2);
00257                  green.write(led_off);
00258                  wait(0.2);
00259                  green.write(led_on);
00260                  wait(4);
00261                  pc.printf("Beginning with Ball-E board settings\n"); 
00262                  green.write(led_off);
00263                  wait(2);
00264                  y1 = 0;
00265                  y2 = 0;
00266                  
00267                  j = 1;                                         // Wachten van fase switch initialiseren 
00268                  fase_switch_wait = true;
00269          }        
00270       
00271             
00272     //************************* CONTROL MOTOR ****************************************
00273         
00274             
00275             
00276             if (flag_s)
00277             {
00278                 Encoderread1 = wheel1.getPulses();
00279                 pos_arm = (Encoderread1/((64.0*131.0)/360.0));   // Omrekenen naar graden van arm
00280                 
00281                 Encoderread2 = wheel2.getPulses();
00282                 pos_board = (Encoderread2/((64.0*131.0)/360.0));   // Omrekenen naar graden van board
00283                 flag_calibration = false;
00284             }
00285     //************************* FASE SWITCH ******************************************
00286         //******************** Fase determination *************
00287         if (fase_switch_wait == true)
00288        {
00289            j++;
00290            wait(0.01);                                              // Problemen met EMG metingen die te hoog zijn op het begin van script na calibratie. vandaar ff wachten en de sample loop een paar keer doorlopen.
00291       pc.printf("waarde j = %i \n",j);
00292        }
00293        
00294        if( j > N){
00295         fase_switch_wait = false;
00296         switch(fase)
00297         {
00298             
00299             //******************* Fase 1 **************************
00300             case(1):
00301             rondjes = 0;
00302                 if (y1> contract)
00303                 {
00304                     flag_right = false;
00305                     flag_left = true;
00306                 }
00307                 
00308                 if (y2 > contract) 
00309                 {
00310                     flag_right = true;
00311                     flag_left = false;
00312                 }
00313                 
00314                 if (pos_board <= maxleft) 
00315                 {
00316                     flag_left = false;
00317                     motor2speed.write(relax);
00318                 }
00319                 
00320                 if (pos_board >= maxright) 
00321                 {
00322                     flag_right = false;
00323                     motor2speed.write(relax);
00324                 }
00325 
00326                 if (flag_left == true)
00327                 {
00328                     if (y1> contract) 
00329                     {
00330                         motor2direction.write(ccw);      
00331                         motor2speed.write(speed_plate_1); 
00332                     }
00333                     else
00334                     {
00335                         motor2speed.write(relax); 
00336                     }
00337                 }
00338         
00339                 if (flag_right == true)
00340                 {
00341                     if (y2 > contract) 
00342                     {
00343                         motor2direction.write(cw);           
00344                         motor2speed.write(speed_plate_1); 
00345                     }
00346                     else
00347                     {
00348                         motor2speed.write(relax);
00349                     }
00350                 }
00351                 pc.printf("Boardposition \t %f  EMG1 en EMG2 signaal = %f \t %f\n", pos_board, y1, y2);
00352                 if (y1> fasecontract && y2 > fasecontract) 
00353                 {
00354                     motor2speed.write(relax);
00355                     fase = 2;
00356                     fase_switch_wait = true;
00357                     j = 0;
00358                 }
00359                 break;
00360             //******************* Fase 2 **************************
00361             case(2):
00362             motor1direction.write(cw); 
00363             pos_arm1 = (pos_arm - (rondjes * 360));
00364             
00365                     switch(switch_rondjes){
00366                         case(1):
00367                         rondjes ++;
00368                         switch_rondjes = 2;
00369                         break;
00370                         case(2):
00371                         if(pos_arm1>360 & 368<pos_arm1)
00372                         {
00373                             switch_rondjes = 1;
00374                         }
00375                         break;
00376                     }
00377                 
00378                  
00379                     if (y2 > minimum_contract & y2 < medium_contract) 
00380                     {
00381                         motor1speed.write((y2 - minimum_contract)/(medium_contract - minimum_contract));
00382                     }
00383                     if (y2 > medium_contract)                 // Hoger dan drempelwaarde = Actief
00384                     {
00385                         motor1speed.write((y2 - minimum_contract)/(medium_contract - minimum_contract));
00386                     }
00387                     if (y2 < minimum_contract)                // Lager dan drempel = Rust 
00388                     {
00389                         motor1speed.write(relax);         
00390                     }
00391                     if (pos_arm1 > minimum_throw_angle & pos_arm1 < maximum_throw_angle) 
00392                     {
00393                         if (y1> maximum_leftbiceps) 
00394                         {
00395                             magnet.write(off);
00396                             motor1speed.write(relax);
00397                             fase = 3;
00398                             pc.printf("Van fase 2 naar fase 3\n");
00399                             wait(2);
00400                             j = 0;
00401                             fase_switch_wait = true;    
00402                         } 
00403                         }
00404                 pc.printf("Armposition \t %i \t EMG1 en EMG2 = %f \t %f \n", pos_arm1, y1, y2); 
00405                 break;
00406             //********************************************* Fase 3 **********************************************  
00407             case(3):
00408                 
00409                 switch(switch_reset)
00410                     {
00411                     case(1):
00412                     if(pos_arm < reset_positie)                     //ene kant op draaien
00413                         {                 
00414                             motor1direction.write(cw);
00415                             speedcompensation2 = ((reset_positie - pos_arm)/900.0 + (0.1));
00416                             motor1speed.write(speedcompensation2);
00417                         }
00418                         if(pos_arm > reset_positie)                  //andere kant op
00419                         {
00420                             motor1direction.write(ccw);
00421                             speedcompensation2 = ((pos_arm - reset_positie)/500.0 + (0.1));
00422                             motor1speed.write(speedcompensation2);
00423                         }
00424                         if(pos_arm < reset_positie+5 && pos_arm > reset_positie-5)                    // Dit gaat niet goed komen, omdat het precies die waarde moet zijn
00425                         {
00426                             motor1speed.write(0);
00427                             arm = true;
00428                             switch_reset = 2;
00429                         }
00430                     pc.printf("Positie_arm = %f \t \t snelheid = %f \n",pos_arm, speedcompensation);
00431                     wait(0.0001);    
00432                     break;
00433                         
00434                      case(2):
00435                      pc.printf("\t switch magneet automatisch \n");
00436                         wait(1);
00437                         magnet.write(on);
00438                         wait(0.5);
00439                         switch_reset = 3;
00440                         break;
00441                         
00442                      case(3):
00443                         if(pos_board < reset_board)
00444                         {
00445                             motor2direction.write(cw);
00446                             speedcompensation = ((reset_board - pos_board)/500.0 + (0.1));
00447                             motor2speed.write(speedcompensation);
00448                         }
00449                         
00450                         if(pos_board > reset_board)
00451                         {
00452                             motor2direction.write(ccw);
00453                             speedcompensation = ((pos_board - reset_board)/500.0 + (0.1));
00454                             motor2speed.write(speedcompensation);
00455                         }
00456                         if(pos_board < reset_board+5 && pos_board > reset_board-5)
00457                         {
00458                             motor2speed.write(0);
00459                             board1 = true;
00460                         }
00461                     if(board1 == true)
00462                         {
00463                             red=0;
00464                             pc.printf("fase switch  naar 1\n\n");                   
00465                             board1 = false;
00466                             arm = false;
00467                           //  flag_calibration = true;           !!!!!                Moet naar gekeken worden of we elke spel willen calibreren
00468                             wait(2);
00469                             games_played ++;
00470                             games_played1 = games_played - (3*calibratie_metingen - 3);
00471                             pc.printf("Games played total count = %i and loop %i\n",games_played,games_played1);
00472                         
00473                             if(games_played1 == 3){
00474 
00475                                 flag_calibration = true;
00476                                 while(t){
00477                                     pc.printf("\tCalibratie begint over %i \n",t);
00478                                     t--;
00479                                     wait(1);
00480                             }
00481                             }
00482                                  while(t){
00483                                  pc.printf("\tNieuw spel begint over %i \n",t);
00484                                  t--;
00485                                  wait(1);
00486                                  }
00487                 
00488                                 fase = 1;                                                           // Terug naar fase 1
00489                                 switch_reset = 1;                                                   // De switch op orginele locatie zetten
00490                                 t = 5;
00491                             
00492                     }
00493                         
00494                     pc.printf("Positie_board = %f \t \t snelheid = %f \n",pos_board, speedcompensation);
00495                     wait(0.0001);    
00496                      break; 
00497                     }
00498             break;
00499     //=================================================== STOP SCRIPT ============================================================
00500             }
00501             }            
00502     }
00503 }