Let’s Drive
This of course only applies to Dash, as Dot is immobile. The command to drive is 2, which will be contained in our first byte. The following 3 bytes will contain the driving speed and turning speed.
Let’s build this into a function. The first thing we’ll do is ensure the values passed to us are treated as numbers and not a string, because JavaScript.
function drive(driveSpeed, turningSpeed) {
var driveSpeed = parseInt(driveSpeed);
var turningSpeed = parseInt(turningSpeed);
var data = new Uint8Array(4);
data[0] = 2;
Driving and turning speed values can range from -1023 to 1023. A positive driving speed will move Dash forward, and a negative driving speed backward. A positive turning speed will turn Dash clockwise, and a negative speed counter-clockwise.
We need 10 bits to store a value up to 1023, plus one bit for the sign makes 11 bits. Both values combined take up 22 bits This is more than 2 bytes (16 bits) but less than 3 (24 bits). So we’re going to slice up the bits to fit into the next 3 bytes of our array. The following figure shows our end goal.
First we’ll check to see if either the driving speed or spinning speed values are negative. If they are, we’ll add 2048, or 0x800. (We use hexadecimal values here because it’s easier to understand how they relate to the individual bits. Each individual hexadecimal character is exactly 4 bits.)
if (driveSpeed < 0) driveSpeed = driveSpeed + 0x800;
if (turningSpeed < 0) turningSpeed = turningSpeed + 0x800;
You may be asking why add 0x800? At the bit-level, this moves the sign bit into the right position, right up against our 10 value bits.
We’ll take the lower-order byte of the drive speed value and place it in the second byte, and we’ll take the lower-order byte of the turning speed and place it in the third byte. We can isolate the lower-order byte using an & operation.
data[1] = driveSpeed & 0xff;
data[2] = turningSpeed & 0xff;
We’ll take the last 3 bits of high-order bytes from both drive speed and turning speed, and join them together in the last 6 bits of our third byte. We do this by shifting the drive bits right 8 places, the turning bits right 5 places, and combine them using an | operator.
data[3] = ((driveSpeed & 0xff00) >> 8) | ((turningSpeed & 0xff00) >> 5);
Send the bytes and close off the function.
command.setValue(data);
}
Complete Example
View the complete example here. There is plenty of room to dive deeper. We’ve only covered a subset of the commands available, and haven’t even touched on reading sensor data. There is an official and several unofficial Python libraries that offer some insight into the commands available.
Works Consulted
Wonder Workshop, WonderPy, A Python package providing an interface to the WonderWorkshop robots Dash, Dot, and Cue, (2018), GitHub repository, https://github.com/playi/WonderPy
RobotControl, A simple python library to control Dash and Dot robots from Wonder Workshop, (2015), GitHub repository, https://github.com/vdwel/RobotControl