Hack a Guitar Hero drumset to use it with any computer over USB, Part 2

BitBucket repository is live: https://bitbucket.org/MostThingsWeb/usbdrumming/src
Continuing where we left off from part 1, let’s plan out some of the hardware that will interface with the drumset. A little bit later, we’ll prototype the embedded software.
 

Planning the hardware

We already know that the control box and drumpad controller communicate with SPI. Below is a simple (highly abstracted) schematic showing the existing drumset circuit. Note that the drumset uses 3.3V logic. This will be important when choosing a microcontroller.

SPI is a simple protocol to work with, so let’s plan on somehow having our hardware take control of that SPI bus.
 

Choosing a microcontroller

I decided early on that I wanted to use some kind of Arduino, instead of just a bare microcontroller, for a few reasons:

  • USB connectivity: Many Arduino-compatible development boards have a USB connection built-in, so it would be easy to connect the finished product to my computer. Of the three, this was the most important factor to me.
  • Simplicity: My hope is that other people will follow the (impending) tutorial. I didn’t want to require that people not only solder together the drumset interface circuit, but also a microcontroller circuit.
  • Ease of prototype: After I’m done prototyping on a breadboard, it will be easier to transfer my circuit to protoboard since I’ll have less parts to route.


After researching various Arduinos and Arduino-compatible boards, I decided on the Pro Micro 3.3V from SparkFun, pictured below. I chose this board for its small size and relative low cost ($24.95).

The Pro Micro 3.3V (image is property of SparkFun)

 

Diving in

I’ll walk you through all the things I tried in my quest to get the Pro Micro to talk to the drumset. I’ll explain along the way why my initial attempts didn’t work. Note that from here on, the Pro Micro is referred to as the Arduino.
 

First attempt: Just connect the wires!

Just connect the drumset SPI bus to the Arduino SPI pins. I chose pin 2 to be CS.

Click for larger image

Take note of the Schottky diodes. We want to prevent the Arduino from powering the control box, and vice versa. However, the drumpad controller needs to be powered either way. I accomplish this with a diode on the Arduino and control box power pins. Schottky diodes were chosen for their low voltage drop; we don’t want to under-power anything.

The Schottky diodes were probably the only thing I got right on this design – we’ll use them in every future revision.

What’s wrong with it?

Two things.

  1. When using the drumset with my console (i.e. the control box is powering the circuit), SPI communications fail. For some reason, the Arduino, even though it is not powered, is seen as a load by the rest of the circuit. Taking a look with my logic analyzer confirms that the bus doesn’t operate properly.
  2. More importantly: the Arduino actually is getting powered from the control box! Turns out, if the voltage on any pin is something like 0.5V greater than Vcc (which, thanks to the diode, is 0V), the reverse protection diodes on that pin will conduct current backwards, into the Arduino. This was evidenced by the LEDs on the Arduino lighting up dimly. Worse still, this “parasitic power”, as I will (incorrectly) call it, occured even when the control box was off. I believe this is because as long as the batteries are in the box, the CLK pin of the control box will tick. Removing the batteries did indeed fix the issue, so that’s my best guess. If I’m incorrect, then there is still somehow enough potential between the pins on the Arduino and the control box to create an overvoltage situation.

The first issue is obviously problematic. The second issue, however, is a little more subtle. You might be thinking, who cares if the Arduino is being powered? That was my stance too, until I realized the implications. First, having the Arduino powered 24/7, even with the control box off and USB cable unplugged, will drain the batteries faster than normal. Second, it’s actually dangerous to apply an overvoltage to any pin for too long – you’ll damage your Arduino.
 

Second and third attempts: Needs more cowbell diodes

For my next attempt, I tried using diodes to solve the two problems I detailed above. Isolating the pins with diodes should (a) prevent the drumpad controller from seeing the Arduino as a load and (b) prevent reverse current flow into the Arduino when the Arduino is off. Below is the modified circuit. Nothing has changed except the addition of D3, D4, and D5. These are just standard small signal diodes.

There is no need to protect MISO with a diode, since that line is being driven by the drumpad controller.

What’s wrong with it?

If I remember correctly, this solved problem 1: The Arduino was effectively isolated from the rest of the bus when it was off. However, problem 2 still plagued the circuit. Even with diodes, there existed enough potential to cause reverse current flow. By the way, I tried disconnecting the MISO line, but the problem still occurred.

My third attempt involved using diodes to clamp the SPI lines to the Arduino’s Vcc, similar to the circuit here: http://electronics.stackexchange.com/a/22773/2473. This didn’t solve either problem.
 

Fourth attempt: Standard buffer

Next, I tried using a standard 4xxx series buffer to isolate the Arduino from the bus. That chip requires two voltage sources, plus ground. No matter how I hooked it up (yes, I read the datasheet), current still flowed back into the Arduino. Very frustrating.
 

Fifth attempt: The magic of tri-stating!

Enter the 74126, a magical little 74xx series tri-stating non-inverting buffer. The model that I used to prototype (on my breadboard) is the SN74AHC126N. Great chips to have around.

Here is our new schematic using these chips (we’ll need two):

Click for a bigger version – I’ll apologize in advance, because the layout is not the best it could be.

There are four buffers on the right which interface the Arduino to the drumpad controller. The three on the left (excluding IC2A) interface the control box to the drumpad controller (IC2A is used for a different purpose, described in the next post). On each chip, pins 1, 4, 10, and 13 are the output enable lines. When low, this line puts each buffer output into a high impedance state, essentially removing the buffer from the circuit.

On the right set of the buffers, all the OE lines are tied together, pulled low to ground through R2, and connected to pin 3. The plan is to drive pin 3 high when the Arduino is on, and let R2 pull the line low when the Arduino is off. That way, the Arduino will only be “connected” to the circuit when on.

Similarly, the top three buffers on the left connect the control box to the drumpad controller. The OE lines are configured so that the buffers switch to high-impedance mode when the control box is off. The MISO line on the control box defied my attempts to be buffered, so instead I opted to use a circuit protection technique I found here. Conveniently, I’ve found a use for the fourth buffer that I’ll reveal in the next post.

Problems solved.
 

Prototyping the software

I’ll post and briefly explain the test sketch I ran on the Arduino.
 

Running it yourself

If you are following along (I guess you just had all those parts laying around?), and want to run the sketch on your Pro Micro, then you’ll need to follow these steps to prepare your computer. If you are using some other microcontroller or Arduino, then you are on your own.

  1. Get yourself a long micro USB cable. The white one that came with my Kindle Keyboard was perfect. If you’re planning on following the impending tutorial, then you’ll need to embed one end of this cable in your drumset, so make sure it is long.
  2. Follow the instructions on this page to install the Pro Micro drivers and Addon files. Note that the boards.txt file that they give you will have to appended to the existing file in your Arduino directory. Don’t overwrite it like I did originally.
  3. Plug in your Pro Micro, choose the Pro Micro 3.3V in the Arduino interface’s list of boards, and upload away. Warning: Don’t choose the 5V version of the board.

 

The sketch

Here’s the code. Everything should be self-explanatory, except for the “Initialize drumset” part. I found that the control box sends a command to the drumpad controller to initialize it before polling for pad hits. That’s what those lines do.

#include <SPI.h>

const int PIN_SS = 2;
const int PIN_MISO = 14;
const int PIN_CLK = 15;
const int PIN_MOSI = 16;

void setup(){
  pinMode(PIN_SS, OUTPUT);

  pinMode(3, OUTPUT);
  digitalWrite(3, HIGH);

  // Initialize SPI
  SPI.setDataMode(SPI_MODE1);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.begin();

  Serial.begin(9600);

  // Inititalize drumset
  digitalWrite(PIN_SS, LOW);
  delayMicroseconds(27.5);
  SPI.transfer(0xAA);
  delayMicroseconds(8);
  digitalWrite(PIN_SS, HIGH);
  delayMicroseconds(10004.5);

}

void loop(){
  // Select the slave
  digitalWrite(PIN_SS, LOW);
  delayMicroseconds(27.5);

  // Send preamble
  SPI.transfer(0xAA);
  delayMicroseconds(32.625);

  // Read the number of messages that the drumset has to send
  byte hitCount = SPI.transfer(0x55);
  byte pad;
  byte velocity;

  if (hitCount > 0){ 
    delayMicroseconds(50);

    // All messages are encoded as JSON
    Serial.print("{ "msgType": "hits", "hitCount": ");
    Serial.print(hitCount);
    Serial.print(", "hits": [");

    for (int hit = 0; hit < hitCount; hit++){
      SPI.transfer(0); // Returns 153 (0x99)
      delayMicroseconds(23.125);
      pad = SPI.transfer(0);
      delayMicroseconds(23.125);
      velocity = SPI.transfer(0);
      delayMicroseconds(23.125);

      Serial.print("{"pad": ");
      Serial.print(pad);
      Serial.print(", "veloc": ");
      Serial.print(velocity);
      Serial.print("}");
      if (hit != hitCount - 1){
        Serial.print(",");
      }
    }

    Serial.println("]}");
  } 

  delayMicroseconds(48);
  digitalWrite(PIN_SS, HIGH);

  delay(5);

}

 

Part 3

In part 3, I will refine the drumset interface circuit and embedded software.

Join the Conversation

4 Comments

  1. In most microcontrollers, the I/O pins are turned into inputs (act like tristate) when the device is held in RESET. I just check the ATMEGA168 datasheet which states that the I/O pins are tri-state when in RESET.? This could have saved you all the wiring to the tri-state buffers and the most of the diodes.

    1. Hi William,

      This is a very good point – if I ever update the project (which I hope to one day), I will explore this. The tristating buffers are not ideal, to say the least. However, I’m not sure how the microcontrollers in the GH board will behave when powered off but exposed to voltages on their IO lines. That was why I used the buffers on the GH side initially, but as you suggest, they might not be necessary on the Arduino side if the Arduino is kept in the RESET state.

      To be honest, I don’t remember everything I tried while doing the project (though I know I did not try the RESET state). Next time I need to keep detailed notes.

      Thanks for writing-
      MTW

      1. The good thing the RESET method, is that the processor is powered, so there is no issue with your concerns of voltages applied to the I/O pins when the processor is off. Just add a switch to hold the GH board in RESET when you want to use the drums normally. When running, your only concern will be the SPI Clock and the Master or Slave outputs, unless they are all Open Drain, thus only pull down and are pulled up with a PU resistor. Most multi-node communication protocols use this method. Do you know which devices are masters and slaves? It will determine the interface to the SPI. Good luck!

        1. I couldn’t determine whether the drumset used open drain or not (though I didn’t try very hard), so that’s another thing I’ll experiment with. The drumpad board is the slave, and the control box is the master (with the Arduino becoming master when the drumset isn’t powered). Thanks for all the tips – you’ve given me some more options to explore this summer 🙂

Leave a comment

Leave a Reply