heartrate

Track Your Heartrate on Raspberry Pi with Ant+

Using the Suunto Movestick Mini and Garmin Soft Strap Heart Rate Monitor

This blog post is inspired by the excellent blog post “Monitoring your developer health with an ANT+ sensor” by Tom Wardill. His code works great and this blog does nothing to improve the code. Instead I focus on getting the stick to run on Raspberry Pi.

What you’ll need

ImageDescription
raspberryA Raspberry Pi with power supply and SD card. I’m using Raspbian as the operating system.
movestickThe Suunto Pods Movestick Mini, SS016591000, which serves as the Ant+ receiver.
garminThe Garmin Premium Soft Strap Heart Rate Monitor, which serves as the Ant+ sender.

Step 1: Hardware

Log in to the Raspberry Pi, then insert the Movestick mini. Check that the stick is recognized by running

pi@skyemittari ~ $ dmesg | tail
[ 2430.589870] usb 1-1.3: new full-speed USB device number 4 using dwc_otg
[ 2430.698954] usb 1-1.3: New USB device found, idVendor=0fcf, idProduct=1008
[ 2430.698992] usb 1-1.3: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[ 2430.699012] usb 1-1.3: Product: Movestick mini
[ 2430.699029] usb 1-1.3: Manufacturer: Suunto
[ 2430.699047] usb 1-1.3: SerialNumber: 1339803961

You should see entries for the Suunto Movestick mini and the corresponding vendor id and product id. For the Movestick mini they should always be:

  • idVendor: 0fcf
  • idProduct: 1008

You can also get those ids by running lsusb. The Movestick mini appears as Dynastream Innovations, Inc.. The four digits after ID are the vendor id, the four digits after that the product id:

pi@skyemittari ~ $ lsusb
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
Bus 001 Device 004: ID 0fcf:1008 Dynastream Innovations, Inc.

To get the usb serial kernel driver to create a node for our Movestick mini we need to create an udev rule. First unplug the Movestick then create the following file:

pi@skyemittari ~ $ sudo vi /etc/udev/rules.d/garmin-ant2.rules

with the following content (all one one line):

SUBSYSTEM=="usb", ATTRS{idVendor}=="0fcf", ATTRS{idProduct}=="1008", RUN+="/sbin/modprobe usbserial vendor=0x0fcf product=0x1008", MODE="0666", OWNER="pi", GROUP="root"

Next reinsert the Movestick mini. Now you should have a /dev/ttyUSB0 node:

pi@skyemittari ~ $ ls /dev/ttyUSB0
/dev/ttyUSB0

This is all you need to do to prepare the Movestick mini.

Step 2: Software

I’m using Python-Ant to read the heart rate. First clone python-ant (see the Appendix why I’m using a fork of python-ant instead of the trunk repository):

pi@skyemittari ~ $ git clone https://github.com/baderj/python-ant.git
Cloning into 'python-ant'...
remote: Reusing existing pack: 444, done.
remote: Counting objects: 31, done.
remote: Compressing objects: 100% (21/21), done.
remote: Total 475 (delta 10), reused 20 (delta 4)
Receiving objects: 100% (475/475), 92.16 KiB, done.
Resolving deltas: 100% (224/224), done.

Next install python-setuptools and with that python-ant:

pi@skyemittari ~ $ sudo apt-get install -y python-setuptools
pi@skyemittari ~ $ cd python-ant/
pi@skyemittari ~/python-ant $ sudo python setup.py install

To test the code use the following small Python snippet:

"""
    Code based on:

https://github.com/mvillalba/python-ant/blob/develop/demos/ant.core/03-basicchannel.py

    in the python-ant repository and

https://github.com/tomwardill/developerhealth

    by Tom Wardill
"""
import sys
import time
from ant.core import driver, node, event, message, log
from ant.core.constants import CHANNEL_TYPE_TWOWAY_RECEIVE, TIMEOUT_NEVER

class HRM(event.EventCallback):

    def __init__(self, serial, netkey):
        self.serial = serial
        self.netkey = netkey
        self.antnode = None
        self.channel = None

    def start(self):
        print("starting node")
        self._start_antnode()
        self._setup_channel()
        self.channel.registerCallback(self)
        print("start listening for hr events")

    def stop(self):
        if self.channel:
            self.channel.close()
            self.channel.unassign()
        if self.antnode:
            self.antnode.stop()

    def __enter__(self):
        return self

    def __exit__(self, type_, value, traceback):
        self.stop()

    def _start_antnode(self):
        stick = driver.USB2Driver(self.serial)
        self.antnode = node.Node(stick)
        self.antnode.start()

    def _setup_channel(self):
        key = node.NetworkKey('N:ANT+', self.netkey)
        self.antnode.setNetworkKey(0, key)
        self.channel = self.antnode.getFreeChannel()
        self.channel.name = 'C:HRM'
        self.channel.assign('N:ANT+', CHANNEL_TYPE_TWOWAY_RECEIVE)
        self.channel.setID(120, 0, 0)
        self.channel.setSearchTimeout(TIMEOUT_NEVER)
        self.channel.setPeriod(8070)
        self.channel.setFrequency(57)
        self.channel.open()

    def process(self, msg):
        if isinstance(msg, message.ChannelBroadcastDataMessage):
            print("heart rate is {}".format(ord(msg.payload[-1])))

SERIAL = '/dev/ttyUSB0'
NETKEY = 'B9A521FBBD72C345'.decode('hex')

with HRM(serial=SERIAL, netkey=NETKEY) as hrm:
    hrm.start()
    while True:
        try:
            time.sleep(1)
        except KeyboardInterrupt:
            sys.exit(0)

You can find the code on GitHub. Clone it, then run it with python garmin_ant_demo.py:

pi@skyemittari ~ $ ~
pi@skyemittari ~ $ git clone https://gist.github.com/c41d2bbe0aeded3506cf.git hrmdemo
Cloning into 'hrmdemo'...
remote: Counting objects: 3, done.
remote: Compressing objects: 100% (2/2), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
pi@skyemittari ~ $ cd hrmdemo/
pi@skyemittari ~/hrmdemo $ python garmin_ant_demo.py
starting node
start listening for hr events
heart rate is 69
heart rate is 69
heart rate is 69
heart rate is 70
heart rate is 70

You can stop the script with Ctrl+C; it should end gracefully. Sometimes the python-ant can’t connect to the Movestick and the script stalls at starting node. In this case unplug and reinsert the Movestick and retry.

Appendix: Why use a fork of Python-Ant?

Unfortunately, the current state of the python-ant library has a few minor problems with the Ant Movestick mini. One of those is that you’ll probably see the following error message:

AttributeError: 'Interface' object has no attribute 'AlternateSetting'

Tom Wardill patched those problems in his fork of python-ant. His code worked well for me, I often got the following exception though:

Traceback (most recent call last):
  File "hrm.py", line 34, in <module>
    antnode.start()
  File "/usr/local/lib/python2.7/dist-packages/ant-develop-py2.7.egg/ant/core/node.py", line 158, in start
    self.driver.open()
  File "/usr/local/lib/python2.7/dist-packages/ant-develop-py2.7.egg/ant/core/driver.py", line 61, in open
    self._open()
  File "/usr/local/lib/python2.7/dist-packages/ant-develop-py2.7.egg/ant/core/driver.py", line 191, in _open
    dev.set_configuration()
  File "/usr/local/lib/python2.7/dist-packages/pyusb-1.0.0b1-py2.7.egg/usb/core.py", line 559, in set_configuration
    self._ctx.managed_set_configuration(self, configuration)
  File "/usr/local/lib/python2.7/dist-packages/pyusb-1.0.0b1-py2.7.egg/usb/core.py", line 92, in managed_set_configuration
    self.backend.set_configuration(self.handle, cfg.bConfigurationValue)
  File "/usr/local/lib/python2.7/dist-packages/pyusb-1.0.0b1-py2.7.egg/usb/backend/libusb1.py", line 741, in set_configuration
    _check(self.lib.libusb_set_configuration(dev_handle.handle, config_value))
  File "/usr/local/lib/python2.7/dist-packages/pyusb-1.0.0b1-py2.7.egg/usb/backend/libusb1.py", line 571, in _check
    raise USBError(_str_error[ret], ret, _libusb_errno[ret])
usb.core.USBError: [Errno 16] Resource busy

The exception is no longer thrown if you detach the kernel driver if already attached. To this end I changed USB2Driver in python-ant/src/ant/core/driver.py:

if dev is None:
raise DriverError('Could not open device (not found)')
+
+ # make sure the kernel driver is not active
+ if dev.is_kernel_driver_active(0):
+ try:
+ dev.detach_kernel_driver(0)
+ except usb.core.USBError as e:
+ sys.exit("could not detach kernel driver: {}".format(e))
+
dev.set_configuration()
cfg = dev.get_active_configuration()

Archived Comments

Note: I removed the Disqus integration in an effort to cut down on bloat. The following comments were retrieved with the export functionality of Disqus. If you have comments, please reach out to me by Twitter or email.

Chris Aug 05, 2014 00:11:29 UTC

Many thanks for posting this, most interesting!

I'm planning to monitor heart rate as well as candence and speed as part of my winter cycling setup on an indoor trainer in my garage. Using the raspberry pi will also add other function options such as logging and start/st buttons. The garmin sensor is along the lines of this one:

https://buy.garmin.com/en-U...

I'm a bit of a rookie and learning fast but is the Movestick capable of 'listening' to another device as well? Would you consider this as straightforward?

Johannes Aug 05, 2014 12:20:00 UTC

The Movestick supports up to 8 channels, i.e., can listen to 8 devices at the same time. From what I've seen on Amazon reviews and sites like http://www.dcrainmaker.com/..., the Movestick supports the Garmin cadence/speed sensor profile.

In terms of software you should only need to open up a second channel. The name of the channel changes from HRM to CNS, and the device type to 121:

channel_cns.name = 'C:CNS'
....
channel_cns.setID(121, 0, 0)

The device type is not mandatory (you could just do a wildcard search with all three arguments set to 0), but the device id helps to assign the correct listener later on.

So although I never used a second sensor myself, I believe it shouldn't be hard at all. Ant+ was designed specifically to support many different sensors and networks topologies. And as long as your not using the sensors in public gym environments, you don't need to worry about connecting to the right devices.

Chris Aug 06, 2014 10:30:34 UTC

Great, sounds ideal, I'll let you know how I get on!

Willem Aug 23, 2014 13:35:17 UTC

Thanks for posting this. Works great. Instead of the Garmin heart rate monitor I used the MIO Link heart rate monitor. Without any adaptations to the software, the Raspberry Pi recorded my heartbeat with the MIO Link just as good as with the Garmin. The MIO Link has no chest strap.

Paul Nov 28, 2014 03:23:55 UTC

Hi. I've tried your hrmdemo after going through the setup you describe in the document but it's not working for me.

The output I get is;

$ python garmin_ant_demo.py
starting node
Traceback (most recent call last):
File "garmin_ant_demo.py", line 71, in
sys.exit(0)
File "garmin_ant_demo.py", line 39, in __exit__
self.stop()
File "garmin_ant_demo.py", line 33, in stop
self.antnode.stop()
File "/usr/local/lib/python2.7/dist-packages/ant-develop-py2.7.egg/ant/core/node.py", line 167, in stop
raise NodeError('Could not stop ANT node (not started).')
ant.core.exceptions.NodeError: Could not stop ANT node (not started).

I've checked and my USB ANT stick is connected to /dev/ttyUSB0 and the output from, dmesg | tail, looks good in that the stick shows up as Dynastream Innovations.

If I change USB2Driver to USB1Driver in line 42, I get a different response where after the "starting node" message is output the program hangs and I have to Ctrl+C to exit. I noticed there are two options for USB driver in the python-ant code.

I'm using a Garmin USB stick and not the Suunto mini stick but the chipset is the same, Dynastream Innovations 0x0fcf and 0x1008

Do you have any ideas what the problem is, or how to debug this?

Thanks
Paul

Donald Schoolmaster Jr Jan 19, 2015 02:54:44 UTC

Paul, I get these exact errors. Did you ever figure this out? I too and using a Garmin stick.
Thanks

Magic Jan 27, 2015 08:17:18 UTC

Hi. This bug is due to PyUSB 1.0.0b2. Remove it and :

sudo pip install pyusb==1.0.0b1

BTW Thanks for the demo Johannes.

My pleasure :)

Clive Feb 01, 2015 20:34:45 UTC

The pyusb downgrade worked for me too. I found it independently (wish I'd looked back here sooner) and there's a little more information on links on my own post at http://projects.rosedene.co....

Thanks everyone!

jens Nov 29, 2014 02:34:48 UTC

Hey Paul,

I found the bug. I also use a different stick with VID $0cfc and PID $1004. You have to change the line 188 in ant/core/driver.py to the PID of your Stick. After restarting the Script the errors disappear in y case, cause the usb class found the right device.

But now the skript stops afer line starting node.

Maybe i have to change NETKEY stuff.

But where to get the right one for my HeartRateBand?

Jens

Tristan Feb 11, 2015 05:11:42 UTC

Hey Jens,
did you get this working... Im having the same problem

Paul Dec 04, 2014 14:59:47 UTC

Hi,

I've got the hrm demo running now - I had to use sudo to run the python code; sudo python garmin-ant-demo.py

The details in line 188 of driver.py where correct for my stick.

Something is not right though as my /etc/udev/rules.d/garmin-ant2.rules is either being ignored or not read as I have to manually enter the modprobe command as sudo to create the /dev/ttyUSB0 mount point.

Also I don't want to be running the python code as sudo but as the basic user ("pi" in my case) but I can't get this fixed. I've tried sudo chmod 777 /dev/ttyUSB0 but this didn't help so I don't know where the problem is then.

The NETKEY is in the code (see above)

Thanks
Paul

Nick Dec 19, 2014 13:35:49 UTC

Hi Guys,

can anyone give me any pointers on how to debug this? I am using the Garmin ant stick with VID $0cfc and PID $1009. /dev/ttyUSB0 seems to be all ok and I have updated line 188 in ant/core/driver.py to the PID of my stick. But still problems...

Any pointers would be appreciated!!!

$ sudo python garmin_ant_demo.py
starting node
Traceback (most recent call last):
File "garmin_ant_demo.py", line 71, in
sys.exit(0)
File "garmin_ant_demo.py", line 39, in __exit__
self.stop()
File "garmin_ant_demo.py", line 33, in stop
self.antnode.stop()
File "/usr/local/lib/python2.7/dist-packages/ant-develop-py2.7.egg/ant/core/node.py", line 167, in stop
raise NodeError('Could not stop ANT node (not started).')
ant.core.exceptions.NodeError: Could not stop ANT node (not started).

..Nick

Paul Dec 24, 2014 17:10:04 UTC

Hi Nick,

Searching for "ant+ stick pid 1009" has turned up a few items. pid=1009 is associated with a later USB-m stick from Dynastream Innovations and a couple of sources look at the details of a drivers file in the kernal.

https://gitorious.org/opens...

https://github.com/Tigge/Ga...

Good luck
Paul

Donald Schoolmaster Jr Jan 19, 2015 06:23:32 UTC

First of all, Thank you Johannes for putting this blog post together.
I have the same error as Nick and Paul report in these comments. However, the line 188 info of driver.py is correct for my stick and the /dev/ttyUSB0 is listed. Running gamin_ant_demo.py with or without sudo doesn't change it's behavior. It's not clear to me what this error indicates. Any insights?
Thanks,
Don

Lloyd Jan 25, 2015 17:14:02 UTC

I think I know what the problem is, I've been having the same issue. I had a GPS module connected to my Pi initially and that was listed as ttyUSB0. I'm going to try setting the ANT+ stick as ttyUSB1. I'll let you know how it goes

UPDATE: Still not got it to work, thought that would have fixed it. Back to square one :/

Clive Feb 19, 2015 22:28:56 UTC

Many thanks to Johannes and all the helpful commenters here. From this starting point I've been able to make the simple display I was after for my winter training setup. Next steps: speed and cadence. See post at http://projects.rosedene.co... for a little more information.

Cheers.

Craig Feb 26, 2015 19:10:04 UTC

Thanks for putting this together! Do you see a big difference in this example if I plan to use the ANT USB-m Stick instead of the Suunto?

Alin May 18, 2015 06:47:32 UTC

Should this code be able to capture HR events from G-Coded chest straps? - I would say no, but on the other hand, I used the same G-Coded strap (Geonaute from Decathlon) with a Schwinn spinning bike and it worked. How come? Any hints are greatly appreciated. Thanks.

nerd goes boom Jul 21, 2015 23:14:16 UTC

This is quiet cool , I want to know is there any way I can upload the data to my mysql datbase?

Johannes Bader Jul 22, 2015 13:57:37 UTC

Should be as easy as:

import mysql.connector
config = {'database': 'hr', 'password': ..., 'user': ..., 'host': .. }

cnx = mysql.connector.connect(**config)
cursor = cnx.cursor()
query = ("INSERT INTO heartrates (date, beatspermin) VALUES (date, bpm)")
cursor.execute(query)
cnx.commit()

nerd goes boom Jul 21, 2015 23:23:16 UTC

Would this work on the new raspberry pi 2 b+ ?

Johannes Bader Jul 22, 2015 13:51:53 UTC

I don't have the new Raspberry (yet), but it should work just fine.

nerd goes boom Jul 25, 2015 12:22:19 UTC

Hi would this little cheaper monitor work?
Would it just be the same process?

Jakobud Jul 30, 2015 22:36:59 UTC

Can you track more than heartrate? For example my bike computer and sensors on my bike transmit/receive my bike speed and cadence as well. Can this receiver receive those values as well or just heart rate? What about ANT+ Power Meters?

Johannes Bader Aug 01, 2015 13:57:02 UTC

Yes, the same usb receiver can handle all other Ant+ sensors as well, even at the same time (up to at least 8 concurrent devices)

Mariusz Izydorek Aug 02, 2015 12:07:00 UTC

Hi,

I am trying to connect to 2 heartrate sensors concurrently and I was wondering if I should open second channels or listen to both devices on the same channel? Also how can I check which device is which when I am connecting to both of them.

Thanks,
Mariusz

ylDave Sep 19, 2015 06:51:55 UTC

So I tried this on a Centos VM with my garmin stick; product ID on the stick is 1004 so I changed that everywhere it is being used.

When I run I get this error:

[cloudera@quickstart hrmdemo]$ python garmin_ant_demo.py
starting node
Traceback (most recent call last):
File "garmin_ant_demo.py", line 71, in <module>
sys.exit(0)
File "garmin_ant_demo.py", line 39, in __exit__
self.stop()
File "garmin_ant_demo.py", line 33, in stop
self.antnode.stop()
File "/usr/lib/python2.6/site-packages/ant-develop-py2.6.egg/ant/core/node.py", line 167, in stop
raise NodeError('Could not stop ANT node (not started).')
ant.core.exceptions.NodeError: Could not stop ANT node (not started).

I see the device:
[cloudera@quickstart hrmdemo]$ lsusb
Bus 001 Device 001: ID 1d6b:0001 Linux Foundation 1.1 root hub
Bus 001 Device 004: ID 0fcf:1004 Dynastream Innovations, Inc. ANT2USB

Is there anything else I'm missing to get this running?

ylDave Sep 19, 2015 18:55:52 UTC

I tried the developerhealth repo with similar results; then I found another ant repo where I did get it to run ( git@github.com:joewilliams/antplus_hrm0_5.git ) however the results I'm getting seem to be randomly distributed around what it should be (mid 60s):

1.15365
1.83831
134.442
46.3698
7.5955
4.07616
185.06

(Before I inserted a \n into the print formatting these were all run together)

I do notice that the source has separate keys for Garmin and Suunto that that may be part of the puzzle.

Rowan le Clercq Jan 27, 2016 05:46:04 UTC

Did you get a work around for this? I'm having the same result. Thanks.

acbind Feb 23, 2016 00:46:14 UTC

I am also seeing this error. Would love to know the work around.

Atif Oct 06, 2015 05:42:29 UTC

Can this track HR data from multiple HRM at a time?

Johannes Bader Oct 06, 2015 10:11:00 UTC

Yes, you just need to also consider the channel number to distinguish the sensors.

V Nov 22, 2015 08:43:10 UTC

Is it possible to use this code with a different ANT+ capable device such as a Mio watch? Do I need to change anything in the code? Also, how do I add channels so that it can listen to two or more devices simultaneously?

Jonathan Tyler-moore Feb 05, 2016 21:16:14 UTC

I am having trouble trying to integrate other code into it. For example i was trying to get the heart rate to display on a led matrix display (the sense hat), and it would work once but then stop. It would stop after starting node, and it wouldn't even come up with an error. When i then took out all the stuff i had added into the code, it still didn't work! I then had to delete it and re download it from github again.

Ivo Rocha Sep 02, 2016 15:16:42 UTC

Hello, I know this is an old post but I hoped that you could give me a hand. I'm trying to do this project but when I get to the part in which we need to get the usb serial kernel driver to create a node for our Movestick mini and we need to create an udev rule, I create the udev rule but when I do "pi@skyemittari ~ $ ls /dev/ttyUSB0" it says : ls:cannot access /dev/ttyUSB0: No such file or directory. I was hoping that you could help me, thanks for your time.

Thomas Christie Jan 02, 2017 17:58:52 UTC

Hi Ivo, I'm currently trying to do the project too and I'm getting the same error. Did you every manage to sort it out?
Thanks,
Thomas

cloudrac3r Jan 13, 2017 21:49:52 UTC

First, make sure that your produce ID is in fact 0x1008. Mine was actually 0x1009 and I had to update the relevant parts of the code.
Also, I couldn't make the udev rule work either. Instead I just manually loaded the module with:
sudo modprobe usbserial vendor=0x0fcf product=0x1009
which added the /dev/ttyUSB0 device.

Tom Jan 24, 2017 19:46:03 UTC

Hey there,

Thanks for this it saved me quite a lot of time.

I can report that this approach works with the mio link ant+ heart rate
wristband and this anself ant+ usb stick
(https://www.amazon.co.uk/dp....

The anself stick appears to have the same chipset (it has the same vendor and device ids).

Ithought I had to change the netkey (I'm kind of confused by what netkey
means). Digging through the code it seems like the netkey is something
that you set and give out to devices, so presumably it can be an
arbitrary value?

Tom Jan 24, 2017 19:54:09 UTC

Another thing I notices was the python-ant was not only accessing /dev/ttyUSB0, it was accessing a second device under /dev/bus/usb/...

this device had the same major number, but a different minor number (I had to strace to work this out)

The minor number of /dev/ttyUSB0 was 0, the minor number of /dev/usb/blah seemed to be one less than the device number returned by lsusb.

It may well be that udev fixes this problem (I just blinded ignored the udev rules to start with and used chmod).

Craig Mitchell Jan 26, 2017 18:21:28 UTC

Hi. I'm looking to build a project where I will generate Ant+ data (Power, Cadence, speed) is the Movestick Mini a receiver only or are these devices trx/rcv?

Pedro Nogueira Feb 22, 2017 22:42:31 UTC

Does someone achieved to connect multiple heart monitors ?

Riley Mar 08, 2017 03:55:40 UTC

3/7/2017 Fantastic work! Worked right away with a really old raspberry pi with RASPBIAN JESSIE WITH PIXEL, the movestick mini, broadcasting my heart rate from my Garmin Vivoactive HR. I will edit the python script a bit and try it with power meter on a spin bike tomorrow, and eventually multiple spin bikes.

Anthony Jackson Jul 06, 2017 10:16:13 UTC

hey did you manage to get the power meter done? be interesting.

Riley Jul 06, 2017 12:38:55 UTC

I did not, my company purchased computers for the spin bikes. I just got to the point where I could read in data from one spin bike at a time. I think it's an achievable goal tho!

Anthony Jackson Jul 06, 2017 13:08:59 UTC

no worries, I was thinking of just connecting to one also. Do Power meters send across a calculated figure or am I going to have to use a formula using a force, speed etc..... Ive not yet connected my pi to PM,

Riley Jul 06, 2017 13:12:33 UTC

IIRC they send out a filtered watts measurement in hex. No equations needed!

Anthony Jackson Jul 06, 2017 13:13:54 UTC

nice, very interesting then. Thank you. Have a good day.

Tim Bisson Jan 09, 2018 04:54:30 UTC

I know this is a pretty old thread, but it's been very helpful to me and wanted to share my findings. If you use my fork
of python-ant ( https://github.com/bissont/... ), there is a demo for power ant+ devices at demos/ant.core/12-power.py that prints power and cadence (no need for the garmin_ant_demo.py) for ant+ device sending "Standard Power-Only Main Data Page (0x10) . The device I tested against was a tacx bushido smart trainer.

Note, my fork is a fork from David Hari, who added support to read ant+ power pages.

Phill Price Jan 16, 2019 14:58:25 UTC

So steps I've taken are

Add Movestick as per main article
Install git and python-setuptools and python-pip
clone this repo
run setup.py install
pip install enum34 run
python 12-power.py
and I get this error


Using log file: 2019-01-16T14:49:48.192484.ant

Traceback (most recent call last):
File "12-power.py", line 17, in <module>
antnode.start()
File "build/bdist.linux-armv6l/egg/ant/core/node.py", line 209, in start
File "build/bdist.linux-armv6l/egg/ant/core/event.py", line 173, in start
File "build/bdist.linux-armv6l/egg/ant/core/driver.py", line 53, in open
File "build/bdist.linux-armv6l/egg/ant/core/driver.py", line 189, in _open
ant.core.exceptions.DriverError: Could not open device (not found)

The HRM demo from the main repo in the article works fine, I'm interested in Power

Théo Dec 03, 2017 21:15:06 UTC

12/3/2017 Hi, I have some problems with the project. When I'm running "python garmin_ant_demo.py" I get this error message, can you help me ? https://uploads.disquscdn.c...

Bernard Sauterel Dec 05, 2017 09:08:13 UTC

From https://disqus.com/home/dis... :

You have to change the line 188 in ant/core/driver.py to the PID of your Stick.

Théo Dec 05, 2017 20:26:58 UTC

Thank's I change this part! But I get the same error message. I think I have a problem with the /dev/ttyUSB0 File...

Bernard Sauterel Dec 06, 2017 11:08:32 UTC

The udev rules file should also be with the correct PID

Théo Dec 06, 2017 21:05:33 UTC

Yes, but it already change too. So I change python-ant and use this one : https://github.com/Tigge/op...
Where ANTUSB2 Stick (0fcf:1008: Dynastream Innovations, Inc.) and ANTUSB-m Stick (0fcf:1009: Dynastream Innovations, Inc.) are supported.
I use openant/resources/ant-usb-sticks.rules as udev rules a https://uploads.disquscdn.c... nd I run the example heart_rate_monitor.py : it work !
Thank's for your help!

Bernard Sauterel Dec 07, 2017 08:41:47 UTC

Parfait alors! Cheers!

Mark Mills Jan 30, 2018 00:04:07 UTC

Well done! I had no issues getting this to work with Garmin (Dynastream Innovations) ANT+ usb stick and Wahoo TickrX strap. I'm planning to integrate other sensed data available on ANT+ profiles (running pace, cycling cadence/rpm/power) and correlate to HR and display on a line chart. I'll share what I put together to give back for the head start you and Tom Wardill have provided.

Marc Alban Mar 25, 2018 01:49:20 UTC

The issue with the script stalling at `starting node` can probably be resolved with the following before calling _start_antnode to reset the USB device:

```
import fcntl
fd = os.open(self.serial, os.O_WRONLY)
if fd < 0: sys.exit(1)
USBDEVFS_RESET = ord('U') << (4*2) | 20
fcntl.ioctl(fd, USBDEVFS_RESET, 0)
os.close(fd)
```

See: https://askubuntu.com/a/943053

j_simon Aug 25, 2018 19:56:43 UTC

Nice blog! A question: I am doing a similar project for research currently, and I would also need the HRV. Now I might not get the HRV but according to the ANT+ standard I read it should give me the ms timing till the last heartbeat, which is enough to calculate the HRV for now for me. The only thing, while I did find in the standard that it somehow should have that inside, I did not fine where in the message that info should be. Does anyone of you by any chance know that? Could you help me with that? Best, Jörg