Show us your zwift setup!

Tecnhogym myrun
Apple 4ktv
50” 4K tv
Cable device to transmit HR
Big fan!

True CS800
Apple TV
Replaced True CS800 upper console with Arduino Mega controller. An ESP-32 runs BLE Source GATT sending speed and grade data to Zwift. The shield on top of the Mega is a custom PCB with MAX3232 and 3.3 to 5V line-conversion chips in-place.
The Nextion programmable touch screen (under the monitor) is controlled using serial protocol from the Mega
I have programmed Grade vs Distance for all Watopia runs and most speed (for the 13.1 training series of workouts) as well!
The treadmill adjusts incline automatically (based on internal maps, not, sadly, from Zwift) as % grade changes during run. Sorry about the picture. My shoe was untied.
Future plans include variable fan speeds, Neopixel strips on each side of the treadmill, (Training zones?
Terrain? Disco??) and a video based stride analysis using Pixy2 cameras.



3 Likes

Nice setup.

Thanks— treadmill design has remained unchanged for so long.

I think there is a lot of untapped potential

Chris, I know that Zwift send grade information on ANT+ FE-c for biking, can you use that to get the incline? I don’t know if the bluetooth protocol does the same.

That’s a really really good thought. Let me do some digging. The BLE protocols are (almost unbelievably) transparent, and well documented. I imagine I would configure the ESP32 to spoof a trainer, start a ride and record grade at set intervals.
THANK YOU

:joy: :scream:

I added 2 strips of 144 AdaFruit Neopixels to the treadmill and timed them to flash at my current powerZone Color. E.G. at 103% 10K pace, they blink orange. At 75% 10K pace, they blink blue. The cadence is adjustable, but for me, I’m shooting for 175-180 per minute.
I am doing this because I realize that, when I’m tired, I over-stride and when I over-stride, I run goofy and when I run goofy, I hurt myself. Especially as I get stronger and faster.

Here’s the video on youtube

This will either give me seizures or be an effective training tool.

Something else (that probably works much better for cadence control) is the metronome by google. The tick meshes well with the thud of my shoe, and is adjustable to any cadence you choose.

1 Like

Some pretty cool updates… I incorporated an adjustable metronome to maintain pace. Three Hz (180 BPM) pulsed white noise seems to work best, closely approximating he sound of a second runner.
I also added a VL53LOX laser rangefinder that adjusts treadmill speed based on runner position. When runner is closer than 220mm to front, treadmill accelerates at 0.1 MPH per second. When runner is farther than 550mm, treadmill decelerates.
With these, I can now enjoy a hand-free, grade perfect Zwift run along any course. Without touching the treadmill. Now there are no more excuses not to use the treadmill. I guess I better actually train…
Here’s a picture showing the LIDAR, the pacing speaker, the Nextion touch display and an iPad stand I cobbled together. The components are supported using MakerBeam extruded segments that are bolted to the frame of the treadmill.

2 Likes

1 Like

My iPad looks so small next to the previous posters big screens :slightly_frowning_face:

Your treadmill is MIGHTY!!

More Updates to the treadmill… I added an interval page to the control system. (See picture). This allows me to create some pretty amazing intervals. I can choose speed, distance, METS or time as well as nested repeats. Each interval has a starting and ending grade. In the case of a METs interval, the user chooses how much effort (in mets), and the treadmill alters speed to maintain the same degree of perceived effort. Therefore, an interval can start at negative 2 incline and proceed to 15 percent while adjusting speed 10x per second to maintain METS. Now I just gotta get in shape…

[IMG_4436|690x413(upload://g6s9edsnHquk1oQR9d2uaTibVTK.jpeg)

1 Like

@Chris_Hanger Your setup look awesome!

Wow! I never thought of hacking my treadmill to do this! I’m now officially inspired!

Hi. Is that a Woodway treadmill and Bluetooth capable? Thanks, Ben

It is. It’s a Woodway 4front with the Personal Trainer Console. Works great with Zwift over bluetooth. Zwift recognizes it as a power source. And get’s both speed and incline data from it (but of course does not control either). As a bonus, I noticed that if you have your heart rate monitor paired with the Woodway, then zwift will get your hear rate from the Woodway too. I don’t have an Apple TV, but would imagine that this would be great with the Apple TV’s small number of Bluetooth ports.

Per

Hi Chris,
I can see how you can do the Bluetooth part (thanks to your YouTube info) but the replacement of the console is very clever. Did you use a logic analyzer to work out the serial, if so any recommendations? Did you use the Mega for the extra serial ports and the extra I/O? Your donor treadmill looks a lot more expensive than mine, but saying that the construction of mine looks very good, nice wide deck etc and most seem to have similar basic comms connections to the head unit. I think treadmill conversions are the way to go.

Hey Nick!
What I did… may very-well apply to different TRUE treadmills, and, potentially, different brands, as long as they have a similar motor controller. To reverse engineer the communication from the 20-pin(+) header located on the motor controller board (I’m 1300 miles away and can’t see it right now in my brain…), I first determined which of the wires were ground. Next, I ran the other wires (one-by-one) through an oscilloscope. Strangely, two wires were always strobing between 0 and 12 volts. AHA! Looked like RR-232. I measured the pulses-width of these strobing wires and and… it was about 104 microseconds. A-HA-- looks like 9600 baud!! Becoming very excited, I determined parity (none) and start-stop bits (none). The last step was to put an Arduino Uno D-3 in between the motor controller and the head-unit (display unit) and buffer / write-out all communication, before passing it along. This buffer-snoop worked very well. N.B. The Arduino will explode if you try to put 12 Volts into it’s puny digital input So I used a MAX-2232 chip to up/down regulate the 5V (Arduino) to 12V (treadmill).
Also N.B., the motor controller requires that keep-alive message be sent every 250 mSec. Any interruption to this causes the lower motor controller to shut-down requiring an wall-plug-unplug restart. Actually, it’s a pretty good fail safe.
The last step was to figure what gets passed up and down whenever a button is pressed. That part was pretty logical and pretty fun. The only difficult thing was determining the last byte’s CRC hash code. I’m happy to pass that part along.
I use a lot of serial communication. Some are SoftwareSerial.h 's
Ports used by the Arduino MEGA:
PORT
1 - To/From PC for programming
2 - To/From treadmill.
3 - To ESP-32 for Bluetooth Speed/Incline/HR/Odometer/Power/etc. GATT Service 0x1826
4 - To ESP-32 for Web-Server capability. It’s a local web-server serving up treadmill-controlling web-pages!
5 - To Nextion touch display Nextion Website

I also used I2C for motion (thump/cadence and lidar). This is buggy-- line noise over I2C can hang the mega irrevocably!

The donor treadmill is a TRUE CS-850-- a very well built beast of steel with a 5HP AC motor. Luckily, the motor controller does not allow rapid speed or grade shifts,(otherwise I would be dead).
Here’s the c++ Code for sendCommandCRC (calculates the CRC-checker byte) and setSpeed

void Treadmill::sendCommandCRC (char *szCommand,byte *command,byte s)
{
byte c2[s+1];
memcpy(c2, command, s);
byte crc = doCRC1 (command,s);
c2[s] = crc;
sendCommand(szCommand,c2,sizeof(c2)); //just prints the bytes to a serial port. szCommand is for debugging, it gets written to the computer serial port

}
void Treadmill::setSpeed (float fSpeed)
{
fSpeed = constrain (fSpeed,0,12); //12 MPH is my max
fTargetSpeed = fSpeed; //in MPH
fTargetSpeedK = fSpeed * 1.60934; // in KPH

static word lastMul = 0;

///used to be 0xb0c / 9.0
word mul = int(fSpeed * convMPH + yInt);
if (lastMul == mul) return; //no need to set speed to same speed if already done…
lastMul = mul;

if (fSpeed < 0.25) mul = 0; //no slow—>stop

byte command = {0x00,0xff,0xff,0x2f,0x02,((mul >> 8) & 0xff),mul & 0xff};
sendCommandCRC(“Speed1”,command,sizeof(command));

}
Good luck.

Can you tell me which music stand that is? Looking for something similar for my setup so I can get around the wahoo kicker climb.

Thank you.