Curious to see how the dialog between Powered Up elements and hubs were communicating, I hooked a logical analyzer to the cable between them. Here is what I found...
I haven't spent too much time trying to understand what happens during this phase that occurs after power on of the system. During this phase, communication occurs at 2400 bits per second. Strangely enough, I get framing errors in hub to device direction. It could be using a 9 bits format... Anyway, data is mostly sent in device to hub direction.
Here is a screenshot of the overall initialization
exchange, between Powered Up hub and Control+ XL motor.
About 500 bytes are returned by the motor.
...and a close up of the start of dialog:
Looking at device data in ASCII mode reveals some text strings that seems to indicate that the device sends a description of data that will be available during data phase.
After the initialization phase, the serial link switches to a much higher speed, 115200 bits/s. The host polls the device every 100 ms (sending a single 0x02 byte), the device answers with data frame. If device value(s) change between polls, the device sends a data frame without solicitation from the hub. Data frame contains a start of frame byte (depending on device), then data byte(s) and a checksum byte (Checksum8, NOT(XOR of previously transmitted bytes)). Multi-byte values are sent low byte first (in the example below, accumulated angle is 0x1091 = 4241).
As an example, here is an exchange between hub and Boost motor.
WeDo distance sensor
"Distance" is actually an indication of reflected light. 0 is no reflected light, 9 can be reached with the sensor placed 5mm above a white paper.
WeDo tilt sensor
X direction is the rotation around long side of the brick. Value is clipped at +/-45°.
Boost color and distance sensor
This has a more complex behavior: not only it accepts commands from the hub to control LED color, but after poll it answers with a 3 bytes frame (0x46, 0x08, 0xB1), immediately followed by the true data frame returning data. This data frame is also sent (alone) when sensor values change.
Note that reflected light value is scaled to a 0..10 range in Powered Up app by dividing by about 9 the value returned by sensor.
Rotation speed is calibrated to 100% when the motor is powered at full speed with nominal voltage (9V). You can reach higher values (up to 125%) by manually turning the motor shaft. According to the strings in initialization phase, last data byte might be power in %, but this byte is always 0, and anyway the motor has no way to know the power applied to it. Reserved for future use?
Control+ motors (L and XL)
The data frame is the same as the Boost motor, with added absolute angle position derived from a magnetic angle sensor placed on the output shaft.