Introduction: Buggy Wheelchair Robot

This is a Modification of an electric wheelchair.
I called it "Buggy" for two reasons. #1 My kids can still ride it around because I left the seat intact. #2 I haven't programmed anything for a long time.
I plan to create "jobs" for it in the near future.
I welcome any input. Keep in mind this is my first Instruct-able. 

I found this chair on-line for a great price. The claim was that it was broken.  The OEM battery charger had 2 volts output, the batteries are 24vdc. I found a 24VDC power supply and used the XLR plug that I cut from the charger and it worked fine.  I did have to replace the batteries, they were old and tired.


Step 1: Getting Power

This is the connector for the battery charger. It is a standard XLR microphone type plug. This can be connected at the joystick body or into the battery pack at the base.

With the center pin down, top left is green. This is Positive 24VDC. Top right is white. This is Negative 24VDC. The bottom center pin, from what I've read, is a programming pin to adjust various operating protocols for the drive systems.  The manufacturer of this model doesn't share programming protocols. 

Step 2: Inside the Box

Upon power-up, the controller verifies that the joystick is centered. The voltage supplied at center is about 2.5 VDC. Knowing this I needed to allow the power-up to complete before I took control. So I used two DPDT Relays. Each directional feed from the joystick has two control lines, pins 2,4 and 5,7.  I connected the common on the relay to the feed from the control board, the N.O. to the Arduino Uno circuit and the N.C. to the joystick.

Step 3: Who's in Control

I had cut into the ribbon cable from the joystick to the controller. As shown in the schematic a few of the lines carry straight through. I soldered them all to a circuit board. This is the point that I broke out the directional lines to go to the relay bypass. Then as seen in the picture I had to cut the board in two to get it to fit into the joystick housing. I ran the relay control lines and the Arduino control line through a hole I drilled into the Joystick housing.  Use a strain relief bushing and BE CAREFUL, when drilling. While in there I also soldered a 22 AWG 6 conductor (22/6) to the labeled test points that control power, on / off, speed control, 5 VDC supply  and ground, and a spare conductor. These points can be found running down the left side of the control board. Then I closed and re-mounted the joystick on the   wheelchair. 

Step 4: Connecting the Systems

Once our relays kick on and connect to the Arduino we will need to make sure we produce the 2.5vdc needed to keep the joystick from going in error mode. Remember, if the joystick is not centered (2.5Vcd) it will lockup and stop all operations. If you view the schematic showing pins 9 and 10 PWM, you will see how I connect the output of the Adruino to the input of the joystick. Using the joystick's 5vdc feed into the transistor and modulating it through the PWM output I can control the variance between the 4.0vdc and the 2.0vdc for forward / backward or left / right requests. This is controlled by activating the relay and then changing the PWM to get the direction that I want.

Step 5: Aux Controls

Activating the unit and controlling the speed. Again using the source 5vdc from the joystick controller I am tripping a transistor to pulse each input. The power and speed buttons are momentary, in this case I will use the software to turn the output pin on the Arduino high  then low with a 500ms delay, simulating a button press.

Step 6: What's It Doing.

While working on this project I was given an old fire alarm panel. This panel had a Hitachi LCD display. This display, as I found is one of the most popular types available. So using one of the many examples on-line, I connected it to the Arduino. I use the LCD display to show me what the software is up to, Ie. on-line, power control, forward, backward, etc. I accomplished this using a simple LCD print command at each instruction. I also printed each "direction" to serial output as well.

Step 7: Who, What, Where

The pin-out for the Arduino is as follows. Pin 0-1 are used as rx-tx. Pins 2,3,4,5,11,12,13 are used for the LCD. Pin 13, the onboard LED pin is connected to the LCD back-light.  Pins 6+7 are for future use. Pin 8 trips the override relay. Pins 9+10 are the PWM outputs for directional control. I've used analog inputs 1,2,3 as outputs 14, 15, 16.  Pin 14 is Speed up. Pin 15 is Speed down, and pin 16 is Power control.

Step 8: Get Connected

During the programing I connected to the Arduino using the USB. But to control untethered I needed another option. Since being given the Fire Alarm panel and cabinet I chose to reuse what I had instead of buying new. So during the normal operation I unplugged the USB and connected a TTL to rs232 converter to pins 0+1. I also reused an old Ethernet to RS-232 converter connected to the TTL converter and a very old Linksys 80211b wireless router. I setup the router to bridge to my home network through a Linksys G router. I can telnet into the Arduino using a PC or cellphone on my wifi network and send commands to control the outputs. This connection is too slow however to make any program changes. All of my commands are one letter commands all caps. I.E. O=On, F=Forward, T= Take Control / Override.

Step 9: Brains

I have pasted a copy of my program.  Yes, I used Goto commands... Yes, I know many of you hate them. They worked for what I needed. I am open however to any constructive input on this project.

I haven't written a program since GWbasic. Old school I know. I realize this program looks alot like a basic flashback. It does however work just as I wanted.

/*
 ROBOT DRIVE
 Stephen J. Gardiner, CPS
 
 Created 2012
 Stephen J. Gardiner, CPS

   */
   // include the library code:
   #include <LiquidCrystal.h>

   // initialize the LCD library
   LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

   const int ledPin = 16;      // the DRIVE SYSTEM POWER pin
   const int lCdPin = 13;      // lCdPin
   const int redPin = 8;       // OVER-RIDE ENGAGED
   const int FASTPin = 14;     // Speed-up
   const int SLOWPin = 15;     // Speed-Down
   const int pwm1Pin = 9;      // PWM Pin 1
   const int pwm2Pin = 10;     // PWM Pin2
   int incomingByte;           // a variable to read incoming serial data into
   int OVERRIDEOFF;

   void setup() {
  
   Serial.begin(9600);         // initialize serial communication:
                               // initialize the control pins as an outputs:
   pinMode(ledPin, OUTPUT);
   pinMode(lCdPin, OUTPUT);
   pinMode(redPin, OUTPUT);
   pinMode(FASTPin, OUTPUT);
   pinMode(SLOWPin, OUTPUT);
   pinMode(pwm1Pin, OUTPUT);
   pinMode(pwm2Pin, OUTPUT);
 
  
   lcd.begin(16,4);            // set up the LCD's number of columns and rows:
  
   lcd.setCursor(0, 0);        // Print a message to the LCD.
   digitalWrite(lCdPin, HIGH);
   lcd.print("   ON-LINE ");
   Serial.print("Robot Control v6.1" );
   Serial.print("\r");
   Serial.print(" ON-LINE" );
   Serial.print("\r");
   delay(1000);
   digitalWrite(lCdPin, LOW);
   }

   void loop() {
                               // set the cursor to column 0, line 1
                               // (note: line 1 is the second row, since counting begins with 0):
   lcd.setCursor(0,0);
                               // lcd.setCursor(0,3);
   int val1 = 100;             // variable to store DUTY CYCLE F + B
   int val2 = 100;             // variable to store DUTY CYCLE L + R
   analogWrite(pwm1Pin,val1);  // SET DRIVE- VOLTAGE TO 2.5 (+/-)
   analogWrite(pwm2Pin,val2);  // SET DRIVE- VOLTAGE TO 2.5 (+/-)
 
   // see if there's incoming serial data:
   if (Serial.available() > 0) {
   
   // read the oldest byte in the serial buffer:
   // Yes I know Goto Commands, Ya'll hatem' I works for me
   incomingByte = Serial.read();
   if (incomingByte == 'O') {goto DRIVEPOWER;}
   if (incomingByte == 'T') {goto OVERRIDEON;}
   if (incomingByte == 'C') {goto OVERRIDEOFF;}
   if (incomingByte == 'I') {goto FASTER;}
   if (incomingByte == 'D') {goto SLOWER;}
   if (incomingByte == 'F') {goto FORWARD;}
   if (incomingByte == 'B') {goto BACKWARD;}
   if (incomingByte == 'L') {goto LEFT;}
   if (incomingByte == 'R') {goto RIGHT;}
   Serial.print("Robot Control v6.1 " );
   lcd.print("   READY ");
   Serial.print("\r");
   return;
      
   // if it's a capital O turn on the DRIVE:
   { DRIVEPOWER:
   digitalWrite(ledPin, HIGH);
   digitalWrite(lCdPin, HIGH);
   lcd.print("  DRIVE SYSTEM POWER");
   Serial.print("DRIVE SYSTEM POWER" );
   delay(500);
   lcd.setCursor(0,0);
   digitalWrite(ledPin, LOW);
   delay(500);
   digitalWrite(lCdPin, LOW);
   int val = 169; 
   lcd.clear();
   Serial.print("\r");
   Serial.flush();
   return;
     
   }
       
   { OVERRIDEON:
   // if it's an T OVERRIDE on:
   digitalWrite(redPin, HIGH );
   digitalWrite(lCdPin, HIGH);
   lcd.print("  OVER-RIDE ENGAGED");
   Serial.print("OVER-RIDE ENGAGED " );
   delay(500);
   lcd.setCursor(0,0);
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }   
   // if it's an C OVERRIDE off:
   {  OVERRIDEOFF:
   digitalWrite(redPin, LOW );
   digitalWrite(lCdPin, HIGH);
   lcd.print("  OVER-RIDE DIS-ENGAGED");
   Serial.print("OVER-RIDE DIS-ENGAGED " );
   delay(1000);
   lcd.setCursor(0,0);
   digitalWrite(lCdPin, LOW);
   lcd.clear();
   Serial.print("\r");
   Serial.flush();  
   return;
   }
   // if it's an F TO RAISE SPEED
   { FASTER:
   digitalWrite(FASTPin, HIGH );
   digitalWrite(lCdPin, HIGH);
   lcd.print("    FASTER");
   Serial.print("FASTER " );
   delay(500);
   lcd.setCursor(0,0);
   digitalWrite(FASTPin, LOW);
   delay(500);     
   digitalWrite(lCdPin, LOW);
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }
   // if it's a capital S  TO LOWER SPEED
   { SLOWER:   
   digitalWrite(SLOWPin, HIGH );
   digitalWrite(lCdPin, HIGH);
   lcd.print("    SLOWER");
   Serial.print("SLOWER " );
   delay(500);
   lcd.setCursor(0,0);
   digitalWrite(SLOWPin, LOW);
   delay(500);
   digitalWrite(lCdPin, LOW);          
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }
   { FORWARD:   
   digitalWrite(lCdPin, HIGH);
   lcd.print("    FORWARD");
   Serial.print("FORWARD " );
    
   int val2 = 200;                // variable @ 200 DUTY CYCLE = FORWARD
   analogWrite(pwm2Pin,val2);     // SET DRIVE- VOLTAGE TO FORWARD
   delay(1000);
   lcd.setCursor(0,0);
   digitalWrite(lCdPin, LOW);          
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }
   { BACKWARD:   
   digitalWrite(lCdPin, HIGH);
   lcd.print("    BACKWARD");
   Serial.print("BACKWARD " );
   int val2 = 50;                 // variable @ 75 DUTY CYCLE = BACKWARD
   analogWrite(pwm2Pin,val2);     // SET DRIVE- VOLTAGE TO BACKWARD
   delay(1000);
   lcd.setCursor(0,0);
   digitalWrite(lCdPin, LOW);          
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }
   { LEFT:   
   digitalWrite(lCdPin, HIGH);
   lcd.print("    LEFT");
   Serial.print("LEFT " );
   int val1 = 50;                  // variable @ 100 DUTY CYCLE = LEFT
   analogWrite(pwm1Pin,val1);      // SET DRIVE- VOLTAGE TO LEFT
   delay(1000);
   lcd.setCursor(0,0);
   digitalWrite(lCdPin, LOW);          
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }  
   { RIGHT:   
   digitalWrite(lCdPin, HIGH);
   lcd.print("    RIGHT");
   Serial.print("RIGHT " );
   int val1 = 220;                  // variable @ 200 DUTY CYCLE = RIGHT
   analogWrite(pwm1Pin,val1);       // SET DRIVE- VOLTAGE TO RIGHT
   delay(1000);
   lcd.setCursor(0,0);
   digitalWrite(lCdPin, LOW);          
   lcd.clear();
   Serial.flush();
   Serial.print("\r");
   return;
   }    
   }
   }

Step 10: Extras

I have attached a zip file containing the schematics in a .sch format.

While working on this project and discussing it with friends I was told about modifications to these devices needed by various operators. These modifications vary from Sip and puff to chin controls. I hope that this project is a good starting point for these type of modifications.

Comments

author
jgwinner made it!(author)2015-07-20

I can't quite read the schematic - what format is this in? I tried Eagle but it said the file format was unrecognized (most current version).

So I guess the key here is that you're taking the PWM output and feeding through an NPN transistor into the joystick, as if it was actually the joystick control itself? (I gather they are using it like a simple 5V pot).

Thanks, very inspiring,

== John ==

author
outlaw4freedom made it!(author)2013-06-18

This is really inspiring! My wife is currently in an electric wheelchair and I've joked about turning it into the family robot when she recovers and can walk again.

author
sjgcps made it!(author)2012-05-02

Here is a link to a brief video:
http://prostrategiesinc.com/judo/robotdemo2001.mov

About This Instructable

13,399views

30favorites

License:

More by sjgcps:Domo CostumeZombie HunterBuggy Wheelchair Robot
Add instructable to: