Bluetooth multi-purpose HID device, from paper to soldering

Posted: May 29, 2011 in Hardware projects

Hi everybody!

It’s been quite a while since my last post. I’ve been very busy with my Masters in CG, Games and VR.. wait.., in fact I’m still very busy!!

Today I’d like to tell you guys about a cool project I finished some months ago while I was working at a research institute


We needed a wireless versatile interface for sensoring buttons, joysticks and other human-operated transducers while maximizing compatibility and lowering production costs.

I had previously designed an HID-compliant USB device for sensing digger and crane controls, but the current trend seems to be something like getting rid of wires and filling the environment with radiation :-p.

I wanted the device to be a BT HID, as it has lots of advantages:

  • Many computers and devices are equipped with BT now, there’s no need to build an USB receiver.
  • Mainstream OSes have built-in drivers for HIDs
  • It can be used out-of-the-box with almost every game/app which supports a joystick/gamepad
  • Can be read directly through DirectInput , etc
  • Robust (CRC, they can live in the range of other BTs or 802.x devices…)
  • Multi-platform

And a few drawbacks:

  • More costly than specific point-to-point solutions such as the nRF family
  • Much more power-hungry

Project requirements

  • Wireless
  • Decent stamina
  • Bluetooth (HID profile)
  • Robust
  • Affordable production cost
  • Small enough to be mounted inside control panels

I conducted a bit of a research and couldn’t find a commercial product which fulfilled our requirements. The only HID bluetooth devices I could find were the Wiimote and the PS3’s sixaxis/dualshock 3. Both closed and in the case of the Wiimote, with a proprietary HID report-based subprotocol. Altough we could have been using the WiiUse library I wanted my own solution instead.

Selecting the components

I spent over two weeks surfing the net for the best suited components, and here’s what I came up with:

The Bluetooth transceiver

There’s plenty of all-in-one Bluetooth modules specially tailored for embedded designs. These are extremely useful since they integrate all the radio and baseband hardware (and even the antenna!) in a tiny self-contained mini-board, freeing the designer of those heavy-duty RF design tasks. But most of them are hardcoded with the RFCOMM Bluetooth profile (RS232 serial port over the Bluetooth link), and don’t allow the user to add or change Bluetooth services.

After trying a few of them and exchanging some e-mails with providers and manufacturers, the best I could find then was the Bluegiga’s WT12, a Class 2 Bluetooth module for embedded systems. What makes it different from everything else is that it’s a low cost module which runs a proprietary but documented firmware called iWrap. The iWrap implements the Bluetooth Stack from L2CAP down to the baseband, you can communicate with an external processor/microcontroller via a baudrate-programmable UART. It features a documented plaintext command set for configuring and interacting with the stack (creating L2CAP connections, notifying the host when a new connection is awaiting to be accepted, etc). They even offered us some free samples!. The drawback was that the iWrap3 firmware didn’t support custom Service registers, so you were basically stuck with the stock profiles.

The Microcontroller

The microcontroller would be in charge of running a fully custom firmware to initialize the iWrap stack, sampling its GPIOs for sensor data, managing the status of the battery and signaling the user of the general status via a 2-color LED among other tasks.

Since I had extensive prior experience with the Microchip’s PICmicro family of microcontrollers I decided to go with the PIC18LF4550 in a QFP package. The 18LF2550 is a small yet powerful 8-bit microcontroller with Flash memory which yields up to 12 MIPS at 48 MHz, has built-in USB, timers, PWM and many more peripherals and a great software toolchain and libraries. The ‘L’ stands for extended voltage range, meaning that it’s able to run at 3.3V which is the logic voltage for the WT12 module.

Power management and battery

I thought it would be great to use a USB port for recharging the battery as the 18LF4550 has built-in USB, and being able to use the USB link instead when the battery is nearly dead.

The MAX1811 is a great battery charger/monitor which is able to charge a Li-Ion single cell battery from a 100mA or 500mA USB port. It signals when the charge has finished, monitors the cell temperature and much more.

For the battery I chose to use the PS3 controller battery since it’s inexpensive, available everywhere and there are extended 1200 mAh versions for over 8 € !.

Finally, for power management I used the TI’s BQ2050, a fuel gauge IC able to communicate with an external host via 1-wire protocol for measures like the remaining charge in the battery among many other parameters.

System diagram

The first prototype

After calculating lots of parameters for discrete components from the datasheets of the ICs I wrote a couple of schematics in a piece of paper and built a handwired prototype on a proto-board.

Note the brown wire mess in the external board. That is the WT12 with its pads directly soldered to wires.

The firmware

That was the toughest part of the whole project. When a problem can be equally caused by a line of code or by a loose wire it always result in lots of fun ;-p

As you can see on the previous photo, I had a Microchip ICD2 (which got broken and was replaced by an ICD3) hooked up to the board. That gave me the greatly appreciated possibility of rebuilding the firmware and uploading it directly to the on-board uC, as well as doing painful remote debugging.

I will save you the nuts and bolts of the firmware, since it quickly grew into a complex and hard to debug piece of software. But I’d like to point its main features:

  • Implements a lexical analyzer to parse messages from the WT12.
  • Fully interrupt-driven. Active waits are avoided at all costs.
  • It efficiently disconnects or scales the clock from various parts of the chip depending on the current usage to save power.
  • Manages the status of a bi-color LED to let the user be aware of the current connection/charge status
  • Switches between USB and Bluetooth mode transparently to the user just plugging/unplugging the USB wire
  • Implements the SDP Bluetooth layer (the one in the iWrap was feature-incomplete for my goals)
  • Implements the BT-HID layer (“)
  • Sensors the inputs as a scan-matrix with up to 32 digital inputs
  • Sensors 8 analog inputs
  • Manages 8 3.3V CMOS compatible outputs
  • Warns the user if the battery is almost dead and turns of the device if the voltage level goes down the minimum safe levels
  • Has a custom HID-based protocol for reading the battery and device status from the PC, or perform other tasks such as remote shutdown
  • Implements the OneWire protocol with two CCP modules
  • Wakes up the device from sleep mode on signal changes
  • Implements a Bluetooth pairing PIN code
  • Is bootloader-capable for upgrading the firmware
That took a few months to develop. Tools like a low cost logic analyzer did often come in handy.

The schematic and board layout

I used CADSoft’s Eagle which is a good CAD/layout software that allows you to design 2 sided boards and it’s free (with some constraints) for non-commercial projects. Of course, I had to create new footprints and symbols for components that were missing in the stock Eagle’s library. The Eagle library from SparkFun was very helpful tough.

The system uses a 3.3V LDO voltage regulator-based power source for both USB and Battery operation modes. For the analog part I built a RL filter before the analog reference voltage input pin for power noise filtering, and each analog input has its own low-pass capacitor.

Regarding the digital inputs, 8 diode arrays were used for the scan-matrix method implementation.

A 16 MHz low profile xtal had been placed near the uC.

The I/O pins are simply IDC connectors, so another board with real sensors or better connectors can be stacked-up to this.

There is a special programming port for connecting the MPLAB ICD PIC programmer to the board.

Once I was happy with the schematic, and it had been tested in the proto-board I moved on to board layout. But before doing so, I had to decide where I was going to send the resulting Gerber files for manufacturing. After looking lots of low-cost prototype PCB manufacturers, I finally came upon to Gold Phoenix (which is the backend for SparkFun’s BatchPCB).

Then I studied their board constraints for prototypes that affected the thickness of the vias and tracks, and also the drill sizes. Fortunately, SparkFun have on their site a .dru design rules file for Eagle which was extremely useful.

The final layout was all carefully placed and routed by hand.

I strictly followed design guides from the manufacturers of the ICs, and used ground planes and different thickness tracks according to good design guidelines.

The WT12 has its pads facing the bottom of the board. It’s intended to be soldered in a reflow facility, so I had to figure out how to solder it by hand. My solution was to make the pads slightly larger in the footprint to be able to melt the solder in its pins by applying heat in the part of the pads that show up under the module.

GoldPhoenix sent us 19 boards

Assembly and test

I still remember how hard my heart was beating when I first connected the battery to the finished and assembled board prototype after a whole evening of tweezers, solder paste and looking through a giant magnifier :D… And turned out It didn’t work the first time!

While tracking down the problem I discovered that the datasheet of the voltage regulator had the pinout completely wrong!. Then I desoldered the part and replaced it with a TO-92 with the pins in place.

.. et voilá !!

Fully assembled board (top)

Fully assembled board (bottom)

It turned out that it worked like a charm!, however a bit more of debugging and development was needed with the final thing!

When it’s on the LED flashes in green, indicating that it’s in visible mode. Then you pair your PC with it and asks you for the PIN code. Once that is done, it’s recognized as a standard USB gamepad with 8 axis and 32 buttons! and it’s ready to use with any application. After 5 minutes of inactivity or on receipt of the shutdown command it turns off.

When any of the digital inputs is asserted it turns on again and tries to reestablish the bluetooth link. When you plug the USB cable the LED turns red and the battery gets recharged. The BT link is dropped and the device uses the USB link.

I didn’t have enough time to perform extensive testing but the battery life was more than decent and it works perfectly.

  1. roboticienfr says:

    I’m impressed by your work 🙂 I’m searching a solution to control a dspic based robot with a ps3 controller. Due to the HID service, I think I will use the WT12 module. Have you tried to interface a PS3 controller and the bluetooth module?

    • radexx says:

      Hi, thanks!
      No, I’ve never tried such a thing.
      I don’t see any technical showstoppers to achieve your goal though. However you must keep in mind how the pairing process works with the PS3 controllers.
      – Instead of discovering devices & services via SDP, when you plug the controller via USB to the PS3, it sends a special HID report to tell the controller what’s the BT address of the PS3 Bluetooth host.
      – When the USB cable is unplugged, the controller will try to open a BT-HID connection to that address.
      – I’m not 100% sure of this, but once the BT-HID link is established you may also need to send another special HID report to the controller in order to enable it (I know for sure it’s needed if you use it via USB, but I’m not certain about Bluetooth). That’s how they tried to prevent people from using their controllers with PCs.
      – And of course, if you use the WT12 module, unless their new iWrap software is more feature-rich that the one I used, you will have to implement the BT-HID protocol on your microcontroller and communicate with the WT12 at the L2CAP level via iWrap.

      You can easily get all the information you need (HID report formats for initialization and BT pairing, etc) by googling a bit 🙂
      Good luck!

  2. Rajesh TN says:

    Hi, Very impressive work!
    I need to develop a 16 key configuration BT HID device to operate in Android 4.0 tablet. Keys should be detected as custom keys, and my Android application should get a keypress event, with keycode as parameter.
    Can you help me with this?

    • radexx says:

      Hi and thanks for your kind words!

      In my particular case, the point of making it compliant with the BT-HID protocol was to be supported by any platform running the BT-HID stack (smartphones, PCs and Macs, PlayStation 3, …) so it would be transparent for every game and application. If you are targeting a specific device (an Android 4.0 tablet) and you have the source code of the app you want to send the input to, then you’d better use the RFCOMM protocol because it’s easier to deal with and there’s plenty of cheap Bluetooth modules supporting it out of the box.

      All you have to do is pair the tablet with your RFCOMM module and open a virtual serial COM port. This way you can have your gamepad send the status of the buttons and the tablet receiving them to determine what’s pressed and what’s not.

      If you still want to stick with BT-HID… I haven’t been working on this for a long time so I’m a bit outdated but I know that Bluegiga has greatly improved the features of their WT-xx modules with a new software stack, so BT-HID should be a lot less painful to implement. Unfortunately I can give you no more information on the topic 😦

      Good luck

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )


Connecting to %s