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 TextLCD mbed
Fork of TotalControlEmg2 by
main.cpp
- Committer:
- RemcoDas
- Date:
- 2015-10-27
- Revision:
- 48:07e3cf7dc819
- Parent:
- 47:959ef2792024
- Child:
- 49:b571c822c3f9
File content as of revision 48:07e3cf7dc819:
//--------------------Include files and libraries------- #include "mbed.h" #include "QEI.h" #include "MODSERIAL.h" #include "TextLCD.h" #include "HIDScope.h" #include "Filterdesigns.h" #include "Kalibratie.h" #include "Mode.h" //--------------------Classes------------------------ InterruptIn btnSet(PTC6); // Kalibration button InterruptIn emgSet(PTA4); // EMG on/off button //DigitalOut ledR(LED_RED), LedB(LED3); // Leds on K64F MODSERIAL pc(USBTX, USBRX); // Modserial voor Putty TextLCD lcd(PTC5, PTC7, PTC0, PTC9, PTC8, PTC1); // LCD screen on inner row of K64F, rs, e, d4-d7 PwmOut servo(D3); // PwmOut servo AnalogIn emgL(A0), emgR(A1); // Analog input of EMG, left and right AnalogIn potL(A2), potR(A3); // Potential meter left and right AnalogIn ksLeft(A5), ksRight(A4); // Killswitch left and right HIDScope scope(2); // Hidscope, amount of scopes Ticker EMGticker, tickerControl, tickerLcd; // Ticker for EMG, regulator and break // QEI Encoder(port 1, port 2, ,counts/rev QEI enc1 (D13, D12, NC, 64), enc2 (D11, D10, NC, 64); // Motor1 met PWM power control and direction PwmOut pwmM1(D6); DigitalOut dirM1(D7); // Motor2 met PWM power control and direction PwmOut pwmM2(D5); DigitalOut dirM2(D4); enum spelfase {CALIBRATE_EMG, CALIBRATE_AIM, CALIBRATE_BEAM, AIM, BREAK, FIRE}; // Program states, ACKNOWLEDGEMENT switch: BMT groep 4 2014 uint8_t state = CALIBRATE_EMG; // first state program enum aimFase {OFF, CW, CCW}; // Aim motor possible states uint8_t aimState = OFF; // first state aim motor //-------------------------------Variables--------------------------------------------------------------------- int maxCounts = 13000; // max richt motor counts Aim motor int breakPerc = 0; volatile int modeL = 1, modeR = 1; const double servoBreak = 0.00165, servoFree = 0.002; // Range servo,between servoL en servoR (= pulsewidth pwm servo) const double tControl = 0.05, tLcd = 2; // ticker time (sec) const double Fs = 200; //Sample frequency Hz double t = 1/ Fs; // time EMGticker double thresholdlowL= 0, thresholdmidL = 0, thresholdhighL= 0; double thresholdlowR= 0, thresholdmidR = 0, thresholdhighR= 0; double yL = 0, yR = 0; // y values EMG left and right volatile bool L = false, R = false; // Booleans for checking if mode. has been 1? volatile bool btn = false; // Button is pressed? volatile bool controlFlag = false, btnFlag = false, emgFlag = false, lcdFlag = false, runEmg = true; // Go flags bool boolBrake = false; //----------------------------Functions----------------------------------------------------------------------- void PRINT(const char* text){ lcd.cls(); // clear LCD scherm lcd.printf(text); // print text op lcd } void EMGkalibratieL(){ // Determine thresholds left PRINT("EMG LEFT relax muscle"); double ymin = KalibratieMin(emgL, true); // Minimum value left EMG, boolean indicates left wait(1); PRINT("EMG LEFT flex muscle"); // LCD double ymax = KalibratieMax(emgL, true); // Maxium value left EMG, boolean indicates left PRINT("EMG LEFT well done!"); // LCD if((ymax-ymin) < 0.05 || !runEmg){ // No EMG connected ymin = 10; ymax = 10; } thresholdlowL = 4 * ymin; // Lowest threshold thresholdmidL = 0.5 * ymax; // Midi threshold thresholdhighL = 0.8 * ymax; // Highest threshold pc.printf("ymaxL = %f en yminL = %f \r\n",ymax, ymin); } void EMGkalibratieR(){ // Determine thresholds right EMG, same as left PRINT("EMG RIGHT relax muscle"); double ymin = KalibratieMin(emgR, false); wait(1); PRINT("EMG RIGHT flex muscle"); double ymax = KalibratieMax(emgR, false); PRINT("EMG LEFT well done!"); if((ymax-ymin) < 0.05|| !runEmg){ ymin = 10; ymax = 10; } thresholdlowR = 4 * ymin; thresholdmidR = 0.5 * ymax; thresholdhighR = 0.8 * ymax; pc.printf("ymaxR = %f en yminR = %f \r\n",ymax, ymin); // terminal } int EMGfilter(AnalogIn& emg, bool side){ double u = emg.read(); // read emg signal (left or right EMG) int mode = 1; if(side){ double y = FilterdesignsLeft(u); // filter signal left EMG mode = Mode(modeL, y, thresholdlowL, thresholdmidL, thresholdhighL); // Determine mode with thresholds (1, 2, 3) } else { double y = FilterdesignsRight(u); mode = Mode(modeR, y, thresholdlowR, thresholdmidR, thresholdhighR); // right EMG } return mode; } int PotReader(AnalogIn& pot){ // read potentialmeter and determine its mode (1 = default, 2, 3) double volt = pot.read(); int mode = 1; if(volt > 0.8){ mode = 3; } else if(volt>0.35 && volt<0.65){ mode = 2; } return mode; } int defMode(AnalogIn& emg, AnalogIn& pot, bool side){ // Determine mode both from EMG and Potentialmeter, ONE of them must be ONE! int emgMode = EMGfilter(emg, side); int potMode = PotReader(pot); int mode = 1; if(!(emgMode==1) != !(potMode==1)){ // emgMode = 1 XOR potMode = 1 if(emgMode > potMode){ // maximum of emg and pot mode = emgMode; } else{ mode = potMode; } } return mode; } void setEmgFlag(){ // Goflag EMG emgFlag = true; } void setLcdFlag(){ // Goflag EMG lcdFlag = true; } void btnSetAction(){ // Set knop K64F btn = true; // GoFlag setknop } void emgOnOff(){ // Set knop K64F, push runEmg = !runEmg; // switch enable emg pc.printf("EMG is enabled: &i\r\n", runEmg); } void setControlFlag(){ // Go flag setButton controlFlag = true; } void checkSide(AnalogIn& ks, int dir){ if((dirM2.read() == dir) && (pwmM2.read()>0)){ // direction motor clashes with killswitch and motor is on if(ks.read()>0.8){ pwmM2.write(0); // Aim motor freeze pc.printf("BOEM! CRASH! KASTUK!\r\n"); // Terminal PRINT("BOEM! CRASH!"); // LCD } } } void checkAim(){ // check if killswitch clashes with direction motor checkSide(ksLeft, 1); checkSide(ksRight, 0); } void motorAim(int dir){ // Rotate Aim motor with given direction dirM2.write(dir); pwmM2.write(0.2); } bool controlAim(){ // Function to control aim motor with modes bool both = false; // boolean if both modes are 3 modeL = defMode(emgL, potL, true); // determine mode left modeR = defMode(emgR, potR, false); // determine mode right scope.set(0, modeL); scope.set(1, modeR); scope.send(); //send values to HIDScope if(modeR < 2 && !R){ // control if mode has been 1 R = true; } if(modeL < 2 && !L){ L = true; } if((modeL>2 && L) && (modeR >2 && R)) { // mode L and mode R both 3, and both has been 1 herefore both = true; // Return true pwmM2.write(0); // Aim motor freeze aimState = OFF; // next state } /*else if((modeR == 2 && R) && (modeL == 2 && L)) { // modes are both 2 both = true; // Return true pwmM2.write(0); // Aim motor freeze aimState = OFF; // next state }*/ else if((modeR == 2)) { // modeR ==2 if(aimState != CCW){ aimState = CCW; // Rotate CCW pc.printf("Rotate -, CCW\r\n"); PRINT("Rotate CCW"); motorAim(0); } } else if((modeL == 2)) { // modeL == 2 if(aimState != CW){ aimState = CW; // Rotate CW pc.printf("Rotate +, CW\r\n"); PRINT("Rotate CW"); motorAim(1); } } // modeR AND CCW OR modeL and CW else if((modeR == 1 && aimState == CCW) || (modeL == 1 && aimState == CW)) { // R=1 en CW pwmM2.write(0); // Aim motor freeze aimState = OFF; pc.printf("Freeze\r\n"); PRINT("Freeze"); } return both; } int main(){ btnSet.mode(PullUp); // Button mode btnSet.rise(&btnSetAction); // Connect button to function emgSet.mode(PullUp); // Button mode emgSet.rise(&emgOnOff); // Connect button to function tickerControl.attach(&setControlFlag,tControl); // ticker control motor EMGticker.attach(&setEmgFlag, t); // ticker EMG, 500H tickerLcd.attach(&setLcdFlag,tLcd); // ticker lcd pc.printf("\n\n\n\n\n"); // Terminal pc.printf("---NEW GAME---\r\n"); PRINT("--- NEW GAME ---"); // LCD while(1){ // Run program switch(state){ case CALIBRATE_EMG: { EMGkalibratieL(); // calibrate left EMG, determine thresholds EMGkalibratieR(); // calibrate right EMG, determine thresholds state = CALIBRATE_AIM; // Next state break; } case CALIBRATE_AIM: { pwmM2.period(1/100000); // period motor 2 printf("Position is kalibrating\r\n"); // terminal PRINT("Wait a moment, please"); // LCD dirM2.write(0); // direction aim motor pwmM2.write(0.2); // percentage motor power bool calibrated = false; // while(state==CALIBRATE_AIM){ if(controlFlag){ controlFlag = false; if(!calibrated){ // Not calibrated if((ksRight.read()>0.8)){ // Killswitch? pwmM2.write(0); // Aim motor freeze enc2.reset(); // Reset encoder PRINT("Aim calibrated"); // LCD pc.printf("Aim calibrated\r\n");// Terminal calibrated = true; pc.printf("Go to midi position\r\n"); dirM2.write(1); // direction aim motor pwmM2.write(0.2); // percentage motor power, turn it on } } if(calibrated) { // Calibrated checkAim(); // Check killswitches if(abs(enc2.getPulses()) > 600){ // rotate aim motor to midi position pwmM2.write(0); // Aim motor freeze state = CALIBRATE_BEAM; // next state } } } } break; } case CALIBRATE_BEAM: { pc.printf("Calibrate beam motor with setknop\r\n"); // Terminal dirM1.write(0); // direction beam motor pwmM1.period(1/100000); // period beam motor servo.period(0.02); // 20ms period servo btn = false; // Button is unpressed PRINT("Calibrate beam to 10 o'clock"); while(state==CALIBRATE_BEAM){ if(controlFlag){ pc.printf(""); // lege regel printen, anders doet setknop het niet controlFlag = false; if(btn){ // If setbutton is on or one mode is 3, and has been 1 enc1.reset(); // encoder 1 reset PRINT("Beam calibrated"); pc.printf("Beam calibrated\r\n"); btn = false; // button op false state = AIM; // next state } } } lcd.cls(); break; } case AIM: { pc.printf("Aim with EMG\r\n"); // terminal int i = 0; // counter for lcd R = false; L = false; while(state == AIM){ if(controlFlag){ // motor control on GoFlag controlFlag = false; checkAim(); // Check position } if(emgFlag){ // Go flag EMG sampel emgFlag = false; if(controlAim()){ pc.printf("Position chosen\r\n"); // terminal state = BREAK; // Next state (BREAK) } } if(lcdFlag){ // LCD loopje to project 3 texts on lcd lcdFlag = false; if(i%3 == 0){ PRINT("Flex left or right half to aim"); } else if(i%3 == 1){ PRINT("Flex both half to freeze"); } else { PRINT("Flex both full to continue"); } i++; } } lcd.cls(); break; } case BREAK: { pc.printf("Set break percentage, current is: %i\r\n", breakPerc); L = false; R = false; int i = 0; // counter for lcd PRINT("L := -1, R := +1 L+R = continue"); wait(1); while(state == BREAK){ if(emgFlag){ // Go flag EMG sampelen emgFlag = false; modeL = defMode(emgL, potL, true); modeR = defMode(emgR, potR, false); if((modeL > 1) && (modeR > 1) && L && R) { // both modes > 1 state = FIRE; } else if((modeL > 2 && L)|| (modeR > 2 && R)) { // left of right mode 3 = fire state = FIRE; } else { if(modeR < 2) { // modeR is 1 R = true; } if(modeL < 2) { // modeL is 1 L = true; } if(L && R){ // L and R has been 1 if((modeL == 2) && L) { // modeL = BREAK lower with one if(boolBrake){ boolBrake = false; } L = false; } else if((modeR == 2) && R) { // modeR = Break +1 if(!boolBrake){ boolBrake = true; } R = false; } if(modeL > 1 || modeR > 1){ // Print BREAK scale if one of both modes > 1 pc.printf("Current breaking scale: %i \r\n", boolBrake); } } } if(lcdFlag){ // every 2 seconds update lcd lcdFlag = false; lcd.cls(); lcd.printf("Break scale: %i", boolBrake); } } } PRINT("Break fixed"); // lcd pc.printf("Break fixed\r\n"); // terminal L = false; // modeL must be one for another action can take place R = false; // modeR "" lcd.cls(); break; } case FIRE: { pc.printf("Shooting\r\n"); // terminal PRINT("FIRING"); // lcd pwmM1.write(0.3); // beam motor on bool breaking = false; if(boolBrake){ servo.pulsewidth(servoBreak); // Servo to break position breaking = true; // boolean breaking? } //int countBreak = 2100*abs(breakPerc)/10; // Amount of counts where must be breaked while(state == FIRE){ // while in FIRE state if(controlFlag){ // BREAK goFlag half rotation beam = breaking controlFlag = false; // GoFlag int counts = abs(enc1.getPulses())+250; // counts encoder beam, +250 is to correct 10 to 12 o'clock // encoder is 0 on 100 counts before 12 o'clock if(breaking && boolBrake){ if((counts+2100)%4200 < 100){ servo.pulsewidth(servoFree); // Servo to free position breaking = false; } } if(!breaking || !boolBrake){ // Not breaking if((counts-100)%4200 < 100){ // rotated 1 rev? pwmM1.write(0); // motor beam off pc.printf("Beam on startposition\r\n"); // terminal state = AIM; // Next stage } } } } lcd.cls(); break; } } } }