Thursday, May 5, 2011

The Speed Stick -- Research Article

Introduction:
In the United States, there are 3.3 million people over the age of 40 with vision impairments that cannot be mitigated with glasses, contacts, pharmaceuticals, or surgery. Of these 3.3 million, 937,000 are blind. The most common causes of blindness are age-related diseases such as macular degeneration, cataract, and glaucoma. Due to the aging population, the number of blind people is expected to increase to 1.6 million in 2020 (Congdon, et al., 2004).

In order to navigate independently, the vision impaired people require mobility tools. The standard is the long white cane, which is used to sweep the ground for obstacles and to indicate to others that the user is blind. The cane is lightweight and inexpensive, and requires minimal maintenance. However, these canes give a limited range of information. The optimal cane length is 8 inches shorter than the user, which means that a 5’6” person would have a 4’10” cane (National Federation of the Blind, 2011). Since the cane is held at an angle, the actual range is approximately 3.5 feet. This limited range restricts the speed at which the person can travel and forces the person to react quickly to obstacles. Furthermore, the cane cannot tell the user if there is a fast approaching obstacle, whether it is a person or a car. Therefore, walking down the street and crossing the road are much more perilous and nerve wracking for the blind.

Another common tool for the vision impaired is the guide dog. Dogs possess natural intelligence and can communicate to a certain extent with humans. However, some people are allergic to dogs or do not want to spend time and money caring for dogs. Furthermore, dogs cannot perceive color the same way humans do, so they cannot be trained to understand traffic lights. The human has to determine when to cross the road by listening to the flow of traffic, which leaves room for uncertainty and risk (Hersh & Johnson, 2008).

Enhanced canes using ultrasound technology include the GuideCane, a prototype with wheels designed by Borenstein and Ulrich. The GuideCane is a rolling unit with ten ultrasound sensors, a computer, and servo motors. The sensors receive inputs from the environment that the computer processes. If there is an obstacle in the user’s path, the servo motors steer the wheels of the cane, changing the user’s path. However, this device is relatively heavy at 4 kg, which limits its portability, especially when navigating stairs. Other enhanced canes use infrared laser technology to detect obstacles; however, this technology can sometimes miss glass or transparent plastic barriers such as glass buildings, doors or bus shelters (Hersh & Johnson, 2008).

Objectives:
The aim was to increase the range of the common white cane and to add a speed detection function. The device was named “Speed Stick” and we considered several criteria when designing it. First, the device needs to produce a real-time analysis of the environment in order to provide useful information when the person is moving. Second, the cane should be easy to understand and use with minimal training. More specifically, the outputs of the cane need to solicit the correct intuitive reactions from the user. For example, the user should not have to think extensively in order to figure out that the cane is trying to tell him to “get out of the way now.” Third, the cane needs to accommodate people of varying heights. Lastly, the cane should be light weight and balanced.

Hardware:
The cane utilizes one LV-MaxSonar-EZ4 ultrasonic transducer, one cellphone vibrating motor, two battery packs of four AA batteries, and one Arduino microcontroller. The vibrator housing was designed using SolidWorks.  It was printed using Penn’s 3D printer in the MEAM department.  
 
The inputs to the system come from the ultrasound transducer, which both sends and receives ultrasound waves. The Arduino then processes the input and sends signals to the cellphone vibrating motor. Finally, the motor provides vibrational outputs.

The transducer is secured to approximately the halfway point of the shaft of the cane so that it is located close enough to the ground to detect low lying obstacles. The transducer is not placed directly on the tip of the cane because the tip is used to tap objects and sustains the most damage from uneven terrain (Hersh & Johnson, 2008). Furthermore, the angle of the transducer relative to the ground is manually adjustable to accommodate people of varying heights who may hold the cane at different angles. The microcontroller and the battery packs are secured directly behind the transducer on the backside of the cane, which minimizes lengthy wires and tangling. Additionally, it is intuitive to the user which side the transducer is on because the cane will naturally rest in the proper position as a result of weight distribution. The cane and its components can be seen in the following image.  One battery pack supplies the ultrasound transducer, while the other pack powers the rest of the components. The vibrator is secured to the top of the cane, near the handle, for optimal transfer of vibrational information. The motor is housed in a specially-designed plastic shell that protects the wiring from accidental damage.

Software:
The software design is one of the more important aspects of the Speed Stick.  The coding enables the microcontroller to take as an input ultrasound pulse width and output that into vibration frequency.  The approach to coding the input and output will now be delineated.

Input:
The ultrasound transducer is capable of providing several types of information to the microcontroller.  The Speed Stick uses pulse width as its input.  The pulse width, according to the transducer’s datasheet, is the “time duration of the time domain envelope that is 20dB above the rising and decaying cycles of a transducer response.”  The pulse width thus varies depending upon the distance that an ultrasound signal has to travel to reach an object.

A time duration variable is first created that takes as its value the time domain length of the pulse width.  This time value is then converted into distance using the "microsecondsToInches" function, seen in the following.  The conversion factor is based off the fact that there are 73.75 microseconds per inch, assuming sound travels at a speed of 1130 feet per second.  This result is divided by 2 to account for the fact that the sound travels to the object and back.  The validity of this conversion was verified with a meter stick.  This function was harvested from the Arduino references pages. 

long microsecondsToInches(long microseconds)
{
  return microseconds / 74 / 2;
}

Output:
With a distance value in hand, the next step is to tell the cellphone vibrator when to vibrate.  There are two target functionalities that use the vibrator within the Speed Stick: to alert the user if there is an object moving toward them above a given velocity, and to inform the user of the distance between the Speed Stick and an object. 

The velocity functionality works as a binary operator: either there is an object quickly approaching them or there is not.  The output is a simple yet distinctive 2-second vibration.  To determine when to give this emergency output, however, is more interesting.

The algorithm uses an array called distanceArraySpeed.  The algorithm assigns 3 values into the array over time, sorts them in numerical order using a function called bSort1, and then takes the middle value.  This middle value, after these operations, is the median.  This approach acts as a sort of filter that removes outlying values reported by the transducer.  Because this happens on the fly and a median is collected every 3 loop iterations no matter what, minimal delay is instituted.  The velocity is then calculated by taking the difference between two consecutive median values, and subsequently dividing that by the delta time.  The final step is to check the velocity against a velocity threshold, and to have the 2-second emergency vibration go off whenever the reported velocity exceeds it.

The second functionality, which tells the user how far objects are in front of them, is coded to behave in a very similar manner to the velocity functionality.  In this way, an array called distanceArray is used to collect distance values over time.  However, instead of taking only 3 distance values, it takes 5 values.  The rationality behind using 5 values instead of 3 values for this functionality is twofold: 5 values afford a much more robust filtering of outlying values, and practice tests indicated that the extra time it took to store 2 more values was negligible for this feature.  A median is thus calculated using the same sort function that is used in the velocity-warning algorithm.

The median is then sent through a band-pass filter that removes low and high aberrant values.  The high end cutoff is set to 100 inches, but can be increased to augment the amount of distance information that the user gets.  The hardware gives far less accurate information as the distance increases, however, so 100 inches was determined to be optimal for providing accurate information over a large area.

With an acceptable median value in hand, the next step is to tell the vibrator to vibrate at a frequency that correlates with the distance value.  It was decided that the frequency of vibrations should be high when objects are close, and the frequency of vibrations should be low when the objects are far.  A formula that utilizes a linear equation, shown in the following, was used to accomplish this.

digitalWrite(pin,HIGH);
delay(200.0+((median-5.0)/100.0)*800.0);
digitalWrite(pin,LOW);                  

In this way, when the median distance value is low (i.e. when objects are close), the delay is small and the frequency of vibration is thus high.  The opposite is true for when the median distance value is high.  Another equation was also attempted that was non-linear (see Appendix), but the linear function gave a better performance in the end.

It is important to note that the velocity detection functionality can easily be turned off by setting velocityFeature to zero.  The distance detection functionality is always on.

Conclusion:
The Speed Stick is effective at providing the user with two types of information: whether there is an object moving towards the user above a velocity threshold, and informing the user the distance between the Speed Stick and an object.  The velocity-warning feature is limited by the rapidity with which data points are collected as well as the error-prone hardware that is used in the prototype.  The distance-detection feature is very robust in its current state, but would benefit from a more sophisticated ultrasound transducer.  The prototype demonstrates that the blind can be hopeful that there will be strong navigation-support alternatives to current options in the future. 



Works Cited:

Congdon, N., O'Colmain, B., Klaver, C. C., Klein, R., Munoz, B., Friedman, D. S., et al. (2004). Causes and prevalence of visual impairment among adults in the United States. Archives of Ophthalmology, 477-485.

Hersh, M. A., & Johnson, M. A. (2008). Assistive Technology for Visually Impaired and Blind People. London: Springer.
National Federation of the Blind. (2011). Free White Cane Program. Retrieved April 5, 2011, from National Federation of the Blind: http://www.nfb.org/nfb/free_cane_program.asp




Appendix:

/*
Nathan Carberry
Betty Huang
Project
April 27, 2011
*/

//variable definitions
int pin = 10;
int pinUS = 5;
float duration = 0;
int counter = 0;
int counterSpeed = 0;
const int arrayLength = 5;
const int arrayLengthSpeed = 3;
int distanceArray[arrayLength];
int distanceArraySpeed[arrayLengthSpeed];
int timeArray[2]={0,millis()};
float deltaX;
float deltaT;
float velocity;
float speedLimit = 2.8;
int velocityFeature = 0;

int printOn=0;  //give printing feedback on (1) or off (0)

void setup()
{
  pinMode(pin,OUTPUT);
  Serial.begin(9600);
}

//Note: Some of the following code relating to ping was borrowed from the Arduino references.

void loop()
{
  static int oldMedian=0;  //constant values created with static
  static int newMedian=0;
  // establish variables for duration of the ping,
  // and the distance result in inches and centimeters:
  long duration, inches, cm;
  int pingPin = pinUS;

  // The PING))) is triggered by a HIGH pulse of 2 or more microseconds.
  // Give a short LOW pulse beforehand to ensure a clean HIGH pulse:
  pinMode(pingPin, OUTPUT);
  digitalWrite(pingPin, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin, LOW);

  // The same pin is used to read the signal from the PING))): a HIGH
  // pulse whose duration is the time (in microseconds) from the sending
  // of the ping to the reception of its echo off of an object.
  pinMode(pingPin, INPUT);
  duration = pulseIn(pingPin, HIGH);

  // convert the pulseIn time into a distance
  inches = microsecondsToInches(duration);
  cm = microsecondsToCentimeters(duration);

  if(printOn==1)  //for observation purposes
  {
    Serial.print(inches);
    Serial.print("in, ");
    Serial.print(cm);
    Serial.print("cm");
    Serial.println();
  }

  distanceArray[counter] = inches;
  distanceArraySpeed[counterSpeed] = inches;
  timeArray[counter] = millis();
  counter = counter + 1;
  counterSpeed = counterSpeed + 1;

  int x = 1;
  int Value;
  int ValueIndex;
  int True = 0;
  int RangeHigh = 0;
  int RangeLow = 0;
  int RangeHighTwo = 0;
  int RangeLowTwo = 0;
  int median;

  //************************************************************************
  //alerts user if detected object moves at a certain speed towards the walking stick
  //************************************************************************

  if(counterSpeed==arrayLengthSpeed && velocityFeature==1)
  {
    bSort1(distanceArraySpeed, 0, arrayLengthSpeed);
    median = distanceArraySpeed[arrayLengthSpeed/2];  //finds the median value in the distanceArraySpeed

    timeArray[0]=timeArray[1];
    timeArray[1]=millis();

    oldMedian=newMedian;
    newMedian=median;

    deltaX=newMedian-oldMedian;
    deltaT=timeArray[1]-timeArray[0];

    velocity = deltaX*1.0/deltaT*1.0;

    if(velocity>=speedLimit && velocity<30)
    {
      Serial.println("FAST!!");
      digitalWrite(pin,HIGH);
      delay(2000);
      digitalWrite(pin,LOW);
    }
    else if(velocity<=-speedLimit && velocity>-30)
    {
      Serial.println("FAST!!");
      digitalWrite(pin,HIGH);
      delay(2000);
      digitalWrite(pin,LOW);
    }

    counterSpeed = 0;
  }

  //************************************************************************
  //creates vibration feedback that is correlated with distance
  //************************************************************************

  if(counter==arrayLength)
  {
    bSort1(distanceArray, 0, arrayLength);
    median = distanceArray[arrayLength/2];  //finds the median in the distanceArray

    if(printOn==1)
    {
       Serial.println(median);  //for checking values if printing is on
    }
    if(median<5)  //do nothing if median is less than 5 inches
    {
    }
    else if(median>100)  //do nothing if median is greater than 100 inches
    {
    }
    else
    {
      digitalWrite(pin,HIGH);
      delay(200.0+((median-5.0)/100.0)*800.0); //linear function that creates vibrations at a
      digitalWrite(pin,LOW);                   //frequency inverted with distance
    }
    counter = 0;

    //non-linear attempt at correlating distance and vibration frequency
    /*
    else if(median>50)
    {
    }
    else
    {
      digitalWrite(pin,HIGH);
      delay(200.0+sqrt(((median-5)/50.0)*900.0*900.0));
      digitalWrite(pin,LOW);
    }
    */
  }
}

//sorting function to aid in finding the median value
void bSort1(int array [], int from, int upTo) {
// code size = 74 bytes
 int swaps;
 do {
    swaps=0;
    for(int i = from; i < upTo; i++)
        if(array[i] > array[i+1]) {
          int x = array[i+1];
          array[i+1] = array[i];
          array[i] = x;
            ++swaps;
        }//for
  } while (swaps);
}//bsort1

long microsecondsToInches(long microseconds)
{
  // According to Parallax's datasheet for the PING))), there are
  // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per
  // second).  This gives the distance travelled by the ping, outbound
  // and return, so we divide by 2 to get the distance of the obstacle.
  // See:
http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf
  return microseconds / 74 / 2;
}

long microsecondsToCentimeters(long microseconds)
{
  // The speed of sound is 340 m/s or 29 microseconds per centimeter.
  // The ping travels out and back, so to find the distance of the
  // object we take half of the distance travelled.
  return microseconds / 29 / 2;
}

Wednesday, May 4, 2011

The Speed Stick

The following is an image of the Speed Stick prototype.


The following is an image of the vibrator housing right below the handle of the Speed Stick.  Vibrations can easily be felt, but are not distracting.


The following is an image of the circuitry.  The top battery back powers the microcontroller and the vibrator.  The bottom battery pack powers the ultrasound sensor on the other side of the Speed Stick.  The power is disconnected in this image.

The Vibrator Housing

The following is the SolidWorks design we used for our vibrator housing, and the end product after using Penn's 3D-printer.

The Circuit

The following is a picture of the circuit that we used for our device.

Demonstration of our Device

The following video shows how the device can be used to detect walls for the blind as they walk on a sidewalk.


The following video shows the second function of the device: alerting the user to high-velocity objects.  This would be useful for blind people who are trying to cross the street.  It is akin to looking left and right before crossing the street.

Monday, April 11, 2011

The parts...

Below is a picture of all the parts that we will need for our product (minus the walking cane).

In the middle of the picture is the Arduino microcontroller.  In the bottom-right hand of the picture is our ultrasonic range finder -- the LV-MaxSonar-EZ4.  To the left of that is a cell phone vibrator within a plastic housing that we printed out using Penn's 3D printer.

Our Design

Below is concept art for "The Speed Stick."

What the art shows is a blind person being alerted that there is an object in front of them before the end of their stick makes contact with the object.  This is being performed with a microcontroller interfacing with an ultrasonic range finder and a cell phone vibrator.

There is, however, one additional functionality to "The Speed Stick."  Our device can also determine if there is an object moving toward it at a speed above a certain threshold.  It then communicates this information to the user with a unique vibration pattern so that they are aware that there is an object moving toward them.

Thursday, April 7, 2011

Competing Technology Search and Reverse Engineering


Competing Technologies:
  • The white cane
    • Simple stick that is made of light-weight aluminum
    • Color is universally identifiable as being for the blind
    • Most-used walking assistant
    • Requires up to 100 hours of training1
  • GuideCane
    • Walking aid that physically guides the user
    • Uses 10 ultrasound sensors
  • The Mygo
    • Rolling cane (1 wheel)
    • Detects with a “smart sensor” and a live camera
    • Gives audio feedback to the user
    • Battery life up to 6 hours
  • The guide dog
    • Dog specially trained for physically guiding the user
    • Are expensive: Cost between $12,000 and $20,0001
    • Only useful for about 5 years1
    • Only 1% of the blind population use this method1
  • C-5 Laser Cane2
    • Cane that is useful for detecting curbs and edges using infrared light
    • Feedback is via auditory measures
    • 3 hours of continual use
  • Mowat Sensor
    • No longer being developed
  • Nottingham Obstacle Detector
    • Ultrasonic hand-held detector
  • Sonicguide
    • Eyeglass-type sensors that emit and receive sonar signals
  • NavBelt
    • Uses ultrasonic sensors placed on the belt to detect objects
    • Uses auditory feedback (image below)



Reverse-Engineering the GuideCane:




Pros:
  • Decreases work and conscious effort
    • No active scanning
    • Is on wheels
    • Only 1 piece of information given – direction
  • Minimal training required
  • No sound cues necessary – all haptic feedback
  • Passive wheels use less batteries – but still puts a time limit on the device’s use
  • Handle angle is adjustable to adapt to users of various heights
  • User’s can walk effectively at speeds up to 1 m/s

Cons:
  • Drops when going down stairs
  • No easy way to get up stairs
  • Detects minor disturbances on ground (false positives)
  • Square-shaped handle is not ergonomically designed
  • Tabletops and other objects higher than the detecting range of the sensors will be ignored by the device
  • Relatively heavy (4 kg)
  • Only 8 directions that the user can choose between

Components:
  • Consists of: housing, wheelbase, handle
  • Housing: made of acrylic, contains most of the electronic components
  • 8 ultrasonic sensors are placed on the front of the housing with an angular spacing of 15o; 2 ultrasonic sensors are on the side to detect walls
  • Sensors are close to the ground
  • Housing/wheelbase: 43 cm wide, 25 cm high, 23 cm deep; weighs 4 kg
  • Lightweight quadrature encoders to move the wheels; 2000 pulses per revolution, 5 pulses for a wheel movement of 1 mm
  • Handle that changes angles to adapt to various user heights
  • Electronics: PC/104 computer equipped with 486 microprocessors clocked at 33 MHz; 125 MB hard drive; custom built interface between PC and the sensors and actuators
  • Interface sends signals for constant US rays and readings
  • “The interface consists mainly of three MC68HC11E2 microcontrollers, two quadrature decoders, a FIFO buffer, and a decoder.”
  • Powered by recharcheable NiMH batteries; lasts several hours
  • No global navigation – just local
  • Ultrasonic sensors controlled by the Error Eliminating Rapid Ultrasonic Firing (EERUF) method; allows firing 5-10 faster than conventional methods; EERUF is necessary to eliminate cross-talk between sensors
  • Ultrasounds fire at 10 Hz
  • Uses Histogramic in-motion mapping (HIMM) for map-building
Works Cited:
1 Ulrich, Iwan. "The GuideCane -- Applying Mobile Robot Technologies to Assist the Visually Impaired." IEEE Transactions on Systems, Man, and Cybernetics. 31.2 (2001): 131-136. Print.

2 Benjamin, J. Malverin. "The Laser Cane." State of Effort. Print.

Thursday, March 31, 2011

"The Speed Stick"


Our project idea is essentially a walking stick for the blind that gives the user haptic feedback about their surroundings.  It would do this by detecting surroundings within a 20-feet range using an ultrasound sensor that is planted halfway up the walking stick.  The sensor would be attached to an interfacing microprocessor that communicates with a vibrator.  The vibrator would motion at a frequency dependent upon the relative distance of objects. 

There are some competing technologies that incorporate some form of this functionality (see below).  However, we are adding the wrinkle that our device would be able to interpret the speed of surrounding objects.  This would be useful for situations in which the user needs to be aware of moving objects, such as when they are trying to cross a busy street.  At a cross walk, the user could point the stick both left and right to see if there are moving cars on the street within a 20-foot range.  This could be accomplished by notifying the user with specific objects moving at a speed greater than a certain threshold.  This gives the user the same advantage as people who have vision and look both ways before crossing.

Devices that we would need would be the following:
  • Walking stick
  • Cell phone vibrators
  • Ultrasound transceiver
  • Microprocessor

Competing Technology
  • Retinal implants
    • http://www.midwestlens.com/blogger/2010/11/new-advance-in-medical-technology-enables-blind-people-to-see-shapes-and-objects/
  • Walking stick
    • Kuchenbecker’s lab (publication pending)

Thursday, March 17, 2011

Lab #4 - Servo motors!

There were two main parts to this lab.  The first involved data storage, while the second involved manipulating a servo motor to perform various tasks.

The first portion of the lab was data storage.  In essence, we were tasked with saving data into our microcontroller's very limited memory, and then recalling it to prove that we were successful.  To write data into the microcontroller, the write() function was used.

Since the microcontroller's memory can only be rewritten about 100,000 times before it breaks, we had to add measures into the code to prevent infinite looping.  We did this by making the microcontroller only record numbers when the letter "W" was entered into the Serial Monitor.  The microcontroller outputted the information saved into its memory only when the letter "R" was entered into the Serial Monitor.  The code that handles this process is below.

void loop()
{
  if(Serial.available()>0)
  {
    input = Serial.read();
  }
  if(input==87) //for writing must press W
  {
    EEPROM.write(i,dummy);
    i=i+1;
    dummy=dummy+2;
  }
  else if(input==82) //for reading press R
  {
    while(k<i)
    {
      value=EEPROM.read(k);
      Serial.println(value);
      k=k+1;
    }
    k=0;
  }
  input=0;
}

The second part of this lab concerned the maniuplation of a servo motor.  We first learned how to simply tell the servo motor how far to rotate.  We did this by changing the amount of time that pulses were sent to the servo motor.  This was enacted with the digitalWrite(pin,HIGH) function, then the delayMicroseconds() function, and finally the digitalWrite(pin,LOW) function.  It was noted that the longer the pulses were left on, the more that the servo motor would rotate.  If the pulse widths did not fall approximately within the 1-2 ms range, the servo motor did not function.  Also, pulses had to be sent every 20 ms.

The next part of the lab was to make the servo motor rotate between two positions.  This was performed with two "for" loops that counted to certain values.  The method used is below.

  for(i=200;i>2500;i++)
  {
    digitalWrite(pin,HIGH);
    delayMicroseconds(i);
    digitalWrite(pin,LOW);
    delayMicroseconds(19000-i);
    //delayMicroseconds(1);
  }
  for(i=2500;i>200;i--)
  {
    digitalWrite(pin,HIGH);
    delayMicroseconds(i);
    digitalWrite(pin,LOW);
    delayMicroseconds(19000-i);
    //delayMicroseconds(1);
  }

As can be seen in this method, one counted up to a value, and the other counted down to a value.  This effectively rotated the servo motor back and forth.

The next step in the lab was to manipulate the speed with which the servo motor rotated between the two positions.  This was enacted with a "stepSize" variable that was inputted from the user.  The code can be seen below.

void loop()
{
  int degree = 180;
  final=13.89*degree;
  if(Serial.available()>0)
  {
    int inputChar=Serial.read();
    int stepSize = inputChar;
    i=200;
    if(stepSize==70)
    {
      stepSize=2;
    }
    else if(stepSize==77)
    {
      stepSize=1.5;
    }
    else if(stepSize==83)
    {
      stepSize=1;
    }
    while(i<final)
    {
      digitalWrite(pin,HIGH);
      delayMicroseconds(i);
      digitalWrite(pin,LOW);
      delayMicroseconds(19000-i);
      //delayMicroseconds(1);
      i=i+stepSize;
    }
  }
}

In this way, if the user entered "F" for fast, the step size would be 2.  If they entered "M" for medium, the step size would be 1.5.  Likewise, if they entered "S" for slow, the step size would be 1.  This functionality accounted for the user-interactivity required by the lab.

The next part of the lab was to place a cardboard disk with holes in it and controlling where the holes are placed by manipulating the servo.  The setup used can be seen below.  The picture is for the "multiple holes" portion of the experiment, but the concept is the same for both "single hole" and "multiple holes."


The code  for this portion of the experiment can be seen below. 

void loop()
{
  int degree = 90;
  final=13.89*degree;
  if(Serial.available()>0)
  {
    int inputChar=Serial.read();
    int stepSize = inputChar;
    i=200;
    if(stepSize==70)
    {
      stepSize=2;
    }
    else if(stepSize==77)
    {
      stepSize=1.5;
    }
    else if(stepSize==83)
    {
      stepSize=1;
    }
    while(i<final)
    {
      digitalWrite(pin,HIGH);
      delayMicroseconds(i);
      digitalWrite(pin,LOW);
      delayMicroseconds(19000-i);
      //delayMicroseconds(1);
      i=i+stepSize;
      Serial.println(RCtime(6));
    }
  }
  Serial.println(RCtime(6));
}

long RCtime(int sensPin)
{
   long result = 0;
   pinMode(sensPin, OUTPUT);       // make pin OUTPUT
   digitalWrite(sensPin, HIGH);    // make pin HIGH to discharge capacitor - study the schematic
   delay(1);                       // wait a  ms to make sure cap is discharged
   pinMode(sensPin, INPUT);        // turn pin into an input and time till pin goes low
   digitalWrite(sensPin, LOW);     // turn pullups off - or it won't work
   while(digitalRead(sensPin)){    // wait for pin to go low
      result++;
   }
   return result;                   // report results  

The same basic setup that was used for servo motor manipulation is used, except the "degree" variable was changed.  After some calibration, a multiplying constant is multiplied by the "degree" variable to yield a "final" variable.  The result is that the degree can easily be coded into the program to place the holes wherever one pleases.

It is also worth noting that the voltage running through a photoresistor was monitored using the "RCtime()" function.  This enabled us to determine quantitatively when a hole was successfully placed over a photoresistor.

Monday, February 21, 2011

Lab 3

This lab had two major parts: character reading and color reading.

The first portion of the lab, character reading, utilized the textbox on the serial monitor to enable the user to interact with the program.  The backbone of this functionality is below.

inputChar = Serial.read();

The circuit used for this operation can be seen below.

 What we were able to do with this program is to output audio whose frequency depended on the input.  The way that we did this was to note that characters and numbers entered into the serial monitor had attached a numerical value.  For example, the letter 'a' is equivalent to the number 95. 

frequency = inputChar * 10;
tone(pin,frequency);

This coding enabled us to produce audio based solely on the input commands that we gave.

The second major part of the lab was reading colors with the ColorPAL device.  This device can be seen below (From Dr. Bogen's lab manual).


The first task that we undertook with this device was simply implementing the read_colorPAL code that was available to the students.  After putting together the circuit, we tested the device out by reading the colors of various objects in the lab.  When we ran the program, the serial monitor outputted a dynamic 1x3 matrix that read the red, green, and blue values at that moment.  The values seemed to run the gamut from 1 to over 300.  Interestingly, black did not give a 0 value for either red, green, or blue.

The next task that we undertook with this device was calibrate the output values so that black would give a value of 0 for red, green, and blue.  We also wanted the numbers to be percentages rather than raw numbers.  In this way, we also wanted a white object to output a value of 100 for red, green, and blue.  The way that we did this was to find the red, green, and blue readings for both white and black objects.  We then implemented the formulas found in the lab manual to modify the red, green, and blue variables.  These formulas can be see below.

red = 100*(red - Kr)/(Wr - Kr);
grn = 100*(grn - Kg)/(Wg - Kg);
blu = 100*(blu - Kb)/(Wb - Kb);  

With these changes, a black object gave RGB values very close to zero, and a white object gave RGB values very close to one.


The final task that we undertook with this ColorPAL device was to modify our program so it detected and classified objects as either red, green, blue, white, or black.  The way that we did this was first to observe the RGB values that control red, green, blue, white, and black objects yielded.  We then implemented five "if" and "else if" statements so that the serial monitor outputted the color of objects in front it.  The coding statements can be seen below.



  int RG = abs(red/grn);
  int RB = abs(red/blu);
  int GR = abs(grn/red);
  int GB = abs(grn/blu);
  int BR = abs(blu/red);
  int BG = abs(blu/grn);
  int difference = 100-red;
  if(RG>2 && RB>2 && difference>30)
  {
    Serial.println("This is RED!!");
  }
  else if(GR>2 && GB>2 && difference>30)
  {
    Serial.println("This is GREEN!!");
  }
  else if(BR>2 && BG>2 && difference>30)
  {
    Serial.println("This is BLUE!!");
  }
  else if(difference<20)
  {
    Serial.println("This is WHITE!!");
  }
  else if(difference>80)
  {
    Serial.println("This is BLACK!!");
  } 
  delay(100);


The serial monitor as a result of these alterations can be seen below.  At this point, a blue object was in front of the ColorPAL device.