Remote Controlled Robot
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--; } }