Are you prepared for the next couple hours weather?

Problem

With quarantine, I have not been leaving the house all that much, so I seem to have lost my intuition about temperature and my habit of always checking the weather in the morning. This has led me to be surprised by how hot/cold it gets if I’ve gone on a long walk or gone grocery shopping as well as when it starts raining before I’ve gotten home. I’ve found myself really cold in just a sweatshirt in the evening, hot when I wore thick sweatpants on a day that became unusually warm, and caught in the rain unprepared in the infrequent times I’ve been outside for an hour or two this semester.  This led me to the idea of a system that when I leave the house, would let me know about weather changes in the 2 following hours without bothering me.

Proposed Solution

To solve this problem, I propose a small device that can be placed on the wall near the front door that will detect when you leave the house and give notifications appropriate to the current weather and the changes. The opening of the door is detected with a magnetic reed switch.  Whether you are entering or exiting the house is decided based on if the PIR motion sensor detects motion right before the door opens. If you are entering the house, motion will be detected. Notifications will only be given when you are leaving the house, so when no motion is detected. This device uses an esp32 board (I chose the Adafruit Huzzah32) to get the current and hourly weather from the OpenWeather API over WiFi. The current temperature and weather condition as well as that of the next 2 hours are taken from the fetched information. If it will rain or snow, and it isn’t already raining or snowing, the buzzer will play a specific tone sequence 3 times as the door is opening. I chose a sequence that sounds to me a bit like “oh hooray” when it will snow because I love snow. If it will rain, I chose a more warning sound alert because it’s usually not fun to get caught in the rain. The main reason I chose to not give an alert if it will snow/rain when it already is is because you can clearly see what’s happening and should be prepared for it to keep raining/snowing. The buzzer was chosen rather than a speaker because it was loud enough to catch my attention easily, but unlike the speaker it isn’t loud enough to be annoying. I chose to have the LED strip light up to let you know it will be colder or hotter by 5 or more degrees Fahrenheit as that’s when the temperature change bothers me. Red corresponds to hotter and blue to colder. The LED strip will flash for 2 seconds once the door closes to get your attention and then for another 5 seconds it will stay that color so that you can still see the alert but not get annoyed by it as you are leaving. In the next section, you can see demo videos of the cases for this device.

Proof of Concept

Outside videos showing operation when set up:

Demo while leaving the house showing the snow and colder notifications.

Demo while entering the house, showing how there’s no notifications even though the temperature gets colder enough and it will snow.

Videos taken inside to show the different cases:

Demo showing how there are no notifications when temperature doesn’t change enough and it won’t snow or rain.

Demo showing when it just gets colder.

Demo showing when it just gets hotter.

Demo showing when it just will rain.

Demo showing when it just will snow.

Demo showing when it just will rain and is currently raining.

Changes for real implementation

Currently, my device is easily seen and looks bad especially because I had to use so much duct tape for things to stick. To fix this, I would use command strips instead of duct tape to attach everything to the door and wall. The wires for the magnetic reed switch would be all white to blend more. The main board part would be soldered together and put into a box then place under the decorative wreath.

In the final version, a rechargeable 9V battery would be stepped down to 5V would power the LED strip and PIR motion sensor rather than my uno plugged into my laptop which I used because my 9V battery was drained. Using a usb wall plug, I would power the esp32 board rather than my laptop’s port. The outlet my laptop is plugged into would be used for this.

I would run the LED strip wires across the roof of the porch and put the LED strip where the green circle is. This way, it would be where you face while leaving the house and is in the line of sight for going down the porch stairs.

Schematic:

Code:

Note: You will have to enter in your own WiFi information as well as API key- I don’t want to just broadcast that.

//used this tutorial for getting weather: https://techtutorialsx.com/2018/03/17/esp32-arduino-getting-weather-data-from-api/
#include <WiFi.h>
#include <HTTPClient.h>
const char* ssid = "YOUR WIFI NAME";
const char* password =  "YOUR WIFI PASSWORD";

const String endpoint = "https://api.openweathermap.org/data/2.5/onecall?lat=40.445227&lon=-79.934243&exclude=minutely,daily,alerts&units=imperial&appid=";//CHANGE TO LOCATION YOU WANT DATA FROM
const String key = "YOUR UNIQUE KEY";

const int doorSwitchPin = 14;
int justOpened = 0;
int foundWeather = 0;
//const int LEDpin=12;
#include <NeoPixelBus.h>
const int LEDstripPin = 12;
const int numLEDs = 10;
NeoPixelBus<NeoGrbFeature, Neo800KbpsMethod> strip(numLEDs, LEDstripPin);
long startTime;

int hotter = 0;
int colder = 0;
int currentlyRaining = 0;
int currentlySnowing = 0;
int willRain = 0;
int willSnow = 0;
int rainWarning = 0;
int snowWarning = 0;
int maskWarning = 0;
int haveMask = 0;
String content;
#include <Tone32.h>

#define BUZZER_PIN A0
#define BUZZER_CHANNEL 0


const int PIRpin = 27;
int pirVal;

void pirISR() {
  pirVal = digitalRead(PIRpin);
}

//RFID stuff mainly from this tutorial https://randomnerdtutorials.com/security-access-using-mfrc522-rfid-reader-with-arduino/
//#include <SPI.h>
//#include <MFRC522.h>
//
//#define SS_PIN 23
//#define RST_PIN 15
//MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.

void setup() {

  Serial.begin(115200);
  //  SPI.begin();      // Initiate  SPI bus
  //  mfrc522.PCD_Init();   // Initiate MFRC522
  pinMode(doorSwitchPin, INPUT);
  pinMode(PIRpin, INPUT);
  attachInterrupt(digitalPinToInterrupt(PIRpin), pirISR, CHANGE);
  //pinMode(LEDpin, OUTPUT);
  WiFi.begin(ssid, password);

  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting to WiFi..");
  }

  Serial.println("Connected to the WiFi network");
  // this resets all the neopixels to an off state
  strip.Begin();
  strip.Show();
}

void loop() {
  if ((WiFi.status() == WL_CONNECTED)) { //Check the current connection status
    HTTPClient http;
    if (digitalRead(doorSwitchPin) == 0) {//door opened
      //added measure so lights off when the door is opened, will immediately turn of lights if you open it while they are on
      for (int i = 0; i < numLEDs; i = i + 1) {
        strip.SetPixelColor(i, RgbColor(0, 0, 0));
      }
      strip.Show();
      if (pirVal == 0) { //no motion detected at door near knob outside, so ur opening from inside
        //        if (haveMask == 0) { // Look for new cards
        //          if ( ! mfrc522.PICC_IsNewCardPresent())
        //          {
        //            //return;
        //          }
        //          // Select one of the cards
        //          if ( ! mfrc522.PICC_ReadCardSerial())
        //          {
        //            //return;
        //          }
        //        }
        //        //Show UID on serial monitor
        //        // Serial.print("UID tag :");
        //        content = "";
        //        byte letter;
        //        for (byte i = 0; i < mfrc522.uid.size; i++)
        //        {
        //          //          Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
        //          //          Serial.print(mfrc522.uid.uidByte[i], HEX);
        //          content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
        //          content.concat(String(mfrc522.uid.uidByte[i], HEX));
        //        }
        //        content.toUpperCase();
        //
        //        if (content.substring(1) == "ED E4 86 B9" || content.substring(1) ==  "9D 65 7D B9" ) {//change here the UID of the card/cards that you want to give access
        //          int haveMask = 1;
        //        }
        //        else { //dont have mask
        //          if (maskWarning == 0) {
        //            for (int count = 0; count < 4; count++) {
        //              tone(BUZZER_PIN, NOTE_D4, 500, BUZZER_CHANNEL);
        //  noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //  tone(BUZZER_PIN, NOTE_C4, 500, BUZZER_CHANNEL);
        //  noTone(BUZZER_PIN, BUZZER_CHANNEL);
        //            }
        //            maskWarning = 1; //been warned
        //          }
        //        }
        if (foundWeather == 0) {//havent calculated the weather for this opening yet
          // Serial.println("calculating");
          http.begin(endpoint + key); //Specify the URL
          int httpCode = http.GET();  //Make the request

          if (httpCode > 0) { //Check for the returning code

            String payload = http.getString();
            int first1 = payload.indexOf("temp");//gives index of the t
            int start1 = first1 + 6;//add indexso that I'm at the number
            int end1 = payload.indexOf(',', start1);
            Serial.println(payload);
            //Serial.println(start1);
            float currentTemp = payload.substring(start1, end1).toFloat();//making string into float so that I can do math with it

            int first2 = payload.indexOf("temp", end1);
            int start2 = first2 + 6;
            int end2 = payload.indexOf(',', start2);
            float hrOneTemp = payload.substring(start2, end2).toFloat();

            int first3 = payload.indexOf("temp", end2);
            int start3 = first3 + 6;
            int end3 = payload.indexOf(',', start3);
            float hrTwoTemp = payload.substring(start3, end3).toFloat();

            Serial.print("Current temp: ");
            Serial.print(currentTemp);
            Serial.print("\t");
            Serial.print("Temp in 1 hr: ");
            Serial.print(hrOneTemp);
            Serial.print("\t");
            Serial.print("Temp in 2 hrs: ");
            Serial.println(hrTwoTemp);
            if (((hrOneTemp - currentTemp) > 5) || ((hrTwoTemp - currentTemp) > 5)) { //would've been 5 but not fluctuating much at all recently
              hotter = 1;
            }
            else {
              hotter = 0;
            }
            if (((currentTemp - hrOneTemp) > 5) || ((currentTemp - hrTwoTemp) > 5)) { //would've been 5 but not fluctuating much at all recently
              colder = 1;
            }
            else {
              colder = 0;
            }
            int first4 = payload.indexOf("temp", end3);//just using to know around where hour 3 is
            int checkRain = payload.indexOf("Rain");
            if (checkRain != -1) { //means doesn't rain at all in huge data set
              if (checkRain < first2) {
                currentlyRaining = 1;
                willRain = 0; //dont care if it rains later as can already see it's raining
              }//don't bother finding index of another rain bc if it's already raining don't need to see if it'll rain in next 2 hours
              else if (checkRain < first3) {
                willRain = 1; //will rain in an hr
              }
              else if (checkRain < first4) {
                willRain = 1; //will rain in 2 hours
              }
            }
            else {
              willRain = 0;
            }
            int checkSnow = payload.indexOf("Snow");
            if (checkSnow != -1) {
              if (checkSnow < first2) {
                currentlySnowing = 1;
                willSnow = 0;
              }
              else if (checkSnow < first3) {
                willSnow = 1;
              }
              else if (checkSnow < first4) {
                willSnow = 1;
              }
            }
            else {
              willSnow = 0;
            }
            willRain = 1;
            Serial.print("Currently raining: ");
            Serial.print(currentlyRaining);
            Serial.print("\t");
            Serial.print("Will rain: ");
            Serial.println(willRain);
            Serial.print("Currently snowing: ");
            Serial.print(currentlySnowing);
            Serial.print("\t");
            Serial.print("Will snow: ");
            Serial.println(willSnow);
            if (willRain) {
              if (rainWarning == 0) {
                for (int count = 0; count < 4; count++) {//play sequence 3x while door is being closed/your just stepping outside
                  tone(BUZZER_PIN, NOTE_C4, 100, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                  tone(BUZZER_PIN, NOTE_A4, 200, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                  tone(BUZZER_PIN, NOTE_B4, 200, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                }
                rainWarning = 1;//so warning doesn't just keep playing if door is open
              }
            }
            if (willSnow) {
              if (snowWarning == 0) {
                for (int count = 0; count < 4; count++) {
                  tone(BUZZER_PIN, NOTE_D4, 100, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                  tone(BUZZER_PIN, NOTE_E4, 500, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                  tone(BUZZER_PIN, NOTE_C4, 300, BUZZER_CHANNEL);
                  noTone(BUZZER_PIN, BUZZER_CHANNEL);
                }
                snowWarning = 1;
              }
            }
          }

          else {
            Serial.println("Error on HTTP request");
          }

          http.end(); //Free the resources
          foundWeather = 1;
        }
      }
    }
    //}
    else {//door closed again
      if (foundWeather == 1) {
        startTime = millis();
        //resetting the variables above
        rainWarning = 0;
        snowWarning = 0;
        maskWarning = 0;
        haveMask = 0;
        content = "";
      }
      foundWeather = 0;


      if (hotter) {
        if (millis() - startTime < 2000) { //flash to get attention
          static int blinkStart = millis();
          for (uint16_t i = 0; i < numLEDs; i++) {//this rotates through each LED on the strip so that each one will be red
            byte x = millis() - 20 * i;
            strip.SetPixelColor(i, RgbColor(255 - x, 0, 0));
          }
          strip.Show();
          if (millis() - blinkStart >= 10) {
            for (uint16_t i = 0; i < numLEDs; i++) {
              strip.SetPixelColor(i, RgbColor(0, 0, 0));
            }
            strip.Show();
            blinkStart = millis();
          }
        }
        else if (millis() - startTime < 7000) {//stays on just lights as attention probably already caught and dont want to annoy
          for (uint16_t i = 0; i < numLEDs; i++) {
            byte x = millis() - 20 * i;
            strip.SetPixelColor(i, RgbColor(255 - x, 0, 0));
          }
        }
        else {
          for (int i = 0; i < numLEDs; i = i + 1) {
            strip.SetPixelColor(i, RgbColor(0, 0, 0));
          }
          strip.Show();
        }
      }
      else if (colder) {
        if (millis() - startTime < 2000) { 
          static int blinkStart = millis();
          for (uint16_t i = 0; i < numLEDs; i++) {
            byte x = millis() - 20 * i;
            strip.SetPixelColor(i, RgbColor(0, 0, 255 - x));
          }
          strip.Show();
          if (millis() - blinkStart >= 10) {
            for (uint16_t i = 0; i < numLEDs; i++) {
              strip.SetPixelColor(i, RgbColor(0, 0, 0));
            }
            strip.Show();
            blinkStart = millis();
          }
        }
        else if (millis() - startTime < 7000) {
          for (uint16_t i = 0; i < numLEDs; i++) {
            byte x = millis() - 20 * i;
            strip.SetPixelColor(i, RgbColor(0, 0, 255 - x));
          }
        }
        else {
          for (int i = 0; i < numLEDs; i = i + 1) {
            strip.SetPixelColor(i, RgbColor(0, 0, 0));
          }
          strip.Show();
        }
      }
    }
  }
}

Notes on taking project further and functioning that was decided against

  • The idea of having an RFID scanner so that notifications are only given when you aren’t prepared is really interesting and would add great functionality, but doesn’t work well with this project. The RFID scanner I have took too long to read the card and held up the entire system; it took long enough that you could already make it to the stairs before a notification was given. Additionally, the card/tag had to be touching the scanner which isn’t realistic for someone leaving the house to do. Finally, it can’t read multiple cards right next to each other. The first of these problems could be fixed with better equipment, but I don’t think the other two would get solved. If someone fixed these issues and wanted to make my project, especially more commercial, the add-ons would be that the clothes and items that pertain to certain type of weather (ie sweatshirt, raincoat, boots, gloves, etc) could be scanned on the way out. Multiple tags can be used for the same category and the tags could be small and machine washable. Similar to this, in the age of covid, masks could be checked for and if you don’t have one, be warned with an alarm sound. Moreover, our school cards are RFID cards, so I could have set it to react according to who is leaving the house or even only just for me. To really expand, a To-do list could be linked via the internet and if you leave close to the time of grocery shopping, you could get a notification if you don’t have reusable bags.
  • Instead of specific sound sequences, I tried to use the TTS esp library with a speaker and amplifier circuit. This is loud enough with the amplifier circuit, however, it isn’t very understandable. I wanted it to say, rain, snow, and mask (with the RFID implemented but again it didn’t work fast enough). Even changing the text given to try and make it sound better by spelling more like pronunciation didn’t help much.
  • Something relatively easy to do with IFTTT is to send a text message when certain criteria are met. I could have had a text message to me if it was going to be colder, hotter, rain, or snow. I decided against this because it would only really make sense if who was leaving was detected and free accounts only have 3 applets included so I didn’t want to use another on this especially since for me I probably wouldn’t even look at or notice that notification until I’m pretty far away.

Notes about using the esp32 board

In general, it takes much longer to compile and upload to the board than it did for the uno.

Certain libraries that work with the uno don’t work with this and you need to download different ones in general or the same ones modified to work with esp32s.

  • I needed to use the Tone32 library instead of regular one.
  • The PololuLedStrip library is incompatible and so I instead used NeoPixelBus.
  • Not for this project, but for the other one I’m working on, I needed to use download an esp servo library and still included Servo.h like usual.

Are you set for the next couple hours?

Problem

With quarantine, I have not been leaving the house all that much, so I seem to have lost my intuition about temperature and my habit of always checking the weather in the morning. This has led me to be surprised by how hot/cold it gets if I’ve gone on a long walk or gone grocery shopping as well as when it starts raining before I’ve gotten home. This led me to the idea of a system that when I leave the house, would let me know about weather changes in the 2 following hours without bothering me. During initial discussion, Jet brought up the suggestion of having reminders only if the person isn’t prepared for the weather change as well as a notification if the person forgot a mask.

Solution

To realize my idea, I plan to make a system that would notify you depending on the weather change when you are leaving the house. It would be known if you are leaving the house rather than entering house because the motion sensor would not be triggered. When you open the door, the current weather would be compared to the weather in the next 2 hours and if it will rain, snow, and/or the temperature will change by 5°F or more you’ll be notified. This data would be collected by a python web scraper. For rain or snow, a pitter-patter type sound would be played by the speaker and temperature changes would be signified by the LED strip’s colors. To attract the person’s attention, this would flash the appropriate color of red-orange or blue three times before staying on for about 5 seconds more. These reminders would be noticeable but not a bother if you are already prepared. This is what I want to first accomplish and then will move on to implementing the RFID part as this is most important to me and it is easily usable by everyone and tags would not have to be put on clothes. Additionally, this would be my first time using WiFi on a project, connecting the Arduino to Python, and creating a web scraper, so I want to focus first on doing that well.

To create the system that would only notify the person if they aren’t prepared, I’d put an RFID scanner near the door frame beside the magnetic door switch so that the the tags on clothes could be scanned while you walk by. The same barcodes would be on things that fit the same purpose. For example, all masks would have one code, rain jacket and umbrella would have another, sweatshirts another, and light jackets another. This can be customized per user in the household code so that what they’d wear for certain conditions and the matching codes are associated with just that person. Each person would be differentiated by the RFID card that they carry on them whenever they leave the house, here the CMU ID card. For a full product using this, I’ve found laundry safe RFID tags that were pretty cheap and small so could work really well in this application.

Components I plan to use:

  • magnetic door switch
  • esp8266 module or board
  • speaker
  • led strip
  • motion sensor

Add ons

  • RFID sensor and cards

 

Don’t trip on what’s in front of you!

Problem:

People often trip over small objects that are in their path that they may not be expecting, especially if the object isn’t very tall. This is because the object is well below their sight line unless they are looking towards the ground. If someone’s on their phone, they are also more likely to trip over a small object. Blind people also of course have to be able to navigate around things that they cannot see. While they have a cane that will help them to know if something is in front of them by it hitting it, but sounds to notify something within a stride could be helpful.

Proposed Solution:

To help people with this problem, I propose a small wearable device strapped to the ankle that will buzz at different intervals based on how far an object is. This device is made up of a servo motor, ultrasonic distance sensor, accelerometer, and pancake vibration motor. The servo, distance sensor, and accelerometer are all attached. The servo moves such that the accelerometer is level so that the distance sensor is pointed straight ahead. This is important because as you walk, your leg is at various angles and doesn’t stay vertical. The buzzing from the vibration motor is a good way to know how far you are from something because the sound is pretty distinctive and has the added bonus of being able to feel it on your leg. For an actual version of this, I would package this smaller so that it could be actually something small attached to your leg that isn’t cumbersome.  This would go on both ankles so that you’d know if something was in your path for sure and not just on one side. I’d also use a bigger vibration motor so that the sound is a bit louder; with this, I could feel it and hear it fine, but if the house was louder, it would’ve been harder to hear. I also wish that I had soldered the leads of the vibration motor while I was in A10 because the wire kept coming loose while trying to take videos of me walking and I’d have to bend down to fix it and then when I stood up, it would come loose again; along the same vein, I wish I had been recording the whole time because a really good example while walking with the all different buzzing intervals happened when I forgot to restart it.

Proof of Concept:

Schematic
//changed smoothing example from https://www.arduino.cc/en/Tutorial/BuiltInExamples/Smoothing

#include <Servo.h>

Servo myLittleMotor;
const int servoPin = 11;
int servoPosition = 120;

#include <NewPing.h>
const int triggerPin = 8;
const int echoPin = 9;
int maxDistance = 400;
NewPing sonar(triggerPin, echoPin, maxDistance);
const int footSize = 25.4;//cm
int distance;

const int numReadings = 10;
int DISTreadings[numReadings];      // the readings from the analog input
int readIndex = 0;              // the index of the current reading
int DISTtotal = 0;                  // the running total
int DISTaverage = 0;                // the average

const int yPin = A4;
int yVal;

const int pancakePin = 6;

void setup() {
  myLittleMotor.attach(servoPin);


  pinMode(yPin, INPUT);


  pinMode(pancakePin, OUTPUT);

  Serial.begin(9600);
  myLittleMotor.write(servoPosition);
  for (int thisReading = 0; thisReading < numReadings; thisReading++) {
    DISTreadings[thisReading] = 0;
  }

}

void loop() {
  myLittleMotor.write(servoPosition);
  yVal = analogRead(yPin);

  distance = sonar.ping_cm();
  // subtract the last reading:
  DISTtotal = DISTtotal - DISTreadings[readIndex];
  // read from the sensor:
  DISTreadings[readIndex] = distance;
  // add the reading to the total:
  DISTtotal = DISTtotal + DISTreadings[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:
  DISTaverage = DISTtotal / numReadings;
  // send it to the computer as ASCII digits
  //Serial.println(Yaverage);
  if (yVal > 352 && servoPosition > 0) {
    servoPosition -= 1;
  }
  else if (yVal < 348 && servoPosition < 180) {
    servoPosition += 1;
  }
  if (DISTaverage < (1.5 * footSize)) { //1 footSize past your foot
    static int start = millis();
    //Serial.println("closest");
    if ((millis() - start) < 200) {
      //digitalWrite(speakerPin,HIGH);
      digitalWrite(pancakePin, HIGH);
    }
    else if ((millis() - start) < 400) {
      digitalWrite(pancakePin, LOW);
    }
    else {
      start = millis();
    }
  }
  else if (DISTaverage < (1.5 * footSize + footSize)) {
    static int start2 = millis();
    if ((millis() - start2) < 200) {
      digitalWrite(pancakePin, HIGH);
    }
    else if ((millis() - start2) < 600) {
      digitalWrite(pancakePin, LOW);
    }
    else {
      start2 = millis();
    }
  }
  else if (DISTaverage < (1.5 * footSize + 2 * footSize)) {
    static int start3 = millis();
    if ((millis() - start3) < 200) {

      digitalWrite(pancakePin, HIGH);
    }
    else if ((millis() - start3) < 1000) {
      digitalWrite(pancakePin, LOW);
    }
    else {
      start3 = millis();
    }
  }
  else {
    //noTone(speakerPin);
    digitalWrite(pancakePin, LOW);
  }
  Serial.print(yVal);
  Serial.print('\t');
  Serial.println(DISTaverage);
  delay(25);
  //38.1
  //63.1
  //88.9
}

 

Mini Assignment 9

One sound that would be really helpful for our house is a certain song playing as a notification if all our garbage/recycling cans aren’t in their spots on our driveway at 5:30 PM on Wednesdays. This would be a great reminder to take them off the curb so we don’t get in trouble with Pittsburgh.

Another helpful sound inspired by Jet’s weather example is a tone that would be played as we are leaving the house if it’s late afternoon/ early evening and the temperature is supposed to drop by 10 or more degrees. This could be a useful reminder to get a(nother) jacket if you aren’t already prepared for the temperature change. This is more important with everyone spending so much time inside.

Finally, a last helpful sound I thought of is if a package is delivered to have the doorbell ring if the delivery person had not done so. It seems that this year it is up in the air whether there is a notification that a package has arrived.

 

Funky Music Maker

After watching the videos on changes and developments in music in class, I got to thinking about what would be a cool, funky way to make music with electronics. I decided that a fun experimental music making idea would combine the ability to change the type of sound quickly on a speaker (frequency) as well as add in the taps that could go with a beat based on your leg moving up and down. This being triggered by your leg would leave a hand open to change out what is being tapped by the solenoid and thus change the sound heard from it. As someone who knows nothing about music and notes, I chose for someone to just change the frequency so that there would be no barriers from someone trying it out. For this proof of concept, I chose to have the speaker turn off when the IR beam is broken and the solenoid moves as it overpowers the sound otherwise.

int solenoidPin = 9;
const int IRpin = 3;
int IRstate;
int potPin = A0;
int potVal;
int speakerPin = 13;
int frequency;

void setup()
{
  pinMode(solenoidPin, OUTPUT);
  pinMode(IRpin, INPUT);
  digitalWrite(IRpin, HIGH);
  pinMode(potPin, INPUT);
  pinMode(speakerPin, OUTPUT);
  Serial.begin(9600);
}

void loop()
{
  potVal = analogRead(potPin);
  frequency = map(potVal, 0, 1023, 1, 1000);
  IRstate = digitalRead(IRpin);
  Serial.println(IRstate);
  static int start = millis();
  digitalWrite(solenoidPin, !IRstate);
  if (IRstate == 1) {
    tone(speakerPin, frequency);
  }
  else { //broken
    noTone(speakerPin);
  }
}

 

Assignment 8

I have quite a few feelings associated with sounds, so I’m going to just list them below for clarity:

Happy:

  • Jingling sound on a dog collar
  • Oven timer because it means desserts are done usually
  • Housemate playing guitar

Annoyed:

  • Flies buzzing, especially because we have way too many of them in the kitchen
  • Neighbors playing music really loudly
  • When I was in Morewood Gardens, the fire alarm because it went off falsely a bunch of times
  • Loud work-boots on the floor above me

Angry:

  • Neighbor in the room next to mine (duplex) talking and laughing loudly really late at night after I’ve asked for them to at least do so quieter/downstairs if it’s past 1am. Thankfully this has basically stopped since the first few weeks of school where I was kept up till 3-4am consistently…

Sleepy

  • Rain

Without titles/names and no video, I wouldn’t be able to tell most of the sounds from Star Trek, but the red alert, transporter and photon torpedo sounds to me relate well to the names. The computer noises without any other clues sound like what robots would make. To me, car sounds mainly don’t carry an emotion unless it’s honking which is used to convey annoyance much of the time. When it comes to sounds I’ve never heard in movies, I tend to just believe that they make sense without questioning it; I even learn the sound association pretty quickly. Thankfully I’ve never heard a gun go off anywhere near me, but babies crying always seem louder than they probably are. I think this could be because of how high pitched it is.

 

Sound in Physical Interaction

Secret Knock Detecting Door Lock:

This device can recognize a secret knock pattern that’s up to 20 knocks long and unlock the door if it is correct! Instructions on how to make it can be found here.

The world’s deepest bin

This trash can makes it sound like garbage thrown in is taking a really long time. It made throwing trash away more fun and even got some people to pick up litter.

Urban Lights Contacts:

This interactive sound installation changes the sound output based on electrostatic connections; in other words, it will make varying sounds from how close people are and if people are touching. This is a really cool concept, but definitely something that would give me anxiety to try because of COVID.

Worry free curtains and an alarm clock supplement that’s natural!

Problem:

Do you like having natural light in the room during the day, but often forget to close the curtains at night and so get woken up earlier than you wanted in the morning? Do you ever just want to wake up with natural light in the room, but not get woken up too early by it? After not getting enough sleep, do you find yourself having trouble getting up to your alarm or being blinded when you turn on the light or open the curtains because your eyes aren’t used to it? If you’re like me and have answered yes to these questions, this worry free curtain and alarm clock supplement could be the solution!

Proposed Solution:

Enter the time times you want to wake up each day of the week, the current date and time, upload the program, and that’s it your curtains will open according to the time you want to wake up and when you went to bed (set by pressing button) and close when it’s evening and dark. If you didn’t get nearly enough sleep, a fan will also blow in your face when your alarm goes off to help ensure you wake up. The fan could be an overhead one, but one on a nightstand or a taller one on the floor next to the bed would be best. I used the left and right threaded rods coupled together that I had from a previous project to be able to control the open and closing of the curtains movement. The logic I used for when the curtains should open compared to when you want to wake up and when you went to sleep were set by my preferences wherein the less sleep I got, the earlier the curtains would open based on time frames of amount of sleep. For me if I’ve gotten less sleep, I wake up to slight changes less than if I got enough sleep. Also, the fan is set to blow at a low speed for a minute when you’ve had under 5 hours sleep and high speed for 30 seconds if you’ve had between 5 and 6 hours. This is because higher speed will be more annoying and so needs to be on less; the lower speed is for the least sleep case because you are more likely to get sick on less sleep. I used a stepper motor to control the opening and closing of the curtains as that is what I had available and I can easily control the distance moved forward and reverse precisely. I would’ve used a faster motor if available and ideally a DC motor and an encoder instead as I’d be able to control the amounts forward and reverse easily and it’s more efficient in this scenario. Additionally, if I had a pressure sensor, the time you went to bed would be detected by the time you went on the bed and didn’t get up again before the alarm. This way you wouldn’t have to remember to click a button. To add to this, I would add a speaker so that this could be used for an alarm sound itself too. Finally, as someone mentioned during the crit, an app would be really useful for inputting the parameters and quickly making any changes. With the materials I was able to use and the time given, I’m happy with this prototype and in the future may make this for myself on an actual scale.

For reference, this is what the curtains in my room look like:

Ideal fans:

small fan for nightstand
floor stand fan to be put near  head of bed

Proof of Concept:

Closing the curtains after 6:00PM and dark

Setting the time went to bed, opening curtains, and blowing the fan.

You might notice that in this video, the printing format changed from day, month, year to month, day, year. This was an intentional change after the first video because it’s the format we are accustomed to.

Circuit
#include <AccelStepper.h>

// stepper Motor pin definitions:
#define motorPin1  9      // IN1 on the ULN2003 driver
#define motorPin2  10      // IN2 on the ULN2003 driver
#define motorPin3  11     // IN3 on the ULN2003 driver
#define motorPin4  12     // IN4 on the ULN2003 driver

// Define the AccelStepper interface type; 4 wire motor in half step mode:
#define MotorInterfaceType 8

// Initialize with pin sequence IN1-IN3-IN2-IN4 for using the AccelStepper library with 28BYJ-48 stepper motor:
AccelStepper stepper = AccelStepper(MotorInterfaceType, motorPin1, motorPin3, motorPin2, motorPin4);
//above from  https://www.makerguides.com to learn how to use this specific stepper motor and driver

#include <Wire.h>
#include <RTC.h>
const int photoPin = A5;
static DS3231 RTC;

//input times for each day with hr then min; 24 hr time but as it'll be morning, it shouldn't make too much of a difference
int wakeUpTimes[7][2] ={{12, 12}, //sun
                        {9, 0}, //mon
                        {9, 35}, //tues
                        {8, 55}, //wed
                        {9, 30}, //thurs
                        {10, 10}, //fri
                        {11, 11}};//sat

const int fanMotorPin = 3;
int low = 50;
int high = 150;
int fanSpeed;
int turnOnFan;
int fanDuration;

int timeSlept[3];
int openCurtainsXbeforeWakeUpTime;
int sleep = 0;
const int buttonPin = 2;

int timeWentToBed[3];

void calcTimeSlept() {
  //seconds
  int secs = 60 - timeWentToBed[0];
  if (secs == 60) {
    timeSlept[2] = 0;
  }
  else {
    timeSlept[2] = secs;
  }

  //mins
  if (wakeUpTimes[RTC.getWeek() - 1][1] >= timeWentToBed[1]) {
    if (timeSlept[2] == 0) {
      timeSlept[1] = wakeUpTimes[RTC.getWeek() - 1][1] - timeWentToBed[1];
    }
    else {
      timeSlept[1] = wakeUpTimes[RTC.getWeek() - 1][1] - timeWentToBed[1] - 1;
    }
  }
  else {
    if (timeSlept[2] == 0) {
      timeSlept[1] = wakeUpTimes[RTC.getWeek() - 1][1] + 60 - timeWentToBed[1];
    }
    else {
      timeSlept[1] = wakeUpTimes[RTC.getWeek() - 1][1] + 60 - timeWentToBed[1] - 1;
    }
  }

  //hrs
  if (timeWentToBed[0] < 12) {
    if (wakeUpTimes[RTC.getWeek() - 1][1] >= timeWentToBed[1]) {
      timeSlept[0] = wakeUpTimes[RTC.getWeek() - 1][0] - timeWentToBed[0];
    }
    else {
      timeSlept[0] = wakeUpTimes[RTC.getWeek() - 1][0] - timeWentToBed[0] - 1;
    }
  }
  else { //if went to bed before midnight, need to add hours bc subtraction not right otherwise
    int hrsBeforeMidnight = 24 - timeWentToBed[0];
    if (wakeUpTimes[RTC.getWeek() - 1][1] >= timeWentToBed[1]) {
      timeSlept[0] = wakeUpTimes[RTC.getWeek() - 1][0] + hrsBeforeMidnight;
    }
    else {
      timeSlept[0] = wakeUpTimes[RTC.getWeek() - 1][0] + hrsBeforeMidnight - 1;
    }
  }
}

void goinToSleep() {
  if (digitalRead(buttonPin) == HIGH) {
    sleep = 1;
  }
}

void openCurtains() {
  while (stepper.currentPosition() != 4096 * 7) { //choosing this bc it was enough rev to at least show some opening
    stepper.setSpeed(1000);
    stepper.runSpeed();
  }
}
void closeCurtains() {
  while (stepper.currentPosition() != 0) {
    stepper.setSpeed(-1000);
    stepper.runSpeed();
  }
}

void setup() {
  // put your setup code here, to run once:
  stepper.setMaxSpeed(1000);
  Serial.begin(9600);
  RTC.begin();

  RTC.setDay(16);
  RTC.setMonth(10);
  RTC.setYear(2020);

  RTC.setWeek(6);

//to show setting time went to bed from button for Fri
  RTC.setHours(10);
  RTC.setMinutes(8);
  RTC.setSeconds(0);
  
//to show fan turning on when not enough sleep for Mon
//  RTC.setHours(8);
//  RTC.setMinutes(59);
//  RTC.setSeconds(30);

////to show closing:
//  stepper.setCurrentPosition(4096 * 7);
  
  //to show curtains closing past 5 and dark
//  RTC.setHours(17);
//  RTC.setMinutes(59);
//  RTC.setSeconds(45);
  
//to show opening:
    stepper.setCurrentPosition(0);
  //to show curtain opening:
//  RTC.setHours(8);
//  RTC.setMinutes(49);
//  RTC.setSeconds(58);

  RTC.setHourMode(CLOCK_H24);

  pinMode(fanMotorPin, OUTPUT);

  attachInterrupt (digitalPinToInterrupt (buttonPin), goinToSleep, HIGH);

  /*set time went to bed to hr before wakeup as default after woken up
        will change if/when press button before going to sleep
        this way if you forget still get this, and assuming if didn't press,
        you went to bed really late
  */
  //commenting out for demo of button to set time went to bed
  timeWentToBed[0] = wakeUpTimes[RTC.getWeek() - 1][0] - 1;
  timeWentToBed[1] = wakeUpTimes[RTC.getWeek() - 1][1];
  timeWentToBed[2] = 0;
}

void loop() {
  int  photoVal = analogRead(photoPin);
  //Serial.println(photoVal);
  if (RTC.getHours() >= 18) {//6:00PM
    if (photoVal < 600) {
      //if it's past 6PM and dark(here just chose 600, but would be lower in real thing), close curtains
      closeCurtains();
    }
  }
  if (sleep == 1) {
    Serial.println("clicked");
    timeWentToBed[0] = RTC.getHours();
    timeWentToBed[1] = RTC.getMinutes();
    timeWentToBed[2] = RTC.getSeconds();
    calcTimeSlept();
    sleep = 0;
  }
  if (timeSlept[0] >= 8) {
    openCurtainsXbeforeWakeUpTime = 5; //mins
  }
  else if (6 <= timeSlept[0] && timeSlept[0] < 8) {
    openCurtainsXbeforeWakeUpTime = 30; //mins
  }
  else if (5 <= timeSlept[0] && timeSlept[0] < 6) {
    openCurtainsXbeforeWakeUpTime = 45; //mins
    turnOnFan = 1;
    fanSpeed = high;
    fanDuration = 30;
  }
  else {//under 5 hrs
    //for demo
    //openCurtainsXbeforeWakeUpTime = 1; //mins
    openCurtainsXbeforeWakeUpTime = 55; //mins
    turnOnFan = 1;
    fanSpeed = low;
    fanDuration = 60;
  }
  if (wakeUpTimes[RTC.getWeek() - 1][1] >= openCurtainsXbeforeWakeUpTime) {
    if (RTC.getHours() == wakeUpTimes[RTC.getWeek() - 1][0]) {
//Serial.println(openCurtainsXbeforeWakeUpTime);
        //Serial.println((wakeUpTimes[RTC.getWeek() - 1][1] - openCurtainsXbeforeWakeUpTime));
      if (RTC.getMinutes() == (wakeUpTimes[RTC.getWeek() - 1][1] - openCurtainsXbeforeWakeUpTime)) {
        openCurtains();
        timeWentToBed[0] = wakeUpTimes[RTC.getWeek() - 1][0] - 1;
        timeWentToBed[1] = wakeUpTimes[RTC.getWeek() - 1][1];
        timeWentToBed[2] = 0;
      }
    }
  }
  else {//minutes of wakeUpTime<time to subtract to wake up
    if (RTC.getHours() == (wakeUpTimes[RTC.getWeek() - 1][0] - 1)) { //took hr off here
      //right side of eq subtracted amount of time left after changing hr
      if (RTC.getMinutes() == (60 - openCurtainsXbeforeWakeUpTime + wakeUpTimes[RTC.getWeek() - 1][1])) {
        openCurtains();
        timeWentToBed[0] = wakeUpTimes[RTC.getWeek() - 1][0] - 1;
        timeWentToBed[1] = wakeUpTimes[RTC.getWeek() - 1][1];
        timeWentToBed[2] = 0;
      }
    }
  }
  
  if (RTC.getHours() == wakeUpTimes[RTC.getWeek() - 1][0]) {
    if (RTC.getMinutes() == wakeUpTimes[RTC.getWeek() - 1][1]) {
      //Serial.println(RTC.getSeconds());
      if (turnOnFan) {
        if (RTC.getSeconds() <= fanDuration) {
          //Serial.println(RTC.getSeconds());
          analogWrite(fanMotorPin, fanSpeed);
        }
        else {
                    analogWrite(fanMotorPin, 0);
          turnOnFan = 0;        
          }
      }

    }
  }
  static int startPrint=millis();
  if ((millis()-startPrint)>=1000){//putting this here so don't use delay while also showing the times
   switch (RTC.getWeek())
    {
      case 1:
        Serial.print("SUN");
        break;
      case 2:
        Serial.print("MON");
        break;
      case 3:
        Serial.print("TUE");
        break;
      case 4:
        Serial.print("WED");
        break;
      case 5:
        Serial.print("THU");
        break;
      case 6:
        Serial.print("FRI");
        break;
      case 7:
        Serial.print("SAT");
        break;
    }
    Serial.print(" ");
    Serial.print(RTC.getMonth());
    Serial.print("-");
    Serial.print(RTC.getDay());
    Serial.print("-");
    Serial.print(RTC.getYear());
  
    Serial.print(" ");
  
    Serial.print(RTC.getHours());
    Serial.print(":");
    Serial.print(RTC.getMinutes());
    Serial.print(":");
    Serial.println(RTC.getSeconds());

    startPrint=millis();
  }
  //  delay(1000);
}

 

 

 

 

 

Intuitive TV (Volume) Remote

Problem:

When watching something on TV, the volume we want it to be at is highly dependent on what is on the screen. If there is an action scene, the volume is usually way too loud and needs to be lowered. If the scene is dialogue with some background music, the volume often needs to be raised to understand what is being said. This is something that myself, my family, and my housemates have often faced and leads to us button smashing the remote after certain scene changes.

Proposed Solution:

After raising and lowering the volume three times, the volume automatically goes to the average of the low/high by simply holding the corresponding button for a second thereafter. The volume could still be adjusted from there by pressing the buttons, but being able to consistently go back and forth to a value would make things much more convenient. I chose three times of going back and forth because that leads to a pretty good average which would be quite close to the volume actually wanted each time as well as because three times is when I want to just hold the button down and go back to the previous low/high.

Proof of Concept:

Here I used two tactile push buttons to represent the up and down volume button respectively. I chose not to take too high or low volumes so that the video could be relatively short, but still make the point. As can be seen after cycling up and down the volume a few times, I long hold the up button and it goes to the average high. I then adjust it a bit lower to a medium volume followed by going back to the high. Finally, I skip to the low volume. I chose to start at volume 30 arbitrarily here, but for an actual TV, it would start at whatever the last volume was.

Sound/Visual Cues Transformed into Mechanical

Honks can be really important information sources for drivers. This can be problematic for people that are deaf or if someone is listening to music loudly in the car. One possible solution is to have a visual cue, but driving already relies so much on visual input from the outside world and indicator lights on the dashboard that it would be overwhelming and not very helpful. Because of this, a mechanical notification such as the steering wheel vibrating would be a really helpful alternative. The wheel can vibrate with different frequencies based on the frequency of the honks and this information would be easily passed on to the driver as at least one of their hands would be on the wheel.

Another idea I had was if someone is blind they need to rely on hearing or haptic feedback. Oftentimes I get someones attention by saying something and if they don’t hear me I will wave my hand a couple feet in front of their face. If someone who is blind who’s working on something say on their computer while listening to something would not be notified by either of these actions. I would potentially feel awkward about just walking up to them and tapping their shoulder. If there was a device that they could wear that would tap them for me weather as a watch or armband it would be really useful.