Wednesday, December 10, 2014

On hardware versioning

I don't know if this is a particularly interesting topic for a blog post, but I sort of had a realization last night about how best to manage hardware version numbering.

What it comes down to is the nature of the change that requires crossing a particular boundary. I've identified three boundaries:

  1. A major design change - wholesale changing of chips, new hardware features, etc.
  2. A change that impact the "cream" layer - requiring a new solder paste stencil and/or PnP programming.
  3. A change in signal routing or silkscreen - requiring new PCBs.
  4. Any other change - typically just parts substitution, stuff/no-stuff or solder jumpers.
Going forward, this is how I'm going to version hardware. I'm going to use the old software standard of n.m.o formatted version numbers, but other folks prefer Axy style, and that's fine too. But I've discovered that there is value to characterizing which changes require a new stencil, and this scheme means I don't have to try and remember that 0.3 could still use the 0.2 stencil.

Sunday, November 9, 2014

AP2331 FTW

I've been using and selling my USBTiny clone for a little while now, and it's been a great little device for the most part. But there's one little detail that's bugged me just a tiny bit: It's not hot-plug safe. In general, you need to attach the ISP header first, then plug the USB cable in. If you try and hot-plug it,  particularly when it's jumpered for 3.3 volts, you risk glitching the Vcc supply of the Tiny2313. This can cause the USB to reenumerate, at best, but most of the time it just causes the 2313 to lock up. Solving the hot-plug problem is particularly meaningful when you're using pogo pin programming, as cycling the USB connection while holding the pogo pins perfectly in place is difficult at best. I've tried to address this in the past by adding additional capacitance before and after the 3.3 volt LDO, but that didn't really help.

I happened to think about the Raspberry Pi. On the model B, I was able to cause a reset by removing the WiFi USB dongle. But for the B+, they added additional circuitry to mitigate this. What was it? The AP2331. The device is simplicity itself. It's an SO23-3 with pins for in, out and ground. It was designed for USB power applications, but it's usable at 3.3 volts as well, which makes it ideal for my purposes.

I tested one using pin clips to attach it to my current revision of board, making it the bridge between the 3.3 volt and target power pins of the jumper block, and pulling ground from the controller. Without it in place, I could cause glitches on the controller fairly consistently with a pogo adapter and a Crazy Clock board. But with the device in place? Nothing. It just worked.

So I'll be adding one to the 0.5 version of the µISP. That'll raise the price of it by a dollar, but that won't go into effect until the current inventory of 0.4 boards is cleared out.

Sunday, October 26, 2014

usbtinyisp source code update for modern AVR GCC

For those besides me who have downloaded the source code to the USB Tiny from AdaFruit, you'll note that on the download page it says you must use gcc-3.4.6 to build it. That's an antique.

I started down the road of patching the code so that it can be compiled by a modern AVR GCC and libc, but eventually discovered that someone had already done it.

I then went on to find the original home of the code. He has a 1.7 version of the code, but the pin assignments are different. The following patch makes it work with the USB µISP up through the current version (0.4) (it should also work with the original AdaFruit USBTiny and the SparkFun pocket AVR programmer):

EDIT: Turns out the patch was unnecessary... I was trying to build from the 'spi' directory, but the correct place is the 'usbtinyisp' directory. That has the correct pin assignments and requires no modifications. Just 'make' and reflash. Joy!

Thursday, October 16, 2014

Learning more and more about AVR libc

Since I converted the crazy clock to straight AVR GCC, I've been learning more and more about the AVR libc.

Before, I had written my own delay_ms() method for the ticking, but in looking into the library-supplied _delay_ms(), I discovered enough that I've switched entirely over to using it.

In particular, as long as you call _delay_ms() with a value that's constant at compile-time, the actual assembler code that will be generated will be nothing more than the assembler equivalent of "for(i = 0; i < magic_value; i++) ;" The compiler will select the "magic_value" based on the F_CPU macro (which is the frequency of the clock in Hz) and the actual number of clock cycles that the compiler knows each instruction will require. In my case, the code actually shrank by a few bytes compared to my old code which watched the timer0 count (the old code was also problematic in that it would lock up if the counter overflowed during a delay). This is all despite the fact that the ostensible argument to _delay_ms() is a double. But as long as the value is a compile-time constant, the compiler will optimize away all of the floating point requirements and will figure out that it needs to delay a particular number of cycles, and will generate assembly code to do exactly that. Brilliant!

And if you just need to waste a certain number of cycles, then __builtin_avr_delay_cycles() will generate exactly the correct code. I believe this might be useful to simplify some of the bit-bang USB code in the usbtinyisp. That will need careful consideration...

Sunday, October 12, 2014

Initial crazy clock programming/test jig

I still can't bring myself to pull the trigger on a panel of crazy clocks. But in the meantime, I have decided to go ahead with a jig for at least single boards.

The concept is that the two ISP footprints are connected together, the two battery footprints are connected together and the clock footprint is connected to two inverse parallel LEDs. The battery, clock and ISP footprints that match up with the actual board will be populated with pogo pins. The extra battery jack will connect to a right-angle 1x2 header and the extra ISP footprint will connect to a right-angle 2x3 header. That will form the bottom board of the jig. The top board will have the two SMD LEDs mounted. The pogo pins will project out of the top, and there will be some rubber feet for stability on the bottom.

To use it, you connect an AVR programmer configured for a self-powered target to the 2x3 header and a single AA battery to the battery connector. You then hold a freshly manufactured board on top of the pins and press down (for hands-free operation, you could use a few ounces of weight - say a paperweight wrapped in electrical tape). You then use your other hand and press return on the Raspberry Pi that has the AVRDUDE operations scripted. If the programming steps work (and if the programmer is configured to not deliver target power), then that confirms that the boost converter works. At the end of programming, the two LEDs should start blinking in the correct sequence for the firmware that was loaded. That confirms that the firmware works and that the series resistors and flyback diodes aren't wired incorrectly.

Monday, October 6, 2014

DIY AVR ISP Pogo adapter

I've been using the SparkFun one for a while, but it's not absolute nirvana. In particular, I don't have any use for the molex connection or the JST power jack, and having the host jack be on the top makes it somewhat more awkward to hold.

So I came up with what I think is a better design.

You start with a very simple board with two 6 pin AVR ISP footprints. Be sure that the holes are 40 mils. Connect each pin on one to the matching pin on the other. Put two #4 holes on either side, insuring that you've got enough space so that the screw head won't abrade any of the traces.

Here's the OSH Park shared project for my design.

To make one adapter, you need two of these boards. You also need two 1/2" #4 bolts, two #4 nuts and two #4 1/4" standoffs. You'll also need 6 pogo pins and a 2x3 .1" right angle header.

Start by picking one of the boards to be the bottom board. Solder the right angle header into one of the ISP footprints.

Next, use 2 1/2" #4 bolts and nuts and a 1/4" #4 standoff to attach the two boards together, placing the one with the right-angle header on the bottom. It is critical to insure that the two boards are oriented the same way - both TOP sides up, and both facing the same direction. If you get this wrong, the adapter will be miswired.

Place some scotch tape on the top of the top board, covering all of the holes in the ISP footprint that is not above the header you installed. That's the side of the adapter that will take the pogo pins.

Flip the boards over and carefully insert the pogo pins into the holes, with the silverish, pointy ends up. Be very careful with this, as the pins are easy to bend (which will ruin them), and are a very, very snug fit (they're 40 mils wide, and the holes are ostensibly 40 mils wide). Make sure the ends of the pins come through the holes in the top board and rest against the tape. When all the pins are in place, the tops of the pins must be level.

Take a moment to check that the pins are square, straight and the tops are level. If the pins are racked at all, twist the boards relative to each other, loosening the hardware slightly if necessary.

When the pins are placed properly, solder them to the bottom board. Once that's done, remove the scotch tape from the top board and solder the tops of the pins to the top board.

And you're done!

Attach your programmer to the header, being sure to put pin 1 on the pin 1 end (you can look at the markings on the top board to figure that out). Orient the pogo pins so that the pin 1 marking on the board match the target. Press down slightly so that the springs put a little tension on the target, but not so much that the springs bottom out. Hold it there and do whatever needs doing.

The only downside is that it's not so much less expensive than the SparkFun one that I can stock them in the store.

Saturday, October 4, 2014

Recovering pooched ATTiny chips

I never thought I would resort to AVR HV programming to recover chips. I probably still am not going to do it for parts actually installed in-circuit. But I had one DIP Attiny85 handy and wanted to get it going again, and no combination of SPI clocking and various other tricks got it to answer.

So I decided to set down the road to see if it were reasonable to do just this once.

I found this page, which was the most helpful. It turns out, that if you just want to do a quick-n-dirty one-off, you don't need to go to quite as much trouble.

Here's what I did:

I loaded the sketch into my Uno. D9 goes to pin 2 of the target. D10 to pin 5, D11 to pin 6, D12 to pin 7, +5 to pin 8, GND to pin 4, and then I took my bench power supply and set it for 12 volts and applied that to pin 1 (with its ground also going to pin 4).

I opened the Arduino serial monitor, entered a character in the input line and it promptly reset the fuses to the factory default. Mischief managed.