Skip to content

Instantly share code, notes, and snippets.

@halldorel
Last active March 20, 2017 15:18
Show Gist options
  • Save halldorel/7acf6d7081e550afdc4637fe97a2de60 to your computer and use it in GitHub Desktop.
Save halldorel/7acf6d7081e550afdc4637fe97a2de60 to your computer and use it in GitHub Desktop.
Script that controls a shower with singing
//
// 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