This post will be mostly about hardware side of InputStick project. I'd like to write a little something about each phase, form the idea to (almost) final PCB version.
1. The idea.
I wanted a way to use my phone as a input device: keyboard, mouse, etc. So the idea was rather simple: I need some sort of USB adapter that my phone will be able to connect to.
I know that there are many other ways to achieve this (without using additional hardware) but I wanted something that:
- works out of the box with any hardware/OS,
- doesn't require additional server software/drivers,
- doesn't need root,
- is wireless,
Here's a very short demo:
You'll find more details here:
2. Proof of concept.
I've built my first setup using things that I already had lying around:
- STM32F103 development board (ZL31ARM),
- breadboard for USB connector and required resistors (dev board doesn't have one),
- BTM222 Bluetooth SPP module,
- Sony Ericsson K770i phone (back then I was more familiar with Java2ME than Java for Android platform).
Getting started was really easy, after one day I already had a working proof of concept device.
3. Choosing components.
After playing for some time with my breadboard setup it was time to move on to a dedicated PCB. This time I could select any components I wanted to:
Bluetooth module: HC-06: very popular Bluetooth module supporting Serial Port Profile. This version is slave-role only. Highest reliable baud rate is 115200, what is more than enough for sending and receiving data necessary for HID class devices: keyboard, mouse, game controllers etc. Class 2 (up to 10m) is also fine. The only thing that it lacks is ability to get Bluetooth MAC address of connected Bluetooth master device. This would allow to add "MAC filtering" as an additional security feature, but after all, you can never fully rely on MAC address (it can be rather easily changed), also there are other ways to prevent unauthorized access.
MCU: At that point I was already familiar with F1 series form STMicroelectronics (I own a development board after all), so that was rather obvious choice. At first, using ARM Cortex M-3 MCU may seem like an overkill, but later on it turns out additional flash/RAM/processing power comes useful. My initial choice was STM32F102C8T6 - cheapest STM32 chip which comes with USB peripheral (and 64KB flash). In the end I had to replace it with STM32F103T8U6, because unfortunately F102 is not available in QFN package.
16MHz Crystal: STM32F1 series requires external crystal to generate 48MHz clock signal for its USB peripheral. As it turns out, every single chip that I've used was working just fine using its internal high speed oscillator as a clock source. I know that this is not guaranteed in any way and there are many factors that can affect this.
Power supply: both MCU and Bluetooth module requires 3.3V. Any LDO that can supply at least 100mA should be fine. My choice: AP7313-33.
ESD protection: since InputStick will be often plugged/unplugged it is definitely a good idea to protect USB lines with USBLC6-2SC6.
Enclosure: my first choice was Bud Industries USB-7201. Later it turned out that getting the right enclosure was actually the most difficult task.
Here's a schematics:
This is a "minimum" version. The first prototype has some additional parts that are not shown here: LED, push-button. I think that the only non-obvious thing is using pin-remapping feature of the MCU. Instead of PA9 and PA10, PB6 and PB7 are used for RX/TX lines of USART1. This little trick made PCB routing a bit easier and allowed to keep the data lines as short as possible.
4. Building first prototype.
Here's my post covering building the first prototype. I still use this one while working on firmware.
After using this for a few days it I've started to notice a few things that I really didn't like about the enclosure:
- it's a bit too big for something that I'd like to carry with me all the time. Lot of PCB space is left unused, so there is definitely a room for improvement,
- annoying USB cap,
- if you use it somewhere in public, for example: to type your passwords while using PC at work/school it definitely draws unwanted attention and looks kind of suspicious,
- let's be honest, it doesn't look good no matter if it is a transparent/clear/gray version.
After many hours of looking for something better on Digikey, Mouser and some similar sites I've ended up with nothing. The best solution would be to get a custom made enclosure. There are basically two options: 3D printing (which is fine if you need just a few units) or injection mold (simply too expensive unless you want thousands units). At this moment I've came up with an idea that I should be looking for a "pendrive" enclosure, big enough to fit Bluetooth module inside (the largest component). Such enclosures are relatively cheap and available even in small quantities.
5. Making it smaller.
My first choice was this enclosure:
At first everything looked fine, but there were again some things that I didn't like, so later on I switched to a slightly different model (more info):
This time, placing components and routing were much more challenging tasks. Top PCB side is now entirely occupied by Bluetooth module. Everything else had to be placed on bottom side. What made it even more difficult was the fact that space below antenna must be left empty. At the same time I wanted the PCB to be possibly easy to manufacture and assemble:
- 8/8 mil spacing/thickness,
- 2 layers,
- 16 mil min via diameter,
- 0603 resistors/capacitors (assembly costs more when 0402s are used),
Another thing worth pointing out is that USB connector is 4.5mm high and that is exactly what is available inside most "pendrive" enclosures. So let's take a look at height of main parts:
- Bluetooth module: 2.2mm,
- MCU: 1.6mm (LQFP)/1mm (QFN),
- PCB: 1.0mm/0.8mm/0.6mm/going lower than that doesn't seem like a good idea, USB connector is soldered directly to the PCB and the whole device will be plugged/unplugged many many times over its lifetime.
At this moment I had to replace F102 with F103 in QFN package. Now: 2.2+1.0+0.8 gives 4.0mm so at first it looks like the height problem has been solved. but then you realize that you can't place PCB at an arbitrary position: it is determined by the type of USB connector:
Luckily, the one on the top allowed me to get exactly what I needed: 2.2mm for the top side and 1.5 for the bottom side (enough for LDO and ESD chips). For some reason this type of connector is much more expensive and difficult to get.
Here you can see first prototype compared to a final version:
In my opinion it is much better now and was definitely worth all the additional effort. Now I can easily carry it with my keys, and it looks like just an ordinary pendrive.
6. Interfacing programmer/debugger.
In case of my earliest prototype the goal was to have a programming/debugging connector that can be easily attached (for longer periods of time) and removed if necessary. There was more than enough board space to use standard 2.54mm spaced pins (ST-Link: clock, data, reset and ground). For final PCB things are different. Now I need the programming interface only for uploading firmware, what is done only once. I wanted something that can be quickly attached for just a few seconds. Unlike earlier, I couldn't afford to "waste" PCB space on a connector, so this time I used 1.27mm spaced vias. As you can see plug consists mainly of three pogo pins and a lot of hot glue: looks terrible, but does its job just fine. Power supply is delivered via USB plug.
7. Radio testing.
In order to perform RF testing it is necessary to put Bluetooth module in DUT (device under test) mode. This allows for example: to force the module to transmit on a selected Bluetooth channel, or to manually set channel hopping sequence etc. The module is based on CSR BC417 chip, so it is necessary to use BlueTest3 utility provided by CSR.
The main problem here is how to connect PC with the module. There are two options:
- get a USB-SPI adapter (must be supported by CSR drivers). Unfortunately it's relatively expensive for something that you are going to use once or twice. $100 was the cheapest option I could find online.
- use LPT port to emulate SPI. LPT port must support ECP mode, so this won't work with most USB-LPT adapters, you'll need native LPT port. If you want to make a LPT-SPI adapter, take a look at this blog.
8. ESD testing.
At first I assumed that there should be no problems with ESD: there is no user interface (buttons), USB data lines are already protected with USBLC6 chip. First ESD test proved that my assumption was wrong, long story short: I've ended up with two completely dead devices. The problem here is that the distance between PCB edges and enclosure is very, very small. My solution to the ESD problem was adding a "guard ring" along PCB edges and connecting it with shield of USB connector:
This solved only half of the problem: there were no more dead devices, but from time to time MCU or Bluetooth module would experience random resets. In order to pass the test the device must be able to recover its functionality automatically, without any kind of users interaction. This time solution was purely software-based. Last week InputStick finally have passed ESD testing :)
9. What's next?
Looks like current PCB revision is (almost) final one. It may be necessary to make some minor modifications to make it ready for SMT assembly (like adding fiducial markers).
Next time I want to cover firmware related things in a similar way.