Wii Balance Board
For an excellent high-level overview of the Wii Balance Board, see the Wikipedia entry.
The Wii Balance Board is the bundled input device with the Wii game Wii Fit. It is a wireless device, using standard Bluetooth technology to communicate with the Wii. It implements the same protocol as the Wiimote for host communications, and exposes most of its functionality via an extension controller. It is recommended this page be read in conjunction with the Wiimote page.
Summary
Enough information is available to be able to get calibrated readings from the four pressure sensors, receive events from the single button, and drive the single LED. There is other information available in the extension controller registers, but with no identified purpose.
Bluetooth Communication
The Wii Balance Board exposes the sames services over the Bluetooth Service Discovery Protocol (SDP) as a Wiimote.
HID Interface
The Wii Balance Board operates similarly to a Wiimote as a HID device, however the friendly name exposed to HID is Nintendo RVL-WBC-01
Specifically, it will generate reports for the various features of a Wiimote, even though the hardware is absent.
Data Reporting
All Data reporting modes of the Wiimote are supported. Since the weight data is in the first 8 bytes, report 0x32 "Core Buttons with 8 Extension bytes" is most appropriate. To also include battery values, report 0x34 "Core Buttons with 19 Extension bytes" is appropriate.
Memory and Registers
EEPROM Memory
Just like with the Wiimote, the Balance Board exposes 0x1700 bytes of EEPROM that can be read and written normally. This data is initially all 0, and is not known to be used by any games.
The top byte is still ignored, so values are mirrored every 0x10000 bytes (for example, 0x010000 through 0x0116FF). Out of bounds reads and writes will still return error code 8.
Control Registers
Access to the extension controller registers is identical to that of the Wiimote, and these are the only registers that are actually used. There is no IR or speaker hardware in the Wii Balance Board, and attempts to read from those will result in error code 7.
Input Features
The Wii Balance Board has only a single physical button, accessible as core button "A", bit 3 of the second byte of button status.
Note that the Wii Balance Board will generate input reports for hardware it does not have, but that a Wiimote does.
Feedback Features
The Wii Balance Board has only a single LED, controlled by the same reports as the Wiimote uses to control the player 1 LED. There is no rumble or speaker feature.
Extension Controllers
The Wii Balance Board appears as a Wiimote with a Balance Board extension controller permanently connected. The Balance Board extension is accessed similarly to a normal extension controller on a Wiimote
Registers / Initialization
The Balance Board extension is initialized similarly to a normal extension controller, however no encryption or decryption needs to be undertaken on data either read from the registers, or streamed through the output reports.
Identification
The last two bytes of the register block identify the connected Extension Controller. A two-byte read of register 0xa400fe will return these bytes. The Extension Controller must have been initialized prior to this (by writing 0x00 to the key register).
Value | Decrypted | Meaning |
0x0402 | 0x2A2C | Wii Balance Board |
Note that the decrypted value is here as a convenience for those dealing with libraries that automatically decrypt this identifier before presenting it to the code that identifies the extension controller. The unencrypted value is more consistent with existing extension controller identifiers.
Extension Controller Documentation
The Wii Balance Board exposes four 16-bit pressure sensors through its extension controller interface, along with the necessary calibration data to allow conversions to mass measurements.
Data Format
The Balance Board reports its information as 11 bytes of data, readable from 0xa40000 to 0xa4000a and streamable using Data Reporting Modes that include Extension bytes (unused bytes that would be streamable (i.e. the first 21) are filled with 0x00). The data is as follows:
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0 | Top Right<15:8> | |||||||
1 | Top Right<7:0> | |||||||
2 | Bottom Right<15:8> | |||||||
3 | Bottom Right<7:0> | |||||||
4 | Top Left<15:8> | |||||||
5 | Top Left<7:0> | |||||||
6 | Bottom Left<15:8> | |||||||
7 | Bottom Left<7:0> | |||||||
8 | Temperature | |||||||
9 | 0 | |||||||
10 | Battery Level |
A battery level ≥ 0x82 is 4 bars, less than 0x82 and ≥ 0x7D is 3 bars, less than 0x7D and ≥ 0x78 is 2 bars, less than 0x78 and ≥ 0x6A is 1 bar, and otherwise is considered empty.
Temperature values less than the reference temperature (see below) indicate colder boards with more stiff sensors (so the same weight would result in a lower reading, or the same reading indicates more weight). A balance board that was left in a refrigerator for an hour reported a temperature of 0xc compared to 0x1a at room temperature (~68° Fareinheit or 20° Celcius) (with a Reference Temperature of 0x19).
Wii Fit compensates for the temperature value with the calculation (.999 * totalWeight * -(.007 * ((boardTemp - refTemp) / 10.0) - 1.0))
, where .999 is actually 0.9990813732147217 (0x3feff87980000000) and .007 is actually 0.007000000216066837 (0x3f7cac0840000000, (double).007f
). This equation simplifies to (.999 * totalWeight * (1.0 - .0007 * (boardTemp - refTemp)))
; in other words, boardTemp being one less than refTemp results in a .07% increase in the total weight, and boardTemp being 14 more than refTemp results in a .98% increase in the total weight.
Calibration Data
Calibration Data for the Balance Board sensors is found unencrypted in the 32 bytes from 0xa40020 to 0xa4003f, as follows:
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0x20 | Unknown (always 0x01) | |||||||
0x21 | Reference Battery Level (always 0x69) | |||||||
0x22 | 0 | |||||||
0x23 | 0 | |||||||
0x24 | Top Right 0kg value<15:8> | |||||||
0x25 | Top Right 0kg value<7:0> | |||||||
0x26 | Bottom Right 0kg value<15:8> | |||||||
0x27 | Bottom Right 0kg value<7:0> | |||||||
0x28 | Top Left 0kg value<15:8> | |||||||
0x29 | Top Left 0kg value<7:0> | |||||||
0x2A | Bottom Left 0kg value<15:8> | |||||||
0x2B | Bottom Left 0kg value<7:0> | |||||||
0x2C | Top Right 17kg value<15:8> | |||||||
0x2D | Top Right 17kg value<7:0> | |||||||
0x2E | Bottom Right 17kg value<15:8> | |||||||
0x2F | Bottom Right 17kg value<7:0> | |||||||
0x30 | Top Left 17kg value<15:8> | |||||||
0x31 | Top Left 17kg value<7:0> | |||||||
0x32 | Bottom Left 17kg value<15:8> | |||||||
0x33 | Bottom Left 17kg value<7:0> | |||||||
0x34 | Top Right 34kg value<15:8> | |||||||
0x35 | Top Right 34kg value<7:0> | |||||||
0x36 | Bottom Right 34kg value<15:8> | |||||||
0x37 | Bottom Right 34kg value<7:0> | |||||||
0x38 | Top Left 34kg value<15:8> | |||||||
0x39 | Top Left 34kg value<7:0> | |||||||
0x3A | Bottom Left 34kg value<15:8> | |||||||
0x3B | Bottom Left 34kg value<7:0> | |||||||
0x3C | Checksum<31:24> | |||||||
0x3D | Checksum<23:16> | |||||||
0x3E | Checksum<15:8> | |||||||
0x3F | Checksum<7:0> |
Calculating the weight on each sensor simply involves interpolating between the two calibration values your reading falls between (or using the higher two values if your reading exceeds the highest calibration value), and the total weight on the board is the sum of these values.
The reference battery level is unused, but matches the point at which the battery reading (0xA) is considered empty.
There are also values at 0xa40060 and 0xa40061, and the other values in the range of 0xa40050 through 0xa4006f all read 0.
Bit | ||||||||
Byte | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
0x60 | Reference Temperature | |||||||
0x61 | Unknown (always 0x01) |
The reference temperature is presumably the temperature reading when the board was calibrated.
The checksum is a CRC32 computed using the reversed polynomial 0xEDB88320 of 28 bytes: the 24 bytes from 0x24 through 0x3b, then the bytes at 0x20 and 0x21, and then the bytes at 0x60 and 0x61.
Sample Calibration
Some sample calibration data obtained from various balance boards. Note that this is simply a sample, and different boards will have different data.
Australian Board |
---|
The (Australian) Balance Board belonging to Carl Kenner returns the following data for that range:
(4)A40020: 10 69 00 00 (4)A40024: 07C3 3CF8 048C 296B (bigendian calibrations for 0 kg, TR BR TL BL) (4)A4002C: 0ED2 4384 0B3A 3069 (bigendian calibrations for 17 kg) (4)A40034: 15E9 4A10 11EF 376E (bigendian calibrations for 34 kg) (4)A4003C: 5E 40 E9 B6Brute-forcing for values that match the checksum gives 1a 01 as the values at (4)A40060/1. |
Finnish Board |
---|
A (Finnish) brand new Balance Board returns the following data for that range:
(4)A40020: 55 69 00 00 (4)A40024: 4D A9 42 7B 4C 23 36 58 (4)A4002C: 54 36 49 6D 53 09 3D 1C (4)A40034: 5A C9 50 66 59 FC 43 EF (4)A4003C: 79 55 CB 1ABrute-forcing for values that match the checksum gives 18 01 as the values at (4)A40060/1. |
US Board |
---|
A (US) Balance Board returns the following data:
(4)A40020: 01 69 00 00 (4)A40024: 07 BC 11 8B 06 BA 46 52 (4)A4002C: 0E 6E 18 79 0D 5D 4D 4C (4)A40034: 15 2E 1F 71 14 07 54 51 (4)A4003C: A9 06 B4 F0 (4)A40060: 19 01 |
Japanese Boards |
---|
Two Japanese boards from Hiroyuki Ogasawara return the following data (source):
Board 1: (4)A40020: 41 69 00 00 (4)A40024: 49 69 0c 67 0a a4 4a b6 (4)A4002C: 50 7c 13 3d 11 6d 51 a6 (4)A40034: 57 87 1a 17 18 3f 58 9e (4)A4003C: d8 94 ce 81 (4)A40060: 1b 01 Board 2: (4)A40020: 01 69 00 00 (4)A40024: 13 66 13 f2 0b f6 48 91 (4)A4002C: 1a 5f 1a a3 12 dd 4f 48 (4)A40034: 21 5a 21 62 19 ce 56 0f (4)A4003C: b9 34 f5 28 (4)A40060: 11 01 |
Wii Initialisation Sequence
This is a listing of the initialisation sequence which my [drhugh's] Wii performs on the balance board, as determined by snooping the 2-wire bus of the Broadcom chip (TWI). At TWI level reads are always 16 bytes, so read length is not specified. For writes the starting address is given. The snooping was needed because my balance boards were working with the Wii, but were having one or more of the 4 weight sensors disabled with my PC interface (based on WiiUse). At PC interface level the addresses should have 0xa40000 added.
Write f0: 55 (standard extension initialisation without encryption) Write fb: 00 Read fa: (reads the extension identifier) Write f0: aa (enable encryption - following three lines are the 16 byte key) Write 40: ab 7c b4 1e 97 8d (example - data bytes are highly variable) Write 46: 9e 7e 81 1b 99 29 (example) Write 4c: 17 07 a6 1e (example) Write f1: aa (the purpose of this byte is unknown, possibly calibration?) Write f1: aa Write f1: aa Read 20: (reading calibration data) Read 30: (reading calibration data) Write f1: aa aa aa 55 aa aa aa Write f1: aa Write f1: aa ... (wait) Write f1: aa Read 24: Read 34: Read 3c: Read 60: Read 21: Read 20: Read 24: ... (wait) Write f1: aa
Following initialisation the only activity is constant reading of address 00 (the weight sensor and battery data).
Using this sequence in the PC interface is found to correct the problem with disabled weight sensors. The problem recurs when the balance board is not used for a while, and several power and/or connect cycles may be necessary to get the sensors all working, after which they continue to work. A minor change is necessary to make the sequence work at all: the "write f0: aa" causes strange behaviour (encryption) in the balance board and must be omitted (no explanation is offered for why this happens to work).
Status Information
The Wii Balance Board presents the same status information as the Wiimote
Using the Balance Board in Homebrew
This was taken from the Balance Board Tools application
u32 devtype;
//(1) Check in which wiimotes expansion port the balance board is hiding in
for (i=0;i<WPAD_MAX_WIIMOTES;i++)
{
WPAD_Probe(i,&devtype);
if (devtype==WPAD_EXP_WIIBOARD) bbport=i; //(2) Save it
}
WPAD_Expansion(bbport, &exp); //(3) Extract the balance board struct
x=exp.wb.x; // The position
y=exp.wb.y; // on the board
weight=exp.wb.tl+exp.wb.tr+exp.wb.bl+exp.wb.br; // Weight in kilograms
Acknowledgments
Much of the information here that differs from a Wiimote is based on the research of Hiroyuki Ogasawara documented in the Sports category of his blog (in Japanese), and the partial translation available at Wiili.