As of a few days ago, I’ve begun working on the third version of the custom Keyglove controller board. It’s been a couple of months since I started working on the first version, so I figure I should really share some of the details of the process, how it’s going, and what I’ve learned.
The WT12 breakout boards that I created previously gave me a very good working introduction to the Eagle circuit design software, so I had a decent place to start on this more complicated project. I considered KiCad and Fritzing, but I decided to go with Eagle because it’s what I know (so far), and I can always convert stuff later if I really need to.
I had a few basic requirements for the controller: it had to be compact, modular, and based on readily accessible standards—nothing proprietary or hard to work with. It also needed to use a connector with enough pins to connect all of the glove sensors. With these requirements in mind, I settled on the Mini PCI Express form factor, which has 52 pins and satisfies all of those requirements. The only difficulty is that the specification requires a PCB that is exactly 1mm thick, and the most common PCB thickness is actually 1.6mm, which is too large to fit. It isn’t particularly difficult to find a PCB service that can do this for you, but Laen’s excellent DorkbotPDX service doesn’t handle it. The card also requires a feature known as “gold fingers,” the fab-house term for the card edge pins, etched contact surfaces that go to the very edge of the PCB.
After checking out a few PCB fabrication services on Laen’s recommendation, I decided to give PCBWing a try. They are based in China like many PCB shops, but they had excellent prices and handled all of the features I needed. Having used them now for a few orders, I can say I am very happy with their services, and for the time being will continue to go back to them for new prototype revisions. They don’t speak English very well, but they speak way better English than I do Chinese, so I can’t complain. Not once have they messed up anything at all about an order, and I’ve had a lot of very specific requests. PCBWing also does very reasonably priced etched and framed solder stencils. They aren’t the absolute cheapest stencil option out there, but they are much less expensive than everything else of the same quality I’ve seen advertised. I got 3x complex (though small) PCB copies and a great solder stencil for ~$200 including FedEx international 2-day shipping. Hard to beat that for low-quantity prototyping.
I based the controller board off the Teensy++ design, since that’s what I’ve been using for testing and I know the AT90USB1286 has excellent USB functionality. I also added a LiPo charging circuit, vibration motor, piezo buzzer, a couple of RGB LEDs, a Bluetooth connection, a battery connector, and of course, a combination accel/gyro motion sensor.
The design process in Eagle was painless up until the point where I had to route all of the connections. A full-size Mini PCI Express board is exactly 30mm by 51mm including the card edge connector. Even using both sides, this is not a lot of space for everything. It’s very easy to fit everything on the board, but getting it to route properly was totally different. It took many hours of very tedious and minute adjustments to finally get something that routed to 100%. I didn’t even try starting to route by hand, since the board is so complicated. I just let Eagle’s autorouter do its thing, and finally came up with something that worked with 6mil traces. I didn’t want to push it smaller than that because of the increased cost of production. Here is the result of what came back from PCBWing:
That’s the top and bottom of the bare PCB on the top row, and the top and bottom of the assembled board on the bottom. Yes, I did build everything by hand (and so far, I have continued to do so). That has been an exciting learning process as well. This being the first complicated PCB I’d ever designed, let alone the first surface-mount technology I’d ever worked with, I must say I was (and still am) extremely please with how everything turned out. I loosely followed SparkFun’s Hot Plate Reflowing Tutorial, and after a few hiccups, everything went pretty smoothly.
However, this first attempt definitely showed me more than a few things about what to do and what not to do, such as:
- Don’t use lead-free solder paste.
I just got something generic on eBay that looked reasonable. It probably is fine stuff, but not for what I needed it for. I melted the solder mask partially off one side of my first board while trying to get the paste to reflow because of the significantly higher threshold temperature. After I got some Kester Easy 256 and tried again, it worked beautifully.
- Use less paste than you think you’ll need.
…until you get the hang of it, of course. I used many times more than I needed the first time. A little paste really does go a very long way. You can always add more if you happen to run out while you’re spreading it around.
- A utility knife blade works pretty well to spread paste.
I’m sure there are disadvantages (such as the danger of cutting yourself), but a very fine, very straight edge can get solder paste into even very tiny stencil holes, and a few quick vertical swipes of the blade cleans 99% of the excess off the stencil surface. I’m still using that technique since I haven’t managed to get a real solder paste squeegee yet. I hear they’re expensive.
- Use specialty ceramic tweezers to place SMT parts.
I started out using standard needle-nose pliers, but those parts are so tiny that I quickly realized that I didn’t have the best tool. I picked up a set of Aven ceramic tweezers (from eBay since Amazon doesn’t have them stocked), and found them to be significantly better.
- Place identical components at the same time, and similar components afterwards.
For example, mount all of your 1K resistors at the same time, then move on to 10K resistors, and then the rest of them. Then do capacitors, etc. Working with 0603-size SMT parts in cut-tape reels by hand should be done as logically as possible to avoid mistakes, and doing things in order really helps.
- Place large components first, then smaller ones.
Some people may disagree with this, and if you have a good reason, then that’s fine. But I found it to be easier to place tiny resistors around big voltage regulators instead of the other way around, because you’re less likely to bump other parts that you’ve already placed. Yes, I did bump some parts more than once doing it the other way.
- Keep your parts in bags or other secure containers away from the edge of the desk.
It’s really not easy to find a 2mm carpet-colored LED in the carpet. Really.
- Always get enough parts to build at least three copies of the device.
More is better if you can afford it, but especially when it takes 10 days or more to get each PCB manufactured, there is nothing more disappointing than being stalled because you damaged one PCB, or fried the only critical part you had, or something of that nature. I barely made it with three of the first order, but it turned out okay. I upped it to five for my next revision, just for good measure.
All in all, it turned out very well despite the lessons learned the hard way. I got the first board built, plugged in the USB connector, turned on the power switch, and something actually happened. I was ecstatic. Windows Device Manager showed a new USB device, which eventually enumerated as an “AT90USB128”, exactly what I was hoping to see. Atmel’s FLIP tool read the chip status successfully, and I was on my merry way.
Then I realized that I forgot something important in the PCB design: no 6-pin ISP header. Drat. The FLIP tool works okay for programming, but it can’t change the fuses or bootloader on the AT90USB1287 as far as I could figure out, and the chip has to be put into a special mode to program it using the HWB pin with Atmel’s default bootloader. So, there’s another lesson learned:
- Always include an ISP header for prototype AVR boards.
You won’t regret it, ever. An ISP header can save a lot of time and get you out of trouble if something goes very wrong (though you might want a JTAG header too if you manage to do something catastrophic).
It wasn’t completely hopeless though, since the necessary pins are actually broken out in various other places on the board. I had to solder individual wires in odd places on the board, but I did eventually get a connection that was electrically equivalent to an ISP header. Lucky me—I don’t think I would have liked trying to solder anything directly to pins on a TQFP64 chip.
This development brought to light a new problem though. Although my USBtinyISP worked perfectly on an ATTiny2313 I had lying around, it would not reliably connect to the AT90USB1287 chip for anything. It didn’t fail entirely, but the 3-byte device signature was always random. It just would not reliably connect, and the last thing you want is an unreliable flash programming connection, since who knows what kind of bugs you’d be introducing without having any idea.
Anyway, to make a long story short, I ended up using my soldering iron to carefully reflow every pin of the AT90USB chip (which was possible since I was using the pin-visible TQFP version), and that finally solved the problem. Lesson learned:
- Make sure all of your solder paste completely reflows.
I’m sure I had enough paste on the board, but for some reason, some part of that particular connection was unreliable. That’s very difficult to detect visually, but just make sure you give the whole board 10 seconds or on the hot plate (or under the hot air nozzle) so after you think everything is done.
I quickly realized that the current board would not last long for development because of the missing ISP header and, more importantly, the fact that only one of the three PCBs I ordered appeared to be in any kind of pseudo-working state. The first one was fried because of the lead-free solder paste and subsequent extreme heat, and the second one wouldn’t respond to FLIP or my hard-wired ISP connection. The third one responded reliably to the ISP connection and FLIP, but no matter what I did, I couldn’t get the rest of the hardware on the board to behave the way it was being told to.
I blame the problems with the first two boards on my lack of experience (too many assembly mistakes), but in retrospect, the third board’s problem was likely something software-related that I didn’t realize at the time. Specifically, I was using the Arduino/Teensyduino-compiled .hex file with Atmel’s FLIP programmer and default DFU bootloader, and I’m pretty sure the Teensyduino-compatible .hex files are only meant to be used with the proprietary Teensy bootloader. It programmed successfully every time, but it would never work when I tried to reboot the board into user program mode. I’m not familiar enough with the Teensy bootloader/program structure to say for sure, but I think the lack of the Teensy bootloader on my chip was the culprit. This knowledge came after the second revision of the board arrived, so I didn’t care to go back and debug more at that point.
After I realized that I really needed an ISP header, I started working on the next version of the board. The schematic stayed almost the same, but the layout changed notably:
- I added an ISP header, of course.
- I flipped the battery connector around so it plugs in from the outside, not the inside.
- A removed the hardwired HWB/ground connection and replaced it with a pushbutton.
- I changed from the TQFP64 to the QFN64 version of the AT90USB1287.
Now, I had a good reason originally for making the battery connector point inwards instead of outwards (future cable management inside a case), but decided that was a bad idea for prototyping and maybe even for the finished product.
The Teensy board has the HWB pin (#43, PE2) tied to GND, but it also has a special bootloader. On my board, this “feature” meant it would boot in programming mode every time with Atmel’s default bootloader. Obviously, this is not good. So, I turned it into a button to be used if and when desired—though, with the addition of the ISP header, it’s not really that useful most of the time.
I made the change to the smaller QFN64 package for space considerations, though not without some fear and trepidation at the thought of working with a 64-pin QFN package. The 20-pin and 24-pin LiPo charger and MEMS chip were hard enough with less than half the pin count. But I couldn’t come up with a better way to lay out everything I needed on the board. Of course, I got to have another “first” adventure in order to get my hands on some QFN64 AT90USB1287 chips by ordering them direct from a distributor in China (nobody else had them in stock). It was quite different from buying from Mouser or SparkFun, but everything worked out fine, so I have no complaints. (For the curious, I ordered 10x AT90USB1287-16MU from Shenzhen Shijibaike Electronic Co., whom I located through Alibaba.)
Hours of Eagle-tweaking and another PCBWing order later, I eventually ended up with the following board:
I learned one more SMT lesson through while working with the 20-pin, 24-pin, and especially the 64-pin QFN chips:
- Make sure all solder paste is perfectly lined up on the pads and as minimal as possible.
Even with very small resistors and capacitors, this isn’t as big of a deal, but it can quickly become a problem with 0.5mm-pitch QFN ICs. The solder paste should be just barely covering the pads on the board, not overlapping anywhere, not offset in any direction, and certainly not smeared around at all. Two of the four v0.2 boards I’ve built so far suffer from this problem because I wasn’t careful enough. A few of the pins on the AT90USB chip are shorted together. I am not sure whether those chips are damaged, but I haven’t attempted removal, cleaning, and remounting yet because I do have two other working boards. Trying to fix a 64-pin QFN chip with a hot air station is really not that easy.
I did have to make a significant change to the way the sensor I/O connections were routed to the card edge in order to make the layout work. This also required a new controller mount board, since my previous board had only specific pins broken out from the connector. I created a new board that breaks out all 52 pins, so no matter what I do in the future, I can use it to test any controller board that fits. Incidentally, if anyone needs a generic Mini PCI Express breakout board, this would serve well for that purpose also. Here’s the v0.2 board mounted with the battery and USB cable connected:
This new board has been working much better for development compared to my last attempt. I’ve been able to make use of the ISP header almost exclusively and program it directly using avrdude. The LiPo charging circuit seems to work well. The RGB LED is working correctly, now that I’ve figured out that the pins I was using to control it are also used for JTAG connections and JTAG must be disabled to use them for I/O. The vibration motor is also working well. I haven’t progressed far enough in the new code adjustments to get I2C working (which means no motion sensors), but that will hopefully happen shortly.
There are only two problems I’ve run into so far on these otherwise-working boards:
- The piezo buzzer isn’t responding.
I know the part works because I wired it up manually to my old prototype, and it makes noise just fine (albeit quietly). I believe this is a problem with my current implementation of the Arduino’s “Tone()” function inside of the LUFA code structure. LUFA is awesome and powerful, but so far I haven’t fully integrated it with the current Arduino-friendly codebase. I’m still working on this one.
- The power switch turns it on fine, but not off again while USB is plugged in.
Weird, right? I haven’t figured out what’s going on here, since everything works as expected when if it’s just running on the battery. But even though the switch very specifically cuts off power to both VCC pins of the AT90USB chip, it doesn’t turn off. The USB port still supplies power to the UVCC pin, but that’s true regardless of the state of the power switch, and it doesn’t automatically turn on if I plug in the USB cable. I have to turn on the power switch once first, but then I can’t turn it off. I guess I should read through the datasheet a bit more.
I’m currently working on v0.3 of the controller board, which will incorporate the following changes:
- Add a magnetometer in order to allow complete 9-DOF motion measurements provided by the built-in MotionFusion code in InvenSense’s MPU-6050. A magnetometer like the HMC5883L is only about $1.50 extra, which is completely worth it for the added functionality.
- Add two I2C TCA6424A 24-bit I/O expanders to simplify layout and free up some of the MCU pins, which are 100% utilized right now. I need those pins for interrupts from the motion sensor.
- Add external 24LC512 EEPROM memory for storing configuration settings, especially touchset definitions. As it is now, to change the touchset you have to completely recompile the code and reprogram the MCU. This is not difficult for me or other developers, but it is certainly not easy for most end-users. The AT90USB’s onboard EEPROM is simply not big enough for a complex touchset definition, let alone multiple simultaneous sets to enable rapid switching between them.
- Add external 23K256 SRAM for fast access to touchset definition readings. Storing the touchset info in EEPROM is great, but it’s not fast enough for executing any desired action immediately (or so I’ve heard—I need to verify this). Being able to load the entire touchset into RAM once at the beginning should also help the EEPROM last a bit longer.
I’m also working on cleaning up the code base some more to make it easy to work with using the Arduino Mega 1280 or 2560, the Teensy++, or my custom board. Some of the source files are a bit messy and disorganized. It’s coming along though! You can see/watch/fork the current code on Github.