Skip to content

Instantly share code, notes, and snippets.

@tbnbooij
Created April 29, 2017 19:48
Show Gist options
  • Save tbnbooij/c14193de36c7397f8836b6991d62de82 to your computer and use it in GitHub Desktop.
Save tbnbooij/c14193de36c7397f8836b6991d62de82 to your computer and use it in GitHub Desktop.
Rock Your Baby - Final Code
/*
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