Monday, November 19, 2012

Can You Still Call it "Walking a Mile in their Moccassins?"

Can You Still Call it "Walking a Mile in their Moccasins?"

Up until now, my personal all time favorite essay was written back in 1997 for my History of Science class when I wrote about the history of the barber-surgeons and how they fixed a delicate problem for the King Of France. This piece is now my favorite and is dedicated to the wonderful people at the South Saskatchewan Independent Living Centre.

Back in May of 2012 my daughter, Elizabeth, ended up injuring both ankles badly enough that she could not walk a step; she would require the use of a wheelchair. Since we didn’t know how long she would need it, we decided to purchase a second hand manual wheelchair for about eighty dollars. She is now recovered, and the wheelchair had been sitting unused in the storage room in our house for a few months. Her experiences in the chair gave her a personal appreciation for the accomplishments of the disabled along with the struggles, both physical and social, they face on a daily basis. In November of 2012, I decided as a personal challenge to spend two days as a paraplegic and get a sense of the realities of life in a wheelchair.

While I could talk in depth about how difficult it is as a big fat guy to propel myself using the handrims, and how my arms were quickly exhausted from the effort, I will not, because that is an issue that is quickly solved with exercise and practice. By the end of the day, I was getting better. Given time, the apparent effort needed for self-propulsion in a wheelchair would be no different than the normal effort needed for walking. I’m out of shape, the wheelchair simply pointed that fact out to me in a roundabout way. Despite my inexperience in a wheelchair, I was still able to notice a few challenges that people in wheelchairs face on a daily basis.

The first thing I really noticed about moving around in a wheelchair is that Saskatchewan is not as flat as it appears. Since I am not allowed to use my daughter’s handicapped parking permit, and I wouldn’t use it myself even if I could, I parked in my normal spot in Lot 17 at the University of Regina, a gravel parking lot that normally leaves me with an easy ten minute mosey over to class, over what appears to be flat terrain. Even when sleepy after a long night working on my Computer Science projects, I can still walk in a straight line to class and avoid walking on the grass or running into light poles.

There is no such thing as flat when you are in a wheelchair. Downhill is easy, right? Point the chair in the direction you want to go and coast to the bottom, keeping your hands close to the handrims so you can apply the brakes when needed. Um, no. While speeding downhill in a wheelchair, you will discover the sideways slant that pulls the chair to one side, forcing the front off the sidewalk and tipping the chair over, throwing you into the grass. Properly aiming the chair is much like putting in golf. On the golf green, if you aim the ball directly at the hole, you will miss. Instead, you have to read the break of the green and aim the ball uphill from the hole so that gravity does the rest, dropping the ball in the center of the hole. In a chair, if you only aim at where you walk to go, you will either end up in the ditch or you will have to keep readjusting your aim, wasting a lot of energy in the process. If I drove like I move about in a wheelchair, I would end up with a DUI.

When walking, do you slow down when walking through an open door? If you are like me, one moment you are in the Archer Library Building, the next moment you are in the AdHum building without realizing you walked through a doorway. A closed door isn’t even much of an obstacle to a fully bipedal human, open the door with one hand, hold it open for the person behind you and keep on walking. I can even do that, drink from my water bottle, and respond to a text message without slowing down at all.

This does not happen in the wheelchair. Even an open door is an obstacle, as the width of most door frames is just a bit bigger than the width of the wheelchair. The process of going through an open door isn’t too bad, but you have to make sure the chair is lined up directly through the center of the doorframe, and that your hands won’t get pinched between the frame and the handrims as you slowly push your way through the door. Another way is to just grab the door with one hand, the frame with your other, and pull your way through.

Closed doors can have a huge effect on the accessibility of the building, especially in some corners of the University. If you are lucky, there will be an automatic door opening button, and it will be on the same side of the hall as the door it opens. Others, like the one connecting the Archer Library to the Residences, have the door button on the right, but the door on the left is the one that opens. This means you have to travel right to push the button, reverse in traffic, line up the chair properly, and pass through the door as it shuts behind you trying to catch your rear wheel. If the button is instead beside the door, it’s a simple matter to line up the chair to the door, push the button, and go through. Why can’t they all be like that?

Worst of all is a closed door that does not have a button to open it. If it is your classroom door, your best bet is to simply thank your classmate for opening and holding the door for you. However, if you are alone in the CS lab, trying to find and fix the annoying bug in your code after everyone has left, you will have to open the door yourself. This is a process that involves setting your brake, turning the doorknob, push (or pull) the door, and use the chair to keep it open while you pull yourself through the door frame. Good luck sipping a drink and texting while doing this.

Carrying a drink and your lunch is not easy in the chair. For someone able to walk ordering a drink and a meal is simple. Order, pay, grab your drink, find a table, sit down, wait for your number to be called, walk to the bar, grab your food, return to your table, and eat. Easy. However, in the wheelchair, how do you carry a glass filled with your beverage of choice with one hand, and propel the chair with the other? It’s not easy. A real paraplegic likely wouldn’t be able to hold the drink between their legs. Even if I cheated and used my thighs to hold the glass, it would likely spill as I made my way to the table. My only real option was to hold the drink with one hand and propel myself with the other hand, and switch hands every push of the chair. This is not very efficient, but it does work. It is easier to simply place the food platter in your lap to move to your table, but anything bigger, like a bag of groceries, and you will begin to have a much more difficult time.

After eating and drinking, the next step is to visit the washroom. Normally this function is completely automatic. You walk in, do your business, wash up, and walk out. Able bodied people do not rate washrooms on their degree of difficulty to get in and use. Unfortunately for those in wheelchairs, not all washrooms are accessible. It takes more than just a wider stall; just like a door, you must also be able to line up the chair to the entrance. Inside the stall, you have to spin the chair 180 degrees, and reverse to the toilet in order to transfer over. I still have not figured out how true paraplegics lower their pants in order to use the toilet. To be honest, once I got the chair over to the toilet, I cheated. After finishing up, there was another problem: I could not reach the soap dispenser, and it was quite the stretch to reach the sink to let the motion sensors activate the water taps. Again I had to cheat, either because the sink area was inaccessible or I was just too inexperienced to figure out how to do it.

The most surprising aspect of working with a wheelchair is that surfaces matter. Hard, smooth surfaces are best. A soft carpeted surface makes it seem like you are wheeling uphill due to the excessive friction between the carpet and the wheels. You have to continue to push the handrims to move; if you stop, so will the chair. Decorative surfaces, like in the Education and Kinesiology Centre, that may look hard still rub against the wheels, slowing them down, making every meter a hard push. The plain linoleum in the Classroom building is the best surface I found for using the wheelchair; I was actually able to glide a bit through the hallways and rest my aching hands a bit. The worst surface is a frosty sidewalk. The light dusting of snow and frost takes away all traction from the wheels preventing almost all movement. You can spin the wheel as much as you want, but the chair only moves a few centimeters at a time. It was so bad, that I actually had to abandon my simulation and walk the chair back to my van. Very few people would notice a difference in the effort needed to walk across these surfaces, but in a chair you notice every change; not all of them are good.

I finished my two days as a paraplegic exhausted, sore, but incredibly thankful for the experience. Two days after finishing the experiment, my hands are rubbed raw with small blisters on the fingers, and the muscles in my wrists, forearms, and pectoral region are still stiff and sore from the unexpected workout. My experiences with the wheelchair have alerted me to the more subtle issues that make it more difficult for people in wheelchairs to move about and take care of daily living. Prior to my daughter or myself being in the chair, I believed that the only consideration for wheelchair accessibility would be extra maneuvering space and alternatives to stairs. Wider bathroom stalls, wider aisles in classrooms, and ramps or elevators to deal with elevation changes. Spending two days in the chair has opened my eyes to the subtle challenges that face the users of wheelchairs and other mobility aids. When others complain of the cost of making modifications to make building more accessible, my response is simple:

“What if it was you who couldn’t use the washroom in this building?”

Thursday, November 1, 2012

Build update: Which way are you going?



While my kids went out with their mother for Hallowe'en, I stayed home to work on the chair while handing out candy. When I initially planned this project, I broke it down into 5 milestones in the 3 sections of the chair build. Those milestones were:

# Turn/Brake/Reverse Indicators Proximity Sensors Quote of the Day
1 2 LEDs, one for left, one for Right. No reverse or brake lights None None
2 Multiple LEDs to form an arrow shape. Brake and reverse indicators included None Brake light blinks message in Morse Code
3 Speaker included for reverse audio alerts Rear Installation only Messages appear on LED; Messages hard coded into Arduino sketch
4 Same as 3 Front and rear. Same audible alert for each side. Text alert in rear for tailgaters Messages on LED controlled by a web interface accessible when Arduino attached to the Internet
5 Turn signals turn off based on the differential speed of the wheels Audible alerts for front and rear will be different. Vibration alert in the seat as well Twitter interface - displays the latest tweets with a certain #hashtag

Entries for Milestone 5 are my stretch goals, chances are I won't get there in the time I have, but it means I always have something to do.

I have accomplished Milestone 1.5 for the Indicator lights. Both my left and right turn signals work in addition to the reverse light. I am currently having difficulty with the brake light (it is always on) and the system is not calculating the speed properly yet. The sensors are working properly so I know its just a matter of fixing the code. I think the problem is that I'm running out of SRAM memory on the Arduino, it only has 1024 bytes.

Creating a Rotary Encoder


The most complicated sensor on the wheelchair is also the most important. A rotary encoder measures the rotation of a wheel and with a bit of math and physics can measure real world data like distance traveled, the current speed, and even the direction of the wheel.
For this project I am using two photo sensitive resistors to build the rotary encoder. One of them is visible in the picture, the other is hidden by the spoke on the bottom of the chair. These sensors can detect the changing light levels caused by the spokes moving past them.
If I only had one sensor, I could measure the speed of the chair, the distance it has traveled, and when it is accelerating or braking. Although either one of the sensors can make these measurements, I am using the "Brake Sensor" to make these measurements.
The purpose of the "Reverse Sensor" is to work with the Brake Sensor to determine when the wheel is moving in reverse. Since they are offset from each other, one of the sensors will always be covered by a spoke before the other one.
The graph shows troughs as the spokes pass the light sensitive resistor. When moving forward you can see that the trough for the forward sensor happens a few microseconds before the reverse sensor is blocked by the spoke on the chair. When reversing, the brake sensor will be covered just before the reverse sensor (you can picture this if you imagine the graph going from right to left). The Arduino is sensitive enough to detect this minute difference.

Saturday, October 20, 2012

Reading the Fake Sensor Data

Now that we have created the fake sensor data and put it into a CSV file, we can now re-use the sensor data to help troubleshoot and debug the rest of your system. The first step is to download Processing (if using a Windows system, get the 32 bit version or you won't be able to use its Serial features).

The Processing environment is almost the same as that for the Arduino. Processing will be responsible for reading the CSV file and sending it over the serial connection to the Arduino.

While running the Processing Serial connection, you WILL NOT be able to use the Serial Monitor on the Arduino or upload updated sketches to the micro controller.

However, you can have Processing display any Serial.print() output from the Arduino.

When you need to upload a sketch to the Arduino, just make sure you press the STOP button on the Processing IDE prior to uploading.

The biggest advantage with this is that you can test your much cooler code quickly and easily with a predicable test environment. When you are ready to move to testing with real sensors (which will have to be done anyway later on) it will be trivial to get the input from the sensors themselves rather than from the serial connection.

Enjoy!

Processing Sketch

import processing.serial.*;
String myFile = "c:/mydata.csv";   //note the direction of the slash
String arduinoResponse;            //for displaying Arduino Serial.print() data
Serial myPort;
int delayTime = 25;    
//How long between each byte being transferred. If there isn't enough of a pause
//you could have some unpredictable results.
void setup() {
  //Replace COM3 with your actual serial port
  myPort = new Serial(this, "COM3", 9600);
  
  //The entire csv file will be stored in a string array.
  //One line of the csv per array element
  String lines[] = loadStrings(myFile);

  //Write each line to the serial port, one character at a time
  for (int i =0; i < lines.length; i++) {

    for (int j = 0; j < lines[i].length(); j++) {
      //print (lines[i].charAt(j));
      myPort.write (lines[i].charAt(j));
      delay(delayTime);
    }

    delay(delayTime); 

    //Read any output the Arduino sends over Serial. Great for debugging.
    arduinoResponse = myPort.readString();
    println (arduinoResponse);
  }
}

Arduino Sketch
//Global Variables and Constants

int NUMCOL = 5;    //Number of columns in the sensor data

//Input pins
const int TS = 0;       //time stamp, not really a pin, but...
const int brake = A1;   //Arduino Analog Pin 1
const int BRAKE = 1;    //Column 1 in the array
const int reverse = A2;
const int REVERSE = 2;
const int left = A3;
const int LEFT = 3;
const int right = A4;
const int RIGHT = 4;

//Array that holds sensor readings
const int HISTORY = 100;
//Length of the reading history (set to 1 if only only need the current dataset)
const int CURR = 0;      //0th row is the current reading
long int sensorReading[HISTORY][NUMCOL];    //Sensor readings stored here.

void setup() {
  //Initialize historical arrays to -1 (a reading that is always invalid)

  for (int i = 0; i < HISTORY; i++) { 
    for (int j = 0; j < NUMCOL; j++) {
      wheelSensor[i][j] = -1;
    }
  }

  //Open serial connection to Processing sketch
  Serial.begin(9600); //Make sure Processing and Arduino agree on this number
}


void loop () { 
  readSensor();
  //DoCoolStuffWithSensorReadings(). Your other code goes here.
}



void readSensor () {

  //Get the current reading from the wheel sensors, place them in
  //the current line.

  char currByte;      //Current incoming byte
  int currDigit;      //Convert char to digits
  int currColumn = 0;  //Current column we are working on
  long int currNumber = 0;  //Current number we are builing one byte at a time
  boolean readComplete = false;  //Have we read a full row yet?
  const char SEP = ',';  //Separator character
  const char END_FILE ='@'; //End of file character


  /*Shift the sensor reading array one row down to make room 
  for the current reading. Picture the most recent readings being 
  at the top of the array, and older ones at the bottom*/

  for (int i = HISTORY -1 ; i >=0; i--) { 
    for (int j = 0; j < NUMCOL; j++) {
      wheelSensor[i][j] = wheelSensor[i-1][j];
    }
  }

  //Get the next reading

  while (!readComplete) {

    if (Serial.available())  {

      currByte = Serial.read(); //Next byte on the serial line

      if (currByte >='0' && currByte <='9') {
        /*Get a number, convert it to an int, then put it in the one's place
         in the number we are building. Eg if the entry in the CSV is 654
         we will get 6, then 65, finally 654.*/
        currDigit = currByte - '0';
        currNumber = (currNumber * 10) + currDigit;
      }


      else if (currByte == SEP) {
        //Got a separater, number is complete, add it to the sensor array
        //We always add to the CURR row
        sensorReading[CURR][currColumn] = currNumber;

        //Reset the number we are building to make it ready for the next column
        currNumber = 0;

        if (currColumn == NUMCOL -1) {  
          //Last Column, reading is complete
          currColumn = 0;        
          readComplete = true;
        }

        else {
          //Move to the next column
          currColumn++;
        }

      }//End of Separator stuff

      else if (currByte == END_FILE) {

        Serial.end();
        break;  //Break out of while and close connection

      }

      else {
        //Invalid character
        //You can add your own error handling here if desired.
      }

    }// end of serial reading

  } // end of while loop

} // end of readSensor() function
Creative Commons License
Making a Better Wheelchair is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Faking It

The wheelchair project is progressing but one element is more difficult than I had initially anticipated; The ability of the chair to react appropriately to sensor input will require a lot of testing to get the results I want. The test procedure looks like this:
  1. Haul the wheelchair to the test site. Unlike other projects, I can't test it in my living room
  2. Hookup the Arduino, breadboard and wires.
  3. Run and videotape the test.
  4. Disassemble the chair, return home
  5. Find,  fix, and facepalm for typing if (a=b) instead of if (a==b)
  6. Repeat
Naturally, this is not feasible. I need a way to simulate all my sensor data from the computer and feed that information to the Arduino. A CSV file would be a natural way to do this. Simply send the contents of the file through the Serial point and I now have a way to run repeated tests, fiddle with my code, and make it work without having to keep running to the test site.

In other words, I have to fake the sensor inputs. This will take a few steps, and more than one post.

Building the Fake Date File (in CSV)

For my project I have 4 sensors planned at the moment and if things go well I may have 5 or 6. Each line in the CSV file will be in this format (the final comma is important):

   timestamp, brakeSensor, reverseSensor, leftSignal, rightSignal,

The Arduino Code to generate the CSV file from real sensor input is below:

//Global variables

const int NUMCOL = 5;  //How many columns in your CSV file
const char SEP = ',';  //Comma is the separator character
long int sensor[NUMCOL];  //long int because the timestamp could get long quickly
const int DELAY_TIME = 10; //How long between sensor readings

//Input pins

const int TS = 0;       //time stamp, not really a pin, but...
const int brake = A1;   //Arduino Analog Pin 1
const int BRAKE = 1;    //Column 1 in the array
const int reverse = A2;
const int REVERSE = 2;
const int left = A3;
const int LEFT = 3;
const int right = A4;
const int RIGHT = 4;

void setup() {
  Serial.begin(9600);  //Begin a serial connection
}

void loop () {
  
  //Since it's so fast, all readings can all share a single time stamp
  sensor[TS] = millis();  //get timestamp
  sensor[BRAKE] = analogRead(brake);
  sensor[REVERSE] = analogRead(reverse);
  sensor[LEFT] = analogRead(left);
  sensor[RIGHT] = analogRead(right);
  
  //Print to serial monitor
  
  for (int i = 0; i < NUMCOL; i++) {
    Serial.print(sensor[i]);
    Serial.print(SEP);
  }
  
  //Output the \n character to make the CSV easier to read
  
  Serial.print('\n'); 
  delay(DELAY_TIME);
  
} // end loop

To get the data to a CSV file, simply open up the Serial Monitor, and copy and paste to Notepad.  To make the next steps easier, you will need to do the following:

  1. At the very top, include or or two lines of "dummy data". When reading the file, this will give the serial port time to connect on both ends without risk of missing real data. I used two rows of all zeroes.
  2. Indicate the end of the file with an '@' character. I actually used @,@,@,@,@ but only one should be needed.


In the next post I will include the code needed to send the sensor data to the Arduino to allow you to "fake it" with your sensors.

Creative Commons License
Making a Better Wheelchair is licensed under a Creative Commons Attribution-ShareAlike 3.0 Unported License.

Friday, September 21, 2012

Planning the Chair

It's one thing to have the idea, it's another to get out there and build it, and finally its another thing all together to spend some money to get the parts you need. Since there aren't any real local electronic stores around here, I will be buying my parts from http://www.solarbotics.com since they are Canadian, eh?

Prior to actually getting the parts, and maybe ordering stuff I don't need, or missing stuff I DO need, I need to plan the build carefully.

Rear View Side View

Makes perfect sense? Actually it isn't really all that complicated.

On the rear view of the chair you see the main display screen in green. This will show the active turn signals, brake lights, reverse indicator, and the Quote of the Day (not all at the same time). Next to it in grey is the speaker system which at this point will provide both an audible reverse signal along with proximity alarms (someone's standing too close).

The white rectangle is the breadboard. A handy little device that allows wires to be connected without the need for soldering. I'm not very good at soldering so this is a life saver. It is attached with a bunch of data wires to the Arduino UNO (in blue) which is the brains of the whole operation. The Arduino is an open source micro-controller that allows easy hacking of electronics. It can read input from sensors or humans, process that input, and send output to various other devices. For example, if the user taps the yellow touch sensor on the left side of the chair, the Arduino will know that the sensor was triggered, then tell the LED display to blink the left arrow for 5 seconds. If the proximity sensor (orange diamond on the bottom of the chair) notes there is a "something" within 1.5 meters, the Arduino will show a "You are walking too close" message on the LED display, and beep the speaker to alert the user that someone or something is behind them.

The user will signal left and right turns by tapping on the yellow circles on the sides of the chair. Tapping both at the same time will also "power down" or "power up" the system. A combination of a magnet attached to the spokes of the chair (red), and a pair of Hall-effect sensors (pink) will continuously calculate the speed and direction of the chair. If the chair slows down suddenly, the LED display will show the brake light, and if the chair goes in reverse, the reverse indicator will light up, and an audible alarm will sound.

The entire system will be powered by 5 AA batteries on the rear of the wheelchair (brown with gray stripes).

There you go, all you need to know. Simple really. Maybe I should have gone with something more complicated.


Thursday, September 20, 2012

The Project



The Class


My CS 207 (Building Gadgets) class at the University of Regina is going to simply be, without exaggeration, the most thrilling, the most educational, the most exciting class I have ever taken. Why? Because of final projects like these:


Who doesn't want to build a motion sensing, automatic paintball gun security system?

Ok, I don't want to, but I did think about a bull made out of Lego that would charge only at red things.

Then I remembered the misery daughter had with her wheelchair, and thought, "There has to be something I can do to make it better." After all, that's what dads do, isn't it.

What I Hope to Accomplish

In this project, I will be solving a problem that users of manual wheelchairs face on a daily basis - they are invisible to able bodied people walking near them. This leads to collisions, and squished toes, as people don’t see the person in the wheelchair as they make turns, stop, and back up. This becomes even more important in more crowded areas like schools and shopping malls where traffic becomes stupider the more people added. The proposed solution borrows from another well known facet of Western Civilization that suffers from stupid people -- traffic.

The Current Chair

I will be using a typical manual folding wheelchair. Now that my daughter is using a walking boot cast and seems to be recovering, I have the chair all to myself.

Complete with Cat

The Tricked Out Chair

We will create a system that will show turn signals, break lights, reverse gear indication (along with the Beeeeep, Beeeeep, Beeeep sound) so that others will know to get out of the way of the person in the chair.  In addition to the turn signals, it can also display custom messages (easily updated in the source code), and rotate them on a regular basis. For example:

I heard what you said about my chair
It wasn’t very nice.

I’m only 11 and have my own wheels.
U Jelly?

You can’t hurt my toes.
My wheels can hurt yours - stay clear.

Sit down for what you believe in!

The system should be able to get input from the user or the environment so that the turn signals and brake signals do not have to be complicated to signal. Preferably, it should be able to read the body language of the owner, KNOW that the owner is turning left, and put on the Left Signal automagically without requiring specific input from the user. (Unlike turn signals in a car that are manually activated).

Signals will turn off automatically after a few seconds. The user should also be able to easily turn off the system so that you don’t have distractions when settling into a classroom or other things where small, tight, maneuvers are required.

Sketch (c) 2012,  Elizabeth Johnston, used with permission