Change of tune

Problem:
There are many factors that have to be considered in managing risk of contagion during the pandemic. One particularly difficult element to get a good gauge on and keep continuous track of is is how well ventilated the air around you is at any given time.

This is crucial and can counterbalance whether it is safe to remain where you are at any given point of time. It can significantly overcome the risk odds of being less than 6ft away from people, both indoors and outdoors.

Without ventilation, aerosols remain suspended in the air, becoming increasingly concentrated as time goes by. (Source)

Solution:
A concealed wind sensor housed in a lapel pin that gives you audio feedback about the air ventilation around you. Ideally, this would be able to connect to your phone or audio device wirelessly so that you can check on this discretely whenever needed.
To engage, push a button on the pin and the reading will be sent to your audio device.
Visual indicators:
For demo purposes, I have added LEDs to help visualize the invisible elements present in the solution.
White LED: visual feedback of wind sensor values changing
Green/yellow/red LED: indicator of what range of ventilation is safe or not.
Audio feedback:
I chose 3 different tunes for the 3 risk levels:
High risk – morse code for SOS
Medium risk – tense, suspenseful tune
Low risk – major key arpeggio as a simple, positive sounding indicator.
Demo:

At the start, the wind sensor reads a low level of ventilation, and starts playing the SOS tune. As the ventilation increases, it switches to the low risk tune of a major arpeggio. As that value falls slightly, it starts playing the suspenseful tune before reverting back to the major arpeggio as the values increase again.

Components:

  • 1x RGB Diffused Common Cathode
  • 3x LED (Red, Green, Yellow)
  • 1x button
  • 7x Resistor 220 ohm
  • Wind Sensor Rev. C
  • 35CSB speaker

Schematic:

Code:

/*************************************************
* Sound Sensor
*************************************************/
#define analogPinForRV    1   // blue jumper wire
#define analogPinForTMP   0   // yellow jumper wire

// to calibrate your sensor, put a glass over it, but the sensor should not be
// touching the desktop surface however.
// adjust the zeroWindAdjustment until your sensor reads about zero with the glass over it. 

const float zeroWindAdjustment =  .2; // negative numbers yield smaller wind speeds and vice versa.

int TMP_Therm_ADunits;  //temp termistor value from wind sensor
float RV_Wind_ADunits;    //RV output from wind sensor 
float RV_Wind_Volts;
unsigned long lastMillis;
int TempCtimes100;
float zeroWind_ADunits;
float zeroWind_volts;
float WindSpeed_MPH;

//LED Feedback
int redPin = 9; //Pin for the red RGB led pin
int greenPin = 10; //Pin for the green RGB led pin
int bluePin = 11; //Pin for the blue RGB led pin 

int writeValue_red; //declare variable to send to the red LED
int writeValue_green; //declare variable to send to the green LED
int writeValue_blue; //declare variable to send to the blue LED



/*************************************************
* Interrupt Button
*************************************************/
static const int togglePin = 5;
bool buttonState = false;
const bool isInterrupt = true;

/*************************************************
* Melodies
*************************************************/
#include "pitches.h"
int speakerPin = 8;

// notes in the major melody (9 notes):
int majorMelody[] = {
NOTE_C4, NOTE_D4,NOTE_G4, NOTE_C5, 0, NOTE_C4, NOTE_D4, NOTE_G4, NOTE_C5};

// note durations: 4 = quarter note, 8 = eighth note, etc.:
int majorNoteDurations[] = {
   4, 4, 4, 4, 4, 4, 4, 4, 4
};

// notes in the minor melody (9 notes):
int minorMelody[] = {
NOTE_FS4, NOTE_FS4, NOTE_FS4, NOTE_DS4, 0, NOTE_E4, NOTE_E4, NOTE_E4, NOTE_CS4};
// note durations: 4 = quarter note, 8 = eighth note, etc.:

int minorNoteDurations[] = {
   8, 8, 8, 2, 4, 8, 8, 8, 2
};

// notes in morse code (11 notes):
int SOS[] = {
  NOTE_GS5, NOTE_GS5, NOTE_GS5, 0, NOTE_GS5, NOTE_GS5, NOTE_GS5, 0, NOTE_GS5, NOTE_GS5, NOTE_GS5
};

int SOSDurations[] = {
  8, 8, 8, 4, 2, 2, 2, 4, 8, 8, 8
};


/*************************************************
 * 
 * SETUP
 * 
*************************************************/

//void SwitchPressed(){
//  buttonState =! buttonState;
//}

void setup() {

  Serial.begin(57600);   // faster printing to get a bit better throughput on extended info
  // remember to change your serial monitor

  Serial.println("start");
  // put your setup code here, to run once:

  //   Uncomment the three lines below to reset the analog pins A2 & A3
  //   This is code from the Modern Device temp sensor (not required)
  pinMode(A2, INPUT);        // GND pin      
  pinMode(A3, INPUT);        // VCC pin
  digitalWrite(A3, LOW);     // turn off pullups

  //initialize button pin as input
//  pinMode(buttonPin, INPUT_PULLUP);

  //Risk feedback state
  int greenLED = 2;
  int yellowLED = 3;
  int redLED = 4;
  pinMode(greenLED, OUTPUT);
  pinMode(yellowLED, OUTPUT);
  pinMode(redLED, OUTPUT);

//  if (isInterrupt){
//      attachInterrupt(digitalPinToInterrupt(togglePin), SwitchPressed, RISING);    
//  }
  
}

void loop() {
  
/*************************************************
* Reading Wind Sensor
*************************************************/
  if (millis() - lastMillis > 200){      // read every 200 ms - printing slows this down further
    
    TMP_Therm_ADunits = analogRead(analogPinForTMP);
    RV_Wind_ADunits = analogRead(analogPinForRV);
    RV_Wind_Volts = (RV_Wind_ADunits *  0.0048828125);

    // these are all derived from regressions from raw data as such they depend on a lot of experimental factors
    // such as accuracy of temp sensors, and voltage at the actual wind sensor, (wire losses) which were unaccouted for.
    TempCtimes100 = (0.005 *((float)TMP_Therm_ADunits * (float)TMP_Therm_ADunits)) - (16.862 * (float)TMP_Therm_ADunits) + 9075.4;  

    zeroWind_ADunits = -0.0006*((float)TMP_Therm_ADunits * (float)TMP_Therm_ADunits) + 1.0727 * (float)TMP_Therm_ADunits + 47.172;  //  13.0C  553  482.39

    zeroWind_volts = (zeroWind_ADunits * 0.0048828125) - zeroWindAdjustment;  

    // This from a regression from data in the form of 
    // Vraw = V0 + b * WindSpeed ^ c
    // V0 is zero wind at a particular temperature
    // The constants b and c were determined by some Excel wrangling with the solver.
    
   WindSpeed_MPH =  pow(((RV_Wind_Volts - zeroWind_volts) /.2300) , 2.7265);   
   
//    Serial.print("  TMP volts ");
//    Serial.print(TMP_Therm_ADunits * 0.0048828125);
//    
//    Serial.print(" RV volts ");
//    Serial.print((float)RV_Wind_Volts);
//
//    Serial.print("\t  TempC*100 ");
//    Serial.print(TempCtimes100 );
//
//    Serial.print("   ZeroWind volts ");
//    Serial.print(zeroWind_volts);

    Serial.print("   WindSpeed MPH ");
    Serial.println((float)WindSpeed_MPH);

    lastMillis = millis();
  }

/*************************************************
* Wind sensor LED feedback
*************************************************/

  writeValue_red = (255./10.)*WindSpeed_MPH; //Calculate the value to write on the red LED (add point to change to float point)
  writeValue_green = (255./10.)*WindSpeed_MPH; //Calculate the value to write on the green LED
  writeValue_blue = (255./10.)*WindSpeed_MPH; ///Calculate the value to write on the blue LED
  
  analogWrite(redPin,writeValue_red); //write value to set the brightness of the red LED
  analogWrite(greenPin,writeValue_green); //write value to set the brightness of the green LED
  analogWrite(bluePin,writeValue_blue); //write value to set the brightness of the blue LED



/*************************************************
* State + Sound
*************************************************/

//if (buttonState == true){
//  

    if(WindSpeed_MPH <= 2){
    // turn red LED on:
    digitalWrite(4, HIGH);
    // turn the rest off:
    digitalWrite(2, LOW);
    digitalWrite(3, LOW);

    // play SOS melody:
     for (int thisNote = 0; thisNote < 11; thisNote++) {
      int noteDuration = 1000/SOSDurations[thisNote];
      tone(8, SOS[thisNote],noteDuration);
      //pause for the note's duration plus 30 ms:
      delay(noteDuration +30);
      noTone(8);
    }
  }

    else if (WindSpeed_MPH >7) {
      //turn green LED on:
      digitalWrite(2, HIGH);
      // turn the rest off:
      digitalWrite(4, LOW);
      digitalWrite(3, LOW);

      //play major melody:
      for (int thisNote = 0; thisNote < 9; thisNote++) {
      int noteDuration = 1000/majorNoteDurations[thisNote];
      tone(8, majorMelody[thisNote],noteDuration);
      //pause for the note's duration plus 30 ms:
      delay(noteDuration +30);
      noTone(8);
    }
   }

    else {
      //turn yellow LED on:
      digitalWrite(3, HIGH);
      // turn the rest off:
      digitalWrite(2, LOW);
      digitalWrite(4, LOW);

      //play minor melody:
      for (int thisNote = 0; thisNote < 9; thisNote++) {
      int noteDuration = 1000/minorNoteDurations[thisNote];
      tone(8, minorMelody[thisNote],noteDuration);
      //pause for the note's duration plus 30 ms:
      delay(noteDuration +30);
      noTone(8);
      
    }
    }
//    }
//    else {
//      noTone(8);
//      //turn all LEDs off:
//      digitalWrite(3, LOW);
//      digitalWrite(2, LOW);
//      digitalWrite(4, LOW);
//    }
/*************************************************
* Wind sensor LED feedback on button press
*************************************************/
//buttonState = digitalRead(buttonPin);
//
//if (buttonState == HIGH){
//
//  if (flag == 0){
//    //light up white LED
//    analogWrite(redPin,writeValue_red); //write value to set the brightness of the red LED
//    analogWrite(greenPin,writeValue_green); //write value to set the brightness of the green LED
//    analogWrite(bluePin,writeValue_blue); //write value to set the brightness of the blue LED
//  flag = 1;
//  }
//
//  if (flag == 1){
//    //turn off white LED
//    analogWrite(redPin,0); //write value to set the brightness of the red LED
//    analogWrite(greenPin,0); //write value to set the brightness of the green LED
//    analogWrite(bluePin,0); //write value to set the brightness of the blue LED
//    flag = 0;
//  }
//}
//
//if (buttonState == HIGH){
//    //light up white LED
//    analogWrite(redPin,writeValue_red); //write value to set the brightness of the red LED
//    analogWrite(greenPin,writeValue_green); //write value to set the brightness of the green LED
//    analogWrite(bluePin,writeValue_blue); //write value to set the brightness of the blue LED
//}
//
//else if (buttonState == LOW){
//    //turn off white LED
//    analogWrite(redPin,0); //write value to set the brightness of the red LED
//    analogWrite(greenPin,0); //write value to set the brightness of the green LED
//    analogWrite(bluePin,0); //write value to set the brightness of the blue LED
//}

}

Reminder: include pitches.h for code to work

 

Leave a Reply

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