Created
April 29, 2017 19:48
-
-
Save tbnbooij/c14193de36c7397f8836b6991d62de82 to your computer and use it in GitHub Desktop.
Rock Your Baby - Final Code
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
/* | |
8888888b. 888 Y88b d88P 888888b. 888 | |
888 Y88b 888 Y88b d88P 888 "88b 888 | |
888 888 888 Y88o88P 888 .88P 888 | |
888 d88P .d88b. .d8888b 888 888 Y888P .d88b. 888 888 888d888 8888888K. 8888b. 88888b. 888 888 | |
8888888P" d88""88b d88P" 888 .88P 888 d88""88b 888 888 888P" 888 "Y88b "88b 888 "88b 888 888 | |
888 T88b 888 888 888 888888K 888 888 888 888 888 888 888 888 .d888888 888 888 888 888 | |
888 T88b Y88..88P Y88b. 888 "88b 888 Y88..88P Y88b 888 888 888 d88P 888 888 888 d88P Y88b 888 | |
888 T88b "Y88P" "Y8888P 888 888 888 "Y88P" "Y88888 888 8888888P" "Y888888 88888P" "Y88888 | |
888 | |
Y8b d88P | |
"Y88P" | |
Authors: jack-arts, NosaDielingen, tbnbooij | |
Academic year 2016-2017 | |
Department of Electrical Engineering | |
University of Technology Eindhoven | |
Version 0.4 | |
*/ | |
// [=========================== PIN NUMBERS ===========================] | |
int heart = 4; // The heartbeat sensor | |
int mic = A0; // The microphone filter/amp output | |
int f_out = 7; // Frequency output | |
int a_out = 5; // Amplitude output | |
// [=========================== PARAMETERS ===========================] | |
int initial_delay = 2000; // Delay to be used at the start of the program | |
int heart_delay = 9500; // The delay of the heartbeat signal with respect to the stress level | |
int f_value = 5; // The value of the frequency [1-5] | |
int a_value = 5; // The value of the amplitude [1-5] | |
//int heart_read_time = 4000; // The time [ms] the heartrate-function will read heartbeats | |
int mic_read_time = 1000; // The time [ms] the microphone-function will read the crying sound | |
int last_state = 0; // The last_state of the heartbeat (used in read_sensor_values()) | |
int last_BPM = 220; // The last BPM value, used in comparison with new BPM value | |
int heart_threshold = 10; // The threshold for the change in the heartrate (heartbeat is considered to have improbed when new heartrate + heart_threshold < old heartrate) | |
int mic_value = 0; // Placeholder for return value of the microphone function | |
int mic_new_value = 0; // Comparison value for the microphone | |
int mic_old_value = 0; // Reference for the microphone function | |
int mic_threshold = 50; // Threshold for the change in the amplitude of the crying sound | |
int baby_update_delay = 2300; // Delay for the grsdient of stress level | |
bool mic_started = false; // Flag for the microphone input (if true, the sensor function won't listen to the heartbeat sensor anymore) | |
int sensor_iteration = 1; // Used for debugging purposes | |
const int rel_array_size = 3; // The size of the BPM storage array | |
int relative_threshold = 2; // Threshold for the absolute difference between two adjacent elements in the BPM storage array | |
int storage_container[rel_array_size]; // Initializing the BPM storage array | |
float settings[5] = {0.05, 0.2, 0.4, 0.6, 0.8}; // The PWM settings of f and a | |
bool first = false; // Boolean to test whether mic has already started | |
int mic_start_BPM = 140; // BPM at which the mic should be started | |
void setF_A(int current_freq, int current_ampl) { // [=========================== *** SET F AND A *** ===========================] | |
analogWrite(a_out, settings[current_ampl-1]*255); | |
analogWrite(f_out, settings[current_freq-1]*255); | |
} | |
int microphone(void) { // [=========================== *** MICROPHONE FUNCTION *** ===========================] | |
mic_value = 0; // Set mic_value to 0 | |
long start_time = millis(); // The time at which the reading of the mic has started | |
while(millis() - start_time < mic_read_time) { // Read the microphone for mic_read_time milliseconds | |
if(mic_value < analogRead(mic)) { // If the mic_value is smaller than the current read | |
mic_value = analogRead(mic); // Set mic_value to that current read | |
} | |
} | |
return mic_value; // Return the mic_value (in other words, return the maximum value of all the reads) | |
} | |
bool comparemic(int *mic_old_value){ // [=========================== *** MICROPHONE COMPARISON FUNCTION *** ===========================] p.s. Jack, why did you put a pointer into this line? | |
Serial.println("Old microphone value:"); | |
Serial.println(*mic_old_value); | |
Serial.println("New microphone value"); | |
mic_new_value=microphone(); // Call the microphone function to get a new value for the crying intensity | |
Serial.println(mic_new_value); | |
if(*mic_old_value-mic_threshold > mic_new_value){ // If the new result is significantly better than the old result | |
*mic_old_value=mic_new_value; // Update the old result ... | |
return true; // And return true to the sensor function | |
} | |
else { // In all other cases (same/worse) | |
return false; | |
} | |
} | |
int heartbeat() { // [=========================== *** HEARTBEAT FUNCTION *** ===========================] | |
Serial.println("[=========================== Heartbeat ===========================]"); | |
bool eq_reached = false; // This boolean just indicates if equilibrium (rel_array_size (amount) stable numbers in a row) | |
int cont[rel_array_size] = {NULL}; // Create an empty array of size rel_array_size | |
int i = 0; // Size of the empty array | |
long last_time = millis(); // At what time does the measurement start? | |
while(!eq_reached) { // While eq_reached == false | |
bool GG = true; // This boolean is used for setting eq_reached to true if needed | |
int new_state = digitalRead(heart); // Read the heartbeat-circuit's output | |
if((new_state != last_state) && (new_state == HIGH)) { // Rising edge trigger | |
long new_time = millis(); // At what time has the rising edge occured? | |
long interval = new_time - last_time; // Determine the change between the starting time/time of the last rising edge and the new rising edge | |
last_time = new_time; // Update the reference time | |
int BPM = 60000/((int) interval); // Calculate the BPM | |
//Serial.println(BPM); | |
if(BPM >= 60-heart_threshold && BPM <= 240+heart_threshold) { // If the registered BPM lies within reasonable bounds | |
//Serial.println("Is ay-okay!"); | |
cont[i%rel_array_size] = BPM; // Add it to the array | |
i++; // And increment the size-variable | |
if(i >= rel_array_size) { // If the array has been filled | |
int j = 0; | |
bool done = true; | |
while((j < 2) && GG) { // For all adjacent couples of values in the array AND the boolean GG | |
if(abs(cont[j] - cont[j+1]) > relative_threshold) { // If two adjacent values are too far away | |
GG = false; // GG is false ==> END THIS LOOP | |
} | |
j++; | |
} | |
if(GG) { // If GG is still true (if it hasn't been set to false), then all adjacent values must be approx. equal | |
eq_reached = true; // That means equilibrium has been reached ==> END THE BIG WHILE LOOP | |
} | |
} | |
} | |
} | |
last_state = new_state; // Update the last state for the rising-edge trigger | |
} | |
int sum = 0; // Now calculate and return the average | |
for(int i = 0; i < rel_array_size; i++) { | |
sum += cont[i]; | |
} | |
int average = sum/rel_array_size; | |
Serial.println("================="); | |
Serial.println("Average BPM value:"); | |
Serial.println(average); | |
return average; | |
} | |
bool read_sensor_values() { // [=========================== *** SENSOR FUNCTION *** ===========================] | |
// These lines generate a banner for the current sensor read (used for debugging purposes) | |
Serial.print("[================== SENSOR READ "); | |
Serial.print(sensor_iteration); | |
Serial.print(" ==================]\n"); | |
if((last_BPM <= mic_start_BPM + 5) && (last_BPM >= mic_start_BPM - 5) && first == false) { | |
Serial.println("MIC STARTED!"); | |
mic_started = true; | |
first = true; | |
delay(1000); | |
} | |
delay(baby_update_delay); // Wait an amount of time for the baby to update (loudspeaker, grid) | |
sensor_iteration++; | |
Serial.println("[================== MICROPHONE ==================]"); | |
bool mic_return = comparemic(&mic_old_value); // Get a read from the microphone and test whether it has improved | |
if(mic_started == true) { // If the mic has been started, then just return what comparemic() returns | |
return mic_return; | |
} | |
delay(heart_delay-mic_read_time-baby_update_delay); | |
int new_BPM = heartbeat(); | |
Serial.print("New heartbeat: "); | |
Serial.println(new_BPM); | |
Serial.print("Reference heartbeat: "); | |
Serial.println(last_BPM); | |
bool return_value; // [=========================== COMPARING THE NEW BPM TO THE OLD BPM ===========================] | |
if (new_BPM - last_BPM < -1*heart_threshold) { // If the new BPM and the old BPM value have a difference larger than -1*heart_threshold | |
// Which implies that new_BPM + heart_threshold < last_BPM | |
// So the situation has significantly improved! | |
return_value = true; // Return true | |
} | |
else { // If this isn't the case, the situation is the same or worse | |
return_value = false; // So return false | |
} | |
last_BPM = new_BPM; | |
return return_value; | |
} | |
void setup() { // [=========================== *** SETUP *** ===========================] | |
Serial.begin(9600); // Open the serial-port at 9600 baud [= bits/sec] | |
Serial.println("[=========================== *** BOOTING *** ===========================]"); | |
pinMode(heart, INPUT); // Set the pinmodes to the respective functions of the pins | |
pinMode(mic, INPUT); | |
pinMode(f_out, OUTPUT); | |
pinMode(a_out, OUTPUT); | |
delay(initial_delay); // Wait initial_delay milliseconds | |
setF_A(f_value, a_value); // Setting the frequency and the amplitude to their max values (WARNING: Highly unethical!) | |
Serial.println("Set to initial values!"); | |
mic_old_value = microphone(); // Register the initial values the sensors read | |
delay(baby_update_delay); | |
} | |
void loop() { // [=========================== *** MAIN LOOP *** ===========================] | |
f_value -= 1; // Decrease frequency by 1 | |
setF_A(f_value, a_value); // Make the cradle rock at the current frequency and amplitude | |
bool sensor_response = read_sensor_values(); | |
Serial.println("The response of the sensor function is: "); | |
Serial.println(sensor_response); | |
if(sensor_response == false) { // If the sensors have recorded the same or a worse result than before ... | |
f_value += 1; // Let the frequency increase by one | |
setF_A(f_value, a_value); | |
delay(1); | |
a_value -= 1; // And the amplitude decrease by one | |
setF_A(f_value, a_value); | |
delay(baby_update_delay); | |
last_BPM -= 20; // Every time the BPM decreases, it does so by 20. So as a reference we can just subtract 20 from the old reference BPM. | |
mic_old_value = microphone(); // Update the reference mic value | |
if(comparemic(&mic_old_value) == true) { | |
mic_started = true; | |
} | |
} | |
if(a_value == 1) { // If we've hit one of the edges, then just decrease f/a until we get to (f,a) = (1,1) | |
while(f_value > 1) { | |
f_value--; | |
setF_A(f_value, a_value); | |
delay(baby_update_delay); | |
} | |
} | |
if(f_value == 1) { | |
while(a_value > 1) { | |
a_value--; | |
setF_A(f_value, a_value); | |
delay(baby_update_delay); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment