Using Zwift With Nearly Any Fitness Device

Introduction: Using Zwift With Nearly Any Fitness Device

About: I am always young, because i feel so!

On Zwift the best results are with a Power Meter.

But what when you have no Bicycle with Power Meter, or no High Expensive Standalone Trainer?

With this Instructable you are able to Running / Driving on Zwift with virtual Data from a Power Table.

The most cheap Trainer have this table in the manual. If you dont have the manual anymore, google can help you to find it. Just search with "manual" + your Training device. Without this table you cant use my Instructable.

See the example:

Step 1: What You Need

An Ergometer or Elliptical Trainer works good. If you have a rowing device with flywheel, then it should work, too.

2x ANT+ Stick *I use Garmin and a noName Ebay Link

1x Raspberry PI 2 or 3 All in package

Some 4.7K Resistors Resistors

Some 50K Resistors Resistors

1x Magnet (I use a cube neodym)

1x reed Switch (fast) KSK 1A87

1x connector/ terminal strip (4 ports are good) Terminal Strip

Some Wires / Dupont connectors Cableset

A piece of PCB *optional PCB

A PC or Laptop / MAC for Zwift Software To Zwift

For your Fitness Device you have 2 Options:

Open the Display an place a cable parallel to the switches for the level + -

Or place a foil switch over your switches.

I use the 1 Option. The second works too.

Be sure what you do! If you are not familiar with wiring and soldering then someone should help you!

Step 2: Hard and Soft Lets Do Some Nerd Stuff

Place the Terminal strip with power glue on the chassis of the fitness device.

Carefully put the reed switch in your terminal strip (It is Glass) From the terminal let 2 wires out 1-2 meter are fine. On the moving round plate(flywheel) place the magnet with power glue. (I use a neodym magnet). Check that the reed contact closes when the magnet pass the reed switch (You hear a click).

Install for the Raspberry PI a actuality debian jessie: Full Image

Raspberry PI Download

Do not connect any wires to your Raspberry PI yet.

Put 1 ANT+ Stick in the Raspberry PI and boot your PI

Step 3: The Software Part

install some stuff:

sudo apt-get update

sudo apt-get upgrade

you do grab a coffee * :)

sudo apt-get install mc (I use mc often)

sudo apt-get install git

you will clone this rep:

git clone

install some more stuff :)

sudo apt install libudev-dev

sudo apt-get install nodejs npm

sudo npm install -g typings

sudo npm install -g typescript

cd ant-cycling-power

sudo typings install

sudo npm install

If you fail put a sudo before the installer command. If you have issues follow the instructions on:

test it with "sudo node test.js" You need to see an output! If not you have an issue.

I try to help, ask here.

When you seeing an output with power and cadence go on:

if you are not there:

cd ant-cycling-power

sudo npm install rpi-gpio

clone my git in your ant-cycling-power:

git clone

copy SpeedMeter.js and test.js

in ant-cycling-power

My table have 16 Level and example for 24 Levels is also included.

If the values are not yours open the SpeedMeter.js and correct the table for your needs.

Many Thanks for helping me with the code goes to tsseh from

Shutdown your PI and remove the power supply.

Step 4: The Hard Hardwarepart

Wire up (Do not make a Chaos like me in the 1 Picture!) :) :

Connect to GPIO 20(PIN 38) and 21(PIN 40) the Switch lines the reed goes to GPIO 4 (PIN 7)

How i did connect the switches:

From (Pin1 3.3V) --> 4.7K Resistor --> to Level Switch Training Device.

From Training Device Level+ output Wire --> to GPIO20 from GPIO20 --> 50K Resistor --> Ground

From Training Device Level- output Wire --> to GPIO21 from GPIO21 --> 50K Resistor --> Ground

You need to put a voltage divider, if you use the open Display Version, because the output voltage on my device are 5.5Volt.

My Voltage divider from GND to a 10k Resistor, from the 10k Resistor to a (10k and 4,7k parallel) Resistors.

Lazy Version:

The ReedSwitch: GPIO4 --> to reed Switch, from reed Switch to Ground. Check twice! All correct placed? No short circuit?


Step 5: Lets Test It. and Do Not Doubt Yourself...

Turn on your PC and install Zwift with the second ANT+ Stick. (may be you need to install driver for the Stick)

Check if the ANT+ Stick working on PC see the ANT+ icon upper left in Zwift. Working?

OK start your Rapsberry PI and login

then go to directoy:

cd /ant-cycling-power

sudo node test.js

your output should be Power 0w Cadence 0rpm

let the console running and start pedaling / walking The power and rpm should have values now.

OK Go to Zwift and pair your new power meter and cadence You should see them now in Zwift pair Window!

Make sure that PC Windows ANT+ device and Raspberry PI ANT+ Device close together, 1-2 Meter i wrote above :)

Congrats you have a cheap accurate cadence and power meter to ride in Zwift what is also usable for Intervall Training.

do not cheating! Cheating makes you small and you lie to yourself.

Ride on!

Step 6: Troubleshooting...

When you plug in a USB-m ANT+ stick, the default permissions are for only root to get access to it:

$ node test.js /home/pi/ant-plus/node_modules/usb/usb.js:33 this.__open() ^

Error: LIBUSB_ERROR_ACCESS at Error (native) at (/home/pi/ant-plus/node_modules/usb/usb.js:33:7)

We can fix this by changing udev settings, for Garmin v1 and v2 sticks:

$ cat /etc/udev/rules.d/51-garmin-usb.rules SUBSYSTEM=="usb", ATTRS{idVendor}=="0fcf", ATTRS{idProduct}=="1009", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1" SUBSYSTEM=="usb", ATTRS{idVendor}=="0fcf", ATTRS{idProduct}=="1008", MODE="0666", ENV{ID_MM_DEVICE_IGNORE}="1"

And reload udev rules: $ sudo udevadm control --reload-rules

In power-meter.js change:

stick.write(Ant.Messages.setPeriod(channel, 8182)); to

stick.write(Ant.Messages.setPeriod(channel, 4096)); // (Hz

This should reduce the drop outs to 1%

if you have still problems with radio, make sure that the both stick see each other to stable the signal.

If you have power freezes, because you have NaN values in console logout update the test.js to the latest version

Good Luck!

1 Person Made This Project!


  • Build a Tool Contest

    Build a Tool Contest
  • Backyard Contest

    Backyard Contest
  • First Time Author Contest

    First Time Author Contest



2 years ago

Really interesting project. I'm going to try to make it work with an Omega2 board I have lying around (I'll share the code if I get it to work).

However, I'm a complete electronics newbie, and don't really understand how to connect the level switches to my GPIOs (I want to try the open display version). Could you perhaps draw a schematic of how you connected everything? I'll probably need different resistor values for the voltage divider, as the Omega2 can only handle up to 3.3V on the inputs.

By the way, I also have a Christopeit machine, just like you (different model though). I think the machine already contains a reed switch for RPM measurement, and I think I found the two wires that go in and out of the reed switch. Would you think it is possible to connect this reed switch to GPIO, instead of adding another reed switch to the machine? If so, any tips for how to connect that?

Many thanks in advance!


Reply 2 years ago

I got a bit further, managed to tap into the reed switch circuit of my Christopeit EM3 so didn't need to add one myself. With a bit of experimenting I got the resistor values to a level that the home trainer keeps working (reading RPM, responding to level+/- switch) and my Omega2 is able to read the RPM correctly and detect level switch +/-.

Attached how I connected it all (newbie electronics drawing, but I hope you get the idea). It works, but I hope someone can provide feedback as if this is safe and good practice. Note that my home trainer operates at 4-5V so I added voltage dividers. The GPIOs are "pulled up" now by the home trainer voltage, not sure if that's good practice.

I was also thinking I might be able to simply add the option to control the level switches from the Omega, by connecting a GPIO output to a transistor base the connects the level+/- to ground. Any idea/suggestions if that would work?

Hope someone more advanced can provide some feedback. I'm still working on it, but will provide my code / schematics once it's finished.

Omega2 power meter.png

Question 4 years ago

I have problems with the code and libraries. I hope you can guide me to the source of the issue, please.

I'm using a CYCPLUS U1 usb ant+ stick on a Raspberry Pi 3, and latest Raspbian version and updates.

Installed node.js 8.1.1 with these lines:
sudo su -
apt-get remove nodered -y
apt-get remove nodejs nodejs-legacy -y
apt-get remove npm -y # if you installed npm
curl -sL | sudo bash -
apt-get install nodejs -y
node -v
npm -v

Then I copied the code to my raspberry pi 3:
1) Cloned ant-cycling-power
2) Copied SpeedMeter.js into that folder.
3) npm install rpi-gpio
4) npm link rpi-gpio
5) npm install ant-plus
6) npm link ant-plus
7) Finally, I run sudo node test.js

My errors are this:

pi@raspberrypi:~/ant-cycling-power $ sudo node test.js
Max channels: 8
stick.write(Ant.Messages.assignChannel(channel, 'transmit'));

TypeError: Cannot read property 'assignChannel' of undefined
at GarminStick2.<anonymous> (/home/pi/ant-cycling-power/power-meter.js:15:30)
at emitOne (events.js:116:13)
at GarminStick2.emit (events.js:211:7)
at (/home/pi/.nvm/versions/node/v8.11.1/lib/node_modules/ant-plus/build/ant.js:527:18)
at InEndpoint.<anonymous> (/home/pi/.nvm/versions/node/v8.11.1/lib/node_modules/ant-plus/build/ant.js:374:23)
at emitOne (events.js:116:13)
at InEndpoint.emit (events.js:211:7)
at Transfer.transferDone (/home/pi/.nvm/versions/node/v8.11.1/lib/node_modules/ant-plus/node_modules/usb/usb.js:328:9)

I tried to investigate, but I cannot figure this out. :-(


Answer 4 years ago

Hi, I solved the problem. This error was because of a bug in ant-plus.js missing this line in the module.exports = { } block:

Messages: Ant.Messages,

There were other specific setup stuff I had to do differently than this document, so a little later I will send you the suggested corrections.


Reply 2 years ago

Hi, I got the same trouble, how did you fix it ? Thank you


Answer 4 years ago

I send you an email


2 years ago

The links to the components are a bit outdated.
Any idea where I can buy the correct resistors?


2 years ago

Any way to include a "controllable trainer"? Creating a magnet device to break the wheel


Tip 2 years ago

Hi. A person said he was goin to make this easier to understand and I am wondering if he ever did this? Thanks


Question 3 years ago on Step 2

Hello All,

i'm trying to put this project in place too
Using a raspberry 3b+ with Debian Raspian installed.

Following the instructions i get in trouble

When using:
sudo npm install -g typings
i get two warnings:
npm WARN deprecated typings@2.1.1: Typings is deprecated in favor of NPM @types -- see README for more information
npm WARN deprecated popsicle-proxy-agent@3.0.0: Use `agent` option with `popsicle` directly

then using: sudo typings install
and iḿ in big trouble:
typings WARN enoent Path "/root/ant-cycling-power/typings.json" is missing

I have no idea to solve this - can somebody provide me a solution to this missing file?

Thx in Advance


3 years ago

Anyone try this project with nRF51422 board


3 years ago

Hello All,

I am trying to put the project in place, thanks for all the code that's really useful.
I encountered some issue also with the Message object not properly defined but the solution provided in the comments is working.

Now I am facing another issue, I did implement the Lazy version: just connecting the sensor to GPIO 4 and GRD. When lauching the script i get : RPM (xxxxxxx) out of range. I believe it is coming from the speed meter.js as IdxUpper is above 12 but i am not sure what is this valiue suposed to represent.

thanks for your help,


Question 3 years ago on Step 4

Sudo npm Install
Error git Clone Permission denied
Konnte nicht lesen
Does it exists ?


Question 4 years ago

Hi, Andreas. Thanks. I made this project recently (thanks to you), however I struggled with understanding your English and grammar. I request your permission to re-write the instructions, diagrams, and code, or your permission for me to publish a new version this document while giving credit to you?
I found there are some key things in this document that should be a lot more clear and specific. Fortunately I was able to overcome obstacles through intuition and some experience, but other people might not have success without clarification and better words and pictures. I also modified the code a little. I'm also hoping to add support for automatically changing the level based on the the % grade incline of the road if possible.
Please let me know. Thanks! :-)


Answer 4 years ago

Sure! I appreciate this!

Yes my English grammar is terrible, but i give my best :)

In the past i used 2 relays for shifting up and down. You find it here:

Please share it when ready, i like to test your improvement.


Question 4 years ago

What voltage should I see on a voltmeter after I used the voltage divider circuit? In your case, you say you need it because your Elliptical machine's voltage is 5.5v. So what voltage are you hoping to have by "dividing" it?


Answer 4 years ago

My output of the trainer gives 5.5 V to the gpios, i dont know why. So i have to reduce the voltage below 3.3V to not kill the gpio ports.

When you see under 3.3V you are good to go. If you see 0 is also good :)


Question 4 years ago on Step 3

Hallo Andreas,

ich bekomme folgende Warnmeldung:

typings is deprecated in favor of npm @types (sudo npm install -g typings).

Habe ich mit Rasphian stretch und jessie versucht.

Da ich sehr an deinem Projekt interessiert bin bitte ich um Hilfe.

Was kann ich tun ?

Vielen Dank



4 years ago

Amazing! Have you thought about building a system to control fan speed according to ant + sensors like speed and power? Would be amazing!