Weighing in on the Balance Board
Like a lot of people I bought a Wii at some point, I still do have it, but the novelty eventually wore off, and it hasn’t seen much or any use in years.
The Wii did include some nice peripheral devices, one such such device was the Wii Balance Board. This board was included with the lifestyle application/game named WiiFit, which encouraged its users to measure their weight/balance daily to track progress over time. At some point I did do this, but despite their earnest attempts at gamification, the streak didn’t last very long and the stamps in my calendar grew ever so sparse. It certainly didn’t help that doing an actual measurement was a fairly time-consuming procedure constisting of:
- Turning on the television
- Booting the Wii
- Navigating to the Wii Fit application and selecting “Body Test”
- Turning on the balance board
- Measuring and selecting the weight of my outfit
And even though the concept of tracking things over time is definitely the way to go, the time needed to perform the above simply required too much effort to maintain. The whole measurement procedure should have been reduced to two simple steps:
- Turn on the balance board
- Measure
So let’s do that
Technicals
Protocol & pairing
Like the Wiimotes, the hardware is bluetooth based, but unlike the Wiimotes it has historically had a nasty pain point, pairing. Many have struggled to pair with the board, and persist that state, so it doesn’t require a new sync on each power cycle. And that is a problem, as the little red sync button is awkwardly placed under the board in the battery pack, and flipping the board and opening it up to press it really sabotages the whole idea of doing a quick measure.
Some clever hardware hacks have been attempted, such as Greg Nichols’ pencil trick, but the real limitation was that the pin used for pairing was the Bluetooth MAC address bytes reversed, which included character representations not accepted by most Bluetooth stacks. You could also work around it by patching your own bluetooth stack, but that’s a fairly big barrier of entry. Thankfully these issues are now fixed and pairing can be done in the following way using bluetoothctl:
$ bluetoothctl
power on
agent on
# Press red sync button on way
scan on
pair <MAC of the found wii board, use TAB for autocompletion>
connect <MAC of the wii board>
trust <MAC of the wii board>
disconnect <MAC of the wii board>
scan off
exit
Reading the board
The balance board consists internally of four weight scales, this is represented in code as an array of size 4:
+---------------+---------------+
| | |
| abs[2] | abs[3] |
| | |
+---------------|---------------|
| | |
| abs[0] | abs[1] |
| | |
+---------------+---------------+
and by measuring how the weight is distributed, and how it shifts, while you’re standing on the device is how it measures balance and weight.
Using libxwiimote we can read a measurement with:
static int read(struct xwii_iface *iface, void *userdata) {
int ret = xwii_iface_open(iface, XWII_IFACE_BALANCE_BOARD);
if (ret) {
("Failed to open iface");
g_printreturn -1;
}
struct xwii_event event;
while (reading) {
= xwii_iface_poll(iface, &event);
ret if (ret == -EAGAIN) {
continue;
}
// Read data n format
// event.v.abs[n].x;
...
}
}
where event.v.abs
is a vector of integers, each
representing one of the four scales. The values are in kilograms scaled
by two orders of magnitude. So the total weight reading is the sum of
the entire vector:
int weight = 0;
for (int i = 0; i<4; ++i) {
+= event.v.abs[i].x;
weight }
double weight_in_kg = weight / 1e2;
Here’s a little video showing terminal output and weight distribution as a stand on my toes.
Measurement over time
To gather measurements over time I wrote a small measurement program
called weightloop
. Its sole task is to discover when the
balance board is activated, gather a measurement for a few seconds, then
disconnect the balance board and write the measurement to a CSV
file.
This program was deployed on my Home Assistant Raspberry pi, which is in Bluetooth radio distance of the scale.
Now getting a measurement is as simple as:
Visualizing the results
To best see trends I plotted the data in a line chart, using uPlot, and added a moving average:
The page is just a static HTML page which fetches / parses the CSV as a static resource from the same server.
Code
All the code is available on Github.