Nap Spot Indicator
 

Step 1 - Build the Project

Use temperature, light, and sound sensors to measure the environment around you. Then use three LEDs as indicators. Each LED will be either off, half-on, or fully on depending on the sensor readings. When you've found somewhere that's dark, warm, and quiet, you've found a perfect nap spot!

Step 2 - Upload the Code

/* * Use the temp sensor, sound trigger, and light sensor to indicate * quality of a nap spot */ //Hold the average noise level float averageNoise; //Timer to control the display long timer = millis(); void setup() { pinMode(A4,INPUT); //Center pin of sound trigger pinMode(A2,INPUT_PULLUP); //light sensor //Check the temp sensor pinout, getting it backwards ruins it pinMode(A3,INPUT); //Center pin of temp sensor //One of the outside pins is in 5V, the other is in GND row //LEDs pinMode(9,OUTPUT); pinMode(10,OUTPUT); pinMode(11,OUTPUT); //Get initial sound measurement to 'seed' the average averageNoise = analogRead(A4); } void loop() { //Compute the moving average of the noise level //Each new reading contributes 1% to the average averageNoise = 0.01*(float)(analogRead(A4)) + 0.99*(averageNoise); //soundValue is cast to a float so it can be multiplied by decimals /* Because the microphone needs to be read very often, * use millis to print only once every 500 ms*/ if (millis()-timer > 500){ //Converting reading to F with conversion equation int tempF = int(0.88*float(analogRead(A3)) - 58.0); int lightValue = analogRead(A2); //Read the light sensor //When it's cold, LED is off if (tempF < 68){ analogWrite(9,0);} //LED off else if (tempF < 75){ analogWrite(9,127);} //Half brightness else{ analogWrite(9,255);} //Full brightness //When it's dark, LED is at full brightness if (lightValue < 300){ analogWrite(11,0);} //LED off else if (lightValue < 600){ analogWrite(11,127);} //Half brightness else{ analogWrite(11,255);} //Full brightness //When it's quiet, LED is at full brightness if (averageNoise < 350){ analogWrite(10,255);} //Full brightness else if (averageNoise < 500){ analogWrite(10,127);} //Half brightness else{ analogWrite(10,0);} //LED off timer = millis(); //Reset the timer } } //Change the analogWrites so that blue/green indicates a good spot // and red indicates a bad spot // (c) 2017 Let's Start Coding. License: www.letsstartcoding.com/bsdlicense
 

Step 3 - Read the Walkthrough

At the top of your code, create a 'float' type variable called averageNoise. 

Next, create a 'long' type variable and name it timer. This timer allows you to take measurements at certain intervals without using the delay() command. Since delay() actually pauses the program, you can't do anything in that time period. The timer variable eliminates that.

In the setup() section of the code, make the center pin of the sound trigger an INPUT. Set the pinMode of the light sensor to INPUT_PULLUP, so it sends a signal close to 0 for brightness and close to 1000 for darkness. Now set the pinMode of your temperature sensor's center pin as an INPUT. Ensure that you have the outer legs plugged in the correct orientation to + and - or the sensor will get very hot.

Finally, set the LED pins as OUTPUTs in the code so they are receiving instructions from the code, not trying to send data in to the code.

Here you'll set the value of averageNoise equal to the analogRead of A4. You will add each reading of the sound to this average in the loop, so you want to start with a typical sound reading, not 0.

First in the loop you're going to update the value of the averageNoise variable. Look at the first half of the equation. When you see float(analogRead(A4)), that's called a cast. You're telling the code "for this calculation only, treat analogRead(A4) as a float variable". Doing that allows you to multiply analogRead(A4) by a decimal. Otherwise, an integer variable type will just cut decimals off the end of the value. Once you have cast analogRead(A4) as a float, you multiply it by 0.01. 

In the second half of the equation, you multiply averageNoise (already a float) by 0.99. In effect, you are saying "The new value of averageNoise should be made up of 1% soundValue and 99% averageNoise.". You can change the impact of any new reading by changing the decimals attached to analogRead(A4) and averageNoise.

averageNoise is updated very quickly, once per loop. The rest of the loop sits inside an 'if' statement that runs only once per 500 milliseconds. How does this work? The 'if' statement compares the value of millis() and the value of the variable timer. If the difference between them is more than 500 milliseconds, the 'if' statement is true. Otherwise, the 'if' statement is false. Remember that millis() is a built-in timer in the Arduino software and it is always counting up, which is why you don't need to create it as a variable. 

Inside the 'if' statement, you'll create an integer variable called tempF. The numbers in this equation are specific to this sensor, don't change those. However, you can see another variable cast in this line. You temporarily make analogRead(A3) a float variable so that you can multiply it by the decimals. On the very outside of the parentheses, though, you can see 'int'. That means that after your calculations are complete, you actually re-cast the value to an integer. tempF ends up as an integer.

Taking the light reading is much simpler. You simply create an integer variable called lightValue and set its value to analogRead(A2). 

Once all of the readings are taken, you can check each value with a series of if-else statements. The first set of if-else statements checks the lightValue variable. If it's less than 300 (meaning it is very bright), the analogWrite() sends a brightness of 0 to the LED. 

The else-if statement is only checked when the 'if' statement above is false. So only if the light value is not less than 300, the else-if statement is checked. If the light value is greater than 300 but less than 600, the light is turned on half brightness with analogWrite.

The else statement comes last. It's not checked unless both statements above it are false. In effect, this means that if the light value is greater than 600, the light is turned on all the way with analogWrite(255);

You can see that you can create priorities in the code with if-else if-else statements. If you rearrange the order of the if-else if-else statements, you will make some strange things happen in the code.

Next come two more sets of if-else if-else statements. They check the readings from the temperature variable and the noise variable and change their LED brightness based on that reading. You could repeat this pattern with other sensors and inputs, too. 

Finally, you reset the value of the timer variable to the value of millis(). That way, the next time millis() and timer are compared, the difference between them is less than 500 and the if-else if- else statements are skipped, but a new noise reading is still taken.