Skip to content

Software: PC

campbeb6 edited this page May 9, 2016 · 6 revisions

All of the Processing code can be found here: LINK


How It Works

The main job of the processing program is to create the user interface. The processing code creates the GUI, and also controls when instructions are executed by the robot. The code draws the interface based on global variables that change based on the state of the GUI, and the users selections. I would recommend looking up the interface before trying to understand this code. For more information on the interface and its functionality, go here: LINK

To see it in action: LINK


Global Variables

The GUI employs multiple global variables to properly run and display things to the user. There are two global ArrayLists that store the list of instructions the user has created to send to the robot, as well as to track the instructions as they are being executed:

ArrayList<Integer> operations = new ArrayList<Integer>();
ArrayList<Integer> program    = new ArrayList<Integer>();

If the mouse is pressed, the mousePressed() function is called, and data from the mouses location is stored in global variables in order to determine if the user has touched one of the buttons:

int xPos = 0;
int yPos = 0; 
boolean clicked = false; //tells if the user has clicked the mouse;

void mousePressed(){
   xPos = mouseX;
   yPos = mouseY;
   clicked = true;
} 

There are variables that have to do with the location and size of all the buttons:

int[] buttonX = { 250, 250, 150, 350,  1,  1,   1};
int[] buttonY = {  75, 275, 175, 175,  0, 51, 102};
int buttonSize = 50;

There is a variable that keeps track of the current state of the GUI, this variable is important for preventing the user from performing certain actions if the GUI is in certain states; for instance, the user can only add more instructions to the program if the GUI is in the "STOPPED" state:

final int STOPPED = 1;
final int RUNNING = 2;
final int PAUSED = 3;

int state = STOPPED;

Changing the Globals, and Conditions

The user's tool for using the interface is the mouse. Whenever the mouse is pressed, the program must determine if the user has selected a button, and what to do if they have selected a button. In some conditions, pressing a button does nothing. There is a method that determines whether a button is pressed:

void getOperation(){
  int op = 0;  
    for(int i = 0; i < buttonX.length; i++){
        if(mouseX >= buttonX[i] && mouseX < (buttonX[i] + buttonSize)){
          if(mouseY > buttonY[i] && mouseY < (buttonY[i] + buttonSize)){
              op = i + 1;
              if(op < 5 && state == STOPPED){
                program.add(op);
                operations.add(op);
                drawOpList();
                drawProgram();
              }
          } 
        }  
     }
     handleOp(op);
     clicked = false;
}

This method determines if a button is pressed using the location and size of each of the buttons along with the mouse data. If a button is pressed, the buttons number is saved in int op. Buttons 1-4 are the four directional buttons for the simplistic reasons. See Robot Code Breakdown. The handleOp() function is a helper method that handles all of the conditions:

void handleOp(int op){
   if(op == 5 && state == STOPPED){
     state = RUNNING;
     drawOpList();
   } 
   else if(op == 5){
     state = RUNNING;
   } 
   else if(op == 6 && state == RUNNING){
     state = PAUSED;
   } 
   else if(op == 7 && state == STOPPED){
       operations.clear();
       program.clear();
       drawOpList();
       drawProgram();
   } 
   else if(op == 7){
     state = STOPPED; 
     operations.clear();
     copyOp();
     drawOpList();
   } 
}

The draw() method in processing is similar to the loop() method in arduino language. Here we loop through the code, checking 2 things, if the mouse has been clicked, and if the state is "RUNNING". if the mouse is clicked, then we need to check if it hit a button and all of our conditions, if the state is "RUNNING", we need to check if we can send our next instruction from the operations ArrayList to the robot. sendValue() is shown in the Serial section below:

void draw(){  
  drawState();
  if(clicked){
     getOperation(); 
  }
  
  if(state == RUNNING){
      if(operations.size() == 0){
         state = STOPPED; 
         operations.clear();
         copyOp();
         drawOpList();
      } 
      else {
        sendValue();
      }  
  }   
}

Serial Data

The processing sketch connects to the bluetooth module via the serial COM ports on the PC, processing has a very easy way to access these ports.

printArray(Serial.list());
myPort = new Serial(this, "COM15", 9600); 

Serial.list() shows all of the serial ports currently available

"COM15" is the name of the port where the bluetooth module is

now, we can easily send serial data to the bluetooth module in a way very similar to the arduino language

myPort.write('f');

we send a character to the arduino when the interface is booted up in order to make sure that it is ready to receive instructions. The arduino will send a byte of data, more specifically, a 7, to notify that it is prepared to execute instructions. The interface will not send values if a 7 is not read from the serial buffer.

void sendValue(){
  if(myPort.available() > 0 && operations.size() > 0){ //if there is serial data available and there is data to send
    if(myPort.read() == 7){
      delay(1000);
      myPort.write(operations.get(0)); //send value
      operations.remove(0);
      delay(20);
      drawOpList();
    }
  }
}

above is the method that sends the instructions to the arduino, notice the conditional that will not send data unless a 7 is detected.


Drawing the interface

Helper methods found here employ the use of basic methods from the processing reference to draw the interface. The interface changes based on global variables that store the current state of the interface, the current program created by the user, as well as the current operations that are left to execute.

void drawButtons(){

draws the "buttons" that the user uses to control the interface. These bounds of theses buttons are represented by a white rectangle, and their locations and size are stored in Global variables. The buttons' shapes are drawn on top of their buttons, the shapes are stored as .svg files in the data folder, and are loaded into PShape objects when the GUI starts up:

PShape play;
play = loadShape("play.svg");

The current "program" and "operations" global ArrayLists are drawn using:

void drawProgram(){
void drawOpList(){

These methods are called whenever the lists change, and are necessary so the user can have feedback on what is going on within the GUI.


Clone this wiki locally