Giles Barton-Owen
/
MbedRanger
Allows the M3Pi to be used as a Sumo robot, using the sharp 100 distance sensors on the front.
main.cpp
- Committer:
- p07gbar
- Date:
- 2012-03-14
- Revision:
- 0:342c14fb10c0
File content as of revision 0:342c14fb10c0:
/** Author: Giles Barton-Owen Name: mbed ranger Description: This program keeps a m3pi inside a ring, and has 6 (4 Active) different game modes. It relies on a Sharp Digital Distance sensor (GP2Y0D810) attached to pin 30 and 11 (the two headers on the right and left of the board). The system refreshes at 10Hz when it reads the line sensors on the 3pi and the distance states. The states are then handled in a big FSM to reach the conclusions. To keep the robot saving itself for longer a timeout was programmed, such that the robot belives itself on a line (as was reported when the timeout was set) until 0.3 seconds has elapsed. This could be adjusted. The fore-ground loop just switches the LEDs on the board as instructed. The current state of the robot is reported on line 2 of the LCD screen on the 3pi, displaying first mode and the last character being line detection state (none, front, back). **/ #include "mbed.h" #include "SharpDigiDist100.h" #include "m3pi.h" DigitalOut Left[2] = {LED1,LED2}; //Some indicator LEDs for the range finders DigitalOut Right[2] = {LED4,LED3}; SharpDigiDist100 right(p30); // The range finder class initialisations SharpDigiDist100 left(p11); m3pi m3pi; // Initialise the m3pi InterruptIn button(p21); // SW1 on the shield, for stratergy switching Ticker guidance; // The main guidance caller Serial pc(USBTX, USBRX); // For debugging and pc messages, uses commented out to prevent hanging Timer debounce; // To debounce the switch int previousLine; // A set of variables to sort out the line detection, previousLine is pretty much not used int isLine; int lineCatch; Timeout liner; // A timeout to stop it ignoring the line void CycleMode(); // Function defs void guideCall(); void clearLiner(); enum Stratergies { // The enum for stratergies Off, Dormant, RunMid, RunNear, AttackMid, AttackFar, Hunt }; void updateScreen(int line, enum Stratergies stratergy); enum Stratergies stratMode = Off; // The current stratergy int main() { guidance.attach(&guideCall,0.1); // Sets up the control loop button.mode(PullUp); // Sets the internal pull up on SW1 button.fall(&CycleMode); // Attaches an interupt for when it is pressed m3pi.locate(0,0); // Write the name to the screen m3pi.printf("m3PiRngr"); m3pi.get_white_levels(); // Saves the current levels of the sensors to know what is white debounce.start(); // Starts the debounce timer so that the switch thinks it isnt a bounce first time //pc.printf("\n\n\rMbedRanger\n\r"); // Prints a hello to the computer while (1) { //pc.printf("Loop\n\r"); switch (right.getDistance()) { // Sets up the distance indicator LEDs for the right side case SharpDigiDist100::Far : Right[0] = true; Right[1] = false; break; case SharpDigiDist100::Near : Right[1] = true; Right[0] = false; break; case SharpDigiDist100::Mid : Right[0] = true; Right[1] = true; break; default: break; } switch (left.getDistance()) { // Sets up the distance indicator LEDs for the left side case SharpDigiDist100::Far : Left[0] = true; Left[1] = false; break; case SharpDigiDist100::Near : Left[1] = true; Left[0] = false; break; case SharpDigiDist100::Mid : Left[0] = true; Left[1] = true; break; default: break; } /*int calibrated[5]; m3pi.get_raw_sensors(calibrated); pc.printf("Sensors read:"); for (int i = 0; i<5;i++) { pc.printf(" %i ",calibrated[i]); } if (m3pi.is_line() > 0) { pc.printf("LINE"); m3pi.locate(0,1); m3pi.printf("LINE"); } pc.printf("\n\r"); wait(0.1);*/ } } void CycleMode() { // Cycles through the modes, probably could have written this with a simple ++ statement... debounce.stop(); // Stops and reads the timer since the last press of the button if (debounce.read_ms() > 100) { // If it was more than 100ms ago it treats it as a button press, otherwise it just ignores it switch (stratMode) { case Off: stratMode = Dormant; m3pi.locate(0,1); m3pi.printf("\nDormant "); break; case Dormant: stratMode = RunMid; m3pi.locate(0,1); m3pi.printf("\nRunMid "); break; case RunMid: stratMode = RunNear; m3pi.locate(0,1); m3pi.printf("\nRunNear "); break; case RunNear: stratMode = AttackMid; m3pi.locate(0,1); m3pi.printf("\nTakNear "); break; case AttackMid: stratMode = AttackFar; m3pi.locate(0,1); m3pi.printf("\nTakFar "); break; case AttackFar: stratMode = Hunt; m3pi.locate(0,1); m3pi.printf("\nHUNTING! "); break; case Hunt: stratMode = Off; m3pi.printf("\nOFF "); break; } } debounce.reset(); debounce.start(); } void guideCall() { isLine = m3pi.is_line(); // Gets whether the m3pi is on a line, and if so front/back if (lineCatch == 0) { // Has it been off a line for long enough? isLine = isLine; // Yes - then go ahead } else { isLine = lineCatch; // No - pretend to still be on that line } float position; switch (isLine) { case 0: // No line, not even recently so go ahead with the stratergies updateScreen(isLine, stratMode); bool atRight = false; bool atLeft = false; switch (stratMode) { case Off: // No motors case Dormant: // Will take action against lines though m3pi.stop(); break; case RunNear: // Runs if something is near if (right.getDistance() == SharpDigiDist100::Near) { atRight = true; } else atRight = false; if (left.getDistance() == SharpDigiDist100::Near) { atLeft = true; } else atLeft = false; case RunMid: // Runs if something is in the middle distance if (right.getDistance() == SharpDigiDist100::Mid) { atRight = true; } if (left.getDistance() == SharpDigiDist100::Mid) { atLeft = true; } if (atRight && atLeft) { m3pi.backward(0.5); } else { if (atRight == true) { m3pi.left_motor(-0.3); m3pi.right_motor(-0.5); } else { if (atLeft == true) { m3pi.left_motor(-0.5); m3pi.right_motor(-0.3); } else { m3pi.stop(); } } } break; case AttackMid: // Attacks something in the middle distance if (right.getDistance() == SharpDigiDist100::Mid) { atRight = true; } if (left.getDistance() == SharpDigiDist100::Mid) { atLeft = true; } if (atRight && atLeft) { m3pi.forward(0.6); } else { if (atRight == true) { m3pi.left_motor(0.5); m3pi.right_motor(0.7); } else { if (atLeft == true) { m3pi.left_motor(0.7); m3pi.right_motor(0.5); } else { m3pi.stop(); } } } if (right.getDistance() == SharpDigiDist100::Near) { atRight = true; } else atRight = false; if (left.getDistance() == SharpDigiDist100::Near) { atLeft = true; } else atLeft = false; if (atRight && atLeft) { m3pi.forward(0.5); } else { if (atRight == true) { m3pi.left_motor(0.1); m3pi.right_motor(0.2); } else { if (atLeft == true) { m3pi.left_motor(0.2); m3pi.right_motor(0.1); } } } break; case AttackFar: break; case Hunt: // Runs forward until something is really close if (right.getDistance() == SharpDigiDist100::Mid || right.getDistance() == SharpDigiDist100::Near) { atRight = true; } else atRight = false; if (left.getDistance() == SharpDigiDist100::Mid || left.getDistance() == SharpDigiDist100::Near) { atLeft = true; } else atLeft = false; if (atRight && atLeft) { m3pi.stop(); } else { if (atRight == true) { m3pi.left_motor(0.1); m3pi.right_motor(0.2); } else { if (atLeft == true) { m3pi.left_motor(0.2); m3pi.right_motor(0.1); } else { m3pi.forward(0.3); } } } break; default: break; } break; case 1: // Line in front, reverse if(stratMode != Off) { if (lineCatch == 0) { lineCatch = 1; liner.attach(&clearLiner, 0.3); } position = m3pi.line_position(); if (position < 0) { m3pi.left_motor(-1); m3pi.right_motor(-0.8); } else if (position == 0) { m3pi.backward(1); } else if (position > 0) { m3pi.left_motor(-0.8); m3pi.right_motor(-1); } //m3pi.locate(0,1); //m3pi.printf("LINE_FWD"); } else { m3pi.stop(); } updateScreen(isLine, stratMode); break; case -1: // Line behind, forward if(stratMode != Off) { if (lineCatch == 0) { lineCatch = -1; liner.attach(&clearLiner, 0.3); } position = m3pi.line_position(); if (position < 0) { m3pi.left_motor(1); m3pi.right_motor(0.8); } else if (position == 0) { m3pi.forward(1); } else if (position > 0) { m3pi.left_motor(0.8); m3pi.right_motor(1); } } else { m3pi.stop(); } //m3pi.locate(0,1); //m3pi.printf("LINE_BKD"); updateScreen(isLine, stratMode); break; } //previousLine = isLine; } void clearLiner() { // Gets called a bit after a line is detected lineCatch = 0; //pc.printf("Cleared liner\n\r"); } void updateScreen(int line, enum Stratergies stratergy) { // Update the bottom line with the running info m3pi.locate(0,1); char lineState; switch (line) { case 0: lineState = 'N'; break; case 1: lineState = 'F'; break; case -1: lineState = 'B'; break; default: break; } char strat[6]; switch (stratergy) { case Off: sprintf(strat,"OFF "); break; case Dormant: sprintf(strat,"DORMNT"); break; case RunMid: sprintf(strat,"RUNMID"); break; case RunNear: sprintf(strat,"RNNEAR"); break; case AttackMid: sprintf(strat,"TAKMID"); break; case AttackFar: sprintf(strat,"TAKFAR"); break; case Hunt: sprintf(strat,"HUNTER"); break; } m3pi.printf("%s %c",strat,lineState); }