Stertere
Made by Diana Sun
Made by Diana Sun
The goal of Stertere is to help alleviate the disturbances that public snoring may cause on people nearby.
Created: September 14th, 2015
Ever had someone snore loudly next to you on the plane? Or were you ever the roommate who disrupted the peace at night?
Snores cause disturbances in public, and while the sleeper is completely oblivious to the effect they're having on others, people nearby are adversely affected. They may be trying to sleep, read, work, or do other tasks, but hearing loud snores every few seconds can be very distracting.
Stertere causes a slight disturbance in the snorer's sleep, causing them to stop snoring but not wake up.
If you've ever seen your roommate stop snoring when they turn over in their sleep, then you've seen the effect that Stertere tries to recreate. Whenever Stertere's mic picks up a loud snore (a low frequency high amplitude sound), the vibration motors in the pillow will activate for 2 seconds, giving the snorer enough of a strange sensation to disrupt their snores. If the snore is consistently very loud, the vibration motors will stay activated until the snores stop.
Stertere is designed to have both a travel pillow and a home pillow. This eliminates the need to carry around a large pillow in public or the need to use a small pillow in bed. For the purpose of this project, only the travel pillow was created.
First, I found the optimal placement for the mic and vibration motors. (See pictures below)
Then I needed to know the frequency of typical snores. Turns out there is quite a range for snore frequencies, depending on each person's biological differences and the quality of sleep. The average snore is around 137Hz but the peak frequency was over 1200Hz. (This would serve as the basis for the conditions in my code)
I tested the average snore amplitude with the mic, and at around 350amps, the sound felt disruptive to the environment. I lowered the threshold of this amplitude significantly to account for the loss of sensitivity in the mic when it was covered with the fluffy fabric.
To put my idea into action, I first found a sample code that could detect frequencies (source referenced in the code). Then I hooked up an LED so that whenever the frequency and loudness met certain conditions, the LED would light up for 2 seconds. From there, I replaced the LED output with the vibration motors (along with all the other components needed to make the vibration motors work).
To see my full code and more detailed comments/explanation, click below:
Code: https://gist.github.com/anonymous/b0fd1cf90895f9a457c6
//***Sample code for frequency detection**/
//generalized wave freq detection with 38.5kHz sampling rate and interrupts
//http://www.instructables.com/id/Arduino-Frequency-Detection/
/*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
*/
#include <Time.h> //so you can detect the time between snores later
//clipping indicator variables
boolean clipping = 0;
//data storage variables
byte newData = 0;
byte prevData = 0;
unsigned int time = 0;//keeps time and sends vales to store in timer[] occasionally
int timer[10];//sstorage for timing of events
int slope[10];//storage for slope of events
unsigned int totalTimer;//used to calculate period
unsigned int period;//storage for period of wave
byte index = 0;//current storage index
float frequency;//storage for frequency calculations
int maxSlope = 0;//used to calculate max slope as trigger point
int newSlope;//storage for incoming slope data
//variables for decided whether you have a match
byte noMatch = 0;//counts how many non-matches you've received to reset variables if it's been too long
byte slopeTol = 3;//slope tolerance- adjust this if you need
int timerTol = 10;//timer tolerance- adjust this if you need
//variables for amp detection
unsigned int ampTimer = 0;
byte maxAmp = 0;
byte checkMaxAmp;
byte ampThreshold = 30;//raise if you have a very noisy signal
int count = 0; //number of seconds to vibrate!
boolean startOver = true; //starts detecting snores again
boolean motorOn = false; //start vibe motors as off
time_t start;
void setup(){
Serial.begin(9600);
pinMode(5,OUTPUT);//output pin
cli();//diable interrupts
//set up continuous sampling of analog pin 0 at 38.5kHz
//clear ADCSRA and ADCSRB registers
ADCSRA = 0;
ADCSRB = 0;
ADMUX |= (1 << REFS0); //set reference voltage
ADMUX |= (1 << ADLAR); //left align the ADC value- so we can read highest 8 bits from ADCH register only
ADCSRA |= (1 << ADPS2) | (1 << ADPS0); //set ADC clock with 32 prescaler- 16mHz/32=500kHz
ADCSRA |= (1 << ADATE); //enabble auto trigger
ADCSRA |= (1 << ADIE); //enable interrupts when measurement complete
ADCSRA |= (1 << ADEN); //enable ADC
ADCSRA |= (1 << ADSC); //start ADC measurements
sei();//enable interrupts
}
ISR(ADC_vect) {//when new ADC value ready
//PORTB &= B11101111;//set pin 12 low
prevData = newData;//store previous value
newData = ADCH;//get value from A0
if (prevData < 127 && newData >=127){//if increasing and crossing midpoint
newSlope = newData - prevData;//calculate slope
if (abs(newSlope-maxSlope)<slopeTol){//if slopes are ==
//record new data and reset time
slope[index] = newSlope;
timer[index] = time;
time = 0;
if (index == 0){//new max slope just reset
//PORTB |= B00010000;//set pin 12 high
noMatch = 0;
index++;//increment index
}
else if (abs(timer[0]-timer[index])<timerTol && abs(slope[0]-newSlope)<slopeTol){//if timer duration and slopes match
//sum timer values
totalTimer = 0;
for (byte i=0;i<index;i++){
totalTimer+=timer[i];
}
period = totalTimer;//set period
//reset new zero index values to compare with
timer[0] = timer[index];
slope[0] = slope[index];
index = 1;//set index to 1
//PORTB |= B00010000;//set pin 12 high
noMatch = 0;
}
else{//crossing midpoint but not match
index++;//increment index
if (index > 9){
reset();
}
}
}
else if (newSlope>maxSlope){//if new slope is much larger than max slope
maxSlope = newSlope;
time = 0;//reset clock
noMatch = 0;
index = 0;//reset index
}
else{//slope not steep enough
noMatch++;//increment no match counter
if (noMatch>9){
reset();
}
}
}
if (newData == 0 || newData == 1023){//if clipping
//PORTB |= B00100000;//set pin 13 high- turn on clipping indicator led
clipping = 1;//currently clipping
}
time++;//increment timer at rate of 38.5kHz
ampTimer++;//increment amplitude timer
if (abs(127-ADCH)>maxAmp){
maxAmp = abs(127-ADCH);
}
if (ampTimer==1000){
ampTimer = 0;
checkMaxAmp = maxAmp;
maxAmp = 0;
}
}
void reset(){//clean out some variables
index = 0;//reset index
noMatch = 0;//reset match counter
maxSlope = 0;//reset slope
}
void checkClipping(){//manage clipping indicator LED
if (clipping){//if currently clipping
//PORTB &= B11011111;//turn off clipping indicator led
clipping = 0;
}
}
void loop(){
checkClipping();
if (checkMaxAmp>ampThreshold){
frequency = 38462/float(period);//calculate frequency timer rate/period
//print results
}
delay(100);
//snoring stuff starts here
//diana sun
if (frequency <= 800 && frequency >= 50 && newData >= 25) //if its between thess freq & greater than this loudness,
{ //then snoring has been detected
if (startOver)
{
start = now(); //start count of snore time
startOver = false;
}
if (now() - start >= 1) // if the snore sound has persisted within a 1 sec time frame,
{
Serial.println("Snoring detected");
count = 20; //vibrates for 2 seconds after snoring is detected
digitalWrite(5,HIGH); //turn on vibe motors
motorOn = true; //it is on now
}
}
if (count > 0)
{
count = count - 1; //counts down the time
}
else if(motorOn) //if it has been on already
{
motorOn = false; //it will remain false until snores are detected again
startOver = true; //start over the detection for snores
digitalWrite(5, LOW); //turn off the vibe motors
}
}
Click to Expand
Making Things Interactive (MTI) is a studio course based on physical prototyping and computing. You will develop novel sensing, interaction and display techniques through projects and short assignm...more
The goal of Stertere is to help alleviate the disturbances that public snoring may cause on people nearby.