-
Notifications
You must be signed in to change notification settings - Fork 0
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Are there plans to add millisecond timestamps to the ecg waveform acquisition? This would be of great value in achieving data synchronisation for multi-sensor data. #2
Comments
Unfortunately, the Polar H10 just sends the data through two BLE channels
with no associated timestamps and with no apparent correlation:
- BPM and RR intervals
- ECG @ 130Hz sample
Over time, the sum of the RR intervals should accumulate and be reasonably
correct WRT to overall elapsed time.
And we should see 130 samples of ECG data that again is reasonably accurate
compared to the overall elapsed time.
But we are not given any reference between the two channels or an accurate
time base.
The next release of fitnesshrv will capture ECG and save it (and everything
else captured) into FIT files. Just finishing that now.
…On Tue, Nov 22, 2022 at 6:32 AM awesome ***@***.***> wrote:
—
Reply to this email directly, view it on GitHub
<#2>, or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWKSN2NHX7EHUIJUZD3WJTKP7ANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you are subscribed to this thread.Message
ID: ***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
Respiratory rate is definitely on my (long) list of things to do!
Just finishing FIT file creation and making sure I can get uVolts added to
that in a sensible way.
Then need to move the ECG display into fitnesshrv, and then I can look at
things like respiratory rate etc.
…On Wed, Dec 14, 2022 at 6:52 AM MedTechCD ***@***.***> wrote:
Stuart, I don't know if or how you will implement breathing frequency but
I'm also closely following the work of Inigo Tolosa on the Garmin IQ app
AlphaHRV. They have breathing frequency derived from RR intervals.
Underneath is a screenshot from my findings using Fitness-ECG alongside the
Garmin IQ app. As you say above, the 130hz sampling rate for the Polar is
quite accurate and when I plot the ECG in Excel with a time base based on
that sampling rate I see something interesting. The screenshot has the ECG
from the first and last 60sec of a AeT ramp test. A side-effect of chest
strap ECG seems to be that the QRS amplitude changes with chest
expansion/breathing. How feasible would it be to implement that?
[image: image]
<https://user-images.githubusercontent.com/85841362/207628385-8fb27861-9eb0-4a0f-bce5-c69352c510ee.png>
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWIJRHFBI7JNGZNLTFLWNHNJTANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
Unfortunately Polar does not give us any timestamp information about the
ECG data. It simply arrives in blocks of about 73 samples via Bluetooth.
From my perspective, a block of data (usually 73*3 bytes) simply arrives,
at a relatively constant interval.
We have no way of knowing the exact time the data stream started. And there
is lag due to buffering in the sensor (at least 73/130 seconds), and the
time it takes for it to prepare the transfer and for it to be transferred.
As best as I can tell once it starts the data stream is complete. So the
analysis of it should be OK, e.g. deriving respiration rate, heart rate,
or RR values.
But we only know the offset to wall clock time to about 1-2 seconds
accuracy for any point, although that offset should not change over the
life of the datastream (although it may not be guaranteed.)
I think it will be possible to map some other data from the same sensor,
for example, RR times and Artifact locations, to be able to look at the ECG
for specific issues (what might have caused an Artifact.)
…On Wed, Jan 25, 2023 at 7:50 AM MedTechCD ***@***.***> wrote:
Extracting RespRate from the ECG is surprisingly easy. Here's an example
with on top 20sec ECG recorded with your app. At the bottom 1 min with the
extracted R-peaks (orange) and in green the chest movement = respiratory
trace.
[image: image]
<https://user-images.githubusercontent.com/85841362/214609574-94826434-a6aa-4953-8f97-a4c41a6f315a.png>
Some simple Excel manipulations.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWIVGZDM7IUBRTYGUVDWUFDVNANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
I'm just finishing adding BLE support to my main fitnesshrv app, and saving
data to FIT files.
Once I have that out one of the near term goals is to pull ECG into the app
and look at deriving respiration rate from either (or both) RR data or ECG
data.
…On Wed, Jan 25, 2023 at 7:50 AM MedTechCD ***@***.***> wrote:
Extracting RespRate from the ECG is surprisingly easy. Here's an example
with on top 20sec ECG recorded with your app. At the bottom 1 min with the
extracted R-peaks (orange) and in green the chest movement = respiratory
trace.
[image: image]
<https://user-images.githubusercontent.com/85841362/214609574-94826434-a6aa-4953-8f97-a4c41a6f315a.png>
Some simple Excel manipulations.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWIVGZDM7IUBRTYGUVDWUFDVNANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
I've used the HR stream to sync data from multiple devices with resonable accuracy. And for resprate, a few seconds will not make a difference. But I understand the problems you're facing. |
Yes. Currently, I'm doing artifact detection and correction using the
Lipponen/Tarvainen paper using the RR data.
# Jukka A. Lipponen & Mika P. Tarvainen (2019) A robust algorithm for
heart
# rate variability time series artefact correction using novel beat
classification, Journal of Medical
# Engineering & Technology, 43:3, 173-181, DOI:
10.1080/03091902.2019.1640306
If getting the RR data via BLE you have essentially the same problem. It
arrives, and hopefully is self-consistent over time, but no anchoring
timestamp.
Via ANT+ we get a slightly better idea of when data is arriving because we
are lower down in the stack, closer to the USB hardware and get a small
message every 250mS that we can timestamp on arrival. Still not perfect,
but better.
Effectively though, I suspect we should be able to show where the artifacts
are on an ECG strip in a manner that puts them close to the ECG data for
that interval. Probably +/- a few hundred mS.
This area is getting more interesting. I've just ordered a Movesense
sensor. They sample at a higher rate (500hz I believe). I haven't dug into
how they are delivering the RR and ECG data via BLE yet. But they appear to
be open (and open as here is the sensor code!).
And there are rumours of Garmin announcing ECG support real soon now.
My email is at the bottom if you want to keep in touch.
…On Wed, Jan 25, 2023 at 1:46 PM MedTechCD ***@***.***> wrote:
map some other data from the same sensor, for example, RR times
I've used the HR stream to sync data from multiple devices with resonable
accuracy. And for resprate, a few seconds will not make a difference. But I
understand the problems you're facing.
Some thoughts:
An artefact like a premature beat should show in both ECG and RR time.
That would be pretty accurate but can't be invoked...
I'm thinking of trying to hook up an ecg simulator and during recording,
at specific time points, shortcircuit the signal. If that turns out to be
consistent in timing difference, it could be part of a solution. But still,
nothing guarantees that all H10 sensors have the same lag.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWNBDHJEWVFQLUYCT7TWUGNLFANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
It's released for the Venu 2 Plus in the US We do have RR from the same H10 via the ANT+ channel in Dashboard, don't we? |
Thanks for the pointer! Hopefully, they will add to the HRM strap like
Polar H10. Not holding my breath!
On Wed, Jan 25, 2023 at 2:16 PM MedTechCD ***@***.***> wrote:
Garmin announcing ECG support real soon now
It's released for the Venu 2 Plus in the US
https://www.dcrainmaker.com/2023/01/garmin-ecg-app-devices-fully-explained.html
We do have RR from the same H10 via the ANT+ channel in Dashboard, don't
we?
Yes, and once I get a bit more testing done the new FitnessHRV Dashboard
will have BLE support for Hrm and if Polar H10 will allow capturing ECG as
well.
The ECG data will be accessible from a CSV file (hmm, have to check that is
the same as the ecg app....)
Also, the ECG data is available from the FIT file. Although I suspect it
may take some time for other developers to add support for looking at it.
:-)
I will provide some Python scripts for pulling apart the fit files. I am
taking advantage of some FIT file techniques that allow saving data from
multiple sensors of the same type.
That allows (for example) having two (or more) HRM straps and capturing the
heartrate, RR and ECG data from each for comparison. And capturing both as
ANT+ and BLE (so four sets of data.)
I am saving the uVolt data in the Record Message at the point received,
each of those is timestamped (resolution of one second.)
One minor (!) issue with the current FIT SDK implementation for saving RR
data is to put it into a separate stream of HRV Messages and they DO NOT
have a timestamp. Again, hopefully, internally consistent, as in adding all
RR intervals up will give you the correct elapsed time. But again, you
don't have a lot of confidence in where in time the streams start.
Since I am putting the uVolts into a separate Record Message that is
specific to each sensor (and that won't interfere with the normal Record
Message used by Strava, WKO, TrainingPeaks etc), I may add the RR data
available to that Record Message as well. At that point we would at least
have all the data received from the sensor at that point, in a timestamped
message.
To get as close as possible now (close enough for what I'm doing), I start
both apps and if the ECG shows a stable trace, I hit the Start Record
button when dasboard is exactly at 4 or 5 min. That gives me an ECG file
with a creation time 4 or 5 min later then the dashboard files. I hit the
button again at an exact minute when stopping. For a recording of 80-90
min, the number of samples in the ECG is very close (within 200-250
samples) to the number of minutes * 130. This off course does not take into
account that the data coming from the sensor may be delayed.
Yes, the data from the other sensor is delayed. For ANT+ probably on the
order of about 1-2 seconds. BLE may be higher and more variable.
… —
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWNOSTZRQIWUCVBOUL3WUGQ5TANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
The way RR data is saved is pretty good. And so on. Every R peak can be exactly positioned by adding up all inter-beat values. |
Yes, I agree that the ECG is consistent. I.e. we can rely on the overall
elapsed time to be correct.
We just don't have the exact offset to match to the other data (heart rate,
RR etc.) And we have a similar issue with RR. And RR values should again be
consistent.
And that is the source of the lag in the display.
And I like your hardware hack!
…On Thu, Jan 26, 2023 at 7:46 AM MedTechCD ***@***.***> wrote:
For timing consistency, I did the following test:
Installed 2 little wires on the clips of the H10 sensor leading to a
pushbutton to shortcircuit.
With the desktop clock displayed, started the ECG recording at 16:26:00.
After 30 sec and then 7 consecutive times with a 10 sec interval, pushed
the button to shortcircuit the strap. Stopped the recording after another
30 sec, for a total recording time of 2 minutes. File creation time =
16:26:00, modified time = 16:28:00.
Plotted in Excel:
[image: image]
<https://user-images.githubusercontent.com/85841362/214880747-c83dced9-d2e9-4925-8314-d91afb0d2524.png>
I think you're worrying to much about timing. From what I see, the ECG is
recorded with negligible time errors. The display on the other hand is
lagging somewhere in between 3 and 3.5 seconds. That's probably caused by
extra filtering and video lag.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWPS7ELXFTWFAKGHP6LWUKL65ANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
The ECG file creation time gives you a date-time stamp (which is already used in the filename). Every 130 samples make up a second. Then it is just a question to reference that to the date-time stamp of the regular datastream or am I overlooking something? |
Yes, start/stop on the list. Also if you are using Zwift and have Sauce for
Zwift installed, I connect to that to get world, location, speed, lap
information etc. Generally switching worlds starts a new FIT file.
Once I have FIT file generation complete it will also make sense to be able
to reload a FIT file to look at. So having a dialogue box to control
start/stop or open file makes sense.
Do you want to play with an early beta of the new release? I don't have ECG
display yet, but the capture is working, and the data is saved into the FIT
file saved.
Not to get too much into the weeds on how FIT files are formatted, but
effectively the two interesting messages are:
- Record Message - has all of the interesting sensor data, generally,
one record per second does NOT have RR data, has a timestamp accurate to
one second
- HRV Message - all of the RR data, no timestamps,
In my implementation, I am generating additional Record Messages for each
sensor, and in the case of the H10 that will include the NN (RR data
corrected) and the uVolts.
I'll have python scripts available for pulling apart the FIT file to get
the raw data. In the case of NN or uVolts you'll have one seconds worth of
data for each one-second resolution timestamp. And easily extracted into
(for example) CSV format.
And of course, the original RR data is available. The placement of the RR
data within the fit file is not guaranteed in the FIT specification
(applications generating the data can place the data in any order WRT to
the other messages).
In my implementation, the RR data is written intermixed with the Record
Messages, so there will be reasonable correspondence to the preceding and
following Record Messages with their timestamp.
…On Fri, Jan 27, 2023 at 4:45 AM MedTechCD ***@***.***> wrote:
We just don't have the exact offset to match to the other data
The ECG file creation time gives you a date-time stamp (which is already
used in the filename). Every 130 samples make up a second. Then it is just
a question to reference that to the date-time stamp of the regular
datastream or am I overlooking something?
One thing I'm absolutely missing in the actual dashboard app, is a Start
button. You have to wait for the 2min data collection window for a1, but
then you have no way to control when the Ra calculation starts because it
starts immediately... I'm usualy doing other prep stuff (Power meter
calibration, trainer control app setup, ...) while dashboard is already
running. I would like a start button to control when data logging starts,
and that button could start ECG collection at the same time.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWLL5OYXAFP4ODNVATLWUO7NNANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
I would be glad to give you my opinion and eventual remarks ;-) |
I dub into the Polar SDK a bit more. It appears that Polar is sending us a
timestamp.
Effectively I am getting a BLE message containing a microsecond timestamp
and 73 data points every 560 mS.
I can put this into the saved CSV file.
Do you want every sample in the CSV file to have a timestamp? I.e. the
recorded timestamp for the first sample and interpolated for the next 72?
Or just put the timestamp in once every 73 samples?
Also, on reviewing the Polar H10 data and comparing it to Movesense, I
think the Polar is giving us millivolt samples, not microvolts.
The documentation in the Polar SDK says uV. But what I'm seeing looks like
mV. I have to dig back into my ECG app further, but I don't see any
conversion from the samples to display in mV.
…On Sun, Jan 29, 2023 at 5:37 AM MedTechCD ***@***.***> wrote:
Do you want to play with an early beta of the new release?
I would be glad to give you my opinion and eventual remarks ;-)
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWO7VCAHWADGUAJQ7JLWUZXCLANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
The values in the recorded csv file from Fitness ECG app are definitely µV. Common p2p amplitudes for ECG are around 1-2,5mV. The csv, for my recordings, has max values around 2500. That can only be µV. But I don't know if they are already manipulated by your app.
Guess you mean a millisecond timestamp?
I think just putting in what you actually get from the Polar SDK is the safest thing to do. Interpolating isn't difficult to do afterwards. |
This could be valuable information to understand the H10 Timestamps! |
On Tue, Feb 7, 2023 at 3:39 AM MedTechCD ***@***.***> wrote:
Also, on reviewing the Polar H10 data and comparing it to Movesense, I
think the Polar is giving us millivolt samples, not microvolts.
The values in the recorded csv file from Fitness ECG app are definitely
µV. Common p2p amplitudes for ECG are around 1-2,5mV. The csv, for my
recordings, has max values around 2500. That can only be µV. But I don't
know if they are already manipulated by your app.
Let me get collect some raw data and send it to you. Not being an ECG
Domain expert I can get lost in the weeds sometimes.
There is definitely a difference in nomenclature between Polar and
Movesense. Polar specifically says uV and sends data as 3-byte integers.
Movesense says mV and sends the data as 2-byte integers.
But at first glance, they appear the same :-(
So a second opinion would be useful to sort it out!
Effectively I am getting a BLE message containing a microsecond timestamp
and 73 data points every 560 mS.
Guess you mean a millisecond timestamp?
That would be slightly higher then 130Hz resulting in 1286 samples extra
per hour compared to the 130 Hz I used now. Or about 10 sec. Not entirely
convinced here...
Polar is sampling at 130 Hz, about every 7.69 mS, and sends 73 samples at a
time. That is presumably all they can fit in the maximum BLE data packet
for their device.
That works out to the 560 mS.
The timestamp provided has a lot more precision (about nanoseconds), I
don't know how accurate it is. I can push as much of that across as is
needed.
I think (but have not verified) that Movesense is only proving millisecond
accuracy on their timestamps. They send data in smaller packets, 16 samples
each and support a number of different sample rates (500 Hz, 250 Hz, 125 Hz
and 100 Hz.)
That should have the effect of smoothing the display updates, unlike the
Polar where you get a half second of data to display every half second etc.
… Or just put the timestamp in once every 73 samples?
I think just putting in what you actually get from the Polar SDK is the
safest thing to do. Interpolating isn't difficult to do afterwards.
—
Reply to this email directly, view it on GitHub
<#2 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AACIUWPNB6TAQOHCLA7MDV3WWIX5ZANCNFSM6AAAAAASH4PYRI>
.
You are receiving this because you commented.Message ID:
***@***.***>
--
__________O___________
_______-\<,____________
_____(_)/_(_)___________
_________________________
***@***.***>____604-518-1749(m)__604-461-7532(h)
|
There is absolutely no need to have that kind of precision. But this info allows correct interpretation of the timestamp. Rounding to milliseconds (eventally µsec) should be more the enough. Plotting ECG is in my opinion best done with the sample index and not with a timeline. Then visualy display a line every second or 10 seconds which aligns with 130 or 1300 samples. Calculating interbeat intervals is the number of samples divided by the sampling rate and multiplied by 1000 to have those in milliseconds. If my interpretation is correct, for the Polar H10 you would get a very large number as a date timestamp, because it is the number of nanoseconds counted from the default date 2019-01-01 - 00:00:00. Your local system date/time minus the default date/time is an offset to display with time-of day. Once you have the precise start-time to sync with other sensor sources, things can be displayed with elapsed time. The first time-stamp is the most important one to make syncing with other sources possible. After that, it's just a matter of checking that no samples were lost every x msec (560?). But the timing should be very consistent by simply using the sample index. Regarding the amplitudes of the ECG signal: if you get any number in the stream that is higher then ~500, it must be µV because the electrical signals from the heart simply don't have amplitudes of 0.5V and higher. |
No description provided.
The text was updated successfully, but these errors were encountered: