RC Wheelchair 1: Difference between revisions
(Created page with "Simple telephone line simulator A while ago I made a video where I connected old computers up to the internet with actual modems, which I had not seen in similar videos like...") |
No edit summary |
||
Line 1: | Line 1: | ||
Making an electric wheelchair remote controlled | |||
Note: If you have the exact same controller as I do (the so called VSI Controller, take a look [http://mowstation.blogspot.com/ here] This guy did a similar hack, and discovered all the connections needed to replace the joystick. It was really helpful | |||
Electric wheelchairs commonly use two styles of joysticks for control, inductive and resistive. Inductive joysticks work using coils and magnetic fields, while resistive joysticks are basically a couple potentiometers stuck together. Resistive units are much easier to hack, so I'll focus on those. | |||
The resistive joystick's potentiometers are set up as two voltage dividers, one for left/right, and another for forward/backward. My unit accually had four potentiometers in the joystick, providing two redundant signals per axis. The joystick outputs variable voltages between ground (0V) and the power supply of the contoller (5v). In my case, I found they output 2.5v at center position, and vary continuously (and linearly) with corresponding joystick motion in that axis. At the maximum limits of travel, the voltage is 1.0v at minimum, and 4.0V at maximum. | |||
The | The voltages output correspond to these desired actions. Each axis represents one of the two channels. | ||
<pre> | |||
Forwards (4.0V) | |||
| | |||
| | |||
Left (1.0V)--------+--------Right(4.0V) | |||
| | |||
| | |||
Backwards (1.0V) | |||
Center at 2.5V | |||
Figure 1. Controls/voltage chart | |||
</pre> | |||
The controller reads the voltages output from the joystick to do its thing. Now, we can replicate the joystick's function by just feeding the corresponding voltage into the controller. An easy way to do this is with an Arduino, and we can power it using the controller's own 5v internal suply. Don't forget to connect the ground to the ground of the controller. Everything has to have a common ground (of the controller) for any of this to work. | |||
Normally, a microcontroller like an arduino will output a pulsed dc signal between 0% and 100%. This is PWM, and is what the arduino outputs with an analogWrite() command. We can convert PWM into a true analog voltage using a low pass filter (See this). I raised the PWM frequency so the filter doesn't have to be massive, and to make sure we are well beyond the cutoff frequency so there is no ripple, and we really do get a voltage (not pulsed dc). This is probably not nessacary. | |||
Figure 2. Low pass filter. | |||
Now, instead of analogWrite() controlling the duty cycle of a 5v square wave from 0% to 100%, we control an analog voltage between 0v (0%) and 5v (100%). We need to be able to control the voltage between 1v and 4v to feed it into the wheelchair motor controller. Also, I have found that if the voltage is outside this range, the wheelchair senses a fault and will lock up. | |||
The two low pass filters (one for each channel) are connected to to the wheelchair controller in place of the "wiper" terminal. Mine has two redundant connections for each channel; I just connected the low pass filter to both of them. Also, I have found that if the other terminals of the potentiometers in the joystick are disconnected, the unit will again report a fault. | |||
Figure 3. Connection to motor controller. | |||
This | Next, we need some input into the arduino. This is provided by a standard hobby radio used to control servos. The pulseIn() function is used to read information from the radio. As it it is designed to for controlling servos, the signal is in the form of short pulses which vary in width depending on the control stick position. In the code, we use the Map function to linearly map the limits of the pulses from the radio to the limits of the PWM duty that will output the maximum (1.0v) and minimum (4.0v) voltages. | ||
We now have the complete system. The radio servo signal is sent to the arduino, which outputs a pwm signal. The pwm is filtered into a true analog voltage, which is then sent into the wheelchair motor controller in place of the joystick potentiometer wiper. Add a second radio servo output and another low pass filter, and both channels needed to control the wheelchair are covered. | |||
The little program that the Arduino runs to do the translation is shown below. It runs on an ATTiny85, but this can easily be adjusted to run on a normal Arduino. I only used an Attiny since I had limited space inside the wheelchair handle. | |||
<pre> | |||
/* | |||
Basic wheelchair controller 1 for ATtiny85 (arduino) | |||
Rc channels in on 3(x) and 4(y) (pins 2 and 3 on hardware), outputs on 1(x) and 0(y) (pins 6 and 5). | |||
Use a low pass filter on the outputs to get var. voltage, a 10uF and 10k resistor worked for me. | |||
pin ctrlr gnd | |||
+--\/\/\--+--](-----+ | |||
in out gnd | |||
*/ | |||
int chX; // channels | |||
int chY; | |||
int x; //outputs (map to whatever value you need) | |||
int y; | |||
void setup() { | |||
TCCR0B = TCCR0B & 0b11111000 | 0b001 ; //raise pwm freq so we can use a low pass filter for a higher frequency (and smaller capacitors) | |||
//if using an arduino this will be diffrent - google it | |||
pinMode(3, INPUT); | |||
pinMode(4, INPUT); | |||
} | |||
void loop() { | |||
chX = pulseIn(3, HIGH, 25000); // Read the pulse width of RC, 25000 microseconds is timeout. | |||
chY = pulseIn(4, HIGH, 25000); | |||
x = map(chX, 880, 1660, 55, 197); //adjust these for mapping (1800 is stick dwn right, 720 is up left) | |||
y = map(chY, 1720, 850, 55, 197); //left (x) on chair is reversed, positive = right (the mapping is a little different because the pulses of the receiver are not a precision timed thing) | |||
// they need to be mapped to between 1 and 4 volts, not 0 to 5, because that is what the potentiometers on the wheelchair joystick output. Stopped is 2.5v (approxamently, I obtained these experimentally.) | |||
if ( x < 0 || x > 255) { //safety, if the reciver shuts off, pulseIn will become 0 and the x and y will map to greater than 255 (this would make the wheelchair get an unexpectedly high voltage and go into error. | |||
x = 126; //so set them to center the joystick instead. | |||
} | |||
if ( y < 0 || y > 255) { | |||
y = 126; | |||
} | |||
if ( x < 55) { //constrain pwm values in specified area (because if the voltage goes outside 4 volts or below 1 volt the wheelchair controller will suspect that somthing is wrong and lock up for safety) | |||
x = 55; | |||
} | |||
if ( y < 55) { | |||
y = 55; | |||
} | |||
if (x > 197) { | |||
x = 197; | |||
} | |||
if (y > 197) { | |||
y = 197; | |||
} | |||
analogWrite(1,x); | |||
analogWrite(0,y); | |||
delay(2); | |||
} | |||
</pre> | |||
Article written Oct. 16, 2016 |
Latest revision as of 21:50, 30 October 2017
Making an electric wheelchair remote controlled
Note: If you have the exact same controller as I do (the so called VSI Controller, take a look here This guy did a similar hack, and discovered all the connections needed to replace the joystick. It was really helpful
Electric wheelchairs commonly use two styles of joysticks for control, inductive and resistive. Inductive joysticks work using coils and magnetic fields, while resistive joysticks are basically a couple potentiometers stuck together. Resistive units are much easier to hack, so I'll focus on those.
The resistive joystick's potentiometers are set up as two voltage dividers, one for left/right, and another for forward/backward. My unit accually had four potentiometers in the joystick, providing two redundant signals per axis. The joystick outputs variable voltages between ground (0V) and the power supply of the contoller (5v). In my case, I found they output 2.5v at center position, and vary continuously (and linearly) with corresponding joystick motion in that axis. At the maximum limits of travel, the voltage is 1.0v at minimum, and 4.0V at maximum.
The voltages output correspond to these desired actions. Each axis represents one of the two channels.
Forwards (4.0V) | | Left (1.0V)--------+--------Right(4.0V) | | Backwards (1.0V) Center at 2.5V Figure 1. Controls/voltage chart
The controller reads the voltages output from the joystick to do its thing. Now, we can replicate the joystick's function by just feeding the corresponding voltage into the controller. An easy way to do this is with an Arduino, and we can power it using the controller's own 5v internal suply. Don't forget to connect the ground to the ground of the controller. Everything has to have a common ground (of the controller) for any of this to work.
Normally, a microcontroller like an arduino will output a pulsed dc signal between 0% and 100%. This is PWM, and is what the arduino outputs with an analogWrite() command. We can convert PWM into a true analog voltage using a low pass filter (See this). I raised the PWM frequency so the filter doesn't have to be massive, and to make sure we are well beyond the cutoff frequency so there is no ripple, and we really do get a voltage (not pulsed dc). This is probably not nessacary.
Figure 2. Low pass filter.
Now, instead of analogWrite() controlling the duty cycle of a 5v square wave from 0% to 100%, we control an analog voltage between 0v (0%) and 5v (100%). We need to be able to control the voltage between 1v and 4v to feed it into the wheelchair motor controller. Also, I have found that if the voltage is outside this range, the wheelchair senses a fault and will lock up.
The two low pass filters (one for each channel) are connected to to the wheelchair controller in place of the "wiper" terminal. Mine has two redundant connections for each channel; I just connected the low pass filter to both of them. Also, I have found that if the other terminals of the potentiometers in the joystick are disconnected, the unit will again report a fault.
Figure 3. Connection to motor controller.
Next, we need some input into the arduino. This is provided by a standard hobby radio used to control servos. The pulseIn() function is used to read information from the radio. As it it is designed to for controlling servos, the signal is in the form of short pulses which vary in width depending on the control stick position. In the code, we use the Map function to linearly map the limits of the pulses from the radio to the limits of the PWM duty that will output the maximum (1.0v) and minimum (4.0v) voltages.
We now have the complete system. The radio servo signal is sent to the arduino, which outputs a pwm signal. The pwm is filtered into a true analog voltage, which is then sent into the wheelchair motor controller in place of the joystick potentiometer wiper. Add a second radio servo output and another low pass filter, and both channels needed to control the wheelchair are covered.
The little program that the Arduino runs to do the translation is shown below. It runs on an ATTiny85, but this can easily be adjusted to run on a normal Arduino. I only used an Attiny since I had limited space inside the wheelchair handle.
/* Basic wheelchair controller 1 for ATtiny85 (arduino) Rc channels in on 3(x) and 4(y) (pins 2 and 3 on hardware), outputs on 1(x) and 0(y) (pins 6 and 5). Use a low pass filter on the outputs to get var. voltage, a 10uF and 10k resistor worked for me. pin ctrlr gnd +--\/\/\--+--](-----+ in out gnd */ int chX; // channels int chY; int x; //outputs (map to whatever value you need) int y; void setup() { TCCR0B = TCCR0B & 0b11111000 | 0b001 ; //raise pwm freq so we can use a low pass filter for a higher frequency (and smaller capacitors) //if using an arduino this will be diffrent - google it pinMode(3, INPUT); pinMode(4, INPUT); } void loop() { chX = pulseIn(3, HIGH, 25000); // Read the pulse width of RC, 25000 microseconds is timeout. chY = pulseIn(4, HIGH, 25000); x = map(chX, 880, 1660, 55, 197); //adjust these for mapping (1800 is stick dwn right, 720 is up left) y = map(chY, 1720, 850, 55, 197); //left (x) on chair is reversed, positive = right (the mapping is a little different because the pulses of the receiver are not a precision timed thing) // they need to be mapped to between 1 and 4 volts, not 0 to 5, because that is what the potentiometers on the wheelchair joystick output. Stopped is 2.5v (approxamently, I obtained these experimentally.) if ( x < 0 || x > 255) { //safety, if the reciver shuts off, pulseIn will become 0 and the x and y will map to greater than 255 (this would make the wheelchair get an unexpectedly high voltage and go into error. x = 126; //so set them to center the joystick instead. } if ( y < 0 || y > 255) { y = 126; } if ( x < 55) { //constrain pwm values in specified area (because if the voltage goes outside 4 volts or below 1 volt the wheelchair controller will suspect that somthing is wrong and lock up for safety) x = 55; } if ( y < 55) { y = 55; } if (x > 197) { x = 197; } if (y > 197) { y = 197; } analogWrite(1,x); analogWrite(0,y); delay(2); }
Article written Oct. 16, 2016