Instrumentation Cane Report

advertisement
Challenge Project: Outdoor Cane Competition with Beacon
Allison Connolly and Sarah Gutbrod
580.471 Principles of Biomedical Instrumentation
December 4, 2009
1. Objective
The purpose of our project is to design an electronic device to aid the visually
impaired as they travel to a known exterior destination while avoiding moving and
stationary obstacles. The device must be an improvement to the traditional cane
currently used as an aid and help the user stay centered along a path as they
continue towards their destination
2. Introduction
The freedom to get around independently is a significant challenge for the visually
impaired, especially in an external setting where moving cars, bicyclists, and other
pedestrians complicate the route. Advanced obstacle detection of stationary and
moving objects as well as navigational cues would be a vast improvement over
traditional canes. While a simple cane can detect lower objects or obstacles directly
in front of the user, there is no component to look for low hanging branches or other
similar obstacles that threaten the upper body and face of the individual. It was also
brought to our attention through a consultation with a visually impaired individual
that it would also be extremely beneficial to know the location of the centerline of a
sidewalk. With more than one million blind individuals in the United States there is a
large market available for a device that increases their mobility and the confidence
with which they can safely travel the streets of a city. We have designed an
improved cane that couples distance detection with tactile and auditory feedback to
address this concern.
3. Design Process
3.1. Sensor selection
A short-range infrared sensor was chosen for low obstacle and stair detection. The
sensor has a range of 3 feet or less, and outputs a voltage that varies with obstacle
distance. A single sensor was positioned near the base of the cane and was used to
detect both up and down stairs. This could be done by angling the sensor towards
the floor, giving it an output voltage of approximately 1V. If a drop-off or down step
is in range of the sensor, the output voltage falls to zero. Conversely, the output
voltage jumped towards maximum when an object higher than the floor came in
range of the sensor. This allowed the sensor to detect upwards stairs, curbs, or any
other object a user can trip over.
In order to detect objects that are farther away, either in front of or above the user,
we selected to use the SRF05 ultra-sonic range finder (ultrasound transceiver and
sensor). This sensor was advantageous over a long-range infrared sensor because
its output voltage is digital instead of analog, making the signal processing on the
microchip simpler. When a trigger pulse is input to the sensor, the ultra-sonic
transmitter emits 8 bursts, and the receiver records the echo of these pulses. The
on-board circuitry interprets the time delay between bursts and echo and outputs a
pulse-width modulated signal whose width is dependent on the delay. Two of these
sensors were used on our cane, one aimed directly in front of the user, and another
pointing at an angle in front of and above the user's head. The first sensor is used to
detect objects in front of the user, so he or she does not collide with stationary
objects. It also has a second purpose, to detect objects approaching the user, such
as joggers or bicyclists by comparing the distance of an object at time t and time t
plus a short delay of 100ms. The second sensor is used to detect overhead objects.
The distance threshold for detection is optimized to the height of the user, and
detects objects at forehead level or below. This is an improvement over a passive
cane, which can only detect low or waist-high objects, but not objects such as
branches that can hit the user in the head.
Based on the idea that the desired path will be a different color than the
surroundings, we installed a TSL230R light intensity to frequency converter on the
bottom left and right-hand side of the cane. The TSL230R sensor is an integrated
circuit that uses an array of photo-diodes to detect light. The sensor then outputs a
digital square wave with variable frequencies based on the intensity of the light
reflected off the ground. The digital output signal simplified the analysis, which
allowed more components to be programmed through the same PIC. The TSL230R
also offers the ability to adjust the sensitivity and scale the output to more easily
record the frequency. The circuit is also packaged in an easily integrated 8 pin DIP
chip convenient for assembly.
We shielded the sensors from ambient light in a dark encasing and angled the
sensors towards the ground to increase their sensitivity to changes in the path.
Extending nearly a foot to the left or the right the sensors will perceive a change in
the color of the pathway as the cane is swept from side to side before the user steps
off the desired path. This change is determined by a significant difference between
the frequency outputted from the left sensor compared to the right and calculated in
a manner similar to the ultrasound sensors. We chose not to rely on the absolute
values read by the color sensors because the values were heavily dependent on the
light conditions. The absolute reading on a cloudy day was much less than the
absolute reading on a day when the sun was out. It was also heavily dependent on
the time of day and made testing and calibration more difficult due to the fact that it
had to be performed in the sunlight not indoor lighting. However assessing the
difference between the sensors was an accurate and acceptable solution to
determine the edge of the path. The sign of the difference between the sensors'
reading would alert the user of the location of the edge of the path. For the purpose
of this demonstration where the green grass was off the path, the sensors were
calibrated so that a decrease in light intensity meant "off-path."
Our design also incorporates a wireless XBEE receiver that functions as a beacon
detection sensor. Set to be the same frequency as the transmitting XBEE located at
the destination, the receiver picks up a signal when in range (300 ft). The pulsewidth modulated signal frequency increases when the distance between the two
XBEE chips decreases. The receiving XBEE also outputs a square wave signal; the
length of the positive pulse width corresponds to the strength of the received signal.
Our circuit ignores the XBEE until the wireless chips are within range and then, by
comparing the pulse widths at two different times, determines if the user is
approaching the destination or moving away in the wrong direction.
3.2.
Feedback
Selection
For the obstacle sensors we have selected a combination of tactile and auditory
feedback mechanisms. The tactile feedback is achieved by applying a constant or
pulsed voltage to a mounted shaft motor, causing it to vibrate. During testing we
found that it was difficult to distinguish different vibrating locations on one hand,
especially if the whole cane vibrated. Therefore we chose a variety of locations extra
sensitive to tactile stimulation including the hand, forearm, and neck behind both
ears to differentiate between different sensor feedback. The shaft motors were
encased in flexible, cylindrical plastic housing to protect the rotating piece from
interference as well as to conduct the vibrations to any shaped surface. The hand
motor vibrates if an object is detected by the front ultrasound, whereas the forearm
vibrates if an overhead object is detected. The left ear motor vibrates when the IR
detects an edge or downstairs while the right ear piece vibrates when the IR detects
up stairs. The left ear piece is longer than the right so that they are easily
differentiated by the visually impaired user.
There is also a beeper installed on the cane that beeps twice to signify when the
XBEE is in range and beeps constantly if the XBEE perceives that the user is moving
in the wrong direction. Additionally the beeper will pulse to alert the user that an
object is moving at the cane.
There is a servo motor embedded in the handle of the cane to alert the user when
they are in close proximity of the edge of the path. The user can comfortably rest
their thumb on the bracket attached to the servo motor while holding the cane. If the
reading from the right color sensor is less than the left sensor, signaling off path, the
motor will guide the user's thumb 45 degrees to the left to signal that the center of
the path is to the left. In the same way if the left color sensor is less than the right,
the motor will guide the user's thumb 45 degrees to the right. We chose to simplify
the feedback to left and right and not incorporate how far left or how far right in
order to make the cane more intelligible. The change in orientation and position of
the thumb is easily perceived and the feedback is completely isolated from the other
sensors.
3.3 Calculations and Thresholds
Many of the sensor readings are dependent on initiating the internal timer of the PIC
microcontroller using the following equation:
frequency = 20 MHz = 20*10^6 Hz --> period = 1/(20*10^6) sec
for the timer divide-by-8: each cycle has length 1.6 us
t_delay (ms) = (0.0016 ms/cycle) * (no. of cycles)
The following equation is used to calculate distance from the Ultrasonic range-finder
output:
distance (cm) = (t_delay ms) * (1000 us/ms) / (2*30 us per cm)
Due to the method motion by which a moving object is determined the motion
sensor had to take into account the walking motion of the user, which was
determined to be an average 3ft/s. Only additional movement towards the sensor
results in feedback.
The following equation is used to calculate the distance from the IR sensor output:
voltage (V) = adc_import_value * (5V / 255)
distance
(cm)
40
30
20
15
10
8
5
2
voltage (V)
0.75
0.9
1.4
1.75
2.45
2.5
1.8
0.8
The PIC microcontroller outputs a square wave to rotate the servo motor. The pulse
width of the waveform determines the angle that the motor moves according to the
table below.
angle (deg)
-90
-45
0
45
90
pulse width
(usec)
600
1050
1500
1950
2400
pulse width (usec) = 1500 + (angle deg) * (10 usec/deg)
Due to the fact that the color sensors rely on a difference between the left and the
right signal to detect off-path it was important to establish the baseline difference in
the signals. This difference was dependent on the angle and placement of the sensor
relative to the ground and therefore dependent on how the user chose to hold the
cane. Therefore the sensors are programmed to initialize when the cane is first
turned on. However this means that the user must be relatively sure that both
sensors are facing the same surface during the initialization step. The measured
difference is then set to zero and a difference greater than or less than it is
registered. Unfortunately it is sensitive to the way the cane is held throughout use.
3.4 Incorporating the sensors and feedback together/ PIC Selection
In order to accommodate code with 16-bit variables and code of larger sizes, we
chose to use the PIC18f4550 over the PIC16f877. These chips are easily
interchangeable, meaning we could switch between PICs depending on our needs. In
order to calculate averages and use counters above 255, we used the PIC18 because
it can handle variables with range 0 to 65535. The sensor sampling occurs in series,
meaning a chip can only read from one sensor at a time. If all of the sensors were
on the same chip, then there could possibly be a delay of up to five seconds between
readings from one sensor. This delay is too large for operation in the real world, so
we split the duties between two microchips in order to cut this time in half to
approximately 2 second delay.
The sensors were split according to importance. The color sensors needed to be
sampled most frequently, so they became the dominant sensor on PIC1. Because
the servo provides feedback for these sensors, it was also placed on PIC1 to avoid
any excess communication between the PICs. The XBEE beacon detector was a
secondary feature for our cane, meaning it did not take up much time or space, so it
could be included on PIC1. The object and motion detection sensors were placed on
PIC2, along with their respective vibrating motor and sound feedback. The only
separation of sensor and feedback is with the XBEE receiver, which produces a
certain pattern of beeps depending on the user's proximity to the beacon. The PICs
communicate through rs232 protocol. For this specific purpose, PIC1 will send a
character if the XBEE needs to alert the user. PIC2 reads this character, responds
that it has been read, and then performs the feedback action. Once PIC1 has
received confirmation from PIC2, it continues with its normal function. In this way,
there will be no missed communications between the two chips. This format can be
easily adapted for future, more complex communications between the PICs.
3.5 Power and Current Concerns
The device is designed to be powered by 9V batteries. Therefore it is necessary to
have a 5V regulator to power the PICs and the sensors and a 3.3V regulator to
power the XBEE wireless chip. When assembling the complete device and integrating
the feedback and sensors we found that one battery did not supply enough current
for consistent and accurate performance. The servo motor itself draws 100mA. To
combat this issue we placed the 5V regulator in a heat sink to increase the current
output to near 1A and added two 9V batteries in parallel to add the currents.
4. Problems
4.1. It was difficult to establish consistent communication between the XBEE wireless
chips when the transmitting and receiving chip were powered by different batteries.
We believe this may have been an issue with the 3.3V Regulator. The wireless
communication was highly sensitive to the power source which varied significantly
between our circuit and the beacon circuit. However this issue is expected due to the
relatively high tolerance levels of the capacitors that are used in conjunction with the
regulator. We found, by constructing multiple regulator circuits with various
replacement capacitors, that the resulting output ranged from 3.3V to 3.7V. The
transmitting XBEE was being powered by a supply ~3.57V, which we had to match
closely in order to successfully establish communication.
4.2. Before the color sensors were shielded it was difficult to get a distinct reading
from different surfaces because the signal was contaminated by ambient light. We
were forced to design a physical barrier to block out peripheral light while still
allowing an unobstructed view of the ground surface. In addition we had to change
the parameters of the to increase the sensitivity by 100 and scale the frequency
output by 10 in order to consistently perceive different values for the grass vs. the
path.
4.3. Our first design included vocal feedback so that it did not require interpretation
on the part of the user to understand the sensors. However, after ordering PICs that
were capable of storing pre-recorded files that would then be played through an
earphone, we had difficultly working with Microchip to program the PIC. We did not
have access to the correct compiler and therefore had to abandon the idea and adapt
our design to include tactile feedback.
4.4. We ran into difficulty when testing our device in rainy conditions. The low IR
sensor responded differently to light reflected off puddles than to baseline conditions.
The thresholds were no longer correct and the circuit perceived steps where they did
not exist. Also we were forced to waterproof our cane, which is an important feature
for external use. The servo had to be isolated from the rain and the exposed
electronics had to be protected.
5. Future Work
While the vibration and beeping feedback is effective, it makes the cane bulky and
requires the user to focus on interpreting the vibrations. This reduces focus from
other aspects of navigation, such as his own haptic feedback from feet and feeling
with the cane as well as auditory feedback of his or her environment. However,
almost all people can multitask to the point of holding a conversation while walking,
so having voice feedback instead of vibrations would be less intrusive to the user.
The voice feedback can be incorporated by using an external voice chip module or
voice production board, or the microchip itself can be programmed to produce voice
files from compressed storage. The latter option is ideal, as it would not add an
excess circuitry and thus keep the device from becoming bulkier. This can be
achieved by using a higher-level chip with sufficient memory to store the compressed
sound files as well as the ability to output pulse-width-modulated signals.
In order to be clinically relevant, the device must be maneuverable by all types of
people. In its current state it is too heavy and too thick for a smaller person to
handle. Therefore, in the next prototype, it would be important to consider size and
weight concerns and aim to mimic the conditions of the current cane. This is
achievable by several methods: use a single PIC, use a printed PCB board, use a
single battery, use a smaller/lighter servo motor, make the overall diameter of the
cane smaller. In order to reduce to a single PIC, a more sophisticated PIC with
interrupts and optimized code are necessary. By optimizing the code, this will
reduce the power draw on the battery. Adding solar panels to the cane, which is
useful because it is aimed for outdoor use, will also reduce the power draw on the
battery and allow for a longer lifespan. Based on our own field testing of the device,
we encountered problems in maneuvering over rough ground due to the stopper at
the end of the cane. If the cane were lighter and more balanced, the end could
simply glide over bumps and cracks in the ground and would not get stuck.
6. Appendix A: PIC 1 Code
/*
* Allison Connolly and Sarah Gutbrod
* Smart Cane for the blind - outdoor competition
* November 23, 2009
* Principles of Biomedical Instrumentation
* Pic 1: clock, XBEE, colorL, colorR, servo
*/
#include <18f4550.h>
#include <stdio.h>
#include <stdlib.h>
#define 20_MHZ_CLOCK
#use delay(clock=20000000)
/* pin definitions */
#define TPIC2 PIN_A0
#define RPIC2 PIN_A1
#define RXBEE PIN_A2
#define TXBEE PIN_A4
#define RCOLOR_R PIN_B2
#define RCOLOR_L PIN_B1
#define TSERVO PIN_B4
#define SENSITIVITY_SCALE 100
#define FREQ_SCALING_LEVEL 10
/* the two pics communicate using rs232 */
#use rs232(baud=9600, XMIT=TXBEE, RCV = RPIC2, parity=N, bits=8)
int in_range = 0;
/* variable definitions */
/* for watch_xbee */
unsigned long XB_pulse_width = 0;
/* for color sensors */
float R_freq, L_freq, CR_pulse_width, CL_pulse_width;
float DIFFERENCE_THRESHOLD=0;
/* read the modulated pulses from xbee
* if the signal is railing 0, out of range
* if the signal is railing high, at destination
* otherwise, smaller pulse width means closer to destination
* alert the user if go away from destination or out of range */
int watch_xbee(void)
{
signed long time;
float temp_pulse_width;
/* wait until we get an upstroke from RXBEE or timer runs out */
for ( ; ((!input(RXBEE)) && (get_timer3() < 1000)) ;) {
if (input(RXBEE)) { /* XBEE upstroke triggered exit from for */
set_timer3(0); /* start timer */
}
else {
  if (!in_range)
return 0; /* "false" too far, XBEE out of range */
if (in_range==1) {
in_range = 0;
return 2; /* went out of range, should beep */
}
}
}
/* wait until we get a downstroke from RXBEE or timer runs out */
for ( ; (input(RXBEE) && get_timer3() < 1000) ; ) {
if (!input(RXBEE)) { /* XBEE downstroke triggered exit from for */
time = get_timer3();
if (in_range==0) {
in_range = 1;
}
return 3; /* enter range, long short short beeps */
}
else {
if (in_range)
return 1; /* "true", RXBEE railing positive, too close, at destination */
}
}
temp_pulse_width = (float)time * .0016;
if ((temp_pulse_width - XB_pulse_width) < 0) {
XB_pulse_width = temp_pulse_width;
return 2; /* going away from XBEE, need to beep */
}
XB_pulse_width = temp_pulse_width;
}
/* send out PWM signal to rotate the servo motor
* to the degree passed */
void rotate_motor(signed long degree)
{
int j, k;
for (j=0; j<50; j++) {
output_high(TSERVO);
for (k=0; k<10; k++)
delay_us(150+degree);
output_low(TSERVO);
delay_ms(20);
}
}
/* measure the frequency being read by the right color sensor
* set the global variable
*/
void color_right(void)
{
float temp_pulse_width_R, time_R;
temp_pulse_width_R = 0; time_R = 0;
setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
for ( ; !input(RCOLOR_R); )
set_timer3(0);
for ( ; input(RCOLOR_R); )
time_R = get_timer3();
temp_pulse_width_R = (float)time_R*.0016;
if (temp_pulse_width_R > 5) {
return;
}
CR_pulse_width = temp_pulse_width_R;
R_freq = 1/(2*temp_pulse_width_R);
}
/* measure the frequency being read by the left color sensor
* set the global variable
*/
void color_left(void)
{
float temp_pulse_width_L=0;
float time_L = 0;
setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
for ( ; !input(RCOLOR_L); )
set_timer3(0);
for ( ; input(RCOLOR_L); )
time_L = get_timer3();
temp_pulse_width_L = (float)time_L*.0016;
if (temp_pulse_width_L > 5) {
return;
}
CL_pulse_width = temp_pulse_width_L;
L_freq = 1/(2*temp_pulse_width_L);
}
/* compare the reading from the right sensor and the left sensor
* if the difference is greater than the threshold, rotate the motor left
* if the difference is less than the threshold, rotate the motor right
*/
void compare_color(void)
{
}
float color_difference;
for (;;) {
color_right();
color_left();
color_difference = CR_pulse_width - CL_pulse_width;
if (color_difference >DIFFERENCE_THRESHOLD){
rotate_motor(-45);
delay_ms(10);
rotate_motor(0);
}
if (color_difference<DIFFERENCE_THRESHOLD){
rotate_motor(45);
delay_ms(10);
rotate_motor(0);
}
}
/* called when the cane is first turned on
* the cane must be held still on a solid patch of ground
* reads the values from the left and right sensors and averages over
* many times. then sets the initial difference threshold
*/
float setup(void)
{
float temp_pulse_width_R=0, temp_pulse_width_L=0;
float time_R = 0, time_L = 0;
int got=0;
setup_timer_3(T3_INTERNAL | T3_DIV_BY_8);
delay_ms(1000);
while (!got) {
for ( ; !input(RCOLOR_R); )
set_timer3(0);
for ( ; input(RCOLOR_R); )
time_R = get_timer3();
temp_pulse_width_R = (float)time_R*.0016;
if (temp_pulse_width_R < 5) {
got = 1;
}
}
got = 0;
while (!got) {
for ( ; !input(RCOLOR_L); )
set_timer3(0);
for ( ; input(RCOLOR_L); )
time_L = get_timer3();
temp_pulse_width_L = (float)time_L*.0016;
if (temp_pulse_width_L < 5) {
got = 1;
}
}
return temp_pulse_width_R - temp_pulse_width_L;
}
/* the main loop. after setting up the color sensor threshold, it cycles
* through reading from color sensors, and the xbee
* if the xbee indicates the user needs to be notified,
* this pic must communicate with the feedback pick using rs232
*/
void main()
{
int i; float diff=0;
delay_ms(1000);
for (i=0; i<10; i++) {
diff += setup();
}
DIFFERENCE_THRESHOLD = diff / 10;
for (;;) {
compare_color();
i=watch_xbee();
if (i==0) {}
else if (i==1) {}// at destination
}
}
else if (i==2) {
//going away
//beep long
while (!kbhit()) {
putc('A');
}
}
else if (i==3) {
// out of range
// long short short
while (!kbhit()) {
putc('B');
}
}
7. Appendix B: PIC 2 Code
/*
* Allison Connolly and Sarah Gutbrod
* Smart Cane for the blind - outdoor competition
* November 23, 2009
* Principles of Biomedical Instrumentation
* Pic 2: clock, US_head, US_front, IR, beeper, buzzers
*/
#include <16F877.h>
#include <stdio.h>
#include <stdlib.h>
#define 20_MHZ_CLOCK
#use delay(clock=20000000)
/* pin definitions */
#define TSERIAL PIN_A0
#define RPIC1 PIN_B1
#define TPIC1 PIN_B2
#define RIR PIN_A2
#define TSPEECH PIN_C1
#define TUS_FRONT PIN_B4
#define RUS_FRONT PIN_B5
#define TUS_HEAD PIN_B6
#define RUS_HEAD PIN_B7
/* feedback pin */
#define UP_BUZZ PIN_D4
#define DOWN_BUZZ PIN_C7
#define FRONT_BUZZ PIN_C6
#define HEAD_BUZZ PIN_C5
#define BEEP PIN_D5
/* need interrupt for receiving info from PIC1 about when to speak */
#use rs232(baud=9600, XMIT=TPIC1, RCV = RPIC1, parity=N, bits=8)
/* trigger the ultrasound pulse, then wait for the pulse to be output
* read in the echo from the overhead ultrasound sensor
* if there is an object within ~2.5 ft (the height of our subject),
* then vibrate the overhead buzzer
*/
int overhead_US(void)
{
long OH_echo_delay, OH_echo_delay_time, OH_distance;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
/* send the trigger pulse to ultrasound */
output_high(TUS_HEAD);
/* Get the sensor the chance to see this */
delay_us(10);
output_low(TUS_HEAD);
/* wait for the upstroke of the response */
for ( ; !input(RUS_HEAD); )
set_timer1(0); /* start timer at 0 */
/* wait for the downstroke of the response */
for ( ; input(RUS_HEAD); )
OH_echo_delay = get_timer1(); /* get the delay in samples */
OH_echo_delay_time = .0016 * OH_echo_delay; /*ms, 1.6 us per sample */
if (OH_echo_delay_time >= 36) {
OH_distance = 36*1000/60; // 36 ms * (2*29 us per cm) = cm
/* nothing there or too far to detect */
}
else {
OH_distance = OH_echo_delay_time*1000 / 60; // cm
/* calculate the distance from the time */
}
// if something overhead
if (OH_distance < 80 ) { // 30cm = 1 ft
output_high(HEAD_BUZZ);
delay_ms(200);
output_low(HEAD_BUZZ);
return 1;
}
return 0;
}
/* trigger the ultrasound pulse, then wait for the pulse to be output
* read in the echo from the front ultrasound sensor
* if there is an object within ~3 ft, then vibrate the front buzzer
*/
long front_US(void)
{
long M_echo_delay, M_echo_delay_time, M_distance;
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
/* send the trigger pulse to ultrasound */
output_high(TUS_FRONT);
/* Give the sensor the chance to see this */
delay_us(10);
output_low(TUS_FRONT);
/* wait for the upstroke of the response */
for ( ; !input(RUS_FRONT); )
set_timer1(0); /* start timer at 0 */
/* wait for the downstroke of the response */
for ( ; input(RUS_FRONT); )
M_echo_delay = get_timer1(); /* get the delay in samples */
M_echo_delay_time = .0016 * M_echo_delay; /*ms, 1.6 us per sample */
if (M_echo_delay_time >= 36) {
M_distance = 36*1000/60; // 36 ms * (2*29 us per cm) = cm
/* nothing there or too far to detect */
}
else {
M_distance = M_echo_delay_time*1000 / 60; // cm
/* calculate the distance from the time */
}
if (M_distance < 90) {
output_high(FRONT_BUZZ);
delay_ms(200);
output_low(FRONT_BUZZ);
}
return M_distance;
}
/* read in the analog voltage value from the IR sensor
* if the value is large, then there is a low object ahead,
* vibrate the step up buzzer.
* if the value is very small, then there is a drop off ahead,
* vibrate the step down buzzer.
* if the value is within the given range, then we are detecting
* the floor, so no feedback.
*/
int IR_sensor(void)
{
int input;
setup_adc(ADC_CLOCK_INTERNAL);
setup_adc_ports(ALL_ANALOG);
set_adc_channel(2);
delay_us(10);
input = read_adc();
if (input > 51) {
output_high(UP_BUZZ);
delay_ms(300);
output_low(UP_BUZZ);
return 1;
}
else if (input < 5) {
output_high(DOWN_BUZZ);
delay_ms(300);
output_low(DOWN_BUZZ);
return 1;
}
return 0;
}
/* take two measurements from the front ultrasound sensor
* 100 ms apart. if the difference between the distances is
* greater than the given threshold, then something is approaching
* faster than walking speed. alarm the user with 2 beeps
*/
void motion(void)
{
long dist1, dist2;
dist1 = front_US();
delay_ms(100);
dist2 = front_US();
// walking speed 4.11 ft/sec = 0.125 cm/ms = 12.5cm/100ms
if ((dist1-dist2) > 25) {
output_high(BEEP);
delay_ms(80);
output_low(BEEP);
delay_ms(80);
output_high(BEEP);
delay_ms(80);
output_low(BEEP);
}
}
/* output a long beep */
void beep_long(void)
{
output_high(BEEP);
delay_ms(200);
output_low(BEEP);
}
/* output beeps of the pattern long short short */
void beep_mixed(void)
{
output_high(BEEP);
delay_ms(150);
output_low(BEEP);
delay_ms(50);
output_high(BEEP);
delay_ms(50);
output_low(BEEP);
delay_ms(50);
output_high(BEEP);
delay_ms(50);
output_low(BEEP);
}
/* the main function of the program
* cycle through the overhead sensor, front sensor, IR sensor, and
* motion sensor. then check if PIC1 is trying to communicate.
* if so, output the appropriate beeps, then feedback to PIC1 to stop
* outputting and continue reading from sensors.
*/
void main(void)
{
char c;
output_low(TUS_FRONT);
output_low(TUS_HEAD);
for ( ;; ) {
// get XBEE from other pic
overhead_US();
front_US();
IR_sensor();
motion();
}
}
if (kbhit()) {
c=getc();
if (c == 'A') {
putc('R');
beep_long();
}
else if (c == 'B') {
putc('R');
beep_mixed();
}
}
8. Appendix C: Circuit Diagram
QuickTime™ and a
TIFF (U ncompressed) decompressor
are needed to see this pi cture.
Download