As happens on a fairly regular basis these days, the two- to six-week shipping wait came to an end last night for another so-cheap-as-to-be-questionable eBay electronics purchase from China or Hong Kong. This time, it was an item called “New Mini Mirror Clip Mp3 Sport Music With TF-Card[1] Slot Up To 8GB”. I purchased two of these for $1.45 each, shipping included, with the intention of cracking them open and controlling them using a microcontroller[2], but also with the knowledge that even the non-MP3 parts, including a 3.5mm stereo jack, a USB mini-B jack, a microSD slot, a little rechargeable battery, and maybe some other goodies, would justify the already trifling cost as scrap.

The Player Itself

Backed by a $5 memory card and a USB cable from a far more expensive Sony music player, this tiny device somehow fails to be irrelevant.

Before I went to work on taking it apart, I set about making sure the thing actually worked. Because I didn’t have a card adapter handy, I used the USB interface on the device itself. It’s not fast by any stretch of the imagination—I think it actually uses USB 1.1 (and, after having looked at the guts, I’m guessing the low-speed SPI interface on the card). I put on files in four formats—MP3, WAV, Ogg, and FLAC—in order to determine what it would actually play.

The results are these: Only the MP3 file played. After changing the extensions on the other files to .mp3, the WAV file also played, but the others were still skipped. And while the output of the audio content itself was adequate, there was substantial background noise carried over from the rest of the circuit. For under $8 including the shipping and the memory card, we’re not expecting a hi-fi or even an iPod shuffle—but this is a reminder that we’re working with something suitable for little more than a toy. And that’s okay, because the less shady version of an MCU-controlled MP3 decoder will set you back $40 from a finer (and more legitimate-feeling) retailer.

MP3 player with front face slightly separated

The device comes apart with a light touch.

No screws were visible on the device, so I set about coercing it apart by running my thumbnail down a seam on the face. As you can see, it was more than cooperative. (That said, I think it would take a non-trivial impact for it to come apart on its own.)

MP3 player with mirror face detached

Pink.

The mirror face is actually kind of like a sticker with a backing having roughly the malleability of thin sheet aluminum. It was stuck by a tacky adhesive to the back of the face, which was a slightly thicker piece of pink plastic.

MP3 player with face removed and tactile domes exposed

Clickity.

The rest of the face comes off easily, revealing the PCB with five tactile domes (the kind that deform under your finger and make an obvious click when depressed) taped in place.

MP3 player with tactile domes partly removed

The domes and contacts.

MP3 player with tactile domes removed

Bull’s eye.

Under each dome are concentric outer and inner contacts on the PCB; pressing the dome connects the center to the surrounding ring, registering a button press.

Freeing the PCB from the case was slightly more than my thumbnail could muster, so I used a prong from the plug end of a phone charger I had handy. As before, it was only lightly stuck into place and required only trivial force to remove.

MP3 player full PCB and battery

The guts.

The internals of this thing, at least from what I can see without desoldering anything, are amazingly simple. Other than a number of discretes countable on one or two hands, you have the battery, the microSD slot, the stereo jack, the USB jack, a very small switch (I think SPDT), and the main event—an SOIC-16 chip running the whole show.

Detail of MP3 player PCB

I don’t know who this “JL” guy is.

The latter is marked with a logo that looks like somewhere between “JL” and “π”, followed by the cryptic legend “AB1426CF3Y13.1-83En” for which Google proves useless to make any connection.

Several of the pins on the microSD card are kept intentionally disconnected (there even appears to be a bit of silkscreen to prevent their accidental connection), which is why I think the SPI mode (which uses fewer pins than the full-speed modes) is in use.

Anyway, the whole thing is actually surprisingly simple connection-wise (a good deal less complex than the player in original Instructable). I kind of wonder if I could perhaps get the whole thing desoldered, reverse-engineer a schematic, and put it back together in a way that would have fewer noise issues.

Fun.

  1. [1] TransFlash, or “TF”, is an outdated name for microSD. Given that microSD is far more recognizable, and that an 4GB or 8GB card is not even plain microSD but microSDHC, I have no idea why they’d call it by this name.
  2. [2] in a similar fashion to this Instructable which uses a somewhat more expensive but mostly identical player

In Perl, we have some funny (and often contraindicated) features that are just useful enough not to excise them from the language. One of them is that the sort and grep operators (which reorder and filter lists, respectively) return aliases, rather than copies, of the original array elements whenever possible. Because of this, the original array can be modified through the sorted/filtered result.

my @a = qw/w o r d/;
say sort @a; # 'dorw'
 
# Note that perl sort is not in-place.
say @a; # 'word'
 
# Change index 3 of the sort result, which is 'w', to a 'z'
(sub { $_[3] = 'z' })->(sort @a);
 
# The change is reflected in the original
say @a; # 'zord'

Getting this functionality into a non-builtin sub is not straightforward—I haven’t determined any way to return an array directly that retains its linkage to the original. However, it’s pretty easy to do something almost as good (or possibly better): Return an array reference that can do the same thing. The trick to this is that @_, the parameters array for a function, consists of aliases to its parameters, but a reference to it can be taken and returned.

sub parameter_alias_array_ref { \@_ }
 
sub dumb_alternative_sort {
	parameter_alias_array_ref(sort @_);
}
 
my @a = qw/w o r d/;
my $s = dumb_alternative_sort(@a);
say @a; # 'word'
say @$s; # 'dorw'
$s->[3] = 'z';
say @a; # 'zord'
say @$s; # 'dorz'

One place this might be useful is in tandem with the so-called “Schwartzian transform”, a Perl idiom for sorting a list based on some projection of the elements rather than the elements themselves. The premise is that, for some function foo(), we would like the result of

sort { foo($a) cmp foo($b) } @array

but, foo() being somewhat expensive, we would rather compute its value for each element only once rather than the multiple times that would be done this way. So, each row is mapped into a 2-tuple containing the value itself and its projection. The sort is performed ordering by the latter value, then the projection is stripped, leaving only the original value. That looks like the following:

# Note that the order is the reverse of what is described above
map { $_->[0] } sort { $a->[1] cmp $b->[1] } map { [$_, foo($_)] } @array
# Intuitive order using temp variables
# Append projection
my @tmp_appended = map { [$_, foo($_)] } @array;
# Sort by projection
my @tmp_sorted = sort { $a->[1] cmp $b->[1] } @tmp_appended;
# Strip projection
my @result = map { $_->[0] } @tmp_sorted;

Note, however, that this result is a copy, not an alias to original elements.

One workaround would be to have the transform return an array of scalar refs to the original array elements. That would look like this:

my @refs =
	map { $_->[0] }
	sort { $a->[1] cmp $b->[1] }
	map { [\$_, foo($_)] }
	@array;
 
# Assign to whatever the 4th element of the result was
${$refs[3]} = 'idk';
 
# Get the results as a plain array copy
my @result = map { ${$_} } @refs;

Ugly and unnatural. But what if we had some way to transform an array of scalar refs into an array aliased to those scalars?

my $ref_result = scalar_refs_to_array_ref(
	map { $_->[0] }
	sort { $a->[1] cmp $b->[1] }
	map { [\$_, foo($_)] }
	@array);
 
# Assign to whatever the 4th element of the result was
$ref_result->[3] = 'idk';
 
# Get the results as a plain array copy
my @result = @$ref_result;
 
# OR, just use @$ref_result directly!

The implementation follows. The fact that @_ aliases the parameters is heavily abused here. The parameters are aliased a few at a time because the dereferenced scalars must be passed directly and explicitly; the obvious shortcut (using map) removes the magic we’re trying to exploit. An alternative would be to construct an explicit list in the form of a string and use eval to alias all of the elements at once. This isn’t an altogether bad idea, but it’s avoided here.

sub parameter_alias_array_ref { \@_ }
 
sub scalar_refs_to_array_ref {
	my $result = parameter_alias_array_ref();
 
	my $count = 0;
 
	# The seemingly straightforward way to do this would be map { $$_ } @_, but
	# that doesn't preserve the aliasing magic that we need.
 
	while(@_) {
		my @part = splice(@_, 0, 16);
		$count += @part;
		my $pa = parameter_alias_array_ref(
			${$part[0]}, ${$part[1]}, ${$part[2]}, ${$part[3]},
			${$part[4]}, ${$part[5]}, ${$part[6]}, ${$part[7]},
			${$part[8]}, ${$part[9]}, ${$part[10]}, ${$part[11]},
			${$part[12]}, ${$part[13]}, ${$part[14]}, ${$part[15]},
			);
		$result = parameter_alias_array_ref(@$result, @$pa);
	}
 
	# Trim excess introduced when the length is not a multiple of the part
	# length above.
	splice(@$result, $count);
 
	$result;
}

EDIT: You might have noticed that up to 15 undefined array elements (specifically, the remaining undefined elements when there are fewer than 16 in the last part) are dereferenced as scalars when the last part of the input is processed. Yet the code still works perfectly. Why?

It’s a semi-obscure bit involving what’s known in Perl as autovivification: If an undefined scalar variable (say, $somevar) is dereferenced as if it were a scalar ref ($$somevar), an anonymous scalar is automatically created and a reference to it is assigned to the variable (something like { my $tmp = undef; $somevar = \$tmp }), and only then is it dereferenced.

Note that this only works if what is dereferenced is a variable; something like ${(undef)} always breaks. In our case, the variable would be $part[n] for any n greater than or equal to the size of the last part; an array element counts as a scalar variable.

Unless you find that the autovivification of up to 15 scalars is consequential performance-wise (it probably isn’t), the code can be left as is. Otherwise, a workaround would be straightforward.

Reflow soldering typically makes use of solder paste, which is fairly easy to work with but has a short shelf life and can only be reasonably purchased in quantity (read: I can’t justify buying any). I performed a very loose experiment this weekend in using the more traditional coiled solder for reflow.

I’d seen two important articles whose advice I sought to combine. One was for the concept of performing the reflow itself using plain solder and a hot air station. I have no hot air station; what I do have is a reflow skillet,  but that article deals in solder paste.

With these concepts in mind, and with a fresh supply of SMT components purchased in anticipation of building my Bus Pirate, I decided on an extremely simple circuit, an LED and resistor in series, and got to work.

Please note that mistakes were made; don’t try any of this until you’ve read the whole thing and know what not to repeat.

I started by scratching out a PCB. I used a box knife instead of etching because I didn’t want to delay the experiment with an uncertainty and, given my more recent failures, it seemed like etching was more likely to be a waste of time than I could allow. In this case, I scratched the outline of a trace roughly 3mm wide across the length of the board, and sliced across it in two places, one for each component.

I colored all of that side of the board except the six points that needed to remain exposed with a Sharpie, thinking it might work as a solder mask. (It didn’t. Read on.)

I used my soldering iron to apply solder to each of the six points I left uncovered; this would be the solder to be reflowed.

0309141748

Sharpied and soldered. Only one of these was a good idea.

After it cooled enough to handle, I placed the components atop the now-solid solder on their pads. Both components were 0603[1], roughly the size of a sesame seed, and nudging them around without flipping them over is difficult, especially with my unsteady hands. One also must take care that the part stays in place instead of sticking to the tweezers. This was a trial of patience.

At this point it was necessary to apply flux; the original flux in the core of the solder itself would have already dissipated when soldered the first time. The flux itself exposed the main two errors that I made in this process:

  • Components should probably be placed after the flux. I had expected the flux to be liquid like in the videos, but at somewhat below room temperature (the temperature of the workspace), it is most sincerely a paste, and it is easily stiff enough to knock the already tenuously-placed components out of place. Bigger components are probably less of a problem since they are already easier to place.
  • Sharpie does not work as a solder mask, at least for reflow; flux readily dissolves the ink. Actually, the ink did seem fairly effective when I was applying the solder with the iron, but it started to lift with the paste, and once the flux was warm enough to flow the whole board was a tacky, blue mess. It naturally follows that the solder wicked all the way up the traces, as evident from the picture, but in this case that wasn’t a problem.

Once everything was relatively ready, I put the board in the pan[2] and turned it up to 375°F, which is reportedly slightly above the melting point for my solder. The board was placed off-center in the ring-shaped area directly over the heating element. The flux quickly turned liquid. After only a couple of minutes, the solder liquefied as well, and once it all seemed thoroughly reflowed, I turned off the heat, leaving the board in the pan as it cooled[3].

0309141821b

Nice board, if you like your flux tinted.

I brushed off the excess flux and scratched through the remaining film to the contact spots I made for power to the board. I connected up the gator clips and powered up. Nothing in either direction. Then I realized that I’d left the plane on the far side of the board untouched, causing the clips to be shorted. Whoops.  Touching the clips to the points on the top side of the board allowed it to function properly.

It can be done!

Stuff I’ll keep in mind for next time:

  • If more than a little solder ends up on a pad, it should probably be wicked off. A little is necessary; a lot can be problematic for placement.
    • I’ve also read that, for small enough parts, unevenness between the pads can cause the component to stand on end instead of soldering properly, called “tombstoning”. Let’s try to avoid the parts that are especially prone (the hard-to-imagine-ly small 0402 and 0201 parts).
  • Flux before placing. It may help keep the components in place.
  • Experiment with mask materials before attempting to use one again.

Thanks to Club Cyberia for being a place other than my garage where I can make this stuff happen.

  1. [1] 0.06 by 0.03 inches
  2. [2] To be perfectly honest, the board was in and out of the pan at least twice as I noticed things I’d forgotten to do, but was only allowed to fully heat when ready.
  3. [3] Cooling or quenching it suddenly is likely to damage the components or reduce the structural integrity of the connections.

Will try to leave the extraneous details out so that this actually gets posted.

The Steel Sandwich hasn’t been touched since December, but a test at 450°F, wrench-tightened, for 30 minutes gave the best transfer yet—except that the copper was so oxidized as to be purple. But I didn’t try to etch it. It might have still worked. Will pick that one up at some point.

I got a credit for the Dangerous Prototypes free PCB drawer and snagged a bare Bus Pirate 3.8 board. If you haven’t heard of the Bus Pirate, look it up—it’s a fine digital exploration, analysis, and prototyping tool.

I have an order in for all of the parts, plus a couple of hand tools I needed and some parts that I think will be useful for the universal PIC ICSP adapter thing I keep touching on here. I hope I can keep my hand steady enough to solder all of those surface-mount parts.

I’ve also ordered a few of the PIC16F527, a relatively recent addition to the PIC 12-bit line, which is only a small amount more expensive than the PIC16F57 (the current cheapest 16F) and has more I/O pins and an onboard precision 8MHz oscillator. That last bit means saving a couple of cents from omitting the external RC, improving the viability in timing-sensitive applications, and simplifying PCB layout. The additional I/O also means that, in some cases, a shift register (like 74HC595) or port expander can be eliminated. Overall, probably worth the extra 19 cents.

Finally, for Valentine’s Day, my wife initiated my membership to Club Cyberia, the only hackerspace I’ve ever heard of in this vicinity. I’m interested to see what difficulties this might help alleviate.

A simple one-directional level shifter is easy to build out of an NPN transistor and two resistors in the common-emitter topology, if the application doesn’t need to sink as well as it sources—that is, if a significant output impedance is acceptable when the output is high. If low impedance is needed for high output, an additional PNP transistor and two resistors[1] can be added, again in common-emitter topology, to re-invert the signal, but then the output low has the impedance instead.

To both source and sink with comparably low impedances, the obvious solution, if you’re properly equipped, is probably CMOS: Two complementary MOSFETs configured to pull the output either up or down, with similarly low impedance either way—or, more likely, a CMOS logic IC that does the same thing, but in a more compact fashion.

Still, there are some possible issues:

  • If you don’t keep a stock of (fairly well matched) N-channel and P-channel FETs around, you can’t really build a CMOS inverter out of them.
  • If all you have are 74HC-series ICs, the output voltage must be from 2V to 6V. If your output voltage is, say, 13V, this is a no-go.[2].
  • If the input high voltage is too much lower than the output voltage, a logic high may not register properly. A preliminary low-to-high shifter (such as the single-sided NPN thing from before, 3 parts) would be needed for each input.
  • If the input high voltage is too much higher than the output voltage, a logic high may do some damage to the IC. A preliminary high-to-low shifter (such as a resistive divider, 2 parts) would be needed for each input.

Incidentally, constructing a CMOS-like complementary output using discrete bipolar transistors is not advisable;  even short input transitions can cause high and low transistors to be on simultaneously for a non-trivial amount of time, a condition called shoot-through, which results in a massive current spike likely to damage both transistors and possibly other components. One way to avoid this condition is to add a resistance between the high and low sides, but then we’re back to the original problem. Shoot-through is evidently less of a concern with CMOS, partly because the FETs involved have better tuned and matched thresholds, and partly because a MOSFET is less subject to self-destruction via thermal runaway than a BJT.

Wanting to prototype something with an oddball push-pull 3.3V-to-13V switch led me to concoct an experiment using only stuff available at a reasonably well-stocked Radio Shack[3], with particular attention to ICs that provide push-pull outputs. So far I’ve tried configurations based on the original 555 timer[4] and the TL082 op amp.

My first experiments with the TL082 in Schmitt trigger configuration were not promising, but I’m suspicious something may have been connected wrong; the logic low never went below 1.15V, which happens to have been the reference voltage, half of 3.3V. Either way, the supply voltage had to read 17.3V for a high output of 13V.

In contrast, the 555-based Schmitt trigger appears to be a workable solution, as long as you can drive the chip 1.5V higher than the desired high output.

555 shifter

555 as a level shifter in just two parts (not including the load). Output is a roughly fixed amount below Vcc.

The output stage of the 555 is a push-pull output, but it is implemented with bipolar transistors in a traditional style, meaning both high and low sides are NPN transistors. This works, but at the cost of about 1.5V from Vcc. If you can pay that cost, it should work nicely.

In my experiments with the pictured circuit, using 1K for the load, the output was 12.5V for a 14.0V input. Similarly, it went up to 13.0V for 14.5V input, and 5.0V for 6.5V.

Apart from the 555, there is a diode to set the control voltage. The CV pin is essentially the top split of a 5K:5K:5K resistive divider from Vcc to ground. The splits of this divider set the high and low thresholds of the Schmitt trigger; they are CV (default 2Vcc/3) and CV/2, respectively. A silicon rectifier diode is added from the CV pin to ground, forming a crude shunt regulator with the internal resistors. This sets CV to about 0.6V and the low threshold to about 0.3V. This is suitable to make the input accept a clean signal directly from a 3.3V or 5V CMOS logic output. Adding a second diode in series with the first would double those levels, making input from a somewhat noisy source or from 5V TTL practical. CV could similarly be set using a Zener diode (in reverse) or by constructing a voltage buffer, but at that point you may just want to order a more suitable part.

So, there you have it—an imperfect but still practical low-impedance level shifter in just two parts.

  1. [1] or one resistor, with caveats I haven’t fully investigated
  2. [2] If you have the older CD4000-series ICs, however, up to about 18V is possible, as long as the inputs are brought within range.
  3. [3] For those of us who don’t have 24 hours to wait for progress.
  4. [4] Not the TLC555 they also carry, which may work better or worse.

(Continued from Part I.)

I lead with two developments that required an additional shopping trip—on Hack Friday, no less.

First, I discovered that there could be some situations in which the holes on the two opposing corners of the plates turn out to be insufficient. In particular, the board may need to be of a minimum size and placed symmetrically across the line between the two bolts; otherwise the pressure over the surfaces of the board may be uneven. One remedy for this could be to restore balance with a spacer of the same thickness, such as a scrap piece of the same copper-clad.

Another fix could be to forget about the holes and secure the board more evenly (for example, on each of the four corners) with some sort of clamps. This might be more generally applicable since it could be adapted to larger plates that do not already have holes. So, I had to identify something that would be useful as a clamp that is also inexpensive and capable of surviving being baked. A small steel beam clamp in the electrical section of Chain Home Improvement Store seemed like it could fit the bill for under $1 apiece.

Second, my wife vetoed my use of the oven in the kitchen. This is completely understandable—we use it for food, and the hardware I’ll be heating, not being graded for food safety, could potentially produce all sorts of unfriendly gases and residues. This is a job for a garage oven, and that means a toaster oven. Fortunately, a fancy one isn’t necessary—an arbitrary box that semi-steadily holds its content at a set temperature is all we need. Much-Maligned Chain Department Store stocks a $15 firestarter model. They were out of stock, so I upgraded to the $20 firestarter model.

Supplies

The ragtag bunch of misfits. Clockwise from top: Toaster oven, steel beam clamps, steel electrical work box cover plates, USB mini-B breakout board patterns on baking parchment, double-sided copper-clad PCB blanks.

So, on to the first experiments executed this evening.

I started by printing the layout of Sparkfun’s USB mini-B breakout board several times over on baking parchment paper. I selected this board because it’s small and thus suitable for repeated trials. (As a bonus, I actually need one; I’ve got a couple of the connectors collecting dust in a drawer.)

Parchment

Left to right: A freshly cleaned piece of copper-clad, a nicely printed pattern on parchment, and one that didn’t come out so nicely.

Printing on parchment is tricky. It is something that you can get to work, but it may take a few tries. Parchment paper is coated with silicone, making it difficult to stick anything to. The fact that the paper releases easily is a desirable property for a toner transfer backing, but it does its job perhaps a little too well. Traces printed this way may not stick long enough to fuse correctly, resulting in smears and runs. When a pattern does take correctly, it must be handled somewhat delicately, as it can scratch or flake off without much of an impact. Still, since someone has gotten it to work[1], I think this can be a reasonably useful medium if you have some patience, and it’s certainly priced to sell (sold by the roll in your grocery store of choice).

I may include the other common media (magazine paper, inkjet glossy photo paper) in future experiments.

Incidentally, any sort of slick tape appears to be a bad choice for attaching the medium to ordinary paper; it being all I had at the moment, it caused more paper jams than I’ve ever encountered with this printer. I’ve had more success with matte tape[2].

I cut the copper-clad for the board and gave it a light cleaning with a soft abrasive[3] before building the apparatus around it.

Patterns, board, and one plate

Copper-clad between two patterns on top of the bottom plate.

One copy of the pattern was placed on either side of the board. The registration wasn’t given too much attention because that isn’t the point of the current experiment (I’ll work on it once I have the adhesion process working), and because the patterns are both the same rather than flip sides of a double-sided board. To conserve the clearly printed copies of the pattern, a misprinted copy of the pattern was used on one side.

Apparatus with top plate

All of the above plus the top plate.

The board and patterns were laid down onto one of the steel plates, then the other plate was placed on top.

Apparatus with clamps

Clamps are added to press everything together.

The steel clamps were added to the edges of this sandwich and the bolts tightened.

Apparatus in oven

The smell of fresh-baked productivity. (But seriously, try not to inhale any fumes.)

The full apparatus was then placed on the top rack of the preheated oven (there are two heating elements situated at the top and bottom, so the bake should be fairly even regardless) and baked for a specified amount of time.

Quenching the assembly

If lowered into the water slowly, there is audible boiling. If dropped quickly, as shown, you end up with a watery mess. Some sort of middle ground is probably a good idea.

Afterward, the assembly is removed from the oven and immersed in cool to tepid water, bringing it to a safe temperature for handling.

The results are examined immediately. The medium is removed without any special degree of care; any toner dislodged by normal handling cannot be considered to have adhered properly.

The variables I’m currently seeking to study are:

  • Bake time
  • Bake temperature
  • Clamp pressure

For tonight’s experiments, I decided on:

  • Trials of 10 and 30 minutes
  • Temperature of 350°F (setting of the oven, not measured temperature)
  • Clamp pressure resulting from tightening the bolts as far as I could using only my fingers, rather than a wrench.

10-minute trial, proper side.

10-minute trial, misprint side.

30-minute trial, proper side. Note that the extra time has discolored the copper somewhat.

30-minute trial, misprint side.

Put briefly, neither result was quite satisfactory, but I believe I’m on the right track. The 10-minute trial gave a better result than I’ve achieved with an iron and parchment. The 30-minute trial was somewhat better, but not so much so that I think adding more time is the key. The toner that did transfer was clear and crisp with no real smudging, which to me indicates that we could afford to apply more pressure. So, it’s likely that the next experiment will be a repeat of tonight’s, except using a wrench to tighten the clamps a little harder.

  1. [1] Refer to the Instructable by dustinandrews.
  2. [2] “magic” or “invisible” tape
  3. [3] Bar Keepers Friend soft cleanser.

While lying in bed last night, I was going over in my head everything I could recall having learned about getting a PCB[1] layout out of my computer and onto a piece of copper clad.

At this point in history I’ve managed to successfully iron a toner pattern onto a board only about three times, and each success came at the cost of around ten failures. The glossy photo paper is the only thing I’ve gotten to work; with magazine paper the image was too smudged to use, while with parchment paper hardly any of it stuck (though what did stick was high-fidelity). What has really been frustrating in this whole process is that there are too many variables and not enough correlation. I don’t know whether I haven’t been using enough pressure, waiting enough time, executing the correct motions, or using the right setting on the iron. For all I know, I could just have a crappy iron!

And everyone seems to have something different to try, with the most consistent results apparently from either (a) using a modified laminator for the toner transfer or (b) equipping for photoresist boards. Of the two, I would surely choose the photoresist, in part because it produces truly sharp results but mostly because the failure/success ratio seems to be lower. But both options involve buying new equipment (and in one case ruining it) with no guarantee of out-of-box success, and given the laser printer and copper-clads already in my possession, I’m already well in.

Anyway, I suddenly had an idea that, if it works, combines the even heat and pressure of a laminator with extremely low (new) equipment cost and increased controllability, the latter of which translates into more meaningful experiments and, when an experiment succeeds, more repeatable results.

What I decided was necessary is as simple as this:

  • The patterns are printed in reverse on the medium of choice—for me, it will be parchment paper since it already exists in my house.
  • The board is placed in alignment with the patterns on one or both sides.
  • The board and patterns are placed between two flat plates of rigid metal, such as steel.
  • The plates are bolted together and tightened at least to the point that nothing slides around.
    • Here, the sustained flatness of the plates is important so that the pressure remains fairly even across the entire pattern.
    • If you have any way to gauge it, take note of the tightness or pressure of the plates on the board. This is possibly one of the variables.
  • The oven is set to the target transfer temperature.
    • To be truly scientific about it, use an oven thermometer to ensure the knob is telling the truth.
    • The temperature is certainly one of the variables.
  • The oven is allowed to preheat until up to temperature.
    • My hypothesis is that a consistent result is probably easier to obtain from a preheated oven due to variances in rise time.
  • The plate apparatus is placed in the oven near the heat source.
    • If the apparatus can be hung sideways from the rack, do so allowing equal heat exposure to the two sides.
    • If the oven has a convection mode, it might be worth using.
  • A prescribed amount of time passes.
    • Another variable.
  • The apparatus is removed from the oven.
  • The apparatus is allowed (as by air) or forced (as by water) to cool to a safe temperature for handling.
    • Maybe another variable.
  • The apparatus is disassembled and the results are examined.
    • An effective transfer should stick well enough that it does not lift or flake when the medium is pulled away. Therefore, the medium can be pulled away without being exceedingly gentle.
    • If the result is unsatisfactory, a hypothesis is formed as to why that relates to one of the variables. The variable is adjusted and another attempt is made.

With this basic process in my head, I went to Chain Home Improvement Store to seek something I could use for the plates. What I found was square steel covers for electrical work boxes, in a flat variety with no punchouts. They already have holes for fasteners at two of the corners, and it was only $1 for the pair. I also got #10-24 stainless steel bolts and wingnuts which themselves totaled $4. This setup should adequately accommodate boards up to about 3 by 4 inches (for comparison, the standard Arduino footprint is 2.7 by 2.1 inches).

I now have all the equipment I think I’ll need to give this a shot, and that could happen as early as this weekend (and I’ll try to take photos). I really hope it works, not just because it would be convenient for me, but because it has the potential to lower the blood pressure of many other frustrated hobbyists.

  1. [1] printed circuit board

ICSP in general

From the perspective of actual information to be transferred, an ICSP (in-circuit serial programming) programmer for a PIC microcontroller is not terribly complicated. As with a CPU, there are operands and instructions that must be issued in a particular order.

ICSP

General pinout of PIC ICSP connector

As with a serial shift register or SPI device, there are two lines—one data line (pin 4, ICSPDAT) to carry the information plus one clock line (pin 5, ICSPCLK) to indicate when that information is valid. In ICSP, the data line is bidirectional so that the programmer can read memory from the target PIC; the programmer should be prepared for that.

There are also the Vpp (pin 1) and Vdd target (pin 2) lines. Vpp must be able to assert either 0V or the programming voltage (13V for most targets). Similarly, Vdd must be able to assert either 0V or the target Vdd (often 5V, but may vary). The switching times must be kept to a minimum; for example, a 16F88 target specifies a Vpp rise time of 1µs.

Vss (pin 3) exists but is not usually switched.

Finally, there is AUX (pin 6), a plain output pin from the programmer to indicate LVP (low-voltage programming) instead of supplying the high voltage on Vpp. Programmers not supporting LVP tie this to ground via a resistor.

The application circuit itself, when presenting an ICSP header, must isolate the pins of the header from excessive capacitance or other interference so that the voltages and rise/fall times are as specified. If possible, the pins used for ICSP should be dedicated. If one or more of these pins is needed for I/O in the application, the circuit should be designed to give the ICSP higher priority (such as by connecting the ICSP header directly but connecting the application circuit via a resistor). If Vpp is connected to an RC slow start circuit (as /MCLR), it can also be isolated using a resistor or a Schottky diode.

Production programmers

The documentations for ICSP differentiates a prototyping programmer from a production programmer as follows:

A production programmer is capable of performing the verification step (i.e., reading back the contents of the target device’s memory as written) with target Vdd set to the minimum and maximum specified voltages of the application circuit.

A prototyping programmer…doesn’t.

This verification is intended to ensure that each memory location in question was either written or erased with a sufficient combination of voltage, current, and time to be reliably recovered.

As implemented by Ardpicprog

Ardpicprog is a project that specifies an ICSP-compatible prototyping programmer using an Arduino for the host computer connection and most of the programming logic.

On the one hand, if the application circuit is simple enough, or if you use the ZIF socket configuration instead of ICSP itself, the programmer circuitry could not get much less complicated, constructed only of three resistors and a single transistor, plus whatever 13V supply you have handy for Vpp[1]. If you’re in a hurry, this could be your pick.

Ardpicprog switching

Switching circuitry for Ardpicprog (not shown: 13V linear regulator for Vpp_SRC, indicator LEDs, ZIF socket for non-ICSP use)

However, there are some issues that may prevent it from being generally applicable, at least for ICSP:

  • ICSP_Vdd is driven directly from an Arduino I/O line. For non-in-circuit programming and for the very slightest of application circuits this is fine. But the absolute maximum DC current rating for that pin (ATmega168) is 40mA, so the  Vdd pin on the application circuit might need to be extremely well isolated in order not to harm anything.
  • ICSP_Vpp has a somewhat high impedance (R2) when outputting high. This might not be a problem in most situations, since the target’s Vpp pin is fairly high-impedance itself, but when programming I noticed that this line was closer to 12V when turned on.
  • The programmer’s logic high voltage is the only target Vdd supported.
    • If the programmer is 5V but the application circuit is designed for 3.3V (some PICs can do this), incomplete isolation on the application side could result in damage.
    • If the programmer is 3.3V (some Arduinos and copycats can do this) but the application circuit is designed for 5V, programming would probably fail unless Vdd to the PIC device is well isolated and the PIC is of a model that supports 3.3V (such as 16LF88—note the L).
    • The programmer is not properly buffered for a self-powered target. For one example, a 3.3V programmer with a self-powered 5V target would probably sustain damage from the current sunk by the ICSP_Vdd pin.
    • Naturally, the programmer is not for production.
  • LVP is permanently disabled. (This isn’t necessarily a bad thing; I’ve read that actually getting LVP to work is difficult.)

As implemented by PICkit 2

Microchip’s own PICkit 2 is a mostly production-capable PIC ICSP programmer. The designs for this 18F2550-based programmer aren’t free (in the sense of liberty), but the firmware and schematics have both been published and clones of the device are plentiful.

Pickit2 switching

Switching circuitry for PICkit 2

While not nearly as simple as Ardpicprog, the switching for the PICkit 2 is not utterly complex, either.

  • The Vpp switch uses a sort of push-pull, allowing both high and low voltages to come through with fairly low impedance. This is controlled by two lines, and the firmware must prevent both from being on at the same time to avoid shoot-through.
  • The Vdd switch is similar, but uses MOSFETs, presumably to reduce voltage drop, and a Schottky diode to prevent reverse current from a self-powered target.
    • A self-powered target is supported by turning off both push and pull in firmware.
    • Whether self-powered or not, the actual target Vdd appears on ICSP_Vdd.
  • The data, clock, and AUX lines are clamped, using PNP transistors, to be no higher than ICSP_Vdd. (The 18F2550 correctly reads 3.3V-level highs and lows even at 5V).

Perhaps the most interesting characteristic of the PICkit 2 is the onboard boost regulator.

Pickit2 boost

PICkit 2 Vpp boost regulator

Using a PWM output[2] (PK2_Vpp_PUMP) with an inductor, the programmer is able to produce and regulate the high Vpp voltage (Vpp_SRC) without a second supply. A resistive divider feeds back to an ADC input (PK2_Vpp_FEEDBACK), allowing the firmware to make adjustments to the PWM duty cycle.

This is by no means an original circuit, nor is it specific to PIC (I’ve gotten one working on an Arduino), but it is a useful inclusion.

What makes this a more-or-less production-capable programmer is its built-in adjustment for Vdd.

Pickit2 Vdd buffer

PICkit 2 Vdd buffer

A PWM output[3] (PK2_Vdd_TGT_ADJ) is used as a rough DAC by passing it through an RC lowpass (R22 and C2), resulting in a steady analog level. The op amp is configured to double the input, so the DAC must output half of the intended voltage. The PFET in the feedback loop increases the current capacity of the amp output.

The maximum target Vdd is less than the programmer’s Vdd due to drops that exist within the programmer. One workaround is to make the target self-powered; all of the lines are set up such that even a 6V target shouldn’t harm a programmer running at 3.3V[4]. By self-powering like this (with any programmer), it becomes more difficult to enter program mode with some targets: The timing requirements vary from device to device, but several of them require Vpp to rise a very short time[5] after Vdd initially rises. When the target is self-powered, ICSP_Vdd cannot be driven low by the programmer. There might be some secret to making this work that I just haven’t read yet.

It would also work to patch in a higher voltage (maybe 6-7V) to the source of the PFET instead of Vdd. For an actual PICkit 2, this would involve some messy hacking that would more likely ruin the device than improve it.

My own ideas

I’ve been toying with an idea to make a production-capable (or nearly-production-capable) programmer based on the principles of these designs plus some of my own ideas.

  • Arduino implementation.
    • This is partly because I think it’s funny, but mostly because it caters to impatience: If you suddenly need a PIC programmer, nobody sells a PICkit retail but at least RadioShack and Fry’s have some variation of Arduino for sale.
  • Full support for any combination of 3.3V or 5V programmer and target.
    • Some Arduinos and other development boards are pushing for 3.3V logic. I say, sure, why not?
  • Push-pull switching for Vpp and Vdd.
    • I think the Vpp switch on PICkit 2 would be a good model for both Vpp and Vdd. I don’t dislike MOSFETs, but I have a zillion PNP and NPN devices and only a very small number of FETs.
    • Using the PK2 Vpp switch for Vdd would allow use of e.g. 5V target with 3.3V programmer. Q2 and Q3 serve as a sort of level shifter.
  • Full level shifting for I/O lines.
    • A level shifter I’ve been playing with in a simulator[6] starts with a buffered 1V supply (2 silicon diodes, 1 Schottky diode, 1 NPN, and input voltage of 2V or higher) through 470 ohms to the base of an NPN. The input is the emitter of that transistor, and the output is the collector, which is pulled up to the desired output voltage.
    • A bidirectional variation of this[7] is to use 2 NPNs with the bases tied together (to the same 1V through 470 ohms) and cross couple each collector to the other emitter, finally pulling up each side to the desired voltage.
      • Unlike the common 1-NFET bidirectional shifter, this design does not require the advance knowledge of which side will be higher, so the target is allowed to be either higher or lower than the programmer.
    • Since these shifters pull up rather than down, firmware or other circuitry expecting pull-down behavior would need to be adapted.
  1. [1] Several are listed, the simplest being a 13V linear regulator based on an adjusted 7812.
  2. [2] Configured to 150kHz.
  3. [3] Again, configured to 150kHz.
  4. [4] But don’t quote me on that.
  5. [5] Less than a small number of ms
  6. [6] Not an original creation.
  7. [7] Also not an original creation.
2-channel-power-Pch

If it works as intended, this circuit should allow an Arduino to control 2 different output voltages via PWM.

(EDIT: The above is the second revision.[1] Note also that the above will not work as-is, except perhaps in the NPN or N-channel variants; it doesn’t account for the fact that the op amp outputs peak well below the voltage necessary to turn off a PNP or P-channel transistor.)

Out of nowhere I just happened to find an 18V wall wart in my junk box. The lack of such a thing makes it necessary for a PIC programmer to produce its 12-14V programming voltage some other way, such as with an adjustable regulator and a pair of 9V batteries or with a boost converter. Even so, a programmer for production-quality output must be able to adjust its own programming voltage as well as its own output supply voltage.

Read More

  1. [1] This version uses P-channel MOSFETs instead of PNP, and better explains the power requirements.
piculear Suite

A suite of pieces that just might comprise a working PIC programmer when connected to an Arduino.

Years ago, while frustrated with my Microchip PICkit 2, which I only bought because of two failed attempts at building serial-port-based PIC programmer designs, I considered the possibility of a somewhat more open design that still had solid USB-based communications and the 5-to-13V boost converter, which was still kind of mysterious to me at the time.

Read More