Monthly Archives: March 2013

Power supply

First up, would just like to say thanks to Ray from www.dcrainmaker.com for the mention in his recent post. Certainly helps keep the motivation up to know people are keeping half an eye on the build.

As I touched on last week, I think the time has come to start progressing the hardware design – away from the current mess of wires on my desk towards something a bit more practical.

So, is probably a good moment to recap on what I’m thinking it will look like. I’m envisaging replacing the handlebar resistance lever with a smallish box (a bit bigger than a guitar effects pedal) that can sit on the floor. This will have the resistance cable coming in through a barrel adjuster, a USB port for PC connection, and a power input jack for a mains adapter. There will also be a handlebar mounted controller with a few buttons for resistance control, lap marking, etc.

Power Supply

For the initial versions of the prototype, I’ve been powering the servo motor directly from an adjustable bench power supply, and the microcontroller through whatever development board I’ve been using. Moving forwards, everything will be powered from a dedicated supply.

Assuming that I keep running the servo at 6V and the micro at 5V, this means two separate voltage rails. The current draw for the micro is inconsequential in this context, and can be easily achieved with a low dropout linear regulator on the 6V supply. However the servo can draw a reasonable amount of current, which requires some more careful thought around the design.

Possibly the easiest (and most short sighted) option would be to require a regulated 6V DC supply, and use this for the motor directly. However, imagining for a moment that someone other than myself is going to build one of these some day, it doesn’t make much sense to shave maybe £3 off the bill of materials by skimping here – only to require a fairly uncommon power supply which is likely to cost five times that.

So, I think it’s probably a good design goal to be as inclusive as possible on the power supply, in the hope that there will be something already lying around that fits the bill (am sure I’m not the only person with a collection of random old power bricks).

The next simplest option would be a linear regulator, typically requiring just the regulator itself, a couple of filter capacitors, and a couple of resistors to set the output voltage (if adjustable).

lm317t

But the downside to linear regulators is heat dissipation, as the voltage dropped across the regulator just ends up as waste heat. I know from monitoring the current draw on my existing servo setup, that it ranges from a few 10’s of milliamps at minimum load, up to around 700mA at maximum trainer resistance. From a regulated 12V supply, I’d need to drop 6V across the regulator, which at 700mA current, means just over 4 watts of waste heat.

A TO-220 package with no heatsink will have an approximate junction to ambient thermal resistance of around 60 degrees C / watt. Attempting to dissipate the full 4W would theoretically increase the temperature of the regulator by 240 degrees, except of course it would overheat and shut down long before this point. I could just add a suitable heatsink (this particular one should keep things under 15 deg C/W). But, even then, once everything is inside an enclosure ventilation and airflow would become an issue.

Once again, I think this option is just too restrictive on the power supply choice. A 9V adapter would be ideal, 12V may just about be manageable, but a typical laptop adaptor from my spares box is 18V, which is just asking for problems.

I think the correct solution would be to use a switching regulator.

lt1074

Switching regulators require additional supporting components, and are somewhat more complex to design for, but can be far more efficient across a  far wider input voltage range. I’m considering the Infineon IFX91041EJV which features an adjustable output voltage, output current up to 1.8A, and a supply voltage range up to 45V.

Breadboarding

Not having a suitable switching regulator to hand, I put together a simple test circuit using an LM317 linear regulator on a solderless breadboard. I didn’t have a TO-220 heatsink either, so I’ve been measuring the temperature directly from the tab on the regulator. During a typical workout for me, the regulator reaches 30-40 degrees C above ambient when running from a 12V supply. Of course this relies on me being puny and not using the full resistance of the trainer ;)

stripboard

So, not an ideal solution, but I think it’s acceptable while I work on the PCB design for a switching regulator. I’ll build this version up a bit more permanently on stripboard, with a heatsink added for an extra safety margin.

Advertisements

Adding trim support

In an effort to more accurately track the target load, I’ve added some closed-loop feedback to the resistance setting code. This is just simple linear control for now, but appears to work well enough (it could be enhanced with a more sophisticated PID algorithm, but doesn’t appear to be necessary at this stage).

If the average power is greater than the target load, then the resistance is gradually decreased until they are balanced, and the opposite occurs if the average power is lower than the target load.

Tuning this behaviour consists of adjusting the responsiveness of the average power calculation, the threshold difference between power & load which triggers an adjustment, and the interval between subsequent resistance adjustments. This is mostly a matter of feel, but it’s fairly obvious when the adjustments are being made too aggressively, as the resistance will noticeably oscillate around the correct setting.

Here’s a screenshot from a new ergo session with two 20min intervals, and I’m pretty happy with the results. Seems to be doing a good job of tracking the target power, tested across a deliberately wide range of speeds in the second interval.

ergo4

Next post

While it feels like I’m making good progress on the coding, this prototype is still dependent on my bench power supply, and using an off the shelf development board hooked up to the motor with jumper wires. Would be nice to get the bike out of the house and back into the garage. So next task is to start considering the physical build, with a view to making it more robust & portable.

USB migration

My original prototypes were developed on an Atmel ATmega168, with the PC comms going via a USB-Serial converter. This week I’ve been migrating to a microcontroller with native USB support, the Atmel ATmega32U4. For this first round of USB development, I’m using an Adafruit breakout board.

adafruit_atmega32u4

I’ve chosen to use the CDC-ADM USB device class, which makes the device appear as a virtual serial port. Strictly speaking this class is meant for USB modems, but is a very common choice for embedded projects, as it’s supported out of the box on multiple OS’s.

Note that Windows will require an INF file with matching VID/PID to load the USB serial driver, while Linux may need some udev rules to set permissions, and to prevent ModemManager probing the ports when they appear (this will get annoying quite quickly when the bootloader times out before you can get access to the port).

USB Library

There’s a handful of choices for a USB library to use with the 8-bit AVR micro’s. I suspect it’s fair to say the most popular library for open source projects is the MIT licensed LUFA library by Dean Camera.

Having said that, my initial implementation used the usb_serial demo routines from the PJRC teensy board demo (simply because they were lightweight, with only a couple of files to add to the project to get up & running). This first iteration used the virtual serial port for the comms with Golden Cheetah, and retained the onboard serial for debug messages.

However, the LUFA library supports multiple USB endpoints, which prompted me to adopt it for further development. This has allowed me to present two virtual serial ports over the USB connection, using the first for the GC communication, and the second for debug data.

It is a bit more of a pain to integrate the LUFA library into an Eclipse managed build, as there are a number of symbols and options that need to be migrated from the library makefiles before it will build (it’s also quite a large library, with many features, and supporting multiple platforms). But, once all set up & building correctly, it’s very easy to get started with the supplied demo’s and examples.

Next post

Next week, I’ll be adding support for automatically trimming the resistance setting based on the real-time power data. With luck this will overcome any deficiencies in the power/speed/resistance map, and allow closer tracking of the target load.

Calibration calculations – part 2

Apologies for the delay in posting this update, was away for a few days in Norway. An awesome place to visit – but pricey (not helped by the grim GBP exchange rate).

Calibration from PowerTap data

f(x) = a*x*x + b*x + c

Multiple Data Fitting Results
level_1     48.37   a:0.031647 b:3.0117 c:-6.2383
level_12    51.19   a:0.032029 b:3.3858 c:-5.8462
level_23    42.64   a:0.042916 b:4.0801 c:-14.053
level_34    44.03   a:0.052877 b:5.368  c:-19.749
level_45    34.98   a:0.08673  b:6.3456 c:-14.823
level_56    30.46   a:0.0332   b:11.926 c:-53.106
level_67    33.22   a:0.17617  b:9.3606 c:-30.054
level_78    37.14   a:0.18789  b:11.523 c:-36.988
level_89    22.27   a:0.24039  b:13.578 c:-42.477
level_100    21.4   a:0.1618   b:16.801 c:-59.99

To get more accurate power data, I collected a couple of hours of data, riding at 10 different resistance levels to match the 1-10 standard resistance lever positions. This data was then fed into the xcrvfit curve fitting software to produce the above quadratic equations for power against speed at each resistance level. (These seem to be a better fit than the linear equations derived from the tacx graphs).

curve_fitting

To populate the lookup table, I also wanted to plot power against resistance at steady speeds. In order to get this, I filtered the original data by speed in a spreadsheet, and performed another curve fitting against these new data series. I’m not entirely happy with the outcome from this 2nd curve fitting (more details below), so I may perform this step again with some additional ride data.

curve_fitting2

Lookup table

Using the data collected above, I was able to calculate the resistance levels required to populate a 12×12 lookup table of speed vs power points.

The actual values in the lookup table have been trivially encoded (by adding 50 to the original 1-100 values). This allows the use of estimated values outside of this range to maintain the slope at the limits of the resistance adjustment, while remaining within a uint8_t datatype.

uint8_t lookup_table_1d[POWER_ROWS * SPEED_COLS] = {
/*   0,     5,  10,  15,  20,  25,  30,  35,  40,  45,  50,  55,  60,*/
/*  25,*/  51,  45,  40,  20,  25,  20,  20,  35,  40,  40,  49,  51,
/*  50,*/ 130,  91,  65,  20,  25,  20,  20,  35,  40,  40,  49,  51,
/*  75,*/ 170, 111,  83,  65,  25,  20,  20,  35,  40,  40,  49,  51,
/* 100,*/ 170, 130,  95,  78,  63,  20,  20,  35,  40,  40,  49,  51,
/* 150,*/ 170, 180, 114,  94,  83,  75,  54,  35,  40,  40,  49,  51,
/* 200,*/ 170, 180, 135, 107,  95,  85,  76,  70,  61,  40,  49,  51,
/* 250,*/ 170, 180, 165, 120, 105,  94,  86,  80,  74,  65,  49,  51,
/* 300,*/ 170, 180, 165, 133, 114, 101,  93,  87,  81,  73,  64,  57,
/* 350,*/ 170, 180, 165, 152, 123, 108,  99,  93,  87,  80,  76,  64,
/* 400,*/ 170, 180, 165, 152, 132, 115, 104,  98,  91,  85,  80,  76,
/* 450,*/ 170, 180, 165, 152, 142, 123, 108, 103,  95,  89,  85,  80,
/* 500,*/ 170, 180, 165, 152, 155, 131, 112, 108,  99,  93,  89,  85
};

Knowing the current speed and power, we can then index into this table to find the closest resistance value.

Interpolation

However using just the values at the 12×12 speed/power intersections would be very coarse, so we’ll interpolate between the surrounding four table points to get a more accurate value.

There will doubtless be much better explanations of bilinear interpolation out there on the internet, so I won’t try here, but basically it’s interpolating twice along one axis, and then once along the other axis using the intermediate values from the first step.

//      x1     x     x2
//       |     |      |
// y1---z11----------z21---
//       |     |      |
// y  ---|-----z------|----
//       |     |      |
// y2---z12----------z22---
//       |     |      |

Test ride

Here’s a screenshot from a new ergo session using the lookup table. It’s doing a reasonable job of tracking the target load, but still not as close as I’d like it to be.

ergo3

As mentioned above, I’m not very confident in the output from the 2nd curve fitting, so repeating this step with additional data may help. Alternatively, I suspect it may be just as quick to set a target power using the manual ergo mode of GC, and then tweak the resistance levels as necessary for each speed point in the table. That said, it’s still a lot of faffing around trying to get it spot on, so may be worth trying to trim the resistance based on real-time power data first.

Next post

I’ve had my fill of calibration for a while, so next I’ll be porting the microcontroller code to a USB part.