Monthly Archives: September 2014

New control software


In recent news, I’ve combined the code from my various test harnesses into a single control process (plus the PRU firmware).

I’d be the first to confess the code is a bit ugly as it stands – it’s clearly several separate programs squished together with some threading and (far too many) globals! However, I’ve plenty of time to re-factor and tidy up the codebase, and it’s functional enough to get me started on the next steps. I’ve also added a rudimentary ncurses console interface for mode selection & feedback.



On the power side, I’m transmitting as an ANT+ power meter, broadcasting the ‘power only’ data page (0x10), which reports instant & accumulated power in watts (as well as optional cadence and L/R power balance values – which I’m ignoring). With a small patch to Golden Cheetah, I’m capturing the per-second data from both the PowerTap and Trainer devices into the training mode .csv files, from where I can export it into a spreadsheet for easy analysis. I’ve also got a small python script to extract all the power messages from the GC antlog.bin files (where all the ANT+ traffic is logged) in case I need a closer look at the original 4hz message data.

The data as graphed below came from a training .csv file, with the trainer firmware using a simple 4 sample (1 second) moving average for the acceleration component of the power figure.



With power tracking pretty well, I’ve also started thinking about speed reporting. ANT+ speed messages are essentially broadcasting the time taken for a single wheel revolution, where they are then converted to speed at the receiving side based on a pre-configured wheel size. The wheel rotations could be sent in either speed or power (wheel torque) messages.

From my trainer perspective, I can calculate the road speed very easily, but have no insight into the actual wheel size. If I were to store my own configuration parameter for wheel size, I could work back and provide the necessary fake wheel speed timestamps. The downside is that any changes to wheel size would need to be manually set in two places instead of one.

Another hiccup is that the power message that includes the wheel rotations is the ‘wheel torque’ data page (as broadcast by a PowerTap). Instead of power in watts, this transmits the data as wheel speed and torque, which is then converted to watts on the receiving side. Again, I could just work back and provide the necessary ‘fake’ torque figures to make it all add up, but is starting to feel like a lot of effort for minimal gain…

I suspect it may be easier to present as a dedicated speed sensor alongside the power sensor. But for the moment, I’ll just park the speed reporting in the ‘things to consider later’ pile. Both bikes that I’m testing with already have ANT+ speed data (coming from either a S&C sensor or PowerTap), so doesn’t actually gain me anything just yet.

ANT+ Trainer Profile

I’ve also been wondering whether the upcoming (and snappily named) ANT+ Fitness Equipment – Control (i.e. Trainer) profile might have a provision for either passing road speed to, or receiving wheel size from, a head unit. Either would help make the above speed situation a bit simpler. Unfortunately (for me), this profile is still in it’s ‘competitive advantage’ phase, where it’s only available to paid-up ANT+ Members, not to freeloading ANT+ Adopters like myself!

On a related note, I’ve been working on the assumption that this new ANT+ profile will be available by the time I’m ready to start adding the variable resistance control back in. However, nothing seems to be moving very fast (on either count) at the moment. I think I also have a plan B, which would be to respond to the control messages used by Wahoo for their Kickr trainer, which should at least allow me to hook up to some 3rd party trainer software platforms for further testing.

Next steps

Next job is to get back into the workshop, and make up some new magnets & mounts for the eddy current brake…


Optical speed sensor

For sensing the trainer speed, I have a choice between using the elapsed time between two events, or counting the frequency of events within a specific time period. For now, I’ve opted for this latter approach.

In order to keep things responsive, I need this time period to be quite short, therefore I also need quite a fast pulse train in order to get a reasonable count in this period. To achieve this, I’ve switched from the hall effect sensor to an optical solution, which can easily generate many more events per revolution.

I’m using a Hamamatsu 5587 photo-reflector in conjunction with a laser printed optical encoder pattern on the flywheel. This is quite an old sensor (possibly even discontinued), but gets good write-ups from the robotics community. For ease of mounting, I’ve soldered everything on one side of some protoboard, and stuck it to the trainer with double sided tape. This provides a nice stable mount, and ideally positions the sensor a couple of mm from the flywheel.


The encoder pattern was created using a postscript generator script, converted to PDF, and then laser printed on standard office paper. This was then stuck onto the inner face of the flywheel using a spray mount adhesive.


I’m using 16 black & 16 white segments, and capturing both rising and falling edges to give me 32 events per revolution. I’m currently sampling speed at 4hz (to match the ANT+ transmission rate) and have tested up to ~70pkh, which equates to ~1,000 events per sample.

From BudgetTrainer to BeagleTrainer

As mentioned in the previous update, until recently I’d been sending a serial data stream to a laptop for processing.

This was primarily due to the curve fitting & floating point maths that I’m using in the spindown calibration process. While this code could likely be replaced in the long term, as it stands now it’s a poor fit for a resource constrained 8-bit micro with no hardware floating point support!

So now I’ve switched development to a BeagleBone Black. This is a small development board capable of running Linux on a 1GHz ARM Cortex A8 processor.


One great thing about the TI Sitara processor on this board is that it includes a pair of Programmable Realtime Units (or PRUs). These run independently of the main processor, with a 200MHz clock speed (5ns per instruction), and are perfect for guaranteed real-time tasks. They are programmed in their own assembly language, but there is also a C compiler (currently in beta) available from TI.

For my purposes, I’ll be using PRU assembly for the timing sensitive hardware interaction (frequency measurement, PWM etc), with the main C code running in Linux userspace on the ARM processor, and using an ANT2 USB stick for the comms.

I’ve already written some initial test code for speed measurement, spindown processing, curve fitting, power calculation, and the ANT+ transmission. The individual pieces are all working separately, now I just need to tie them together under a single control program. Once it’s all been tidied up a bit, I’ll post a link to a new github repo for this code.

When that’s done, I’ll be getting back to some metalwork & preparing new electromagnets for the adjustable resistance control.