Crit 2: Sound

This project uses a color sensor (TCS34725) to determine whether or not a banana is ripe. The sketch includes a button for the user to press when ready to evaluate the banana. One series of beeps indicates the banana is ready to eat, another series indicates the banana is not ready to eat. Since there is a data smoothing component, there is also a noise that identifies when new readings are dramatically different from the average reading, and notifies the user that the sensor is still calculating.

#include <Wire.h>
#include "Adafruit_TCS34725.h"

/* Example code for the Adafruit TCS34725 breakout library */

/* Connect SCL    to analog 5
   Connect SDA    to analog 4
   Connect VDD    to 3.3V DC
   Connect GROUND to common ground */

/* Initialise with default values (int time = 2.4ms, gain = 1x) */
Adafruit_TCS34725 tcs = Adafruit_TCS34725();

//* Initialise with specific int time and gain values *
//Adafruit_TCS34725 tcs = Adafruit_TCS34725(TCS34725_INTEGRATIONTIME_500MS, TCS34725_GAIN_1X);

int speakerpin=8;
int buttonpin=2;


// data smoothing
const int numReadings = 10;

int readings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int total = 0;                  // the running total
int averageb = 0;                // the average


void setup(void) {
  Serial.begin(9600);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    readings[thisReading] = 0;
  }

  pinMode(buttonpin,INPUT_PULLUP);

  if (tcs.begin()) {
    Serial.println("Found sensor");
  } else {
    Serial.println("No TCS34725 found ... check your connections");
    while (1);
  }

  // Now we're ready to get readings!
}

void loop(void) {
  uint16_t r, g, b, c, colorTemp, lux;

  tcs.getRawData(&r, &g, &b, &c);
  // colorTemp = tcs.calculateColorTemperature(r, g, b);
  colorTemp = tcs.calculateColorTemperature_dn40(r, g, b, c);
  lux = tcs.calculateLux(r, g, b);


    // subtract the last reading:
  total = total - readings[readIndex];
  // read from the sensor:
  readings[readIndex] = b;
  Serial.println(b);
  // add the reading to the total:
  total = total + readings[readIndex];
  // advance to the next position in the array:
  readIndex = readIndex + 1;

  // if we're at the end of the array...
  if (readIndex >= numReadings) {
    // ...wrap around to the beginning:
    readIndex = 0;
  }

  // calculate the average:
  averageb = total / numReadings;
  // send it to the computer as ASCII digits
  Serial.println(averageb);
  delay(1);        // delay in between reads for stability



  Serial.print("Color Temp: "); Serial.print(colorTemp, DEC); Serial.print(" K - ");
  Serial.print("Lux: "); Serial.print(lux, DEC); Serial.print(" - ");
  Serial.print("R: "); Serial.print(r, DEC); Serial.print(" ");
  Serial.print("G: "); Serial.print(g, DEC); Serial.print(" ");
  Serial.print("B: "); Serial.print(b, DEC); Serial.print(" ");
  Serial.print("C: "); Serial.print(c, DEC); Serial.print(" ");
  Serial.println(" ");
delay(100); delay(100);   delay(100);   

  int buttonvalue=digitalRead(buttonpin);
  Serial.println(buttonvalue);

  if (buttonvalue == HIGH) {
    Serial.println("button is pressed");
    if (averageb>=20){
      Serial.println("not ready");
      tone(speakerpin,293.66,1000);
      delay(1000);
      noTone(speakerpin);
      delay(500);
      tone(speakerpin,293.66,1000);
      delay(1000);
      noTone(speakerpin);
    } else if (b-averageb>=10) {
      Serial.println("calculating");
      tone(speakerpin,200,500);
      delay(500);
      noTone(speakerpin);
      delay(500);
    } else {
      Serial.println("ready to eat");
      tone(speakerpin,329.63,250);
      delay(250);
      noTone(speakerpin);
      delay(250);
      tone(speakerpin,311.13,250);
      noTone(speakerpin);
      delay(1000);
      tone(speakerpin,329.63,1000);
      noTone(speakerpin);
      delay(1000);
      }

  } else {
    Serial.println("button is not pressed");
  }





}

 

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:

 

Sound Crit

Generate sounds related to an environment that make the environment easier to use for people who might not have good data parsing, sight, or physical capabilities.

These can be mechanical sounds made with solenoids, motors, or fans; or sounds created from within the Teensy.

For amplifying sounds sent to speakers there is also the option of using a power transistor the same way you’d power a large motor.