Sunday, 9 June 2013

A serial MultiWii controller: Part 2

We now have a working RC controller for our MultiWii board using the XBees and Nunchuks! I'll update this post soon with a full explanation, wiring diagrams, etc.

In the mean time, here is our code:

Friday, 12 April 2013

A serial MultiWii controller

With two working Nunchuks connected to our Arduino (see last post), we could continue building our RC controller.


1. Converting Nunchuk data into RC signals

We grabbed MultiWii v2.2 from here (the latest release as of this writing), and examined it to determine what kind of RC input it expects. MultiWii expects RC serial messages to contain 8 16-bit integers containing values between 1000 and 2000. PWM signals for servos and ESCs typically vary between 1000µs and 2000µs. Presumably, the RC values are simply the pulse-widths which would be read from the PWM input if the quadcopter was being controlled by a traditional RC radio. The 8 signals are: roll, pitch, yaw, throttle, aux1, aux2, aux3, and aux4.

In our case, the Arduino simply maps the 4 Nunchuk axis onto roll, pitch, yaw, and throttle. We used the normal axis layout for RC helicopters, known as Mode II.

The single complication in this part of the code is the throttle axis. In RC radios, the throttle is at rest at the down position, whereas the other three axis are at rest at the center position. Furthermore, the throttle in RC radios is not sprung, so it does not return to its rest position on its own. We would need to modify out Nunchuk to make the throttle operate in this way. We can compromise however, on the zero-point. We mapped the throttle such that only the top half of the stick is the active range, as shown:

This makes the throttle behave more like an RC radio controller.

As an optional safety precaution, the throttle is only active when both Nunchuks' Z buttons are held down. We chose to do this because it is so easy to accidentally bump the little Nunchuk joysticks.

2. Sending RC signals to MultiWii

Unfortunately, the MultiWii serial protocol (MSP) is described in this form post is vague. We decided to find some existing code which implements the MSP and examine it as a reference. The best existing code which does this is the MultiWii configuration program, which comes with MultiWii. It is written in Processing. Based on the Processing code and the MultiWii source code itself, we determined that MSP data frames are structured as follows:

The configuration program assembled these messages using the following function:

//send msp with payload
private List<byte> requestMSP (int msp, Character[] payload) {
  if(msp < 0) {
   return null;
  List<byte> bf = new LinkedList<byte>();
  for (byte c : MSP_HEADER.getBytes()) {
    bf.add( c );
  byte checksum=0;
  byte pl_size = (byte)((payload != null ? int(payload.length) : 0)&0xFF);
  checksum ^= (pl_size&0xFF);
  bf.add((byte)(msp & 0xFF));
  checksum ^= (msp&0xFF);
  if (payload != null) {
    for (char c :payload){
      checksum ^= (c&0xFF);
  return (bf);

We re-implemented this function in Arduino like so:

// Send a message using the MultiWii serial protocol.
void send_msp(uint8_t opcode, uint8_t * data, uint8_t n_bytes) {
  uint8_t checksum = 0;
  // Send the MSP header and message length
  Serial.write((byte *)"$M<", 3);
  checksum ^= n_bytes;

  // Send the op-code
  checksum ^= opcode;
  // Send the data bytes
  for(int i = 0; i < n_bytes; i++) {
    checksum ^= data[i];
  // Send the checksum

The MSP message which sends RC data is called MSP_SET_RAW_RC and has message type 200. It is composed of 16 bytes which represent 8 16-bit integers. We trivially translated our control signals from Step 1 into an array of bytes, and send it using the function above. For now, we're sending zero for aux1-aux4.

When our control board arrives we will test and debug our code, and post a complete Arduino sketch.

Multiple Wii Nunchuks with Arduino

While the parts are in the mail, we started working on our remote controller. Most hobby RC quadcopters are controlled using a standard RC radio. RC radios typically output PWM signals, which can be connected directly to servos and motor ESCs. Because of this, the MultiWii board and software we are using is designed to take several PWM inputs as RC signals.

We don't have an RC radio, but we do have two Xbee radios, two Wii Nunchuks (with adapters), and a spare Seeeduino Mega. Luckily, the MultiWii software can also accept RC signals over UART as well as PWM, so it should be possible to build our own (primitive) RC radio controller.

Connecting more than one Nunchuk to an Arduino however, is nontrivial. Nunchuks connect to the Wii remote over an I2C bus, but all Nunchuks have the same I2C address, meaning that more than one of them cannot exist on the same bus at the same time without causing problems. One solution is to use transistors to connect and disconnect the Nunchuks from the I2C bus dynamically so they don't conflict with one another.

This solution worked perfectly. We wired it according to the diagram in the linked post above, using 10KΩ resistors.

Rebooting the project

In 2011, I began a quadcopter project which never quite got off the ground. Actually it did get off the ground, but it wasn't stable. I was attempting to design the control system from scratch using an Arduino Duemilanove as the controller and an early model Sparkfun Razor IMU for sensors.

There were many problems. One of the most important ones was that the Razor firmware only outputed attitude data at 50Hz, which is far too slow for a quadcopter. Even if I had been able to speed up the firmware, there were doubts that the UART connection between the Razor and the Duemilanove would be fast enough to transmit the data (most quadcopter systems read sensor data through I2C, not UART).

We're going to give the project another try, this time with more realistic goals. This time, instead of trying to program the controller from scratch, we're going to try to get it flying using off-the-shelf open source software. We will then use that as a foundation for future modifications.

We'll be using some parts from the old project:
And a new control/sensors board, and frame:
We'll post a full list of parts used after assembly is complete.