RC Wheelchair 1: Difference between revisions

From Alnwlsn - Projects Repository
Jump to navigation Jump to search
(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:
Simple telephone line simulator
Making an electric wheelchair remote controlled


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 this one which inspired me to try it out using historically accurate methods.
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


All would probably have gone fine, except that there are no more dial up providers since nobody uses dial up anymore, so I made my own, using another modem, and linux server with software on it intended to provide a way for you to "dial in" from a remote area and access your home computer. Because the server has internet access, it can share it over the connection. But that is another story. Anyway, I could have connected the server up to my phone line, then gone to a friend's house and called my house. But who has a landline anymore? The biggest problem for me was that without a landline, I had no way to connect my old laptops to this server.
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.


Back in the day when you connected to the internet, you would call up your service provider with your modem. The call would be routed through the telephone exchange just like any other call and ring a modem connected to the ISP's infastructure. Modems are telephones, they behave electrically as telephones, and computers use them in the same way as you do when you talk on the phone -- to send and receive information -- except that your voice is replaced with those annoying high piched tones. I have both ends of the connection, my old laptop and my ISP-server-thing, so all I need to do is emulate the telephone exchange and I can do this experiment.
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 easiest way I have found to do this is with this circuit. Modem 1 represents my old laptop and modem 2 is the server.
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)


Cut a normal phone cord in half, and strip the wires inside. The red and green wires connect to the phone line. The other wires don't do anything. Just connect the modems together in series with a 9v battery and 330 ohm resistor. Telephones work by causing small fluctuations in current. In a series circuit the current is the same for all components, and so fluctiuations from one phone will be felt by the other. Anyway, if you replace the modems in the picture with normal telephones, you will notice that if you pick up both handsets and talk into one, you will hear your voice in the other. This "talk" circuit behaves like a telephone line that is permantly connected, and will not disconnect if you hang up. Likewise when the modems are connected, they won't know the diffrence between this and a telephone line, although you will need to disable dial tone detection (via AT command) so the modems will still dial. Piece of cake.
              Center at 2.5V


But this isn't the whole picture. With the dial tone detection disabled, modem 1 will dial, and try to talk to modem 2. But modem 2 can't answer because it is still on hook, and doesn't know that modem 1 is trying to call it. The telephone exchange signals an incomming call with about 90 volts AC current at about 25Hz. This current used to ring the mechanical bells in telephones to alert someone that there was an incomming phone call. For modem 2 in the server, when it recives the ring signal it will automatically pick up and try to talk to the modem that it assumes has called it. To simulate the ring signal on modem 2 after we tell modem 1 to dial, we have to disconnect modem 2 from the talk circuit and apply the ring voltage to it.
  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.


So the process for connecting the modem 1 (the laptop) to modem 2 (the server) is as follows: First, disable the dial tone detection on modem 1. Next, tell the laptop to dial up the ISP. Modem 1 will go off hook and dial the number (this doesn't do anything, so you can set the number to whatever you want). After modem 1 is done dialing, disconnect modem 2 from the circuit and apply the ringing current for a few seconds. Then disconnect it, and connect modem 2 back to the talk circuit. A SPDT switch configured to switch modem 2 between the ring generator and the talk circuit makes it easy to do this switch.
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.


If modem 2 picks up, you're in buisiness. If not, sometimes it takes a couple rings (eg if it is configured to pick up on the 3rd ring) before modem 2 will pick up. Another quick note, some modems will not dial if they don't detect any talk current; they might just think they aren't plugged in. If this is the case for modem 1, you can just connect connect another switch and 330 ohm resistor across the two grey connection points. This will allow you to give current flow to modem 1 when it tries to dial, since modem 2 is off hook and no current would flow otherwise. I am guessig that most modems won't need this, however.
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.


Now, about that "ring generator" component. The correct ring voltage -- 90v AC at 25hz -- is hard to come by. One really easy way to generate it is to use one of these:
Figure 3. Connection to motor controller.


This thing is a ring generator dynamo for a telephone, and is the crank on the side of very early (wooden) wall telephones. Despite being antiques, these phones are still compatible with modern systems. The back has two connetions which go to the blue wires in my drawing. When I want to give modem 2 a ring signal, I just flip the switch and give the crank a few turns. However seeing as these dynamos are pretty rare these days, I have an alternate solution.  
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.


Just get two AC power adapters, the wall-wart kind. They both have to output AC, and one must output 9VAC and the other 12VAC, assuming you have 110V mains. Plug the 9VAC one into the wall. Then, connect the output of the 9VAC to the output of the 12VAC. The prongs on the 12VAC wall-wart will now have about 90VAC on them. So the 12VAC adapter will be used in reverse, to step up a low voltage 9VAC to a higher 90VAC. Most newer equipment doesn't care if the frequency is 60Hz instead of 25, since modems and new phones don't have mechanical bells. Also, the transformers are small and will not output too much current, especially with a 1k resistor on the secondaries, so it is less likely you will damage anything. Still be careful though, since it will give you a nasty shock if touched! Also, in case you were wondering, it is also possible to ring telephones by connecting them directly to mains, though DO NOT DO THIS, since when the phone is picked up it will CATCH ON FIRE which will both break your equipment and burn your house down.
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