Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependencies: HIDScope MODSERIAL QEI biquadFilter mbed
Fork of Samenvoegen_7_5 by
main.cpp
- Committer:
- Wallie117
- Date:
- 2015-10-26
- Revision:
- 7:d55569b92f30
- Parent:
- 6:1518fccc5616
- Child:
- 8:151e43b99156
File content as of revision 7:d55569b92f30:
//======================================================================= Script: Ball-E ==========================================================================
// Authors: 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 ‘arm’ that can turn in the vertical plane and move in the horizontal plane.
*/
//*********************************************** LIBRARY DECLARATION ********************************************
// Libraries are files which contain standard formulas for reading surtain information. Every library contains its own information.
#include "mbed.h" // Standard library. This includes the reading of AnalogIn, DigitalOut, PwmOut and other standard formules.
#include "QEI.h" // This library includes the reading of of the Encoders from motors.
#include "MODSERIAL.h" // MODSERIAL inherits Serial and adds extensions for buffering.
#include "HIDScope.h" // This sends the measured EMG signal to the HIDScope.
#include "biquadFilter.h" // Because of this library we can make different filters.
#include <cmath> // This library declares a set of functions to compute common mathematical operations and transformations. Only used fabs.
#include <stdio.h> // This library defines three variable types, several macros, and various functions for performing input and output.
//*********************************************** FUNCTION DECLARATION *******************************************
//**************************** INPUTS ******************************************************
AnalogIn EMG1(A0); // Input left biceps EMG.
AnalogIn EMG2(A1); // Input right biceps EMG.
QEI wheel1 (D10, D11, NC, 64,QEI::X4_ENCODING); // Function for Encoder1 on the motor1 to the Microcontroller.
QEI wheel2 (D12, D13, NC, 64,QEI::X4_ENCODING); // Function for Encoder2 on the motor2 to the Microcontroller.
//**************************** OUTPUTS *****************************************************
DigitalOut led_red(D1); // Output for red LED decleared.
DigitalOut led_yellow(D3); // Output for yellow LED decleared.
DigitalOut led_green(D9); // Output for green LED delceared.
DigitalOut magnet(D2); // Output for magnet.
DigitalOut motor1direction(D4); // Direction for motor 2 on motorshield. This motor moves the arm in fase 2.
PwmOut motor1speed(D5); // Speed for motor 2 on motorshield. This motor moves the arm in fase 2.
DigitalOut motor2direction(D7); // Direction for motor 1 on motorshield. This motor moves the board in fase 1.
PwmOut motor2speed(D6); // Speed for motor 1 on motorshield. This motor moves the board in fase 1.
//**************************** FUNCTIONS ***************************************************
//HIDScope scope(2); // HIDScope declared with 2 scopes.
MODSERIAL pc(USBTX, USBRX); // Function for Serial communication with the Microcontroller to the pc.
//*********************************************** GLOBAL VARIABLES DECLARATION ***********************************
const int led_on = 0; // This constant turns the led on.
const int led_off = 1; // This constant turns the led off.
int games_played1 = 0; // Counts number of games played.
int games_played = -1; // Shows real number of games played. There is a -1 because the game is first reset before the first throw.
float dt = 0.01; // Time staps
//**************************** VARIABLES FOR MOTOR CONTROL *********************************
const float cw = 1; // Motor1 moves counter clock wise and Motor2 moves clock wise.
const float ccw = 0; // Motor1 moves clock wise and Motor2 moves counter clock wise.
bool flag_s = false; // Var flag_s sensor ticker
const int relax = 0; // The motor speed is zero.
//**************************** VARIABLES FOR CONTROL 1 *************************************
int Fs = 512; // Sampling frequency.
int calibration_measurements = 0; // Integer counts the number of calibrations done. It starts at 0.
//Filter coefficients. a1 is normalized to 1.
const double low_b1 = /*0.0055427172102806843;*/1.480219865318266e-04;
const double low_b2 = /*0.011085434420561369;*/2.960439730636533e-04;
const double low_b3 = /*0.0055427172102806843; */1.480219865318266e-04;
const double low_a2 = /*-1.778631777824585; */-1.965293372622690e+00;
const double low_a3 = /*0.80080264666570777; */9.658854605688177e-01;
const double high_b1 = /*0.63894552515902237;*/8.047897937631126e-01;
const double high_b2 = /*-1.2778910503180447; */-1.609579587526225e+00;
const double high_b3 = /*0.63894552515902237;*/8.047897937631126e-01;
const double high_a2 = /*-1.1429805025399009;*/-1.571102440190402e+00;
const double high_a3 = /*0.41280159809618855;*/6.480567348620491e-01;
// Declaring the input and output variables.
double u1; // Input from EMG 1. The left biceps.
double y1; // Output from the filters from u1.
double u2; // Input from EMG 2. The right biceps.
double y2; // Output from the filters from u2.
double cali_fact1 = 0.9; // Calibration factor to normalize filter output to a scale of 0 - 1. For signal y1.
double cali_fact2 = 0.9; // Calibration factor to normalize filter output to a scale of 0 - 1. For signal y2.
double cali_max1 = 0; // Declares max y1.
double cali_max2 = 0; // Declares max y2.
double cali_array1[2560] = {}; // Array to store values in for the 5 seconds calibartion for y1.
double cali_array2[2560] = {}; // Array to store values in for the 5 seconds calibartion for y2.
bool flag_calibration = true; // Flag to start the calibration.
//**************************** VARIABLES FOR FASE SWITCH ***********************************
int fase = 3; // The fase is used in a switch to switch between the fases. It starts at the reset fase.
int j = 1; // Wait time. Used in problem1 and fase switch
int N = 200; // Maximum value of j.
bool fase_switch_wait = true; // Timer wait to switch between different fases.
//**************************** VARIABLES FOR CONTROL 2 *************************************
const float contract = 0.5; // The minimum value for y1 and y2 for which the motor moves.
const float fasecontract = 0.7; // The value y1 and y2 must be for the fase change.
const float maxleft = -200; // With this angle the motor should stop moving.
const float maxright = 200; // With this angle the motor should stop moving.
const float speed_plate_1 = 0.1; // The speed of the plate in control 2.
bool flag_left = true; // This flag determines if the signals from the left biceps should be measured. This is signal y1.
bool flag_right = true; // This flag determines if the signals from the right biceps should be measured. This is signal y2.
float pos_board = 0; // The begin position of the board. It begins at zero. Reads Encoder2 in degrees. Formula is applied in SensorTicker.
int pos_board1 = 0; //
float Encoderread2 = 0; // Reads travelled distance from Motor2. Reads pulses.
//**************************** VARIABLES FOR CONTROL 3 *************************************
const float minimum_contract = 0.4; // The minimum value for y2 for whicht the motor moves.
const float medium_contract = 0.5; // Value for different speeds of the motor.
const float maximum_leftbiceps = 0.7; // Value for y1 for which the magnet turns off.
const float on = 1.0; // This value turns the magnet on.
const float off = 0.0; // This value turns the magnet off.
const float minimum_throw_angle = 20; // The minimum angle the arm has to be in to be able to turn the magnet off.
const float maximum_throw_angle = 110; // The maximum angle for the arm to turn the magnet off.
float pos_arm = 0; // The begin position of the arm. It begins at zero. Reads Encoder1 in degrees. Formula is applied in SensorTicker.
int pos_arm1 = 0; // This makes from the positon of the arm degrees within a cirkel as an integer.
float pos_arm2 = 0; // This makes from the positon of the arm degrees within a cirkel as an float.
float previous_pos_arm = 0; // Needed to calculate the v_arm.
float v_arm = 0; // The speed of the arm.
float v_arm_com = 0; // The compensated speed of the arm.
float speed_control_arm = 0.000; //
float Encoderread1 = 0; // Reads travelled distance from Motor1.
int switch_rounds = 2; // Value of a switch to calculate the number of rounds made.
int rounds = 0; // Number of rounds made by the arm.
float pos_armrounds_max = 3; // Max rounds the arm can make.
bool problem1 = false; // Stop for fase 2. It is a wait for problem2 begins.
bool problem2 = false; // The reset of fase 2 when the arm reaches its maximum value.
bool flag_v_arm = false; //
float problem_velocity = 0; //
//**************************** VARIABLES FOR CONTROL 4 *************************************
float reset_position = 0; // The reset position of the arm.
int reset_arm = 0; // The reset position of the arm (?).
int reset_board = 0; // The reset position of the board.
float speedcompensation; // Speed of Motor2 during reset.
float speedcompensation2; // Speed of Motor1 during reset.
int t = 5; // Integer for count down to new game.
int switch_reset = 1; // Value of a switch for the different parts of the reset.
bool board = false; //
// **************************************** Tickers ****************************************
/* Tickers count constantly. The formulas attacht to the ticker count with them. */
Ticker Sensor_control; // This ticker counts for the position of the motors and the speed of the arm.
Ticker EMG_Control; // This ticker counts for the filtering of the EMG signal
//=============================================================================================== 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);
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()
{
Encoderread1 = wheel1.getPulses();
previous_pos_arm = pos_arm;
pos_arm = (Encoderread1/((64.0*131.0)/360.0)); // Omrekenen naar graden van arm
pos_arm1 = pos_arm;
v_arm = (pos_arm - previous_pos_arm)/dt;
Encoderread2 = wheel2.getPulses();
pos_board = (Encoderread2/((64.0*131.0)/360.0)); // Omrekenen naar graden van board
pos_board1 = pos_board;
flag_s = true;
}
void EMG_LOOP() // ticker function, set flag to true every sample interval
{
if(flag_calibration == false)
{
hoog_laag_filter();
}
}
//================================================================================================== HEAD LOOP ================================================================================================================
int main()
{
pc.baud(115200);
Sensor_control.attach(&SENSOR_LOOP, 0.01); // TICKER FUNCTION
EMG_Control.attach(&EMG_LOOP, (float)1/Fs);
led_green.write(0);
led_yellow.write(0);
led_red.write(0);
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 (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.
{
calibration_measurements ++;
pc.printf(" \n\n EMG Signal starting up Calibration measurement........... \n");
cali_max1 = 0; // declare max y1
cali_max2 = 0; //declare max y2
cali_fact1 = 0.9; // calibration factor to normalize filter output to a scale of 0 - 1
cali_fact2 = 0.9;
wait(2);
led_red.write(0);
wait(0.2);
led_red.write(1); //Toggles red calibration LED on
wait(0.2);
led_red.write(0);
wait(0.2);
led_red.write(1);
wait(0.2);
led_red.write(0);
wait(0.2);
led_red.write(1);
wait(1);
pc.printf("\t.....Calibrating Signal of EMG 1 and 2 .......\n");
led_red.write(0);
led_yellow.write(1);
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
led_yellow.write(0);
pc.printf(" \t....... Calibration has been completed!\n");
wait(0.2);
led_green.write(led_off);
wait(0.2);
led_green.write(led_on);
wait(0.2);
led_green.write(led_off);
wait(0.2);
led_green.write(led_on);
wait(4);
pc.printf("Beginning with Ball-E board settings\n");
led_green.write(led_off);
wait(2);
y1 = 0;
y2 = 0;
j = 1; // Wachten van fase switch initialiseren
fase_switch_wait = true;
flag_calibration = false;
}
//************************* CONTROL MOTOR ****************************************
if (flag_s)
{
flag_calibration = false;
}
//************************* FASE SWITCH ******************************************
//******************** Fase determination *************
if (fase_switch_wait)
{
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);
led_red.write(0);
led_green.write(1);
led_yellow.write(0);
}
if( j > N)
{
fase_switch_wait = false;
switch(fase)
{
//******************* Fase 1 **************************
case(1):
led_red.write(1);
led_green.write(0);
led_yellow.write(0);
rounds = 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)
{
if (y1> contract)
{
motor2direction.write(ccw);
motor2speed.write(speed_plate_1);
}
else
{
motor2speed.write(relax);
}
}
if (flag_right)
{
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;
led_red.write(0);
led_green.write(0);
led_yellow.write(1);
j = 0;
}
break;
//******************* Fase 2 **************************
case(2):
led_red.write(0);
led_green.write(0);
led_yellow.write(1);
motor1direction.write(cw);
pos_arm1 = (pos_arm - (rounds * 360));
pos_arm2 = pos_arm1;
switch(switch_rounds)
{
case(1):
rounds ++;
switch_rounds = 2;
break;
case(2):
if(pos_arm1>360 & 368<pos_arm1)
{
switch_rounds = 1;
}
break;
}
if (y2 > minimum_contract & y2 < medium_contract)
{
speed_control_arm = 1;//((v_arm/304) + 0.15*(1 -(v_arm/304)));
motor1speed.write(speed_control_arm);
}
if (y2 > medium_contract) // Hoger dan drempelwaarde = Actief
{
speed_control_arm = 1;//((v_arm/304) + 0.15*(1 -(v_arm/304)));
motor1speed.write(speed_control_arm);
}
if (y2 < minimum_contract) // Lager dan drempel = Rust
{
motor1speed.write(relax);
}
if(rounds == pos_armrounds_max) // max aantal draaing gemaakt!!!!!!
{
problem1 = true;
problem2 = true;
motor1speed.write(relax);
while (problem1)
{
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.
if( j > N)
{
problem1 = false;
}
}
wait(0.1);
led_red.write(0);
wait(0.1);
led_red.write(1);
wait(0.1);
led_red.write(0);
wait(0.1);
led_red.write(1);
wait(0.1);
led_red.write(0);
wait(0.1);
led_red.write(1);
wait(1.5);
while(problem2)
{
motor1direction.write(ccw);
if(pos_arm < 170)
{
if(v_arm > 200)
{
flag_v_arm = true;
}
}
if(flag_v_arm)
{
v_arm_com = v_arm;
}
speed_control_arm = (0.4*((pos_arm2 - reset_arm)/500.0) + (0.05) - (v_arm_com/304)*0.3);
motor1speed.write(speed_control_arm);
if (pos_arm < 10)
{
flag_v_arm = false;
problem2 = false;
motor1speed.write(0);
rounds = 0;
wait(1);
}
}
}
if (pos_arm1 > minimum_throw_angle & pos_arm1 < maximum_throw_angle)
{
if (y1> maximum_leftbiceps)
{
magnet.write(off);
wait(0.1);
motor1speed.write(relax);
fase = 3;
pc.printf("Van fase 2 naar fase 3\n");
wait(2);
j = 0;
fase_switch_wait = true;
}
}
pc.printf("Snelheid arm = \t %f \t EMG1 en EMG2 = %f \t %f \n", speed_control_arm, y1, y2);
break;
//********************************************* Fase 3 **********************************************
case(3):
led_red.write(0);
led_green.write(1);
led_yellow.write(0);
switch(switch_reset)
{
case(1):
if(pos_arm < reset_position) //ene kant op draaien
{
motor1direction.write(cw);
speedcompensation2 = 0.05; //((reset_arm - pos_arm1)/900.0 + (0.02));
motor1speed.write(speedcompensation2);
}
if(pos_arm > reset_position) //andere kant op
{
motor1direction.write(ccw);
speedcompensation2 = 0.05;//((pos_arm1 - reset_arm)/500.0 + (0.02));
motor1speed.write(speedcompensation2);
}
if(pos_arm < reset_position+5 && pos_arm > reset_position-5) // Dit gaat niet goed komen, omdat het precies die waarde moet zijn
{
motor1speed.write(0);
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(0.2);
magnet.write(on);
wait(2);
switch_reset = 3;
break;
case(3):
if(pos_board < reset_board)
{
motor2direction.write(cw);
speedcompensation = 0.05; //((reset_board - pos_board1)/500.0 + (0.1));
motor2speed.write(speedcompensation);
}
if(pos_board > reset_board)
{
motor2direction.write(ccw);
speedcompensation = 0.05;//((pos_board1 - reset_board)/500.0 + (0.05));
motor2speed.write(speedcompensation);
}
if(pos_board < reset_board+5 && pos_board > reset_board-5)
{
motor2speed.write(0);
board = true;
}
if(board)
{
pc.printf("fase switch naar 1\n\n");
board = false;
wait(2);
games_played ++;
games_played1 = games_played - (5*calibration_measurements - 5);
pc.printf("Games played total count = %i and loop %i\n",games_played,games_played1);
if(games_played1 == 5)
{
flag_calibration = true;
while(t)
{
pc.printf("\tCalibratie begint over %i \n",t);
t--;
led_yellow.write(1);
wait(0.5);
led_yellow.write(0);
wait(0.5);
}
}
while(t)
{
pc.printf("\tNieuw spel begint over %i \n",t);
t--;
led_yellow.write(1);
wait(0.5);
led_yellow.write(0);
wait(0.5);
}
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 ============================================================
}
}
}
}
