After a year of functional safety blogs, this is my last one of the year. It is a Christmas blog if you like. Similar to last Christmas this blog has a somewhat tenuous connection to functional safety but there is a connection. I like to imagine myself as a functional safety expert, including functional safety of software but I haven’t written much software in the last 10 or even 20 years. I wondered how my own software development skills would stack up as I tried to convert my old treadmill into a smart treadmill. This might also give people some ideas for a project over the Christmas, especially if you are unlucky to be in lockdown, so its win win. Ok – lets go back a bit.
In October/November with Ireland back in lockdown (including a 5k travel distance for exercise), over a resurgence of Covid-19 I decided to look at Zwift. Zwift is an online fitness environment common with cyclists but of late offering a running option too. With the Zwift app you can select from a number of routes where you get to run past volcanos and waterfalls, through under water tunnels, over bridges, through jungles and along beach fronts. In the game you have an avatar which you can somewhat customize, and you can see other runners and cyclists’ avatars also. Your avatar speeds up or slows down depending on your treadmill speed. It does make the runs more interesting, but it would be a lot better again if you could actually speak to the other runners. For now, it’s in Beta testing mode and there in no subscription for running on Zwift.
My running this year has been limited due to the Covid restrictions but I have run two virtual marathons (Belfast and Dublin), in both cases limited to roads within 5km of my home. While the weather in Ireland is relatively benign all year round, I’m not overly keen to do an outdoor marathon in December and wondered about a treadmill marathon. I could have bought a runpod for around Euro 40 which is a small device which fits on your shoe and estimates your running speed but I decided to code it up myself on an ESP32 after seeing this blog. The ESP32 is the next incarnation of a popular ESP8266 and features dual core Tensilica processors running at up to 240Mhz, WiFi and dual mode Bluetooth. The development board features an integrated antenna. Bluetooth is the main reason to use the ESP32 vs the ESP8266 because Zwift accepts BLE (Bluetooth low energy signals) from stationary bicycles, fitness watches and run pods. The easiest way to develop on the ESP32 is using a neat little board for around Euro 8 as shown below. I actually had two spare from a previous automation project so the actual cost to me was zero.
Figure 1 - ESP32 development board
One of the nice things about the ESP32 and ESP8266 series is that they can be programmed using the Arduino IDE and you can normally get most of the code you need online and hack it to meet your needs.
I needed to remove one panel from the treadmill to insert an additional reed switch on one end of the main pulley as shown below. I actually had a reed switch from an older broken treadmill, so I put it in parallel to the existing one so that there was no interference with the treadmill functionality. As the pulley turns a magnet fixed to it passes the reed switches once per revolution. The reed switch location can be seen in the picture below.
Figure 3 - Reed switch for measuring speed
As regards a schematic diagram – there is none. The only required external component is the reed switch which I connected directly to pins 2,3 of the ESP86 development board (GPIO 13 and ground) and used the board directly powered by its USB port.
In the picture below the ESP32 is actually mounted on the leg of the treadmill, contained in a yogurt pot and tied to the treadmill leg with a cable tie. This is not the bit I wanted to be judged on from a functional safety point of view – the functional safety judgement is to be on the code only! I had a USB adapter with a 240V lead but there was nowhere convenient to get 240V power when I opened the treadmill, so I connected it to an external USB adapter instead. If there had been somewhere handy I would have put the circuitry inside the treadmill panel. This isn’t as neat but it works until the day I try to roll the treadmill away and don’t remember the USB cable.
The ESP32 sends the treadmill speed to the Zwift App running on my mobile phone and the mobile phone is then screen sharing with a Chromecast on a HDMI port of the TV.
Figure 2 - final setup - please ignore cobwebs and sensor mounted in a plastic cup
My code worked first time, but I decided to actually create a few test cases by generating a PWM signal using the ESP32 PWM function and I was surprised when I started to discoverer bugs. I found several bugs, fixed and forgot them before I decided it might make a good topic for the blog.
The test cases were the obvious ones including the input tied input high, input tied low, float the input, use a fixed number of ms within the normal range and a fixed number of ms outside the range. All very consistent with the fault models from IEC 61508-2 Annex A.
Anyway, the bugs I found and still remembered included
- I was using the millis routine which returns the number of milliseconds since the last received pulse. However, as a deglitcher I was comparing it to 25.0e-3 so I didn’t have a deglitcher (units = ms, so I should have been comparing it to 25). This bug was exposed when I used an input signal corresponding to 60km/h (a very decent running speed!!)
- I was trying to print out an unsigned int as a float in the debug window
- I had a logic error whereby I was comparing present time to the time since the last pulse rather than to the time since the last valid pulse (valid pulses are after deglitching)
- I had an unexpected design issue whereby pulses < 25ms won’t be completely ignored but will actually be reported as 25ms wide
So where did these problems come from
- Reusing code without looking at it too much
- Coding while drinking beer (remember this is a home not a work project)
- I didn’t have a set of requirements but rather just jumped in and started coding
Most of the bugs were in features added to increase robustness and related to edge cases. I guess this is typical for software. You are forced to debug the core functionality, but the edge cases and robustness features are not in your direct line of fire.
However, it was still a good reminder of how even simple code which appears to be working can in fact be full of bugs. It might even be interesting do a software FMEA for this software and see if I could find more bugs. Its always good to have a test bench on which to try out stuff.
The full code is at the bottom of the blog and if anybody finds any more bugs please let me know. Zwift have a 3-point calibration feature built in so that you can calibrate the sensor vs the reported speed of the treadmill, so you don’t have to have the speed spot on.
I tried to expand it to implement a webserver and allow OTA (over the air updates) but I ran out of space on the device. OTA is expensive in terms of memory as you need to have a copy of both your old and new code in memory at once. I believe I can resolve this with memory partitions, but I didn’t have time. Anyway, from a safety point of view adding unnecessary features is not good practice. I also resisted adding a webserver because I couldn’t think of a practical use for it given that the Zwift app ran upload your heart rate (captured by linking my Garmin watch to the Zwift app over BLE) and speed to the Garmin site for review.
At the time I of writing I have now run over 100 miles on the setup and it seems to be working well. My longest run so far is 19 miles. It is certainly a lot more entertaining than looking at a blank wall. Anybody that’s on Zwift please keep an eye out for me.
Note: I had an old TV which I converted to a smart TV using a Google Chromecast. I ran the app on an old but decent Android phone which I then cast to the Chromecast. Cost of the Chromecast around euro 30 but handy for watching YouTube videos while you run if you get tired of Zwift. A fan and a towel are also very important if using Zwift. Running indoors can be sweaty. Lastly, I have one of the very small Alexa devices nearby and can change radio stations or listen to a podcast to make up for not having my normal running buddies with me.
View the code below to convert your treadmill into a smart treadmill.