Tuesday, September 2, 2014

Make a Web Connected Robot (for about $500) (using an Arduino and Netbook) [Full Tutorial]

This Instructable will show you how to build your own Web Connected Robot (using an Arduino micro-controller and Asus eee pc).

Why would you want a Web Connected Robot? To play with of course. Drive your robot from across the room or across the country, using nothing more than Skype and a web browser (nothing to install on the controlling computer). After that? Dig into the software & adapt it however you like, add a GPS so you can watch where you're driving on a map, add temperature sensors to map temperature gradients in your house, or sonar sensors to add controls on what you're web drivers can and cannot run into.

Features:
  • Inexpensive - (~$500 if you purchase all parts new and considerably cheaper if you dig around in your parts bin)
  • Once up and running controlling the robot requires only a web browser - (and Skype if you want to see where you're driving)
  • Open Source and Easily Adaptable - (uses an Arduino micro-controller, Processing for the web server & all software can be run on Linux (all the code is also heavily commented to make jumping in and changing things easy))
  • Modular Design (not a completely integrated system, if you want to use a different video conferencing service no worries, or if you have a Basic stamp rather than an Arduino just right a small piece of code and slot it in)
Here's a quick video of my Web Connected Robot being driven out of the kitchen.

Step 1: Parts & Tools

Only a few parts are required:

Robot: Arduino Controlled Servo Robot - (SERB)
($175 @ oomlout.com ) or (make your own)
  • An open source robot which uses an Arduino micro-controller as it's brain.
(any dual servo robot platform with an arduino can be used (option 1) (please message me if you discover any other options)

Computer: Asus eee PC 4G
($280) (@Best Buy)
  • A small inexpensive laptop that is perfect for this purpose.
(any laptop (or desktop if you want to run with a chord) capable of running Processing sketches can be used)

Laptop Desk: Laser Cut Acrylic
($25 (@ oomlout) ) or (build your own step 3)
  • A few additional acrylic pieces which bolt onto a (SERB) to give it a desk for the laptop to sit on.
Nuts and Bols: (available at home depot)
  • 3mm x 10mm bolt (x4)
  • 3mm x 15mm bolt (x4)
  • 3mm nut (x8)

Step 2: Cutting Pieces & Assembly

There are three options for getting pieces for your laptop desk.

Cutting

Option 1: (Purchasing from oomlout.com)
  • laser cut desk pieces and the neccesary hardware are available from oomlout for $25 (here)
Option 2: (Cutting on your own laser cutter or Ponoko.com)
  • Download the file below (03-WEBB-Acrylic Parts.cdr or 03-WEBB-Acrylic Parts (Ponoko P2).eps)
  • Cut them from 3mm (1/8") Acrylic
Option 3: (Scroll Saw)
  • Download the scroll saw pattern from below (03-WEBB-ScrollSaw Pattern (A4).pdf (for A4 size paper) or 03-WEBB-ScrollSaw Pattern (letter).pdf (for letter sized paper))
  • Double check that it hasn't been scaled when printing (by measuring the printed rulers)
  • Glue to a piece of 3mm (1/8") acrylic and cut the pieces out.
Assembling:

Download the assembly guide (04-WEBB-Assembly Guide.pdf) below and put the laptop desk together.

Step 3: Software - (Arduino)

For those new to Arduino check out the great getting started guide at Arduino.cc

First off the software running on the Arduino. It is a very simple program, what the Arduino does is monitor its serial port for data.

What it is looking for is a conversation 5 bytes long.
  • Byte 1-3 (Check bytes "AAA")
  • Byte 4 Command (Tells the arduino what to do) (Supported commands 'F' - Forward, 'B' - Backward, 'L' - Left, 'R' - Right, 'S' - Speed, 'X' - SetSpeedLeft, 'Y' - SetSpeedRight, 'C' - Stop)
  • Byte 5 Parameter - For the move commands this is interpretted as a time interval (Parameter * 100 ms), and for the speed commands a percentage from 0-100
The code is commented thoroughly and given this framework adding additional commands should be easy.

To Download:
  • Download the attached zip file. (05-WEBB-Arduino Code.zip)
  • Unzip to your Arduino Sketch directory. (default: My Documents\Arduino\)
  • Open your arduino development enviroment and upload to your Arduino.
To Copy and Paste
  • Copy the code from below.
  • Paste into the Arduino development environment.
  • Upload to your Arduino.
Appendix: The Arduino Program
/* * Arduino Controlled Web Connected Robot (WEBB) - Serial Host * For more details visit: http://www.oomlout.com/serb  *  * Behaviour: The Arduino listens to its Serial port for a command *            in format 254, 88, 88, (COMMAND), (TIME) *            Supported Commands - 'F' - 70 - Forward *                                 'B' - 66 - Backward *                                 'L' - 76 - Left *                                 'R' - 82 - Right *                                 'S' - 83 - Speed *                                 'X' - 88 - SetSpeedLeft *                                 'Y' - 89 - SetSpeedRight  *                                 'C' - 67 - Stop  *            Supported Times - 0 - 255 (0 to 25.5 Seconds) value * 100 milliseconds  *sp * Wiring: Right Servo Signal - pin 9 *         Left Servo Signal - pin 10  * * License: This work is licenced under the Creative Commons  *          Attribution-Share Alike 3.0 Unported License. To  *          view a copy of this licence, visit  *          http://creativecommons.org/licenses/by-sa/3.0/  *          or send a letter to Creative Commons, 171 Second  *          Street, Suite 300, San Francisco, California 94105,  *          USA. *         */  //-------------------------------------------------------------------------//START OF ARDUINO SERIAL SERVER PREAMBLE//Defining constants corresponding to each command (also the ascii code number) #define FORWARD 70       //F#define BACKWARD 66      //B#define LEFT 76          //L#define RIGHT 82         //R#define SETSPEED 83         //S#define STOP 67          //C#define SETSPEEDLEFT 88  //X#define SETSPEEDRIGHT 89 //Y/*The three check bytes (used to keep the robot from responding to random serial *data) currently "AAA" */#define checkByte1 65   // "A"#define checkByte2 65   // "A"#define checkByte3 65   // "A" //--------------------------------------------------------------------------// START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE#include <Servo.h>#define LEFTSERVOPIN  10    //The pin the left servo is connected to#define RIGHTSERVOPIN  9    //The pin the right servo is connected toServo leftServo;           Servo rightServo; int leftSpeed = 50;   //holds the speed of the robots leftServo                       //a percentage between 0 and 100int rightSpeed = 100;  //holds the speed of the robots rightServo                        //a percentage between 0 and 100// END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE//--------------------------------------------------------------------------//Gets everything up and runningvoid setup()                  {  Serial.begin(9600);                //Starts the serial port  serbSetup();                       //sets the state of all neccesary                                      //pins and adds servos to your sketch}//The main program loopvoid loop()                     {  serbPollSerialPort();             //continuously looks to the serial port                                    //if there is data it processes it}//-----------------------------------------------------------------------//START OF ARDUINO SERIAL SERVER ROUTINES/* * Processes commands delivered to the arduino's serial port */void serbPollSerialPort(){  int dta;                              //variable to hold the serial  byte  if ( Serial.available() >= 5) {       //if 5 bytes are in the buffer (length pf a full request)    dta = Serial.read();     if ( dta = checkByte1){                        //Checks for first check byte        dta = Serial.read();        if ( dta = checkByte2){                    //Checks for second check byte          dta = Serial.read();            if ( dta = checkByte3){                //Checks for third check byte               int command = Serial.read();        //Fourth byte is the command               int param1 = Serial.read();         //Fifth byte is param1               interpretCommand(command, param1);  //sends the parsed request to it's handler            }        }      }    }}/* * Takes the command and parameter and passes it to the robot */void interpretCommand(int command, int param1){if       (command == FORWARD){goForward(); delay(param1 * 100); goStop();}   //if forward   else if(command == BACKWARD){goBackward(); delay(param1 * 100); goStop();} //if backwards  else if(command == LEFT){goLeft(); delay(param1 * 100); goStop();}         //if left  else if(command == RIGHT){goRight(); delay(param1 * 100); goStop();}       //if right  else if(command == SETSPEED){setSpeed(param1);}                 //if setting speed  else if(command == STOP){goStop();}                               //if stop  else if(command == SETSPEEDLEFT){setSpeedLeft(param1);}           //if setting left speed  else if(command == SETSPEEDRIGHT){setSpeedRight(param1);}         //if setting right speed  else{                            //if unrecognized command do a little shimmey    goLeft(); delay(150); goRight(); delay(150); goStop();  }}//------------------------------------------------------------------------//START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES/* * sets up your arduino to address your SERB using the included routines*/void serbSetup(){  setSpeed(leftSpeed);  pinMode(LEFTSERVOPIN, OUTPUT);     //sets the left servo signal pin                                      //to output  pinMode(RIGHTSERVOPIN, OUTPUT);    //sets the right servo signal pin                                      //to output  leftServo.attach(LEFTSERVOPIN);    //attaches left servo  rightServo.attach(RIGHTSERVOPIN);  //attaches right servo  goStop();}/* * sets the speed of the robot between 0-(stopped) and 100-(full speed) * NOTE: speed will not change the current speed you must change speed  * then call one of the go methods before changes occur.*/ void setSpeed(int newSpeed){  setSpeedLeft(newSpeed);                 //sets left speed  setSpeedRight(newSpeed);                //sets right speed}/* * Sets the speed of the left wheel */void setSpeedLeft(int newSpeed){  if(newSpeed >= 100) {newSpeed = 100;}     //if speed is greater than 100                                             //make it 100  if(newSpeed <= 0) {newSpeed = 0;}         //if speed is less than 0 make                                             //it 0   leftSpeed = newSpeed * 0.9;               //between 0 and 90}/* * Sets the speed of the right wheel */void setSpeedRight(int newSpeed){    if(newSpeed >= 100) {newSpeed = 100;}     //if speed is greater than 100                                             //make it 100  if(newSpeed <= 0) {newSpeed = 0;}         //if speed is less than 0 make                                             //it 0   rightSpeed = newSpeed * 0.9;               //scales the speed to be }/* * sends the robot forwards */void goForward(){ leftServo.write(90 + leftSpeed);  rightServo.write(90 - rightSpeed);}  /* * sends the robot backwards */void goBackward(){ leftServo.write(90 - leftSpeed); rightServo.write(90 + rightSpeed);}  /* * sends the robot right */void goRight(){ leftServo.write(90 + leftSpeed); rightServo.write(90 + rightSpeed);}/* * sends the robot left */void goLeft(){ leftServo.write(90 - leftSpeed); rightServo.write(90 - rightSpeed);}/* * stops the robot */void goStop(){ leftServo.write(90); rightServo.write(90);}//END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES//---------------------------------------------------------------------------

Step 4: Software - Robot Laptop (WebServer)

(Processing is an open source programming language and environment which is super easy to get started with. For more details visit Processing )

The software that runs on the robot laptop is also quite simple. It is a rather rudimentary web-server (listening for web page requests from a web browser), a small user interface (to set it up), and facilities for passing the commands received from the Web Server to the Arduino.

To Install Quickly: (on windows)
  • Download the zip file below (06-WEBB-Processing Webserver (windows exe).zip)
  • Unzip it and run the .exe file (_WEBB_WebServer_RobotComputer.exe)
To Edit in Processing:
  • Download the zip file below (06-WEBB-Processing Webserver (source files).zip)
  • Unzip anywhere on your computer.
  • Open the Processing environment and open (_WEBB_WebServer_RobotComputer.pde)
To Test:
  • Run the program.
  • In box #1 there will be a list of the available comm ports on your computer (click on the one your Arduino is conneced to. (your robot will twitch a few times as the computer connects, and a cyan dot will appear beside the chosen comm port)
  • In box #2 test to see if your Arduino is connected. Click one of the arrows and hopefully your robot will move in the clicked direction for half a second.
  • In box #3 click the "Start" button to start the web server.
  • Open a web browser (on the Robot Laptop) and visit http://127.0.0.1:12345/ControlPage.html (hopefully the control web page with buttons on it will appear) -Details on how to use this page in the next step-
What is happening:
  • The Web Server listens to port 12345 for http requests (what is sent when you type in a web page address)
  • There are two types of requests it responds to.
1. It listens for "ControlPage.html" and will send the control Webpage
2. It listens for requests of the form "/request?command=F&param1=100" (these commands are parsed and sent to the Arduino (this example would result in the robot going Forward for 10 seconds)

Appendix: (The code for the WebServer)

/* * Arduino Controlled Web Connected Robot (WEBB) - Webserver * For more details visit: http://www.oomlout.com/serb  *  * Behaviour: The program listens for http (webpage) requests in the form *            "/request?command=F&param1=100" and then passes them to the *            Arduino               *            Supported Commands - 'F' - 70 - Forward *                                 'B' - 66 - Backward *                                 'L' - 76 - Left *                                 'R' - 82 - Right *                                 'S' - 83 - Speed *                                 'X' - 88 - SetSpeedLeft *                                 'Y' - 89 - SetSpeedRight  *                                 'C' - 67 - Stop  *            param1's - 0 - 255 (0 to 25.5 Seconds) value * 100 milliseconds  * *            also serves the control webpage to the browser if asking for ControlPage.html * * Operation: 1. Click on the Comm port your Arduino is connected to *            2. Use the test buttons to see if your arduino is listening  *               (will move in the direction clicked for half a second) *            3. Click Start and your webserver will be listening for requests * * * License: This work is licenced under the Creative Commons  *          Attribution-Share Alike 3.0 Unported License. To  *          view a copy of this licence, visit  *          http://creativecommons.org/licenses/by-sa/3.0/  *          or send a letter to Creative Commons, 171 Second  *          Street, Suite 300, San Francisco, California 94105,  *          USA. *         */import processing.serial.*;         //import the serial library to use Serial (for talking to Arduino)import processing.net.*;            //import the net library to use Server    (for talking to the internet)/* Serial Port Related Variables */int serialPortIndex = -1;           //the index of the serial port we are using in the Serial.list() listString[] commOptions;               //A variable to store Serial.list() in so there is no need to poll                                     //the serial ports each time we wish to refrence it (polling causes a                                     //jump in the arduino servos)Serial serialPort;                  //Makes the serial port addressable throughout this sketch/* Graphic and Rendering Related Variables */PFont font;                        //makes font public so it only needs to be loaded once (Arial-72)/* Network Related Variables */Server wServer;                    //The Server which handles web requestsint port = 12345;                  //The port the Server listens toint cycleCount = 0;                //Counts the number of times the draw loop executes (used to                                    //animate the "running" text)           /* Utility Variables */ PImage bg;     //The background image currently \WEBB-background.png/* * Button Related Variables * (buttons are implemented very roughly, bounding boxes are stored and graphic and text are *  drawn on the background image) ie. moving button variables will not move appearance of buttons */Button comm1; Button comm2; Button comm3; Button comm4; //The buttons to choose the correct serial portButton up; Button right; Button left; Button down;//The direction buttons to test if the robot is respondingButton webServer;                                       //The button to start the webServer/* * sets evrything up */void setup() {  frameRate(5);                          //Slows the sketch down a little so it is not as taxing on the system  bg = loadImage("WEBB-background.png"); //Loads the background image (stored in the sketch folder)  size(700, 400);                        //Sets the size of the sketch window  font = loadFont("ArialMT-72.vlw");     //Loads the font we will use throught this sketch  commOptions = Serial.list();           //Polls the Serial ports and gets a list of available ports                                          //(doing this only once keeps the robot from twitching everytime it's                                          //serial port is polled)  defineButtons();            //Defines the bounding boxes for each button  background(bg);             //Paints the background image (this image has all the button graphics on it)}/* The sketches main loop */void draw() {  if(cycleCount==0){  //-- call draw routines    drawCommBox();                        //Draws the emelments in the Comm Box (box 1)    drawTestBox();                        //Draws all the elements in the Test Box (box 2)     drawWebServerBox();                   //Draws all the elements in the WebServer Box (box 3)  }  //-- call working routines  pollWebServer();              //Polls the web server to see if any requests have come in via the network}//----------------------------------------------------------------------------//Start of draw routines (split up just to make code nicer to read)/* * The draw update routine (executed every cycle) for items in the comm box (box 1) */void drawCommBox(){  fill(0,0,0);                                 //Set the fill to black  textFont(font, 15);                          //Set the font to the right size  for(int i = 0; i < commOptions.length; i++){ //For each comm option    text(commOptions[i], 100, 102 + i*70);     //Writes the name of each comm option beside                                                //the appropriate button  }  /* Draw the dot beside the currently active comm port */  if(serialPortIndex != -1){                    //checks to see if a comm port has been chosen    fill(0,147,221);                            //Set fill to cyan    ellipse(180, 96 + 70 * serialPortIndex, 30, 30);     //Draw a circle beside the currently active Comm port  } }/* The draw update routine (executed every cycle) for items in the test box (box 2)*/void drawTestBox(){}/* The draw update routine (executed every cycle) for items in the webserver box (box 3) */void drawWebServerBox(){  fill(0,0,0);                                  //Set the fill to black  textFont(font, 30);                           //Set the font to the right size  if(wServer == null){text("Start", 553, 210);  //If the Webserver has not started writes Start on the button  }else{                                                     String running = "Running.";                        //If the Webserver is running writes running and                                                         //a progression of dots for movement    if((cycleCount / 1) > 0){running = running + ".";} //the number of dots is based on cycleCount         if((cycleCount / 1) > 1){running = running + ".";}    if((cycleCount / 1) > 2){running = running + ".";}    if((cycleCount / 1) > 3){cycleCount=0;}    text(running, 520, 210);  }  cycleCount++;                                     //Every time through cycleCount is incremented by one}  //End of Draw routines//-------------------------------------------------------------//-------------------------------------------------------------//Start of Service routines/* * mousePressed is called everytime the mouse is pressed this  * checks if the mouse is inside any of the button bounding boxes * and if it is the appropriate routine is called*/void mousePressed(){    if(comm1.pressed())      {updateSerialPort(0);}       //Changes to the comm port at index 0 in Serial.list()    else if(comm2.pressed()) {updateSerialPort(1);}       //Changes to the comm port at index 1 in Serial.list()    else if(comm3.pressed()) {updateSerialPort(2);}       //Changes to the comm port at index 2 in Serial.list()    else if(comm4.pressed()) {updateSerialPort(3);}       //Changes to the comm port at index 3 in Serial.list()    else if(up.pressed())    {sendRobotCommand("F", 5);} //Sends a command to move the robot Forward for 0.5 seconds    else if(left.pressed())  {sendRobotCommand("L", 5);} //Sends a command to move the robot Left for 0.5 seconds    else if(right.pressed()) {sendRobotCommand("R", 5);} //Sends a command to move the robot Right for 0.5 seconds    else if(down.pressed())  {sendRobotCommand("B", 5);} //Sends a command to move the robot Backward for 0.5 seconds    else if(webServer.pressed()) {startWebServer();}      //Starts the webServer           cycleCount = 0;    background(bg);                       //Repaints the background image (this image has all the button graphics on it)    draw();}/* * Called once an execution it checks the Server to see if there are any waiting connections * if there is a waiting connection it pulls out the request and passes it to the parseRequest(String) * routine to strip away extra text. This is then sent to the interpretRequest(String) routine to  * call the appropriate action routine (ie send instructions to robot).  * * A Request is passed by entering the computers address and port into a web browser * For local machine "http://127.0.0.1:12345/request?command=F&param1=100" * * Example Request: *   GET /request?command=F&param1=100 HTTP/1.1 *   User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US) AppleWebKit/525.19 (KHTML, like Gecko) *   Accept: *//* *   Accept-Language: en-US,en *   Accept-Charset: ISO-8859-1,*,utf-8 *   Accept-Encoding: gzip,deflate,bzip2 *   Host: 127.0.0.1:12345 *   Connection: Keep-Alive * * Example Reply (for processed request) *   HTTP/1.1 200 OK *   Connection: close *   Content-Type: text/html * *   command: F param1: 100    */void pollWebServer(){  if(wServer != null){                               //If the webServer is running    Client request = wServer.available();            //Load the next Client in line in the                                                      //server (null if no requests waiting)    if(request != null){                             //if there is a request process it      String fullRequest = request.readString();     //Store request contents as a string      String ip = request.ip();                      //Store the clients ip address as a string       String requestString = parseRequest(fullRequest.toUpperCase());  //Strip away all the extra                                          //information leaving only the request string (text after GET)                                         //(shifts to upper case to make string testing easier)       if(requestString.indexOf("REQUEST?") != -1){        //Checks if the request has "REQUEST?"         String reply = interpretRequest(requestString);   //Sends the request to the request interpreter         request.write("HTTP/1.1 200 OK\nConnection: close\nContent-Type: text/html\n\n" + reply);                                                             //Sends the reply a 200 to say the request was                                                           //handled and the "reply" string as the response          wServer.disconnect(request);                     //Disconnects the Client       }else if(requestString.indexOf("CONTROLPAGE") != -1){  //If the request is for the control web page         String[] webPageArray = loadStrings("WEBB-ControlPage.html");                                                            //Loads the control webPage from \data\WEBB-ControlPage.html                                                           //(loaded as an array of lines)         String webPage ="";                              //To make editing easier the webpage has been left with                                                           //line breaks so this for loop striops those lines out         for(int i = 0; i < webPageArray.length; i++){           webPage = webPage + webPageArray[i];         }         request.write("HTTP/1.1 200 OK\nConnection: close\nContent-Type: text/html\n\n" + webPage);                                                           //sends the browser the instructions that the request was not                                                           //processed and the webpage as a string         wServer.disconnect(request);                     //Disconnects the client       }else if(requestString.indexOf("/TEST/") != -1){   //For Testing outputs the request as a println         println(fullRequest);         println(ip);         request.write("HTTP/1.1 200 OK\nConnection: close\nContent-Type: text/html\n\n");                                                           //sends the browser the instructions that the request was not                                                           //processed and the webpage as a string         wServer.disconnect(request);                     //Disconnects the client       }else{         request.write("HTTP/1.1 404 FILE NOT FOUND\nConnection: close\n");                                                           //sends the browser the instructions that the request was                                                           //not processed (usually due to a typo) then tells it to                                                           //close the connection         wServer.disconnect(request);                     //Disconnects the client       }    }  } }//End of Service Routines//-------------------------------------------------------------//-------------------------------------------------------------//Start of setup routines (routines called once or not very often/* * Defines all the bounding boxes for the buttons used in this sketch */void defineButtons(){  comm1 = new Button(30, 65, 60, 60);  //Defines the comm1 button  comm2 = new Button(30, 135, 60, 60); //Defines the comm2 button  comm3 = new Button(30, 205, 60, 60); //Defines the comm3 button  comm4 = new Button(30, 275, 60, 60); //Defines the comm1 button  up = new Button(320, 110, 60, 60);   //Defines the up/forward button  left = new Button(260, 170, 60, 60); //Defines the left button  right = new Button(380, 170, 60, 60);//Defines the right button  down = new Button(320, 230, 60, 60); //Defines the down/backward button  webServer = new Button(493, 170, 180, 60); //Defines the webserver button}/* * When the "Start" button in the webserver box is pressed the server starts listening * for incoming connections on port port (12345) defined in the preamble */void startWebServer(){    if(wServer == null) {wServer = new Server(this, port);}  }/* * This takes a verbose http request from a client and * returns only the request line (what comes after GET) */String parseRequest(String fullRequest){  fullRequest = fullRequest.substring(fullRequest.indexOf("GET ") + "GET ".length());                                               //Cuts off everything in the string before GET  fullRequest = fullRequest.substring(0, fullRequest.indexOf(" "));                                                                 //Takes from the begining of the new string to the first space  return fullRequest;                       //returns the shortened request}/* * updates the serial port being used to comunicate with the arduino * portIndex is the index of the port we wish to use in Serial.list(); * as Serial.list() is loaded into memory at startup adding serial ports  * after startup could cause unexcpected operation */void updateSerialPort(int portIndex){  if(commOptions.length > portIndex){ //if the passed portIndex is a valid index in Serial.list()                                       //(ie. not option three in a list of two)     serialPortIndex = portIndex;     //set the serialPortIndex variable to the new serialport index                                       //(this is used to display the dot beside the active port)  }  if(serialPortIndex != -1){                    //check to make sure a port has been chosen sometime previous    if(serialPort != null){serialPort.stop();}  //if a Serial port is already being used stop it before loading a new one     serialPort = new Serial(this, Serial.list()[serialPortIndex], 9600);                                                  //Create a new Serial object to comunicate with the Arduino 9600 Baud  }}/* * Takes a request string (ex: "request?command=F&param1=100") and will strip out the command * and param1 and pass it to the arduino (adding extra parameters or non arduino commands would be done here) */String interpretRequest(String requestString){ String returnValue = "OK";                     //Prepares a returnValue variable String command;                                //Next three lines extract the value after "command="                                                 //(the extra line is in case the command parameter is at the                                                 //end of the request and not followed by an & if(requestString.indexOf("COMMAND=") != -1){   command = requestString.substring(requestString.indexOf("COMMAND=") + "COMMAND=".length());} else{command = "Z";} if(command.indexOf("&") != -1){   command = command.substring(0,command.indexOf("&"));}else{command = command;} String param1String;                         //Next three lines extract the value after "param1="                                               //(the extra line is in case the command parameter is at                                               //the end of the request and not followed by an & if(requestString.indexOf("PARAM1=") != -1){   param1String = requestString.substring(requestString.indexOf("PARAM1=") + "PARAM1=".length());} else{param1String = "0";} if(param1String.indexOf("& ") != -1){   param1String = param1String.substring(0,param1String.indexOf("&"));} else{param1String = param1String;} int param1 = Integer.parseInt(param1String);  //Turns the param1 String into an integer sendRobotCommand(command,param1);            //Sends the command to the routine that sends it to the Arduino returnValue = "command: " + command + " param1: " + param1;  //at the moment just the parsed command but sending                                                               //as html so formatting can be included return returnValue;}/* * Takes a command (currently one letter) and a parameter (one byte 0-255) and sends it to the arduino * which is listening and reasts * Currrently Supported Commands * F -*/void sendRobotCommand(String command, int param1){  println("command: " + command + " time: " + param1);  String checkString = "AAA";  if(serialPort != null){    serialPort.write(checkString + command);    serialPort.write(byte(param1));  }}//End of setup/not very commonly called routines//-------------------------------------------------------------------------------------//Example button and RectButton code from processing.org example with some changes //made mostly to simplify and remove roll over animation//http://processing.org/learning/topics/buttons.html (2008-09-23)class Button{  int x, y;  int width, height;  Button(int ix, int iy, int iwidth, int iheight) {    x = ix;  y = iy;  width = iwidth;  height = iheight;  }    boolean pressed() {    if(overRect()) { return true; }     else {           return false;}      }  boolean overRect() {    if (mouseX >= x && mouseX <= x+width && mouseY >= y && mouseY <= y+height) { return true; }     else { return false; }  }}

Step 5: Software - (Webpage)

Well we're almost finished all that is left is talking to your robot.

To Get Talking: (over a local network -on windows-)
  • Discover the local ip address of the laptop computer. To do this go to "Start\Programs\Accesories\Command Prompt" and when the terminal window opens up type "ipconfig". Write down "IP Address" and head to another computer on your local network.
  • Open a web browser, type "http://(robot computer ip):12345/ControlPage.html
  • The control web page should load, in the "IP Address" box type the robot computers ip.
  • Begin controlling your robot.
To Get Talking: (over the internet)
Now that you have it working locally getting it talking over the internet is just a few short steps away.

  • (most difficult step) Set up Port Forwarding - Your computer needs to be listening to the internet rather than just the local network. To do this you need to tell your router to pass certain requests through to the computer controlling the robot. This is a bit complex and goes far beyond the scope of this Instructable. However if you visit PortForward.com they will give you all you need to know about configuring your router (you need to forward port 12345 to your robot laptop)
  • Next discover your internet IP (visit WhatIsMyIP.com )
  • Finally fire up skype setup a video call and get whomever you are talking to to visit "http://(internet IP):12345/ControlPage.html"
  • Type in the internet IP into the "IP Adress" box in the control webpage and your Web Connected Robot is being driven from afar.

Step 6: Finished

Well that's it. I hope you're having a fun time driving your robot from a far. If you have any issues with the software or hardware feel free to leave a comment and I'll try and help you out.

If you would like to check out more neat projects try visiting: oomlout.com


Yash_Gupta1 month ago
There is no download link to the laser cut file. It would be great if you could send it or post it.
ygupta96@gmail.com

can any one help me out
while making the connections of my web connected robot i connected the servos with 4 1.5 volt batteries and connected the arduino dumilaenove conector with the 9v battery asinstructed
but i dont know what has happened that after that my arduino stops working how ever now i replaced my arduino with a new one and i have run the blinking led programe on it and its working also
now i want to know how should i power my arduino that it does not damage

ameggs4 years ago
 Can someone post the arduino code in an easier form so us NOOBS and use it. I really love this idea and Im already building the chassis now... just need the software.

shonlh ameggs1 year ago
Here is the code cleaned up.  I did not get a chance to test it.  It does past check in Arduino though.

/*
 * Arduino Controlled Web Connected Robot (WEBB) - Serial Host 
 * For more details visit: http://www.oomlout.com/serb  
 *  
 * Behaviour: The Arduino listens to its Serial port for a command 
 *            in format 254, 88, 88, (COMMAND), (TIME) 
 *            Supported Commands - 'F' - 70 - Forward 
 *                                 'B' - 66 - Backward 
 *                                 'L' - 76 - Left 
 *                                 'R' - 82 - Right 
 *                                 'S' - 83 - Speed 
 *                                 'X' - 88 - SetSpeedLeft 
 *                                 'Y' - 89 - SetSpeedRight  
 *                                 'C' - 67 - Stop  
 *            Supported Times - 0 - 255 (0 to 25.5 Seconds) value 
 * 100 milliseconds  
 *sp 
 * Wiring: Right Servo Signal - pin 9 
 *         Left Servo Signal - pin 10  
 * 
 * License: This work is licenced under the Creative Commons  
 *          Attribution-Share Alike 3.0 Unported License. To  
 *          view a copy of this licence, visit  
 *          http://creativecommons.org/licenses/by-sa/3.0/  
 *          or send a letter to Creative Commons, 171 Second  
 *          Street, Suite 300, San Francisco, California 94105,  
 *          USA. 
 *         
 */  
 //-------------------------------------------------------------------------
 //START OF ARDUINO SERIAL SERVER PREAMBLE
 //Defining constants corresponding to each command (also the ascii code number) 
 #define FORWARD 70       //F
 #define BACKWARD 66       //B
 #define LEFT 76           //L
 #define RIGHT 82         //R
 #define SETSPEED 83         //S
 #define STOP 67           //C
 #define SETSPEEDLEFT 88   //X
 #define SETSPEEDRIGHT 89 //Y
 /*The three check bytes (used to keep the robot from responding to random serial *data) currently "AAA" 
 */
 #define checkByte1 65   // "A"
 #define checkByte2 65   // "A"
 #define checkByte3 65   // "A" 
 //--------------------------------------------------------------------------
 // START OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
 #include <Servo.h>
 #define LEFTSERVOPIN  10    //The pin the left servo is connected to
 #define RIGHTSERVOPIN  9    //The pin the right servo is connected to
 Servo leftServo;           
 Servo rightServo; 
 int leftSpeed = 50; //holds the speed of the robots leftServo
//a percentage between 0 and 100
int rightSpeed = 100; //holds the speed of the robots rightServo
                        //a percentage between 0 and 100
// END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) PREAMBLE
//--------------------------------------------------------------------------
//Gets everything up and running
void setup()
{  
  Serial.begin(9600);                //Starts the serial port  
  serbSetup();                      //sets the state of all neccesary
//pins and adds servos to your sketch}
//The main program loop
}
void loop()                     
{  serbPollSerialPort();             //continuously looks to the serial port
                                    //if there is data it processes it
}
//-----------------------------------------------------------------------
//START OF ARDUINO SERIAL SERVER ROUTINES
/* 
* Processes commands delivered to the arduino's serial port 
*/
void serbPollSerialPort()
{  
int dta;                              //variable to hold the serial  byte  
if ( Serial.available() >= 5) {       //if 5 bytes are in the buffer (length pf a full request)    
dta = Serial.read();     
if ( dta = checkByte1){                        //Checks for first check byte        
dta = Serial.read();        
if ( dta = checkByte2){                    //Checks for second check byte
dta = Serial.read();            
if ( dta = checkByte3){                //Checks for third check byte
int command = Serial.read();        //Fourth byte is the command
int param1 = Serial.read();         //Fifth byte is param1
interpretCommand(command, param1);  //sends the parsed request to it's handler
}
}
}
}
}
/* 
* Takes the command and parameter and passes it to the robot 
*/
void interpretCommand(int command, int param1)
{
if       (command == FORWARD)
{
goForward(); 
delay(param1 * 100); 
goStop();
}   //if forward   
else if(command == BACKWARD)
{
goBackward(); 
delay(param1 * 100);
goStop();
} //if backwards  
else if(command == LEFT)
{
goLeft(); 
delay(param1 * 100); 
goStop();
}         //if left  
else if(command == RIGHT)
{
goRight(); 
delay(param1 * 100); 
goStop();
}       //if right  
else if(command == SETSPEED)
{
setSpeed(param1);
}                 //if setting speed  
else if(command == STOP)
{
goStop();
}                               //if stop  
else if(command == SETSPEEDLEFT)
{
setSpeedLeft(param1);
}           //if setting left speed  
else if(command == SETSPEEDRIGHT)
{
setSpeedRight(param1);
}         //if setting right speed  
else
{                            //if unrecognized command do a little shimmey
goLeft(); 
delay(150); 
goRight(); 
delay(150); 
goStop();
}
}
//------------------------------------------------------------------------
//START OF ARDUINO CONTROLLED S ERVO ROBOT (SERB) ROUTINES
/* 
* sets up your arduino to address your SERB using the included routines
*/
void serbSetup()
{  
setSpeed(leftSpeed);  
pinMode(LEFTSERVOPIN, OUTPUT);     //sets the left servo signal pin
//to output  
pinMode(RIGHTSERVOPIN, OUTPUT);    //sets the right servo signal pin
//to output  
leftServo.attach(LEFTSERVOPIN);    //attaches left servo  
rightServo.attach(RIGHTSERVOPIN);  //attaches right servo  
goStop();
}
/* 
* sets the speed of the robot between 0-(stopped) and 100-(full speed) 
* NOTE: speed will not change the current speed you must change speed  
* then call one of the go methods before changes occur.
*/ 
void setSpeed(int newSpeed)
{  
setSpeedLeft(newSpeed);                 //sets left speed  
setSpeedRight(newSpeed);                //sets right speed}
}
/* 
* Sets the speed of the left wheel 
*/
void setSpeedLeft(int newSpeed)
{  
if(newSpeed >= 100) 
{
newSpeed = 100;
}     //if speed is greater than 100
//make it 100  
if(newSpeed <= 0)
{
newSpeed = 0;
}       //if speed is less than 0 make
//it 0   
leftSpeed = newSpeed * 0.9;               //between 0 and 90}
}
/* 
* Sets the speed of the right wheel 
*/
void setSpeedRight(int newSpeed)
{    
if(newSpeed >= 100) 
{
newSpeed = 100;
}     //if speed is greater than 100
//make it 100  
if(newSpeed <= 0) 
{
newSpeed = 0;
}       //if speed is less than 0 make
//it 0   
rightSpeed = newSpeed * 0.9;               //scales the speed to be 
}
/* * sends the robot forwards 
*/
void goForward()
leftServo.write(90 + leftSpeed);
rightServo.write(90 - rightSpeed);
}  
/* 
* sends the robot backwards 
*/
void goBackward()
leftServo.write(90 - leftSpeed); 
rightServo.write(90 + rightSpeed);}  
/* 
* sends the robot right 
*/
void goRight()
leftServo.write(90 + leftSpeed); 
rightServo.write(90 + rightSpeed);
}
/* 
* sends the robot left 
*/
void goLeft()
leftServo.write(90 - leftSpeed); 
rightServo.write(90 - rightSpeed);
}
/* 
* stops the robot 
*/
void goStop()
leftServo.write(90); 
rightServo.write(90);
}
//END OF ARDUINO CONTROLLED SERVO ROBOT (SERB) ROUTINES
//---------------------------------------------------------------------------

0 comments:

Post a Comment