Emma Nolan Iteration 3




                                                                       HRV Visualization 


The graphical representation above corresponds to the code implementation provided below. In this visual depiction, the blue line signifies the Heart Rate Variability (HRV), capturing the variations in the time intervals between consecutive heartbeats. Meanwhile, the red line represents the Breath Pacer, which follows a specific breathing pattern characterized by a cycle of 4 seconds inhalation followed by 6 seconds exhalation. - The graph shows how my Heart Rate Variability (blue line) and Breath Pacer (red line) work together. It helps me understand how my body responds in real-time. The code and graph are useful for keeping track of my heart-related metrics in a simple and informative way.



Explain the Code

input.onButtonPressed(Button.A, function () {
    maxpulse = pins.analogReadPin(AnalogPin.P2)
    minpulse = pins.analogReadPin(AnalogPin.P2)
})

When button A is pressed, it calibrates the maximum and minimum pulse values by reading the analog signal from pin P2. By setting these initial values, the code ensures that future pulse readings fall within a known range, making it possible to normalize and interpret the data accurately. Essentially, it provides a baseline for monitoring changes in pulse readings over time.

// task #1 Heartbeat
basic.forever(function () {
    led.toggle(2, 2)
})
In an infinite loop, it toggles the LED at position (2, 2), simulating a heartbeat.

// task #2 Breath pacer 4 in 6 out
basic.forever(function () {
    breath_pacer = 800
    basic.pause(4000)
    breath_pacer = 550
    basic.pause(6000)
})
Another infinite loop implementing a breath pacer. It sets the breath pacer value to 800, pauses for 4 seconds, then sets it to 550 and pauses for 6 seconds. - By introducing a breath pacer, the code aims to create a scenario where the user's breathing and HRV are systematically linked, providing insights into the dynamic relationship between respiratory patterns and heart rate variability. This can be useful for stress management, relaxation, and overall well-being assessments.

// task #3 Read and display local level of pulse
basic.forever(function () {
    PulseDet = pins.analogReadPin(AnalogPin.P2)
    led.plotBarGraph(PulseDet, 1023)
})
Continuously reads the analog signal from pin P2 (local level of pulse) and displays it as a bar graph on the LED. - This serves as a helpful visual guide for users, as the device requires calibration to individual heart and pulse rates, providing real-time feedback on their physiological metrics.

// task #4 Calculate max and min levels from pulse sensor
basic.forever(function () {
    if (maxpulse < PulseDet) {
        maxpulse = PulseDet
    }
    if (minpulse > PulseDet) {
        minpulse = PulseDet
    }
})
Continuously updates the max and min pulse levels based on the real-time pulse sensor readings.

// task #5 Calculate the time between pulses in ms, delta_t, also the pulse rate pulse_out,
// and the variation between each heart beat, hrv. Also filter out any noise values above 1000
basic.forever(function () {
    if (PulseDet > maxpulse - 150 && counter == 0) {
        led.toggle(0, 0)
        time2 = input.runningTime()
        delta_t = time2 - time1
        time1 = time2
        counter = 1
        if (delta_t > 1000) {
            delta_t = lastdelta
        } else {
            hrv = Math.abs(delta_t - lastdelta)
        }
        pulse_out = (60000 - 60000 % delta_t) / delta_t
        lastdelta = delta_t
    } else if (PulseDet <= minpulse + 150 && counter == 1) {
        counter = 0
        led.toggle(4, 0)
    }
})
Continuously calculates the time between pulses (delta_t), pulse rate (pulse_out), and the variation between each heartbeat (hrv). It also filters out noise values above 1000. The LED at (0, 0) is toggled when a pulse is detected, and the LED at (4, 0) is toggled when the pulse falls below a certain threshold.

javascript
Copy code
basic.forever(function () {
    serial.writeNumbers([delta_t, breath_pacer])
})
Continuously sends the values of delta_t and breath_pacer over the serial port.


Reflection:

Reflection on the conducted tests revealed several insights. Firstly, opting for the mouth or ear, which has more cartilage facilitating better LED visibility of blood flow, proved effective compared to using the finger for testing. Additionally, the suggestion to incorporate sound alongside visual cues could enhance the usability of the breath pacer. Notably, the ability to visually observe the fluctuation in Heart Rate Variability (HRV) was considered a positive outcome, reinforcing the attainability of the project's goals. The collaborative testing experience, where our class synchronized their breathing, led to a shared sense of calmness, highlighting the potential positive impact of the project. Emphasis was placed on the significance of sensor placement, suggesting a focus on optimizing sensor positioning rather than solely refining the breathing aspects of the application. An idea was proposed to explore an oxygen finger sensor similar to those used in hospitals, ensuring a fixed finger position and reducing the frequency of user calibrations. Or putting tap over it to make it less sensitive. 



Normalize the peaks to determine the max and min


Following the update of maxpulse and minpulse, the code proceeds to normalize these values. Normalization is a process of scaling values to a standard range.
normMaxPulse is set to 1.0, indicating the upper limit of the normalized range.
normMinPulse is calculated by normalizing the minpulse value within the range of (minpulse, maxpulse). The addition of 0.0001 is a small value to prevent division by zero.

This way, no matter what scale we started with, we can say, "Oh, this pulse reading is 80% of the way between the lowest and highest values we've seen."
This helps in making sure that when we talk about our pulse readings, we're all using the same yardstick, regardless of the specific numbers our pulse sensor gives us. It's like putting everyone's pulse measurements on a universal scale so that we can understand and compare them better.

Normalized Pulse: It first calculates a normalized pulse value, which is a way of standardizing the pulse readings to a scale between 0 and 1.

Threshold Check: It then checks if the normalized pulse is above a certain threshold (normMaxPulse - 0.15) and if the counter is 0. 
If this condition is met, it toggles an LED light (led.toggle(0, 0)).
It records the current time as time2 and calculates the time difference (delta_t) between the current time and the last recorded time (time1).
It then updates the counter to 1 and checks if the time difference is greater than 1000 milliseconds. If it is, it uses the last recorded delta_t.
Otherwise, it calculates the heart rate variability (hrv) as the absolute difference between the current and last delta_t.
The pulse rate (pulse_out) is calculated as 60000 divided by delta_t.
The last recorded delta_t is updated.
Else If Check: If the normalized pulse is below a certain threshold (normMinPulse + 0.15) and the counter is 1, it means the pulse is significantly lower than usual, and the counter is reset to 0. Additionally, it toggles another LED light (led.toggle(4, 0)).

calculate the phase difference the HRV and pacer.


Breath Pacer Rising Edge Detection: It checks if the current value of breath_pacer is 1 (indicating a rising edge) and if it's different from the previous value. If both conditions are true, it records the current time (input.runningTime()) as breathPacerRisingEdgeTime.

HRV Rising Edge Detection: It checks if the HRV value is greater than 0 (indicating a rising edge) and if it's different from the previous HRV value. If both conditions are true, it records the current time as hrvRisingEdgeTime.

Calculate Phase Difference: If rising edges are detected in both signals, it calculates the time difference between the rising edges. The phase difference is then calculated based on the breathPacerPeriod. The result is stored in phaseDifference, and the rising edge times are reset to 0.

Update Previous Values: The current values of breath_pacer and hrv are stored as previous values for the next iteration.

This code essentially measures the time difference between rising edges in the breath pacer and HRV signals and calculates the corresponding phase difference. This phase difference can provide insights into the synchronization or relationship between the breath pacer and HRV signals.

Auto-calibration



It continuously reads the analog signal from pin P2, updates the minpulse and maxpulse values accordingly, and adds a small pause to allow for stabilization. This approach ensures that the calibration parameters adapt to changes in the sensor readings over time.

Video:

 






 

 





 




 








Comments

Popular posts from this blog

Iteration 2 | Jack | HRV Micro:bit Research

Iteration 5.2 | Lock In | Jack

Week 1: HRV Review