Zumo 32U4 – Using the Buttons the Select a Start Move

This post discusses one way to handle setting up the Zumo to perform one of three initial moves prior to entering the main body of the program.  If you go back a couple of posts, we discussed the simple state machine for a sumo competition.  In the setup, there was a section for the initial move.  The initial move is the first move you want your robot to make prior to entering the state machine and following a preset algorithm.  This could be a fixed move, in which case, you can ignore this post.  However, you may decide you want to have your robot do a different initial move based on how your competitor is set up, or in the case of BottleSumo, where the bottle is located.  In this case, you often don’t know these conditions until you are set up at the table, ready to go.

This post describes a way that you can use the three buttons to select a particular first move.  So far, we’ve only used the buttons to wait until you press a button.  In this case, we need to record the action we want to take, wait for a button, then take that action.

The basic flow is:

  1. Check to see if any of the three buttons are pressed.
  2. If a button is pressed, record which one.
  3. Go to step 1 if no button is pressed, if not, proceed to step 4.
  4. Wait until button A is pressed to signal the start of the match.
  5. Execute the option selected from step 2.
  6. Proceed to normal state machine.

To make it easier, I like to use the enum function to define a data type.  You cold simply use an integer to represent button A, B, and C, but why not use the actually button name?  Defining the datatype with enum is done as below:

enum ButtonChoice       // Create datatype for the button label.
{
  A,
  B,
  C
}; 

This creates a datatype  named ButtonChoice that allows values of A, B, and C.  The next step is to continuously check the buttons until one is pressed.  For this, you will need a Boolean variable to store whether or not a button has been pressed.  It gets initialized to false, as a button has not been pressed at the beginning.  As usual, I always think it is a good idea to give the user feedback by prompting on the LCD and providing beeps to know if you have pressed a button.

bool buttonPressed = false;       // Boolean whether or not a button has been pressed.
ButtonChoice buttonSelected;      // variable to store which button was pressed.

// Prompt User and Wait for Button.  Record which button is pressed.
  lcd.clear();
  lcd.gotoXY(1, 0);
  lcd.print("Press:");
  lcd.gotoXY(0, 1);
  lcd.print("A  B  C");
  do {
    if (buttonA.isPressed()) {
      buttonSelected = A;
      buttonPressed = true;
      buzzer.playFrequency(300, 200, 15);
    }
    if (buttonB.isPressed()) {
      buttonSelected = B;
      buttonPressed = true;
      buzzer.playFrequency(440, 200, 15);
    }
    if (buttonC.isPressed()) {
      buttonSelected = C;
      buttonPressed = true;
      buzzer.playFrequency(600, 200, 15);
    }
  } while (!buttonPressed); 

At this point, you’ve selected with variant you want to run, you just need to wait till you press the button to start, and run the first move.  for this example, I made the first move options very simple.  If A is pressed, the robot moves forward, if B is pressed, the robot moves backwards, and if C is pressed, the robot turns.  In practice, you probably want something more specific, like targeting a region of the table, moving out of the way, etc.

// Wait for button and execute the selection.
lcd.clear();
lcd.print("Press A");
lcd.gotoXY(0, 1);
lcd.print("to Go!");
buttonA.waitForButton();
buzzer.playFrequency(440, 50, 15);
lcd.clear();

switch (buttonSelected) {
  case A:
    lcd.print("Case A");
    motors.setSpeeds(200, 200);
    delay(1000);
    motors.setSpeeds(0, 0);
    break;
  case B:
    lcd.print("Case B");
    motors.setSpeeds(-200, -200);
    delay(1000);
    motors.setSpeeds(0, 0);
    break;
  case C:
    lcd.print("Case C");
    motors.setSpeeds(-200,200);
    delay(1000);
    motors.setSpeeds(0,0);
    break;
}  

When putting this into your sumo state machine, you will clearly have to add other items such as the initial state to start in, light sensor calibrations, initializations, etc.  Putting the whole example program together:

#include <Zumo32U4.h>
Zumo32U4LCD lcd;
Zumo32U4Motors motors;
Zumo32U4ButtonA buttonA;
Zumo32U4ButtonB buttonB;
Zumo32U4ButtonC buttonC;
Zumo32U4Buzzer buzzer;

enum ButtonChoice       // Create datatype for the button label.
{
  A,
  B,
  C
};

void setup() {
  bool buttonPressed = false;       // Boolean whether or not a button has been pressed.
  ButtonChoice buttonSelected;      // variable to store which button was pressed.

  // Prompt User and Wait for Button.  Record which button is pressed. 
  lcd.clear(); 
  lcd.gotoXY(1, 0); 
  lcd.print("Press:"); 
  lcd.gotoXY(0, 1); 
  lcd.print("A  B  C"); 
  do { 
    if (buttonA.isPressed()) { 
      buttonSelected = A; 
      buttonPressed = true; 
      buzzer.playFrequency(300, 200, 15); 
    } 
    if (buttonB.isPressed()) { 
      buttonSelected = B; 
      buttonPressed = true; 
      buzzer.playFrequency(440, 200, 15); 
    } 
    if (buttonC.isPressed()) { 
      buttonSelected = C; 
      buttonPressed = true; 
      buzzer.playFrequency(600, 200, 15); 
    } 
  } while (!buttonPressed); 
  delay(500);   
  
  // Wait for button and execute the selection. 
  lcd.clear(); 
  lcd.print("Press A"); 
  lcd.gotoXY(0, 1); 
  lcd.print("to Go!"); 
  buttonA.waitForButton(); 
  buzzer.playFrequency(440, 50, 15); 
  lcd.clear(); 
  
  switch (buttonSelected) { 
    case A: 
      lcd.print("Case A"); 
      motors.setSpeeds(200, 200); 
      delay(1000); 
      motors.setSpeeds(0, 0); 
      break; 
    case B: 
      lcd.print("Case B"); 
      motors.setSpeeds(-200, -200); 
      delay(1000); 
      motors.setSpeeds(0, 0); 
      break;     
    case C: 
      lcd.print("Case C"); 
      motors.setSpeeds(-200,200); 
      delay(1000); 
      motors.setSpeeds(0,0); 
      break; 
  } 
} 

void loop() { 
  // Put the rest of the state machine here. 
} 
 In addition to the three options, you could make the menu go deeper into other options.  It might be something like A means go forward, then have another menu for how far forward.  This would essentially allow you to call an audible at the start time to keep your opponents guessing what your robot will do.
This entry was posted in Robotics and tagged , , . Bookmark the permalink.