Abstract

Our goal is to create a smart folding blind cane that helps visually impaired individuals detect nearby objects at the waist level. Currently, folding blind canes can only be used to avoid objects on the ground. We will build a smart cane that alerts the user of objects above the ground, like a table, by using a PING Ultrasonic Sensor. If there is an object, the sensor will alert the user by causing the user’s phone to vibrate or play a sound via text or Bluetooth. In conclusion, we seek to improve the lives of visually impaired people by making their daily lives safer.

Inspiration

When doing some last minute back to school shopping, Jake saw a visually impaired person struggling to find his way around a Walmart parking lot. Even though the man had a cane, he was still prone to potentially dangerous obstacles above the level of his knee. He wanted to build IntelliCane to help people like the man he saw that day, so he shared this vision with Jimmy. Jimmy, who has lived with nearsightedness ever since his uncle gifted him a GameBoy Color, naturally understood the need for such product, and the two decided to create IntelliCane to change the lifestyle of visually impaired people.

What it does

Besides all of the functions a normal folding blind cane has, IntelliCane comes with two additional primary features. First, IntelliCane sets off an alarm if it detects an obstacle near the waste level within twenty centimeters (20cm.). This alarm can then be turned off by pushing the button. Second, IntelliCane will send a text to a predetermined phone number if the cane is dropped, which is often paired with the user falling. This is especially useful in that a guardian or a significant other would receive a text alert the instant the user faces danger.

How we built it

The IntelliCane is built with two Arduinos, one WiFi shield, one PING))) ultrasonic sensor, one accelerometer, one alarm buzzer, and one button. The ultrasonic sensor, accelerometer, buzzer and button are all configured on a single breadboard but are connected separately to the Arduinos. The sensor, buzzer and button are connected to one Arduino, with the programmed function of alerting the user via the buzzer of objects 20 centimeters or less from the handle of the cane. The accelerometer is connected to the other Arduino with the WiFi shield attached. This Arduino has the compiled function of sending a text message to an individual if the cane is dropped.

Challenges we ran into

The biggest challenges we ran into dealt with additional pieces to a cane without voiding the advantages of a regular cane - simple, light, and portable. To do this effectively, we first focused on making our additions as compact as possible, and this proved challenging when putting both the Arduinos, the battery, and complementary wires into the Plexiglass box. Once this was accomplished, we needed to somehow securely attach the box to the cane so that the cane’s center of balance was not heavily disrupted and IntelliCane’s functions would still be work.

Accomplishments that we're proud of

First and foremost, we are proud of developing a product with a tangible need in the market composed of visually impaired people and their loved ones. If IntelliCane were to undergo further development, it could potentially serve a 6.5 million population of people who currently use a cane and/or a walker to assist with mobility. Furthermore, we are proud of developing the product with an incredibly low budget, and a potential add-on device that people who already have canes can purchase would be even more financially feasible. Finally, we are proud of the accuracy of our product. After undergoing multiple rounds of testing, our device is proven to work reliably in most settings.

What we learned

We learned first how to configure circuits efficiently on a breadboard. We combined this skill with efficiently coding Intellicane’s functions onto the Arduinos. We had to combine many ideas that we learned across all labs - like sending a text to a phone and detecting objects with a ping sensor. We also had the neat opportunity to learn how to use the laser cutters to create our box for the cane.

What's next for IntelliCane

The future of IntelliCane consists of a more compact system, in which the sensors will be configured inside the cane. This change will eliminate the bulkiness of the current prototype. Likewise, future products will have more sensors positioned in locations that determine if there are close objects in all different directions. This deviation would be combined with different alarms that alert the user for different proximities.

Code

Arduino One without the WiFi Shield

include include

char ssid[] = "HP-setup-south"; // your network SSID (name) char pass[] = "detkinlabsouth101999"; // your network password (use for WPA, or use as key for WEP) int keyIndex = 0; // your network key Index number (needed only for WEP) int status = WL_IDLE_STATUS;

//thingspeak server char server[] = "api.thingspeak.com";

WiFiClient client;

//API key for the Thingspeak ThingHTTP const String apiKey = "URGFHLT8IYSS4C2B";

//the number the message should be sent to const String sendNumber = "+12487671888";

int buzzerPin = 3; int button = 2; // Push Button pin static boolean buzzer = false;

boolean ping_read = false; // true if obstacle is detected

define trigPin 13 define echoPin 12

const int xPin = 0; const int yPin = 1; const int zPin = 2;

int xOld; int yOld; int zOld;

void setup() { pinMode(buzzerPin, OUTPUT); // Initialize buzzer as output and low digitalWrite(buzzerPin, LOW); pinMode(button, INPUT); // Set the push button pin to input mode pinMode(trigPin, OUTPUT); pinMode(echoPin, INPUT); Serial.begin(9600); int xOld = analogRead(xPin); int yOld = analogRead(yPin); int zOld = analogRead(zPin);

// set up WiFi if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue: while (true); }

// attempt to connect to Wifi network while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 10 seconds for connection: delay(10000); }

Serial.println("Connected to wifi"); printWifiStatus();

}

long beep_time = 1000; // Time to toggle buzzer on and off

void loop() {

static boolean pressed = false; static boolean msg_sent = false;

static long start_time;

int button_read = digitalRead(button);

long duration, distance;

digitalWrite(trigPin, LOW); // start trig at 0 delayMicroseconds(2); digitalWrite(trigPin, HIGH); // The rising edge of trig pulse delayMicroseconds(10); // decides duration of trig pulse digitalWrite(trigPin, LOW); // falling edge of the trig pulse duration = pulseIn(echoPin, HIGH); // duration for which echoPin was HIGH gives the time sensor receives reflected signal at echo pin distance = (duration / 2.0) / 29.1; // Calculate the distance of the reflecting surface in cm Serial.println(distance); if (distance < 10) { ping_read = true; start_time = millis(); }

if (button_read == HIGH) { //If push button was used to reset the system ping_read = false; // Disable buzzer pressed = true; }

if (ping_read) { // Toggles buzzer on and off after every interval of beep_time if (int((millis() - start_time) / beep_time) % 2 == 0) { Serial.println("Buzzer High"); digitalWrite(buzzerPin, HIGH); } else { Serial.println("Buzzer low"); digitalWrite(buzzerPin, LOW); } } else { //No intruder detected Serial.println("Buzzer Low"); digitalWrite(buzzerPin, LOW); if (pressed) { Serial.println("delay"); delay(5000); pressed = false; } }

//read the analog values from the accelerometer int xRead = analogRead(xPin); int yRead = analogRead(yPin); int zRead = analogRead(zPin);

if (abs(zRead - zOld) > 50) { Serial.print("--------------------------------"); //send the sms Serial.println("Sending SMS");

//this function will send the sms
//the first argument is the number to send to, formatted like this +12345678901
//the second argument is the body of the text message, which must be within URLEncode()
sendSMS(sendNumber, URLEncode("Jake's cane has been dropped. Dial 911 if there is an emergency"));
msg_sent = true;
delay(10000);

}

zOld = zRead;

//Output read values to Serial monitor Serial.print("x: "); Serial.print(xRead); Serial.print(" | y: "); Serial.print(yRead); Serial.print(" | z: "); Serial.println(zRead);

delay(100); //slow down the serial display to be able to read easier

}

void sendSMS(String number, String message) { // Make a TCP connection to remote host if (client.connect(server, 80)) {

//should look like this...
//api.thingspeak.com/apps/thinghttp/send_request?api_key={api key}&number={send to number}&message={text body}

client.print("GET /apps/thinghttp/send_request?api_key=");
client.print(apiKey);
client.print("&number=");
client.print(number);
client.print("&message=");
client.print(message);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();

} else { Serial.println(F("Connection failed")); }

// Check for a response from the server, and route it // out the serial port. while (client.connected()) { if ( client.available() ) { char c = client.read(); Serial.print(c); } } Serial.println(); client.stop(); }

String URLEncode(const char* msg) { const char *hex = "0123456789abcdef"; String encodedMsg = "";

while (*msg != '\0') { if ( ('a' <= *msg && *msg <= 'z') || ('A' <= *msg && *msg <= 'Z') || ('0' <= *msg && *msg <= '9') ) { encodedMsg += *msg; } else { encodedMsg += '%'; encodedMsg += hex[*msg >> 4]; encodedMsg += hex[*msg & 15]; } msg++; } return encodedMsg; }

void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID());

// print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip);

// print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }

Arduino Two with WiFi Shield

include

include

char ssid[] = "HP-setup-south"; // your network SSID (name) char pass[] = "detkinlabsouth101999"; // your network password (use for WPA, or use as key for WEP) int keyIndex = 0; // your network key Index number (needed only for WEP) int status = WL_IDLE_STATUS;

// thingspeak server char server[] = "api.thingspeak.com";

WiFiClient client;

// API key for the Thingspeak ThingHTTP const String apiKey = "URGFHLT8IYSS4C2B";

// the number the message should be sent to const String sendNumber = "+12487671888";

const int xPin = 0; const int yPin = 1; const int zPin = 2;

int xOld; int yOld; int zOld;

void setup() { Serial.begin(9600); int xOld = analogRead(xPin); int yOld = analogRead(yPin); int zOld = analogRead(zPin);

// set up WiFi if (WiFi.status() == WL_NO_SHIELD) { Serial.println("WiFi shield not present"); // don't continue: while (true); }

// attempt to connect to Wifi network while (status != WL_CONNECTED) { Serial.print("Attempting to connect to SSID: "); Serial.println(ssid); // Connect to WPA/WPA2 network. Change this line if using open or WEP network: status = WiFi.begin(ssid, pass); // wait 10 seconds for connection: delay(10000); }

Serial.println("Connected to wifi"); printWifiStatus(); }

void loop() { static boolean msg_sent = false;

//read the analog values from the accelerometer int xRead = analogRead(xPin); int yRead = analogRead(yPin); int zRead = analogRead(zPin);

if (abs(zRead - zOld) > 100) { Serial.print("--------------------------------"); //send the sms Serial.println("Sending SMS");

//this function will send the sms
//the first argument is the number to send to, formatted like this +12345678901
//the second argument is the body of the text message, which must be within URLEncode()
sendSMS(sendNumber, URLEncode("Jake's cane has been dropped. Dial 911 if there is an emergency"));
msg_sent = true;
delay(10000);

}

zOld = zRead;

//Output read values to Serial monitor Serial.print("x: "); Serial.print(xRead); Serial.print(" | y: "); Serial.print(yRead); Serial.print(" | z: "); Serial.println(zRead);

delay(100); //slow down the serial display to be able to read easier }

void sendSMS(String number, String message) { // Make a TCP connection to remote host if (client.connect(server, 80)) { //should look like this... //api.thingspeak.com/apps/thinghttp/send_request?api_key={api key}&number={send to number}&message={text body}

client.print("GET /apps/thinghttp/send_request?api_key=");
client.print(apiKey);
client.print("&number=");
client.print(number);
client.print("&message=");
client.print(message);
client.println(" HTTP/1.1");
client.print("Host: ");
client.println(server);
client.println("Connection: close");
client.println();

} else { Serial.println(F("Connection failed")); }

// Check for a response from the server, and route it // out the serial port. while (client.connected()) { if (client.available()) { char c = client.read(); Serial.print(c); } } Serial.println(); client.stop(); }

String URLEncode(const char* msg) { const char *hex = "0123456789abcdef"; String encodedMsg = "";

while (*msg != '\0') { if ( ('a' <= *msg && *msg <= 'z') || ('A' <= *msg && *msg <= 'Z') || ('0' <= *msg && *msg <= '9') ) { encodedMsg += *msg; } else { encodedMsg += '%'; encodedMsg += hex[*msg >> 4]; encodedMsg += hex[*msg & 15]; } msg++; } return encodedMsg; }

void printWifiStatus() { // print the SSID of the network you're attached to: Serial.print("SSID: "); Serial.println(WiFi.SSID());

// print your WiFi shield's IP address: IPAddress ip = WiFi.localIP(); Serial.print("IP Address: "); Serial.println(ip);

// print the received signal strength: long rssi = WiFi.RSSI(); Serial.print("signal strength (RSSI):"); Serial.print(rssi); Serial.println(" dBm"); }

Built With

Share this project:

Updates