Instructables
Picture of Ultimate UpCycling: $40 Wheelchair Robot
joystick.jpg
sam.jpg
AnnaROVcam.jpg
AnnaElectronicsBox.jpg
Anna04092013.jpg
I needed to do some research on Smart Wheelchair technology, and what better way to do it than on an actual wheelchair?

Well, the better way was upcycling 3 broken wheelchairs into one working wheelchair-based robot. Total cost for the entire project: $40 for an Arduino and some ultrasonic sensors. I call her AnnaBot.

Quick glance as of today : Wheelchair base. Wi-fi enabled. Onboard camera. All controlled from the laptop using an Arduino microcontroller. Six ultrasonic sensors are waiting to be installed for basic obstacle avoidance.

Microsoft Robotic Developers Studio will be used to program speech recognition, conversation, and autonomous behavior, including “follow me” capability and gesture recognition using the Kinect sensor.

The first thing I did was take stock of the parts I could use that I already had around the house. I found an old laptop and a webcam. I was already playing with MRDS. That left me with two parts to find: a working wheelchair, and a microcontroller to interface to it.

I like my gadgets, so I ordered an Arduino Mega 2560 and some ultrasonic sensors. However, my budget didn't allow for spending several hundred dollars on a used wheelchair.  Here's where I got creative.

I talked to several nursing homes, a hospital, and anyone who would listen, to tell them what I was trying to do. I also put an ad on craigslist. Wanted: electric wheelchairs, working or not.  One man's trash is another man's treasure. That really paid off for me. Over a two week span, I got 3 wheelchairs. None of them working. None of them cost me a cent. I took the frame and motors from one, the wheels and electronics from another, and batteries and a charger from the third. I put it all together, said the magic word, and presto, I had one working wheelchair and a heap of spare parts after a few evenings of work.

So, the most challenging part was reusing the onboard electronics for the motor control. There's lots of safety features built in, and they aren't easy to hack. But they're designed to handle the high motor current. I wanted to keep them.

Originally, I was hoping to interface to a port on the outside of the controller, but this wasn't possible. I had to hack the joystick. I got lucky again. You can see in the picture of the joystick, it's only 4 wires. One X-axis, one Y-axis, plus power and ground.

I used a multimeter to measure the voltages of the joystick on the blue and yellow wires at neutral, full forward, reverse, left, and right. Then I used the Arduino PWM output to give me those voltages. Should have worked, right? Nope. Two problems. First, the electronics on the chair were sensitive enough to see that the voltage wasn't steady, and they errored out. I fixed this by putting the PWM through what I call a "smoothing circuit". I connected the PWM to a resistor, then to the positive leg of a capacitor. The negative leg of the cap went to ground. Then I connected the positive leg of the cap to the joystick control circuit. This let's the cap carry the voltage in between the pulses, and it was enough to fool the chair's controller. In the RC world, this is called a low-pass filter.

The next problem was a joystick fault every time I changed motor directions. This was solved by connecting the Arduino's ground bus to the ground bus inside the joystick. Giving them a common ground reference solved the last of my electrical problems.

Currently, I've got the Arduino programmed to send the proper voltage to move in whatever direction I choose, based on a keypress. "8" drives it forward, "2" reverse, "4" is left, "6" is right, etc. (The arrows on the number pad). Eventually, this will be under the control of MRDS.

The ultrasonic sensors are going on it next. Then it's ready to start being somewhat autonomous. For now, I remote desktop into the laptop on Anna. I can access her webcam to see what she's doing, and I use a simple serial port monitor to send her commands and recieve her responses.

I'm very happy with how this project came together. Much better and much cheaper than "SAM", the little white robot I built back in the late 80's. He was based on an 80286 desktop computer that I powered by battery. He had speech recognition, a webcam, and joystick control. For about $500 in 1987 dollars. lol.

My next step is to interface the Arduino to MRDS. Then I want to develop some low-cost cliff sensors, chair-based remote home automation,  and such that will enhance the wheelchair user's day to day safety and comfort. At an affordable price so that those who need it can actually afford it.

Thank you for reading about Anna :o) You can read more about my ongoing "Adventures with Anna" on my blog, under the category of Robotics here.

Update 04/09/2013

My Wheelchair Robot Becomes a Teleoperated ROV


It’s been a couple of weeks since I posted anything about Anna, my wheelchair robot I’m using for Smart Chair Technology research. I’ve been busy with family obligations, but I’ve still managed to make some great progress. Here’s a very short update. I’ll try to add a video as soon as I can get my hands on a decent camera!First, I found some open-source robotic software from Oculus used to control their “netbook based” tele-robots. Lucky for me, their controller board is compatible with the Arduino that I’m using. I downloaded the source code for their firmware, made some tweaks, and I now have full remote control/tele-operation of Anna via wifi from any internet connection anywhere in the world, and also via an app on my Iphone. This is a far cry from the simple keyboard control of her I had just a few weeks ago!

This is a screen-grab from my laptop. I remoted in to Anna who was on the other side of the house in the basement, and this is what her camera is looking at. If you can manage to read the screen-grab, you’ll see have I full speed and directional control of her, all while she streams full video and audio to my phone or laptop computer. The status display on the top right is great…battery condition, docked or not-docked status, moving or not, ping time (there is a keep-alive timer that will shut down Anna for safety reasons in the event communications are lost), and more. It’s also got pan/tilt control once I hook a servo up to my camera.

On the hardware side, I made some progress, too. I extended the 24 volts from the wheelchair batteries up into her electronics box, and threw in a 24 to 12 volt DC-DC converter (5 amp), and a 24 to 5 volt DC-DC converter at 10 amps. These will give me the power I need for the Kinect sensor and my ultrasonic and IR sensors, as well as some servos. I brought all three of these voltages out to terminal strips for ease of access. In the center of the picture you can see (from left to right) an 8-relay board, my breadboard for prototyping, and her microcontroller, and Arduino Mega 2560. The phone jack you see in the very lower right corner is where I tapped into the wheelchair’s joystick/controller. If I plug in the Arduino, I’ve got computer control of Anna. If I plug in a loopback jack, she reverts to normal wheelchair mode controlled by her joystick. I did this for ease of moving her around, and safety when I have to take her in public to demonstrate some of the technology I’m working on.

And last, but not least, I put a stable platform on Anna to safely house and isolate her electronics. Although it looks hideous, it kept within my budget (zero dollars for scrap wood. lol). One nice feature to this box is that the wheelchair frame had a reclining seat. By mounting the box between the arm brackets, I am able to release 2 levers at the front of the chair, and the entire electronics box raises up and back to the rear. This makes it easier to work on the batteries and other electronics in her base, and it also doubles the space I can use for electronics because the platform raises up enough that I can mount components on the underside of the board you see in the picture above.

I’ve still got some ultrasonic sensors to mount. Then I’m going to work on tweaking her software until I can purchase a copy of RoboRealm and a Kinect sensor.

So far, I've only got $75 invested (total) in Anna. That only puts me...oh....$75 over budget! lol

Thanks again for reading about Anna! Stay tuned for more Adventures with Anna.


bjf505110 months ago

Could you share the details of your low pass filter, I am having the same issue with my robot where the controller fails since the arduino output it not smoothed and I get an error on the controller. Believe this is because I replaced the joystick with the arduino and the output does not match the joysticks directly. Thanks!

mr fat1 year ago
Brilliant setup and awesome recycling work too!
shonlh1 year ago
 
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 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
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

//---------------------------------------------------------------------------
Dark Light (author)  shonlh1 year ago
Well done, shonlh. Thank you for sharing that!
asmith4331 year ago
I have the general layout for my joystick on my wheelchair controller with the x y and power and i was just wondering if i could use a basic rc controller to control the robot would i have to also put the low pass filter in because it errors when i try to use the rc controller.
Dark Light (author)  asmith4331 year ago
You can use an RC controller if you're NOT using the onboard wheelchair electronics (motor controller). The Sabertooth motorcontroller (from Dynamics), for instance, has an RC mode. You hook your RC reciever right up to the Sabertooth.

If you're keeping the stock wheelchair motor control unit, then there are several issues with remote control. If you're getting errors, I'd check to make sure your "neutral" voltage is correct on X & Y axis....mine is 2.5 for instance. Without 2.5v, my controller errors out. + or - from 2.5 on both axis is what controls my speed and direction. Note that your chair may be different. My joystick controller is a 5 volt unit. Some chairs use 12 or 24V as reference in the joystick. I made all my voltage measurements before hacking into it.

Some wheelchair joysticks also have a reference voltage on a green wire. You may have to supply this as a third voltage, as well.

I also had to hook my arduino GROUND to the joystick Ground, or the chair errored out everytime.

I hope this helps you. Each wheelchair manufacturer does things a little different. You multimeter will be your best friend until you figure out what the chair needs.

I'd try connecting the grounds first. And your reference voltage. Then the low pass filter. And double check your voltages if you can.

John
would there be a way for me to get a arduino to take in the rc input and mimic the wheel chairs joy stick and mine also out puts the same voltage of 2.5v on the x and y and runs on 5 volts also.
Dark Light (author)  asmith4331 year ago
I'm sure there is a way. I just don't know how to make the Arduino read the RC stuff. Start with this post on the Arduino forum: http://arduino.cc/forum/index.php/topic,88946.0.html about getting a wheelchair under Arduino control. There's lots of great info in that post.

I'd also search that forum for RC with the Arduino. I'm sure it's been done tons of times. I can't help you too much there, though, as I know next to nothing about RC or the signalling it uses.

Another site with good information is www.wheelchairdriver.com. The guy there has used RC with his chairs. I'm not sure if he used an Arduino or not.

I hope this helps!