ANT+ heart strap failing to receive some packets in watch app

Hello!

Question:

When my Garmin HRM Pro+ strap is connected to my Garmin 955 solar forerunner watch, why is about 1% of the strap's broadcast data not able to be received? Is this normal behaviour?  What does `Ant.MSG_CODE_EVENT_RX_FAIL` specifically mean?

Context:

I have written a Monkey Barrel library ( at https://github.com/mannyray/ANTPlusHeartStrap ) that allows me to connect my Garmin watch to my heart strap. This library is inspired by existing code, so I am not running anything unusual.

I have successfully tested this library as seen at the bottom of README's highlighting of the `sample_app` project. The watch connects to the strap successfully and displays incoming strap data on the watch display.

However, I noticed that sometimes there was a subtle delay in the printing of the data - suggesting that there was some sort of communication issue between watch and strap. According to protocol, the strap is expected to broadcast the heart data at a rate of about four times a second.

I am interested in reducing delay or communication issues between watch and strap because I am interested in getting as close to real time heart data as possible from the strap. Having a communication issue or packet drop will cause at least an extra quarter of second delay to my data or in the worst case have some data be overwritten with the latest heart beat data as the previous one failed to be received by watch.

What I tried to do to solve the issue:

  1. I created a test branch https://github.com/mannyray/ANTPlusHeartStrap/pull/5/files to investigate the communication via logging. What I found is:
    1. Communications does indeed occur every quarter of a second
    2. When the watch receives data from the strap, then usually the message ID is `Ant.MSG_ID_BROADCAST_DATA == msg.messageId`
    3. The perceived communication issue was that I was still receiving a message from the watch at the expected rate, but now the message ID is `Ant.MSG_ID_CHANNEL_RESPONSE_EVENT == msg.messageId` which I did not process as a regular broadcast event - hence the perceived communication issue
      1. The channel response event was specifically of type `Ant.MSG_CODE_EVENT_RX_FAIL`
      2. For a sample test run of the app on my watch, I discovered that out of 163 message (happening every quarter of a second), 13 where of `Ant.MSG_CODE_EVENT_RX_FAIL` which is about 1% rate
  2. Made sure the battery of my heart strap is OK as I have had the, lightly used, strap for a couple of years (maybe it is OK, but due to battery age, it is starting to fade a little?). I checked the battery level by connecting the strap to my watch and checking settings
  3. Tried running my logging experiment in a variety of contexts. I was not running around, but in a static position in case the broadcast failed due to motion of the strap sensor. I tried moving my watch in different positions in case there was some sort of sensor receiver issue. Nothing really helped.

My next best guess as to what to do to further debug the issue is to

  • get another strap to compare - maybe one with a fresh battery - but that can be pricy
  • ask the forum in case someone has already done some ANT+ crawling and has some knowledge here or can run the app on their watch and see if they have a similar experience

  • >BTW, have you seen this? 

    Yes, just the other day, after making my library. However, I figured it wouldn't affect my experiment.

    ps: I think a pun opportunity in the title was missed: "The beginning of the ANT"

  • BTW, are you actually updating the screen 4 times a second?  I can see there could be delays there, based on what else is going on with the device.  How do you determine if two readings just aren't duplicates and there is a missing one?

  • Note if you are trying to update the screen every 250ms (4 times a second), just updating the full screen could take 50-100 ms or more, as I've seen with MIP devices using onPartialUpdate. You stop getting the calls in a watchface if you use more than a 30ms average over a minute, and then only updating part of the screen.  No idea what it takes on an AMOLED device for a full screen, but I expect it's more.

  • How do you determine if two readings just aren't duplicates and there is a missing one?

    I compare the readings returned by beat count. The heart strap increments the count field for a 'new' beat event in the payload. This counter cycles from 0 to 255. If you are receiving the same beat count right after a previous communication event then it is a duplicate as the strap resends the same data until it encounters a new heart beat event. However, if your previous recorded communication from strap said that it was beat number 22 while the current communication is number 24 and you never processed 23 then that means there is a missing event you did not process. In my code this logic is covered in: https://github.com/mannyray/ANTPlusHeartStrap/blob/master/ANTPlusHeartRateSensor/HeartData.mc#L66-L75 and https://github.com/mannyray/ANTPlusHeartStrap/blob/master/ANTPlusHeartRateSensor/HeartData.mc#L135

    >You stop getting the calls in a watchface if you use more than a 30ms average over a minute,

    This is a good point. I was not aware of the 30ms situation. I will look into it this more later. I reran my simulation, but this time removed all UI updates and just logged. This time out of 900 messages I got 211 `Ant.MSG_CODE_EVENT_RX_FAIL` events which moves the error rate from 1% to about 20%. Another run out of 820 messages got me 46 `Ant.MSG_CODE_EVENT_RX_FAIL` failed events which is 5%.

    For now I decided to get a new battery and an ant+ usb dongle to experiment with on the computer - this will take sometime. If I discover something interesting, I will update this thread.

  • Update:

    I ended up purchasing the ANT+ usb device and a new battery.

    I wrote a quick experiment in https://github.com/mannyray/HeartStrapAnalysis where I discovered that I was dropping about half of the data to the ANT+ USB device from the strap.

    I then switched batteries in the strap and still got 50% drop rate on the ANT+ USB device, BUT on my watch the drop rate was 3% during the exact same run (the strap was broadcasting while both watch and USB device were listening at the same time). I am not sure why there is a discrepancy between the watch and the USB device. Since the drop rate on watch was 3% then a new battery did not assist in improving drop rate.

    Conclusion:

    Purchasing a new battery and using a different, USB, receiver did not help me discover why there is a percent drop rate on my watch. I have no investigation ideas left.

    Moving forward, I will adjust my monkey barrel code https://github.com/mannyray/ANTPlusHeartStrap for connecting watch to strap so that it can handle the drops better by giving the option to the user of the library know exactly when there is a `Ant.MSG_CODE_EVENT_RX_FAIL` file type event. Knowing that there is such an event will allow the user to be able to understand that they may be missing out on fresh data.

  • 1. Can you do the experiment again and move the 2 receivers to different places to see if that has any effect?

    2. I'm not sure what is your use case, why you have to display every heart beat within a few milliseconds, but I have a feeling, that you're trying to fix a non existent problem. I'm not talking about the list connection, that you hopefully will be able to fix. But about the alleged need to be so real-time. If it was a medical device, that a doctor is looking at while you run at the treadmill, then ok. But we're talking about the watch that is on the hand of someone running (maybe not even on a treadmill but on the street, crossing the road and trying not to get driven over by some crazy driver). How much information could someone's eye and brain process that you want to display and that gets outdated within 300ms? 

    Maybe what you should do is reevaluate this. Then maybe it's enough to collect the data, and update it with a 1000ms timer on the screen.

  • I did more deep diving for the ANT+ USB and python code on my computer and discovered a problem with my experiment setup( https://github.com/Tigge/openant/issues/111#issuecomment-2672828117) . Reran my experiment comparing the USB and watch receiver and discovered they both get the same `Ant.MSG_CODE_EVENT_RX_FAIL` data. There is something about my strap (or all specific model and brand of this type) that once in a while gives a `Ant.MSG_CODE_EVENT_RX_FAIL`.  It was good to isolate the issue from maybe being due to the watch OR strap to being just due to the strap.

    But about the alleged need to be so real-time.

    I understand - this is a good point. I am just curious and experimenting. I'll keep in mind not get too carried away.