Remote Controlled Robot

The MATLAB gui of the robot. The associated script is shared below.

The MATLAB gui for the control scheme. The associated script is shared below.

The goal of the robot is to navigate along a white tape ,on a black floor , using whatever method a design group finds fit as long as it uses the provided parts. Parts included a Sparkfun sensor kit, NXT pieces, an Arduino microcontroller, X-Bee wireless adapters and a 9V rechargeable battery.

My group and I initially tried to use a line sensor but we were not very successful — it worked fine on the breadboard, but not on a soldered circuit board. Running out of time to debug the problem, our final decision was to include a human in the closed loop — remote controlled robot via X-Bee.

I configured the X-Bee and designed the controls of the robot from Steering, Backward , Forward and Stopping movements.

    The final control system was in two parts;

  • MATLAB.m GUI
  • Arduino.pde which readable by the Arduino IDE

For help configuring the X-Bee, visit this page

Results

I successfully drove the robot around the baseball field within the required time of 2.5 mins.

 

Class Lab project – Controls course
Time line Spring 2011

MATLAB Script

% jonah kadoko,
% this is the the code that will control the robot

% this is the function that does the setting up of the
% setting up the serial communication
close all
s1=serial('COM3','Baudrate',9600);
fopen(s1);
%Pause to make sure the port is open before we start using it:
pause(3)
setpoint='1';
%draw the User interface
% this is are the controls of the robot
control=0;
% 0 is forward, 1 is backward, 3 start, 4 is stop
forward=0;
backward=1;
start=3;
stop=4;
defaultControl=10;

val=0;
figure
direc=0;
pos=90;
% setting up the slider
sliderBar=uicontrol('Style', 'slider',...
    'Min',1,'Max',255,'Value',90,...
    'Position', [100-pos 200 600 40],...
    'Callback','direc=0');
stopButtonAll = uicontrol('Style', 'pushbutton', 'String', 'Stop Comm','Position', [500-pos 250 95 30], 'Callback', 'd=0;');
forwardButton = uicontrol('Style', 'pushbutton', 'String', 'Forward','Position', [200-pos 250 95 30], 'Callback', 'control=forward;');
backwardButton = uicontrol('Style', 'pushbutton', 'String', 'Backward','Position', [300-pos 250 95 30], 'Callback', 'control=backward;');
startButton = uicontrol('Style', 'pushbutton', 'String', 'Start Robot','Position', [100-pos 250 95 30], 'Callback', 'control=start;');
stopButton = uicontrol('Style', 'pushbutton', 'String', 'Stop Robot','Position', [400-pos 250 95 30], 'Callback', 'control=stop;');
runButton= uicontrol('Style', 'pushbutton', 'String', 'Run','Position', [600-pos 250 95 30], 'Callback', 'controllingrobot');
d=1;
while (d==1)


    %Get the value of the string from the set(sliderBar,'Value');
    disp(val);
    val = 128 - get(sliderBar,'Value');
    setpoint=num2str(val);

    switch control
        case start
            fprintf(s1,'S%s'); % this will start the robot
            control=defaultControl;
            fprintf(s1,'D%s',setpoint);
            disp('start')
        case forward
            set(sliderBar,'Value',128);
            control=defaultControl;
            disp('defaultcontrol')
        case backward
            fprintf(s1,'B%s');
            disp('backward')
        case stop
            fprintf(s1,'X%s');
            disp('stop')
        otherwise
            fprintf(s1,'D%s',setpoint);
    end

    if (forward==1)

    end
    %Pause so we don't bug the arduino too often; the control loop is still
    %running on the Arduino, its just we only send an updated setpoint or
    %ask for the current data every 50 ms:
    pause(0.05)
end

%Tell the arduino to zero everything

fprintf(s1,'R');

%Close the serial port:
fclose(s1)

Arduino sketch

// jonah kadoko,
// this is the main program that runs the arduino
// will use state machines to attack this problem
// first of all lets do the first things first,
// make a class for different hardware components
#include <stdlib.h>
#include <stdio.h>

//Motor definations:
#define Aleft  2
#define Bleft  6
#define Aright  3
#define Bright  8
/* the original code
  #define Aleft  3
  #define Bleft  8
  #define Aright  2
  #define Bright  6
*/
enum Direction {
  Backward = LOW, Forward = HIGH
};

class Motor
{
  public:
    Motor()
    {
      pinDir = -1;
      pinSpeed = -1;
    }

    void attach(int pinDir0, int pinSpeed0)
    {
      pinMode(pinDir0, OUTPUT);
      pinMode(pinSpeed0, OUTPUT);
      pinDir = pinDir0;
      pinSpeed = pinSpeed0;
    }

    void write(Direction dir, int speed)
    {
      digitalWrite(pinDir, dir);
      analogWrite(pinSpeed, speed);
    }

  private:
    int pinDir;
    int pinSpeed;
};
//declaring the motors
Motor motorLeft, motorRight;
int positionRight = 0;
int positionLeft = 0;
long int speedLeft = 0, speedRight = 0; //drive to send to the motor (PWM counts)

// states
int state = 0;
const int start = 1;
const int forward = 2;
const int backward = 3;
const int stopState = 0;
const int drive = 5;
float setpoint = 0; //setpoint from computer via serial port
int n = 0;
char serial_string[15]; //read from serial port


void setup()
{
  Serial.begin(9600);
  // Attach wheel motors.
  motorLeft.attach(13, 11);// you should  change this as the inturupt changes
  // motorLeft.attach(12, 5);// you should  change this as the inturupt changes original
  // motorLeft.write(Backward, 100);
  motorRight.attach(12, 5 );
  // motorRight.attach(13,11 ); original
  // motorRight.write(Backward, 100);
  // attach the encoders
  attachInterrupt(0, doEncoderRight, CHANGE);
  attachInterrupt(1, doEncoderLeft, CHANGE);

}

void loop()
{
  // testing the motors
  Serial.print(positionLeft );
  Serial.print("   ");
  Serial.println(positionRight);

  if (Serial.available() > 0) {
    n = 0;
    delay(1);
    while (Serial.available() > 0) {
      serial_string[n] = Serial.read(); //Sent this from Matlab
      n++;
    }

    if (serial_string[0] == 'D') //in this case Matlab sent a setpoint
    {
      //Convert the string to an float:
      setpoint = strtod(&serial_string[1], NULL);
      state = drive;
      //Clear out the string for next time:
      for (n = 0; n < 15; n++)
        serial_string[n] = ' ';
    }

    else if (serial_string[0] == 'B') //in this case Matlab sent a proportional gain
    {
      state = backward;
      //Clear out the string for next time:
      for (n = 0; n < 15; n++)
        serial_string[n] = ' ';
    }
    else if (serial_string[0] == 'X') //in this case Matlab sent an integral gain
    {
      state = stopState;
      //Clear out the string for next time:
      for (n = 0; n < 15; n++)
        serial_string[n] = ' ';
    }
    else if (serial_string[0] == 'D') //in this case Matlab sent a derivative gain
    {

      //Clear out the string for next time:
      for (n = 0; n < 15; n++)
        serial_string[n] = ' ';
    }

    else if (serial_string[0] == 'R') //in this case Matlab said to reset everything
    {

      //Clear out the string for next time:
      for (n = 0; n < 15; n++)
        serial_string[n] = ' ';
    }
  }
  switch (state)
  {
    case start:
      state = drive;
      Serial.println("start");
      break;
    case stopState:
      motorLeft.write(Forward, 0);
      motorRight.write(Forward, 0);
      Serial.println("stop");

      break;
    case backward:
      motorLeft.write(Backward, 255);
      motorRight.write(Backward, 255);
      Serial.println ("backward");
      break;
    case drive:
      Serial.println("drive");
      // saturating the pwm
      if ((speedLeft > 255) || (speedRight > 255))
      {
        speedLeft = 255;
        speedRight = 255;
      }
      else if ((speedLeft < -255) || (speedRight < -255))
      {
        speedLeft = -255;
        speedRight = -255;
      }
      //Write out to motor and get direction signal correct:
      if ((speedLeft < 0) || (speedRight < 0)) {
        speedLeft = 0;
        speedRight = 0;
      }

      // the communication fro matlab

      speedLeft = 128 + setpoint;
      speedRight = 128 - setpoint;
      // drive the motor
      motorLeft.write(Forward, speedLeft);
      motorRight.write(Forward, speedRight);
      break;
  }
}

/**************************************************************************************/

void doEncoderRight()
{

  if (digitalRead(Aright) == digitalRead(Bright))
  {
    positionRight++;
  }
  else {
    positionRight--;
  }
}

void doEncoderLeft()
{
  if (digitalRead(Aleft) == digitalRead(Bleft)) {
    positionLeft++;
  }
  else
  {
    positionLeft--;
  }
}