Final write up:

Description and Motivation Our inspiration started after working out at Fox gym, running on the treadmill. There’s nothing that kills your workout vibe when you’re running as fast as you can, pushing your body to the limit with your heart rate maxing out at 190 and then the music you’re listening to changes to a slow soothing song. At that moment, you want a song that matches the intensity of your workout. We wanted to design a solution that would take in two sensors 1) a button symbolizing whether the treadmill is off/on and 2) a photodiode sensor for your heart rate and output either a slow-paced, medium-paced, or fast-paced song from our personal song library. This project required the use of 3 Arduino microcontrollers, bluetooth technology, and both Arduino and MATLAB software to come to fruition.

First Demo Day and Interim Progress For our first Demo Day, we can break up our status at that point from a software and hardware perspective. Regarding software, we had written an Arduino sketch to find the peaks in a waveform, calculate the elapsed time between the two peaks, and then calculate the beats per minute based on that, and display the “heart rate” (using an oscilloscope to verify the frequency of the waveform). At the Interim demo, we also were considering different approaches to building a pulse sensor. We decided that building an ECG sensor was too complicated considering we only wanted to collect a pulse. Our TA mentor, Aditya Hota, suggested that we use an RGB sensor. We had code from a past MATLAB project that filtered red RGB data to detect a pulse.

Since the first Demo Day, we had to change several things. First, the script was originally written in Arduino IDE, however we realized that in order to play .mp3 files, the best way to do that would be to convert the Arduino sketch into MATLAB so that was done. Our peak finding algorithm had to be significantly adapted because not all the functions in Arduino had a corresponding function in matlab. Second, we configured a button that’s state could be communicated via Bluetooth to another Arduino. Third, we decided to change approaches once again in order to detect a pulse. We decided not to use an RGB sensor, since it was difficult to implement the necessary filtering using Arduino code. We considered using IoT, but since only one value can be collected every 15 seconds, MATLAB analysis of RGB pulse data was not possible. We decided to use a photodiode and infrared LED, and doing necessary signal filtering in the circuit instead.

Subsystem Implementation

There are 3 subsystems. Heart rate sensor hardware Button state - bluetooth transmitter (hardware, software) MATLAB software code

1) Pulse Sensor We decided to create a contactless pulse sensor using an infrared LED and a photodiode. The user’s index finger would be inserted into a housing with the photodiode and LED, and as blood rushes into the fingertip with each pulse, the photodiode detects the changes in reflected light. This signal from the photodiode was passed through two op amps, housed in an LM 324 chip. Most op amps are powered by a positive and negative supply voltage, but the negative voltage can interfere with the arduino circuit. Therefore we chose the LM 324 chip, since it is single supply, requiring only 5V power. The op amp circuit filters the signal, cutting out high and low frequency noise. A transistor at the end amplified the weak signal output.

2) Button The button state was configured in series with a resistor from 5V to ground, so that that when the button was pressed the wire to the Master (Arduino #1) digital pin 10 went HIGH. That digital pin input was used as a trigger to send an ASCI character H or L serially to the slave bluetooth (Arduino #2). The Slave bluetooth read the ASCI character and if the character was H, then it would use digital output pin 9 to an LED to show it’s working and was wired to the Arduino #3. See the sketches below for more detail.

3) MATLAB software code The MATLAB software relies on the Arduino Support package. It works by defining parameters to help select the peaks: threshold and delay in time. It configures two pins: Digital output to LED for whenever a peak is sensed and Analog Input taking in the photodiode waveform that will determine heart rate. We used tic and toc to determine elapsed time. The peak finding algorithm works as follows: If the voltage is above some threshold, then call function Analog Maxima. This function reads two sequential voltages, and if the second is less than the first (therefore the wave is decreasing), it just returns out of the function. If however the wave is increasing, we know there must be a peak upcoming. It goes into a while loop constantly checking sequential voltage values until the second value is less than the first. At that point, it calls toc and stores that value into an array of times as well as write a HIGH to digital pin where an LED is attached. Since there is no return in MATLAB, we use the variable ret to ensure that once a peak is found in the while loop, it exits out of it and doesn’t try to find another shortly afterwards. The time array (t) is then subtracted from the previous toc call to determine the time that has elapsed, and if you divide 60 by that number, you yield the heart rate. With this heart rate, we can determine which song to play depending on if it is <80, between 80 and 140 or greater than 140. It accomplishes through calling the playmusic function. It is important to note that the music will pick up where it last was playing which required the variables count_slow/medium/fast to remember where in the song it was last at.

Commercial Opportunities Our solution could be a wearable technology and app that integrates with your smartphone while you exercise.

Improvements and Future Directions A couple points of improvement. First, our peak finding algorithm missed a few peaks so therefore the beats per minutes would sometimes get an incorrect value. If that value happened to be at the moment when the song was being determined, the wrong song may play. This algorithm is something that could be further optimized. Second, instead of using a push button it may have been better to use a button that stays down after being pushed so the user only turns on the machine once and it stays on without further pushing. Third, the actual pulse sensor hardware needs further improvement. The signal output from the circuit was way too noisy to truly detect a pulse.

Appendix:

Arduino Script:

MASTER

include

SoftwareSerial BTSerial(2, 4); //TX RX const int button = 10; int val = 0;

void setup() { BTSerial.begin(9600); Serial.begin(9600); pinMode(button, INPUT); }

void loop() { val = digitalRead(button); if(val == HIGH) { BTSerial.print("H"); Serial.println("H"); } else if(val == LOW) { BTSerial.print("L"); Serial.println("L"); } delay(100); }

SLAVE

include

SoftwareSerial BTSerial(2, 4); //TX RX

int led = 9; void setup() { BTSerial.begin(9600); //begin bluetooth communication Serial.begin(9600); //begin serial communication pinMode(led, OUTPUT); }

void loop() { if (BTSerial.available()) { char inChar = (char) BTSerial.read(); //reads single character at a time if(inChar == 'L') { digitalWrite(led, LOW); } else if(inChar == 'H') { digitalWrite(led, HIGH); } Serial.println(inChar); } }

MATLAB code:

%% Read Complete Audio File

clear clc

a=arduino('/dev/cu.usbmodem1421','Uno');

Threshold = 2; delay_time=8/1000; configurePin(a,'D13','DigitalOutput'); %%output to LED configurePin(a, 'A0', 'AnalogInput'); %input analog signal %% Serial.begin(9600); n=2; tic; t(n)= toc;

new_var=0;

count_slow=1; count_medium=1; count_fast=1;

while 1<2 if (readVoltage(a,'A0')>Threshold) %%If current channel reading exceeds threshold [t,n] = AnalogMaxima(a,'A0',Threshold,delay_time,n,t); %%find local maxima and return time. time0=t(n-1); time1=t(n); if (time1 == 1025 || time1 == 0) %%if still ascending or below threshold,
else

    Time_diff=time1-time0; %%//subtracts current time from previous beat (maxima)
    beats_per_min = round(60/Time_diff) %%//calculate beats per minute (1/(time_diff)/1000)*60
    %%Serial.println(beats_per_min);     %%          //Show beats per minute
    %display=Time_diff
    writeDigitalPin(a,'D13',0);

    newer_var=toc;
    if newer_var-new_var > 9 && readDigitalPin(a,'D9')==1 %% add bluetooth pin input as && true
    [count_slow, count_medium, count_fast]=playmusic(beats_per_min, count_slow,count_medium, count_fast);
    new_var=toc;
    end

    end
end

end

%%-------------------------------------------------------------------------------- %* AnalogMaxima compares succesive readings from ADC on channel AnalogCh %and returns : % 1025 if voltage is decreasing,so that only the maxima is returned. % 0 if below threshold. % or returns the highest value when voltage starts to drop (local maxima).

%AnalogCh : Channel on the ADC to check for maxima. %Threshold : Lowest voltage reading to begin maxima evaluation. %Delay : Delay between succesive readings in ms. % */

function [t,n] = AnalogMaxima(a,AnalogCh,Threshold,Delay,n,t)
%//variable to store second reading.

check1 = readVoltage(a,AnalogCh); %//Assessing first reading pause(Delay); %//wait check2 = readVoltage(a,AnalogCh);
ret=0; %//Assing second reading. if (check1>check2) %//If voltage is DECREASING (no maxima)... %//end loop and return 1025. else while (readVoltage(a,AnalogCh)>Threshold && ret==0) %//While above threshold and RISING check1 = readVoltage(a,AnalogCh); %//Assing first reading pause(Delay/2); %//wait check2 = readVoltage(a,AnalogCh); %//Assing second reading. pause(Delay/2); %//wait,and loop unless... if (check1>check2) %//voltage drop is observed writeDigitalPin(a,'D13',1); ret=1; n=n+1; t(n)=toc; %//if so return timer :) end end end end %%// end of AnalogMaxima // %%//--------------------------------------------------------------------------------

%% function [count_slow, count_medium, count_fast]=playmusic(x,count_slow, count_medium, count_fast) % Fs = 44100. per sec. duration=10; %sec samples = [1,duration*44100];

if x<80 [y,Fs]=audioread('allofme.mp3',[samples(1)+(duration*44100)*(count_slow-1) samples(2)+(duration*44100)*(count_slow-1)]); count_slow=count_slow+1; elseif x>80 && x<140 [y,Fs]=audioread('somenights.mp3',[samples(1)+(duration*44100)*(count_medium-1) samples(2)+(duration*44100)*(count_medium-1)]); count_medium=count_medium+1; elseif x>140 [y,Fs]=audioread('cantstop.mp3',[samples(1)+(duration*44100)(count_fast-1) samples(2)+(duration*44100)(count_fast-1)]); count_fast=count_fast+1; end

save new_file y Fs

% Play the audio. sound(y,Fs);
clear y Fs end

Share this project:

Updates