Last active
March 20, 2017 15:18
-
-
Save halldorel/7acf6d7081e550afdc4637fe97a2de60 to your computer and use it in GitHub Desktop.
Script that controls a shower with singing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Voice controlled servos, for Stefán Finnbogason's singing shower project | |
// Author: Halldor Eldjarn 2017 | |
// | |
#include <Servo.h> | |
#define NUM_SHOWERS 4 | |
int inputValues[NUM_SHOWERS]; | |
unsigned long long currentPeaks[NUM_SHOWERS]; | |
Servo servos[NUM_SHOWERS]; | |
int servoPos[NUM_SHOWERS]; | |
////// CONFIG | |
// The value that reads as "silence" from the microphone | |
int centerValue = 512; | |
// How many samples are taken, for the average | |
int sampleCount = 32; | |
// Minimum volume change from centerValue to register as a sound (gate) | |
int minVolume = 20; | |
// Maximum volume before clipping occurs (to prevent too large values in servo) | |
int maxVolume = 70; | |
// How many averages do we make, before sending to servo. | |
// This is mainly needed if we only have one signal and one servo | |
int servoThrottleConstant = 1; | |
// Lowest value to be sent to servo | |
int servoFrom = 60; | |
// Highest value to be sent to servo | |
int servoTo = 150; | |
////// TEMP VARS | |
int averageRms[NUM_SHOWERS]; | |
int avg[NUM_SHOWERS]; | |
int avgClamped[NUM_SHOWERS]; | |
int servoThrottle[NUM_SHOWERS]; | |
void setup() { | |
// put your setup code here, to run once: | |
Serial.begin(9600); | |
// Loop through and reset all variables before starting | |
for(int i = 0; i < NUM_SHOWERS; i++) { | |
inputValues[i] = 0; | |
currentPeaks[i] = 0; | |
avg[i] = 0; | |
avgClamped[i] = 0; | |
servos[i].attach(9+i); | |
servoThrottle[i] = 0; | |
} | |
} | |
void loop() { | |
// Loop through all shower sound inputs, and calculate RMS | |
// over sampleCount samples | |
for(int i = 0; i < NUM_SHOWERS; i++) { | |
inputValues[i] = analogRead(i) - centerValue; | |
currentPeaks[i] = 0; | |
for(int j = 0; j < sampleCount; j++) { | |
currentPeaks[i] += pow(inputValues[i], 2); | |
} | |
avg[i] = sqrt(currentPeaks[i] / sampleCount); | |
// We then add this RMS, as we also want to see | |
// the average of the RMS values calculated within | |
// servoThrottleConstant iterations. | |
averageRms[i] += avg[i]; | |
// We only update servos every `servoThrottleConstant` time | |
// and when we do, we take the average of the RMS values | |
// calculated within that time | |
servoThrottle[i]++; | |
if(servoThrottle[i] > servoThrottleConstant) { | |
Serial.print(inputValues[i]); | |
Serial.print("Averg: "); | |
averageRms[i] = averageRms[i] / servoThrottleConstant; | |
// Clamp the averages and map to servo values | |
avgClamped[i] = max(min(averageRms[i], maxVolume), minVolume); | |
servoPos[i]= map(avgClamped[i], minVolume, maxVolume, servoFrom, servoTo); | |
servos[i].write(servoPos[i]); | |
Serial.print("Writing to servo no. "); | |
Serial.print(i); | |
Serial.print(" value: "); | |
Serial.println(servoPos[i]); | |
servoThrottle[i] = 0; | |
averageRms[i] = 0; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment