not working yet
Dependencies: Motor_with_encoder MODSERIAL mbed HIDScope
main.cpp
- Committer:
- vera1
- Date:
- 2017-10-27
- Revision:
- 11:bda77916d2ea
- Parent:
- 8:9edf32e021a5
- Child:
- 12:5be2001abe62
File content as of revision 11:bda77916d2ea:
#include "mbed.h" #include "MODSERIAL.h" #include "encoder.h" #include "math.h" #include "HIDScope.h" #include "BiQuad.h" #include "EMG_filter.h" MODSERIAL pc(USBTX,USBRX); enum r_states {R_HORIZONTAL, R_VERTICAL, R_BASE}; r_states state; // ---- EMG parameters ---- //HIDScope scope (2); EMG_filter emg1(A0); EMG_filter emg2(A1); // ------------------------ // ---- Motor input and outputs ---- PwmOut speed1(D5); PwmOut speed2(D6); DigitalOut dir1(D4); DigitalOut dir2(D7); DigitalIn press(PTA4); DigitalOut ledred(LED_RED); DigitalOut ledgreen(LED_GREEN); DigitalOut ledblue(LED_BLUE); DigitalOut ledstateswitch(D8); DigitalOut ledstatedef(D11); AnalogIn pot(A2); AnalogIn pot2(A3); Encoder motor1(PTD0,PTC4); Encoder motor2(D12,D13); // ---------------------------------- // --- Define Ticker and Timeout --- Ticker mainticker; //Ticker that calls every function. Functions are called by means of a variable named go, e.g. go_EMG Timeout calibrationgo; // Timeout that will determine the duration of the calibration. // --------------------------------- float PwmPeriod = 0.0001f; double count = 0; //set the counts of the encoder volatile double angle = 0;//set the angles double count2 = 0; //set the counts of the encoder volatile double angle2 = 0;//set the angles double setpoint = 6.28;//I am setting it to move through 180 degrees double setpoint2 = 6.28;//I am setting it to move through 180 degrees double Kp = 500;// you can set these constants however you like depending on trial & error double Ki = 100; double Kd = 0; float last_error = 0; float error1 = 0; float changeError = 0; float totalError = 0; float pidTerm = 0; float pidTerm_scaled = 0; float last_error2 = 0; float error2 = 0; float changeError2 = 0; float totalError2 = 0; float pidTerm2 = 0; float pidTerm_scaled2 = 0;// if the total gain we get is not in the PWM range we scale it down so that it's not bigger than |255| volatile double potvalue = 0.0; volatile double potvalue2 = 0.0; volatile double position = 0.0; volatile double position2 = 0.0; // --- Booleans for the maintickerfunction --- //bool readoutsetpoint = true; bool go_EMG; // Boolean to put on/off the EMG readout bool go_calibration; // Boolean to put on/off the calibration of the EMG bool go_switch; // Boolean to go to different state bool go_PID; // Boolean to calculate PID and motor aansturing // ------------------------------------------- // --- calibrate EMG signal ---- void calibrationGO() // Function for go or no go of calibration { go_calibration = false; } /* Calibration of the robot works as follows: EMG signal is read out for 5 seconds, 1000 times a second. This signal is filtered and the maximum value is compared to the current value of the MVC. The value of the MVC is overwritten when the value of the filtered signal is bigger than the current value. During the calibration the user should exert maximum force. */ void calibrationEMG() // Function for calibrating the EMG signal { if (go_calibration) { emg1.calibration(); // Using the calibration function of the EMG_filter class emg2.calibration(); } } // ------------------------------ // --- motor movements --- void r_movehorizontal() { } void r_movevertical() { } void r_movebase() { } //-------------------------------- //--- State switch function ----- void r_processStateSwitch() { if(go_switch) { //if go_switch is true state is switched go_switch = false; switch(state) { case R_HORIZONTAL: state = R_VERTICAL; ledblue = 1; ledred = 1; ledgreen = 0; pc.printf("state is vertical"); break; case R_VERTICAL: state = R_BASE; ledgreen = 1; ledblue = 1; ledred = 0; pc.printf("state is base"); break; case R_BASE: state = R_HORIZONTAL; ledgreen = 1; ledred = 1; ledblue = 0; pc.printf("state is horizontal"); break; } wait(1.0f); // waits 1 second to continue with the main function. I think ticker does run, but main is on hold. ledstatedef = 1; ledstateswitch = 0; } } //Function that reads out the raw EMG and filters the signal void processEMG () { emg1.filter(); //filter the incoming emg signal emg2.filter(); //emg3.filter(); /* scope.set(0, emg1.normalized); //views emg1.normalized on port 0 of HIDScope scope.set(1, emg1.emg0); scope.send();*/ } void setpointreadout() { potvalue = pot.read(); setpoint = emg1.normalized; potvalue2 = pot2.read(); setpoint2 = emg2.normalized; } void PIDcalculation() // inputs: potvalue, motor#, setpoint { setpointreadout(); angle = motor1.getPosition()/4200.00; angle2 = motor2.getPosition()/4200.00*6.28; //pc.printf("pos: %d, speed %f reference position = %.2f\r ",motor1.getPosition(), motor1.getSpeed(), setpoint); //motorpid = PID(potvalue - position, M1_KP, M1_KI, M1_KD, M1_TS, m1_err_int, m1_prev_err, m1_f_v1, m1_f_v2, M1_F_A1, M1_F_A2, M1_F_B0, M1_F_B1, M1_F_B2); error1 = setpoint - angle; error2 = setpoint2 - angle2; changeError = (error1 - last_error)/0.001f; // derivative term totalError += error1*0.001f; //accumalate errors to find integral term pidTerm = (Kp * error1) + (Ki * totalError) + (Kd * changeError);//total gain pidTerm = pidTerm; if (pidTerm >= 1000) { pidTerm = 1000; } else if (pidTerm <= -1000) { pidTerm = -1000; } else { pidTerm = pidTerm; } //constraining to appropriate value if (pidTerm >= 0) { dir1 = 1;// Forward motion } else { dir1 = 0;//Reverse motion } pidTerm_scaled = abs(pidTerm)/1000.0f; //make sure it's a positive value if(pidTerm_scaled >= 0.55f){ pidTerm_scaled = 0.55f; } changeError2 = (error2 - last_error2)/0.001f; // derivative term totalError2 += error2*0.001f; //accumalate errors to find integral term pidTerm2 = (Kp * error2) + (Ki * totalError2) + (Kd * changeError2);//total gain pidTerm2 = pidTerm2; if (pidTerm2 >= 1000) { pidTerm2 = 1000; } else if (pidTerm2 <= -1000) { pidTerm2 = -1000; } else { pidTerm2 = pidTerm2; } //constraining to appropriate value if (pidTerm2 >= 0) { dir2 = 1;// Forward motion } else { dir2 = 0;//Reverse motion } pidTerm_scaled2 = abs(pidTerm2)/1000.0f; //make sure it's a positive value if(pidTerm_scaled2 >= 0.55f){ pidTerm_scaled2 = 0.55f; } last_error = error1; speed1 = pidTerm_scaled+0.45f; last_error2 = error2; speed2 = pidTerm_scaled2+0.45f; } void maintickerfunction() { r_processStateSwitch(); if(go_EMG) { processEMG(); } /*if(emg1.normalized >=0.2 && emg2.normalized >= 0.2) // PIDcalculation should not happen. { go_PID = false; } else{go_PID = true;}*/ if(go_PID){ PIDcalculation(); } } int main() { pc.baud(9600); go_EMG = true; // Setting ticker variables go_calibration = true; // Setting the timeout variable go_PID = true; go_switch = false; speed1.period(PwmPeriod); speed2.period(PwmPeriod); calibrationgo.attach(&calibrationGO, 5.0); // Attach calibration timeout to calibration function mainticker.attach(&calibrationEMG, 0.001f); // Attach ticker to the calibration function wait(5.0f); mainticker.attach(&maintickerfunction,0.001f); int count = 0; while(true) { ledstatedef = 1; if(emg1.normalized >= 0.7 && emg2.normalized >= 0.7) { ledstateswitch = 1; ledstatedef = 0; go_switch = true; } switch(state) { case R_HORIZONTAL: r_movehorizontal(); break; case R_VERTICAL: r_movevertical(); break; case R_BASE: r_movebase(); break; } count++; if(count == 100){ count = 0; pc.printf("emg1 = %f, emg2 = %f\r\n", emg1.normalized, emg2.normalized); //pc.printf("Angle = %f, pidTerm = %f ,PID_scaled = %f, Error = %f, setpoint = %f\r\n", angle, pidTerm ,pidTerm_scaled, error1, setpoint); //pc.printf("Angle 2 = %f, pidTerm 2 = %f ,PID_scaled 2 = %f, Error 2 = %f, setpoint 2 = %f\r\n", angle2, pidTerm2 ,pidTerm_scaled2, error2,setpoint2); } wait(0.001f); } }