With this script a Ball-E robot can be made and be operative for the use.

Dependencies:   HIDScope MODSERIAL QEI biquadFilter mbed

Fork of Samenvoegen_7_5 by Biorobotics10

Revision:
0:6616d722fed3
Child:
1:0e1d91965b8e
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Oct 19 07:07:21 2015 +0000
@@ -0,0 +1,503 @@
+//================================================================  Script: Ball-E ==================================================================
+// Author: Ewoud Velu, Lisa Verhoeven, Robert van der Wal, Thijs van der Wal, Emily Zoetbrood
+/* This is the script of a EMG measurment moving robot. The purpose of the robot is to amuse people with the disease of Ducenne.
+ 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
+*/
+
+//******************************************** Library DECLARATION **************************************
+#include "mbed.h"
+#include "QEI.h"
+#include "MODSERIAL.h"
+#include "HIDScope.h"
+#include "biquadFilter.h"
+#include <cmath>
+#include <stdio.h>
+
+//******************************************* FUNCTION DECLA *******************************************
+//**************** INPUTS *****************
+AnalogIn  EMG1(A0);                                            // Input EMG
+AnalogIn  EMG2(A1);                                            // Input EMG
+//AnalogIn pot(A2);
+//AnalogIn pot1(A3);
+
+QEI wheel2 (D10, D11, NC, 64,QEI::X4_ENCODING);          // Function for Encoder1 on the motor1 to the Microcontroller
+QEI wheel1 (D12, D13, NC, 64,QEI::X4_ENCODING);          // Function for Encoder2 on the motor2 to the Microcontroller
+
+//**************** OUTPUTS ****************
+DigitalOut red(LED_RED);                                        // LED declared for calibration
+DigitalOut green(LED_GREEN);                                    // LED declared for sampling      
+
+DigitalOut magnet(D2);
+                      
+DigitalOut motor2direction(D4);                                 // D4 en D5 zijn motor 2 (op het motorshield)
+PwmOut motor2speed(D5);
+DigitalOut motor1direction(D7);                                 // D6 en D7 zijn motor 1 (op het motorshield)
+PwmOut motor1speed(D6);
+
+//**************** FUNCTIONS **************
+/* HIDScope    scope(4);          */                              // HIDScope declared with 4 scopes
+MODSERIAL pc(USBTX, USBRX);                                     // Function for Serial communication with the Microcontroller to the pc.
+
+//******************************* GLOBAL VARIABLES DECLARATION ************************************
+const int       led_on             = 0;                         // Needed for the LEDs to turn on and off
+const int       led_off            = 1;
+const int       relax              = 0;
+const int       graden             = 360; 
+
+int             games_played       = -1;                                    // -1 omdat het spel daar eerst loopt voor het spelen om alles na te checken
+int             games_played1       = 0;
+bool            flag_calibration   = true;
+
+//********* VARIABLES FOR MOTOR CONTROL ********                      
+const float     cw                 = 1;                          // The number if: motor1 moves clock wise motor2 moves counterclockwise
+const float     ccw                = 0;                          // The number if: motor1 moves counterclock wise motor2 moves clockwise
+bool            flag_s             = false;                      // Var flag_s sensor ticker
+bool            flag_m             = false;                      // Var flag_m motor ticker
+float           ain                = 0;
+
+//********* VARIABLES FOR CONTROL 1 ************
+volatile bool   sample_go;                                       // Ticker EMG function
+int             Fs                 = 512;                        // Sampling frequency
+
+const double    low_b1             = 1.480219865318266e-04;                        //Filter coefficients
+const double    low_b2             = 2.960439730636533e-04;
+const double    low_b3             = 1.480219865318266e-04;
+const double    low_a2             = -1.965293372622690e+00;                       // a1 is normalized to 1
+const double    low_a3             = 9.658854605688177e-01;
+const double    high_b1            = 8.047897937631126e-01;
+const double    high_b2            = -1.609579587526225e+00;
+const double    high_b3            = 8.047897937631126e-01;
+const double    high_a2            = -1.571102440190402e+00;                      // a1 is normalized to 1
+const double    high_a3            = 6.480567348620491e-01;
+
+double u1; double y1;                                            // Declaring the input variables
+double u2; double y2;
+
+int calibratie_metingen = 0;
+
+//********* VARIABLES FOR FASE SWITCH **********
+bool            begin               = true;                                              
+int             fase                = 3;                                   // To switch between different phases and begins with the reset phase
+const float     fasecontract        = 0.7;                                 // The value the EMG signal must be for fase change
+float           rightbiceps         = y2;
+float           leftbiceps          = ain;
+int             reset               = 0;
+int             button_pressed      = 0;
+int             j                   = 1;
+int             N                   = 200;
+bool            fase_switch_wait    = true;
+
+//********* VARIABLES FOR CONTROL 2 ************
+const float     contract            = 0.2;                                 // The minimum value for which the motor moves
+const float     maxleft             = -1000;                               // With this angle the motor should stop moving
+const float     maxright            = 1000;                                // With this angle the motor should stop moving
+const float     speed_plate_1       = 0.4;                                 // The speed of the plate in control 2
+bool            flag_left           = true;
+bool            flag_right          = true;
+float           pos_board           = 0;                                   // The position of the board begins at zero                                 
+float           Encoderread2        = 0;
+
+
+//********* VARIABLES FOR CONTROL 3 ************
+const float     minimum_contract    = 0.2;                                 // Certain levels for muscle activity to activate motor
+const float     medium_contract     = 0.5;                                 // "Medium contract muscle"
+const float     maximum_leftbiceps  = 0.8;                                 // "Maximum contract muscle"
+const float     on                  = 1.0;
+const float     off                 = 0.0;
+const float     minimum_throw_angle = -5;
+const float     maximum_throw_angle = 110;
+float           pos_arm             = 0;
+int             pos_arm1            = 0;
+float           Encoderread1        = 0;
+int             switch_rondjes      = 2;
+int             rondjes             = 0;
+
+//********* VARIABLES FOR CONTROL 4 ************    
+
+float           reset_positie       = 0;      // Belangrijk
+float           reset_board         = 0;
+float           speedcompensation;
+float           speedcompensation2;
+int             t                   = 5;                           // aftellen naar nieuw spel
+int             switch_reset        = 1;
+bool            arm                 = false;
+bool            board1              = false;
+
+
+// **************************************** Tickers *****************************************
+Ticker Sensor_control;                                          // Adds ticker function for the variable function : Sensors
+Ticker Motor_control; 
+Ticker EMG_Control;
+
+//=============================================================================================== SUB LOOPS ==================================================================================================================
+//**************************** CONTROL 1-EMG CALIBRATION ***********************************
+
+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
+biquadFilter highpass2(high_a2, high_a3, high_b1, high_b2, high_b3);
+biquadFilter lowpass1(low_a2, low_a3, low_b1, low_b2, low_b3);
+biquadFilter lowpass2(low_a2, low_a3, low_b1, low_b2, low_b3);
+
+                                
+double cali_fact1 = 0.9;                                          // calibration factor to normalize filter output to a scale of 0 - 1
+double cali_fact2 = 0.9;
+double cali_array1[2560] = {};                                  // array to store values in
+double cali_array2[2560] = {};                                 
+
+void hoog_laag_filter() 
+{
+    u1 = EMG1; 
+    u2 = EMG2;
+    y1 = highpass1.step(u1); 
+    y2 = highpass2.step(u2);                                // filter order is: high-pass --> rectify --> low-pass
+    y1 = fabs(y1); 
+    y2 = fabs(y2); 
+    y1 = lowpass1.step(y1)*cali_fact1;
+    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.
+}
+ 
+
+//======================================= TICKER LOOPS ==========================================
+void SENSOR_LOOP()
+{
+    flag_s = true;
+}
+
+void MOTOR_LOOP()
+{
+    flag_m = true;
+}
+
+void samplego() {                                     // ticker function, set flag to true every sample interval
+    sample_go = 1;
+}
+
+
+//================================================================================================== HEAD LOOP ================================================================================================================
+int main() 
+{
+    
+    pc.baud(115200);
+    Sensor_control.attach(&SENSOR_LOOP, 0.01);                              // TICKER FUNCTION
+    Motor_control.attach(&MOTOR_LOOP, 0.01);
+    EMG_Control.attach(&samplego, (float)1/Fs);
+    
+    pc.printf("===============================================================\n");
+    pc.printf(" \t\t\t Ball-E\n");
+    pc.printf("In the module Biorobotics on the University of Twente is this script created\n");
+    pc.printf("Autors:\tE. Velu, L. Verhoeven, R. v/d Wal, T. v/d Wal, E. Zoetbrood\n\n");
+    wait(3);
+    pc.printf("The script will begin with a short calibration\n\n");
+    wait(2.5);
+    pc.printf("===============================================================\n");
+    //************************* CONTROL 1-EMG CALIBRATION ****************************
+    while(1) 
+    {   
+    
+     if(sample_go) 
+        {            
+            red.write(led_off);                     // Toggles red calibration LED off
+            green.write(led_on);                    // Toggles green sampling LED on
+            hoog_laag_filter();
+            sample_go = 0;
+        } 
+    
+    if (flag_calibration)
+        {                                                                   // 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.
+                    calibratie_metingen ++;
+                    green.write(led_off);                                   // Toggles green sampling LED off
+                    red.write(led_on);                                      //Toggles red calibration LED on
+                    cali_fact1 = 0.9;                                          // calibration factor to normalize filter output to a scale of 0 - 1
+                    cali_fact2 = 0.9;
+                    double cali_max1 = 0;                                   // declare max y1
+                    double cali_max2 = 0;                                   //declare max y2
+                    pc.printf(" \n\n EMG Signal starting up Calibration measurement........... \n");
+                    wait(2);
+                    pc.printf("\t.....Calibrating Signal of EMG 1 and 2 .......\n");
+                    wait(0.5);
+                    pc.printf("\t......contract muscles..... \n");
+                
+                for(int cali_index1 = 0; cali_index1 < 2560; cali_index1++)  // Records 5 seconds of y1
+                {
+                    hoog_laag_filter();
+                    cali_array1[cali_index1] = y1;
+                    wait((float)1/Fs);
+                }
+                for(int cali_index2 = 0; cali_index2 < 2560; cali_index2++)  // Records 5 seconds of y2
+                {
+                    hoog_laag_filter();
+                    cali_array2[cali_index2] = y2;
+                    wait((float)1/Fs);
+                }
+                for(int cali_index3 = 0; cali_index3 < 2560; cali_index3++)   // Scales y1
+                { 
+                    if(cali_array1[cali_index3] > cali_max1)
+                    {
+                        cali_max1 = cali_array1[cali_index3];
+                    }
+                 }
+                 for(int cali_index4 = 0; cali_index4 < 2560; cali_index4++)  // Scales y2
+                 {
+                    if(cali_array2[cali_index4] > cali_max2)
+                    {
+                        cali_max2 = cali_array2[cali_index4];
+                    }
+                 }
+                 cali_fact1 = (double)1/cali_max1;                              // Calibration factor for y1
+                 cali_fact2 = (double)1/cali_max2;                              // Calibration factor for y2
+                 
+                                                    // Toggles green sampling LED off
+                 red.write(led_off);
+                 green.write(led_on);
+                 pc.printf(" \t....... Calibration has been completed!\n");
+                 wait(0.2);
+                 green.write(led_off);
+                 wait(0.2);
+                 green.write(led_on);
+                 wait(0.2);
+                 green.write(led_off);
+                 wait(0.2);
+                 green.write(led_on);
+                 wait(4);
+                 pc.printf("Beginning with Ball-E board settings\n"); 
+                 green.write(led_off);
+                 wait(2);
+                 y1 = 0;
+                 y2 = 0;
+                 
+                 j = 1;                                         // Wachten van fase switch initialiseren 
+                 fase_switch_wait = true;
+         }        
+      
+            
+    //************************* CONTROL MOTOR ****************************************
+        
+            
+            
+            if (flag_s)
+            {
+                Encoderread1 = wheel1.getPulses();
+                pos_arm = (Encoderread1/((64.0*131.0)/360.0));   // Omrekenen naar graden van arm
+                
+                Encoderread2 = wheel2.getPulses();
+                pos_board = (Encoderread2/((64.0*131.0)/360.0));   // Omrekenen naar graden van board
+                flag_calibration = false;
+            }
+    //************************* FASE SWITCH ******************************************
+        //******************** Fase determination *************
+        if (fase_switch_wait == true)
+       {
+           j++;
+           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.
+      pc.printf("waarde j = %i \n",j);
+       }
+       
+       if( j > N){
+        fase_switch_wait = false;
+        switch(fase)
+        {
+            
+            //******************* Fase 1 **************************
+            case(1):
+            rondjes = 0;
+                if (y1> contract)
+                {
+                    flag_right = false;
+                    flag_left = true;
+                }
+                
+                if (y2 > contract) 
+                {
+                    flag_right = true;
+                    flag_left = false;
+                }
+                
+                if (pos_board <= maxleft) 
+                {
+                    flag_left = false;
+                    motor2speed.write(relax);
+                }
+                
+                if (pos_board >= maxright) 
+                {
+                    flag_right = false;
+                    motor2speed.write(relax);
+                }
+
+                if (flag_left == true)
+                {
+                    if (y1> contract) 
+                    {
+                        motor2direction.write(ccw);      
+                        motor2speed.write(speed_plate_1); 
+                    }
+                    else
+                    {
+                        motor2speed.write(relax); 
+                    }
+                }
+        
+                if (flag_right == true)
+                {
+                    if (y2 > contract) 
+                    {
+                        motor2direction.write(cw);           
+                        motor2speed.write(speed_plate_1); 
+                    }
+                    else
+                    {
+                        motor2speed.write(relax);
+                    }
+                }
+                pc.printf("Boardposition \t %f  EMG1 en EMG2 signaal = %f \t %f\n", pos_board, y1, y2);
+                if (y1> fasecontract && y2 > fasecontract) 
+                {
+                    motor2speed.write(relax);
+                    fase = 2;
+                    fase_switch_wait = true;
+                    j = 0;
+                }
+                break;
+            //******************* Fase 2 **************************
+            case(2):
+            motor1direction.write(cw); 
+            pos_arm1 = (pos_arm - (rondjes * 360));
+            
+                    switch(switch_rondjes){
+                        case(1):
+                        rondjes ++;
+                        switch_rondjes = 2;
+                        break;
+                        case(2):
+                        if(pos_arm1>360 & 368<pos_arm1)
+                        {
+                            switch_rondjes = 1;
+                        }
+                        break;
+                    }
+                
+                 
+                    if (y2 > minimum_contract & y2 < medium_contract) 
+                    {
+                        motor1speed.write((y2 - minimum_contract)/(medium_contract - minimum_contract));
+                    }
+                    if (y2 > medium_contract)                 // Hoger dan drempelwaarde = Actief
+                    {
+                        motor1speed.write((y2 - minimum_contract)/(medium_contract - minimum_contract));
+                    }
+                    if (y2 < minimum_contract)                // Lager dan drempel = Rust 
+                    {
+                        motor1speed.write(relax);         
+                    }
+                    if (pos_arm1 > minimum_throw_angle & pos_arm1 < maximum_throw_angle) 
+                    {
+                        if (y1> maximum_leftbiceps) 
+                        {
+                            magnet.write(off);
+                            motor1speed.write(relax);
+                            fase = 3;
+                            pc.printf("Van fase 2 naar fase 3\n");
+                            wait(2);
+                            j = 0;
+                            fase_switch_wait = true;    
+                        } 
+                        }
+                pc.printf("Armposition \t %i \t EMG1 en EMG2 = %f \t %f \n", pos_arm1, y1, y2); 
+                break;
+            //********************************************* Fase 3 **********************************************  
+            case(3):
+                
+                switch(switch_reset)
+                    {
+                    case(1):
+                    if(pos_arm < reset_positie)                     //ene kant op draaien
+                        {                 
+                            motor1direction.write(cw);
+                            speedcompensation2 = ((reset_positie - pos_arm)/900.0 + (0.1));
+                            motor1speed.write(speedcompensation2);
+                        }
+                        if(pos_arm > reset_positie)                  //andere kant op
+                        {
+                            motor1direction.write(ccw);
+                            speedcompensation2 = ((pos_arm - reset_positie)/500.0 + (0.1));
+                            motor1speed.write(speedcompensation2);
+                        }
+                        if(pos_arm < reset_positie+5 && pos_arm > reset_positie-5)                    // Dit gaat niet goed komen, omdat het precies die waarde moet zijn
+                        {
+                            motor1speed.write(0);
+                            arm = true;
+                            switch_reset = 2;
+                        }
+                    pc.printf("Positie_arm = %f \t \t snelheid = %f \n",pos_arm, speedcompensation);
+                    wait(0.0001);    
+                    break;
+                        
+                     case(2):
+                     pc.printf("\t switch magneet automatisch \n");
+                        wait(1);
+                        magnet.write(on);
+                        wait(0.5);
+                        switch_reset = 3;
+                        break;
+                        
+                     case(3):
+                        if(pos_board < reset_board)
+                        {
+                            motor2direction.write(cw);
+                            speedcompensation = ((reset_board - pos_board)/500.0 + (0.1));
+                            motor2speed.write(speedcompensation);
+                        }
+                        
+                        if(pos_board > reset_board)
+                        {
+                            motor2direction.write(ccw);
+                            speedcompensation = ((pos_board - reset_board)/500.0 + (0.1));
+                            motor2speed.write(speedcompensation);
+                        }
+                        if(pos_board < reset_board+5 && pos_board > reset_board-5)
+                        {
+                            motor2speed.write(0);
+                            board1 = true;
+                        }
+                    if(board1 == true)
+                        {
+                            red=0;
+                            pc.printf("fase switch  naar 1\n\n");                   
+                            board1 = false;
+                            arm = false;
+                          //  flag_calibration = true;           !!!!!                Moet naar gekeken worden of we elke spel willen calibreren
+                            wait(2);
+                            games_played ++;
+                            games_played1 = games_played - (3*calibratie_metingen - 3);
+                            pc.printf("Games played total count = %i and loop %i\n",games_played,games_played1);
+                        
+                            if(games_played1 == 3){
+
+                                flag_calibration = true;
+                                while(t){
+                                    pc.printf("\tCalibratie begint over %i \n",t);
+                                    t--;
+                                    wait(1);
+                            }
+                            }
+                                 while(t){
+                                 pc.printf("\tNieuw spel begint over %i \n",t);
+                                 t--;
+                                 wait(1);
+                                 }
+                
+                                fase = 1;                                                           // Terug naar fase 1
+                                switch_reset = 1;                                                   // De switch op orginele locatie zetten
+                                t = 5;
+                            
+                    }
+                        
+                    pc.printf("Positie_board = %f \t \t snelheid = %f \n",pos_board, speedcompensation);
+                    wait(0.0001);    
+                     break; 
+                    }
+            break;
+    //=================================================== STOP SCRIPT ============================================================
+            }
+            }            
+    }
+}
\ No newline at end of file