Stertere

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

0

Problem

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.

Solution

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.

Process

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

0
Vibe motors located at back of neck for optimal contact
1.thumb
0
Mic located at tip of the pillow curve, where it's closest to the mouth
4.thumb
0
Beginning Ideation
2 sketch book.thumb
0
//***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
x
Share this Project

Found In
Courses

48-739 Making Things Interactive

· 0 members

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


About

The goal of Stertere is to help alleviate the disturbances that public snoring may cause on people nearby.