Room Indicator for the Blind

Description:

The purpose of this device is to assist people in locating themselves when they enter a new room in their home or other location. The basic idea is that when someone enters a room, a speaker will relay what room they are entering. This is accomplished by tracking the user’s position within a house through IR break beam sensors. One set of IR break beams is installed at each doorway or opening where the user can transition from room to room. When a break is detected in one of the beams, the system checks the current sensor being tripped against the previous room the user was in and adjusts the current room accordingly. Additionally, each room has its own sound that plays indicating to the user what room they are entering upon walking in. Finally, the system sends the current room number to a p5.js script that shows a visual layout of the floor plan with the current room highlighted in green.

Images:

Videos:

Demo of physical build

Code:

 

/*
   Crit 2: Location Feedback w/Sound
   Judson Kyle
   judsonk

   Description:
*/

#include <Audio.h>
#include <Wire.h>
#include <SPI.h>
#include <SD.h>
#include <SerialFlash.h>

AudioPlaySdWav           playWav1;
AudioMixer4              mixer1;         //xy=647,408
AudioOutputMQS           mqs1;           //xy=625,279
AudioConnection          patchCord1(playWav1, 0, mqs1, 0);
AudioConnection          patchCord2(playWav1, 1, mqs1, 1);

#define SDCARD_CS_PIN    BUILTIN_SDCARD
#define SDCARD_MOSI_PIN  11  // not actually used
#define SDCARD_SCK_PIN   13  // not actually used

#define TRIGGER0   17
#define TRIGGER1   18
#define TRIGGER2   19
#define TRIGGER3   20
#define TRIGGER4   21
#define TRIGGER5   33
#define TRIGGER6   33
#define TRIGGER7   33
#define TRIGGER8   33
#define TRIGGER9   33
#define TRIGGER10  33
#define TRIGGER11  33
#define TRIGGER12  33

const char* outside = "Outside.WAV";
const char* sunRoom = "Sun Room.WAV";
const char* livingRoom = "Living Room.WAV";
const char* bed1 = "Bedroom 1.WAV";
const char* bed2 = "Bedroom 2.WAV";
const char* bed3 = "Bedroom 3.WAV";
const char* kitchen = "Kitchen.WAV";
const char* laundryRoom = "Laundry Room.WAV";
const char* diningRoom = "Dining Room.WAV";
const char* bath1 = "Bathroom 1.WAV";
const char* bath2 = "Bathroom 2.WAV";
const char* hall1 = "Hallway 1.WAV";
const char* hall2 = "Hallway 2.WAV";

//char *roomNames[13] = { outside,    sunRoom,      livingRoom,
//                        bed1,       bed2,         bed3,
//                        kitchen,    laundryRoom,  diningRoom,
//                        bath1,      bath2,        hall1,
//                        hall2};

int triggerPins[13] = { TRIGGER0,   TRIGGER2,   TRIGGER3,   TRIGGER4,
                        TRIGGER4,   TRIGGER5,   TRIGGER6,   TRIGGER7,
                        TRIGGER8,   TRIGGER9,   TRIGGER10,  TRIGGER11,
                        TRIGGER12
                      };
int numTriggers = 13;
int currTriggerOn = 0;
int prevTriggerOn = -1;
int prevRoom = 0;
volatile int currRoom = 0;

unsigned long currTime = 0;
unsigned long debounceTime = 100;
volatile unsigned long startTime = 0;
volatile bool DEBOUNCE = false;

const char* currFileName = outside;

void setup(void)
{
  // Wait for at least 3 seconds for the USB serial connection
  Serial.begin (9600);

  AudioMemory(8);

  pinMode(TRIGGER0, INPUT);
  pinMode(TRIGGER1, INPUT);
  pinMode(TRIGGER2, INPUT);
  pinMode(TRIGGER3, INPUT);
  pinMode(TRIGGER4, INPUT);

  SPI.setMOSI(SDCARD_MOSI_PIN);
  SPI.setSCK(SDCARD_SCK_PIN);
  if (!(SD.begin(SDCARD_CS_PIN))) {
    // stop here, but print a message repetitively
    while (1) {
      Serial.println("Unable to access the SD card");
      delay(500);
    }
  }

}

void loop (void)
{
  currTime = millis();

  if (!DEBOUNCE && !playWav1.isPlaying()) {
    updateCurrRoom();
    DEBOUNCE = true;
    startTime = currTime;
  }

  if (currTriggerOn != prevTriggerOn) {
    updateCurrRoom();
  }

  if (prevRoom != currRoom) {
    if (playWav1.isPlaying()) {
      playWav1.togglePlayPause();
    }
    playWav1.play(currFileName);
    Serial.println(currRoom);
  }

  prevRoom = currRoom;
  prevTriggerOn = currTriggerOn;

  //Update debounce state
  DEBOUNCE = abs(currTime - startTime) < debounceTime;
}

void updateCurrRoom() {
  switch (currRoom) {
    case 0:
      if (digitalRead(TRIGGER0) > 0) {
        currRoom = 1;
        currFileName = sunRoom;
      }
      break;
    case 1:
      if (digitalRead(TRIGGER0) > 0) {
        currRoom = 0;
        currFileName = outside;
      }
      else if (digitalRead(TRIGGER1) > 0) {
        currRoom = 2;
        currFileName = livingRoom;
      }
      break;
    case 2:
      if (digitalRead(TRIGGER2) > 0) {
        currRoom = 8;
        currFileName = diningRoom;
      }
      else if (digitalRead(TRIGGER1) > 0) {
        currRoom = 1;
        currFileName = sunRoom;
      }
      break;
    case 3:
      if (digitalRead(TRIGGER3) > 0) {
        currRoom = 8;
        currFileName = diningRoom;
      }
      break;
    case 8:
      if (digitalRead(TRIGGER2) > 0) {
        currRoom = 2;
        currFileName = livingRoom;
      }
      else if (digitalRead(TRIGGER4) > 0) {
        currRoom = 9;
        currFileName = bath1;
      }
      else if (digitalRead(TRIGGER3) > 0) {
        currRoom = 3;
        currFileName = bed1;
      }
      break;
    case 9:
      if (digitalRead(TRIGGER4) > 0) {
        currRoom = 8;
        currFileName = diningRoom;
      }
      break;
    default:
      break;
  }
}

 

let serial;
let latestData = "waiting for data";
var outData;

var minWidth = 600;   //set min width and height for canvas
var minHeight = 400;
var width, height;    // actual width and height for the sketch
var squareWidth = 100;

var greenColor = '#64d65d';
var redColor = '#d6220c';

var currRoom = 0;

class Room {
  constructor(length, height, xOffset, yOffset, color, name) {
    this.scale = 40;
    this.length = length*this.scale;
    this.height = height*this.scale;
    this.xOffset = xOffset*this.scale;
    this.yOffset = yOffset*this.scale;
    this.color = color; 
    this.name = name;
  }
  getX(canvasWidth) {
    return (canvasWidth - 12*this.scale)/2 + this.xOffset;
  }
  getY(canvasHeight) {
    return (canvasHeight + 17*this.scale)/2 - this.yOffset - this.height;
  }
}

let sunRoom = new Room(6, 2, 0, 0, redColor, "Sun Room");
let livingRoom = new Room(6, 5, 0, 2, redColor, "Living Room");
let dinningRoom = new Room(6, 4, 0, 7, redColor, "Dinning Room");
let bed1 = new Room(6, 7, 6, 0, redColor, "Bedroom 1");
let bed2 = new Room(6, 5, 6, 11, redColor, "Bedroom 2");
let bed3 = new Room(5, 3, 0, 11, redColor, "Bedroom 3");
let kitchen = new Room(4, 3, 2, 14, redColor, "Kitchen");
let laundryRoom = new Room(2, 1, 0, 16, redColor, "Laundry Room");
let bath1 = new Room(5, 4, 7, 7, redColor, "Bathroom 1");
let bath2 = new Room(2, 2, 0, 14, redColor, "Bathroom 2");
let hall1 = new Room(1, 4, 6, 7, redColor, "Hall 1");
let hall2 = new Room(1, 3, 5, 11, redColor, "Hall 2");
let outside = new Room(0, 0, 0, 0, redColor, "Outside");


var rooms = [ outside, sunRoom,  livingRoom, 
              bed1,     bed2,        bed3, 
              kitchen,  laundryRoom, dinningRoom,
              bath1,    bath2, 
              hall1,    hall2];

var scale = 10;


function setup() {
 // set the canvas to match the window size
 if (window.innerWidth > minWidth){
  width = window.innerWidth;
  } else {
    width = minWidth;
  }
  if (window.innerHeight > minHeight) {
    height = window.innerHeight;
  } else {
    height = minHeight;
  }

  originX = width/2 - 5.5*scale;
  originY = height/2 - 8.5*scale;

  //set up canvas
  createCanvas(width, height);
  noStroke();

 serial = new p5.SerialPort();

 serial.list();
 serial.open('/dev/tty.usbmodem114760901');

 serial.on('connected', serverConnected);

 serial.on('list', gotList);

 serial.on('data', gotData);

 serial.on('error', gotError);

 serial.on('open', gotOpen);

 serial.on('close', gotClose);
}

function serverConnected() {
 print("Connected to Server");
}

function gotList(thelist) {
 print("List of Serial Ports:");

 for (let i = 0; i < thelist.length; i++) {
  print(i + " " + thelist[i]);
 }
}

function gotOpen() {
 print("Serial Port is Open");
}

function gotClose(){
 print("Serial Port is Closed");
 latestData = "Serial Port is Closed";
}

function gotError(theerror) {
 print(theerror);
}

function gotData() {
  let currentString = serial.readLine();
  trim(currentString);
  if (!currentString) return;
  console.log(currentString);
  latestData = Number(currentString);
  currRoom = latestData;
  for (i = 0; i < rooms.length; i++) {
    rooms[i].color = redColor;
  }
  rooms[currRoom].color = greenColor;
}

function draw() {  
  background(0);

  //Draw canvas
  strokeWeight(4);
  stroke('white');
  fill('black');
  noStroke();

  fill(255);
  textSize(16);
  text("House Map", 30, 30);
  text("Current Room: " + rooms[currRoom].name, 30, 50);    // displaying the input

  //Draw Rooms
  strokeWeight(4);
  stroke('black');
  // fill(redColor);
  for (i = 0; i < rooms.length; i++) {
    fill(rooms[i].color);
    rect(rooms[i].getX(width), rooms[i].getY(height), rooms[i].length, rooms[i].height);
  }

}

function mousePressed() {
  var currX = mouseX;
  var currY = mouseY;

  for (i = 0; i < rooms.length; i++) {
    var roomX = rooms[i].getX(width);
    var roomY = rooms[i].getY(height);

    var check1 = (currX > roomX) && (currX < roomX + rooms[i].length);
    var check2 = (currY > roomY) && (currY < roomY + rooms[i].height);
    
    if (check1 && check2) {
      currRoom = i;
      rooms[i].color = greenColor;
    }
    else {
      rooms[i].color = redColor;
    }
  }
  
}

function mouseDragged() {

}

Electrical Schematic:

 

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.