The Smell of Molten Projects in the Morning

Ed Nisley's Blog: Shop notes, electronics, firmware, machinery, 3D printing, laser cuttery, and curiosities. Contents: 100% human thinking, 0% AI slop.

Category: Electronics Workbench

Electrical & Electronic gadgets

  • 7400-Family IC Stash

    Over the years I’ve accumulated a bunch of obsolete ICs; all I can say is they weren’t obsolete at the time. Sometimes I need one, so here’s a list of the jelly-bean collection where I can find & update it as parts emerge from their hidey-holes in the Heap.

    All hulking through-hole

    • 138 1-to-8 demux
    • 221 monstable (!)
    • 139 1-to-4 decoder
    • 156 2-to-4 dual demux / decoder
    • F521 8-bit comparator
    • 373 8-bit latch (transparent)
    • 374 8-bit latch (clocked)
    • 74 dual D flipflop
    • 244 8-bit buffer
    • 393 dual 4-bit counter (ripple)
    • AS869 8-bit up/down counter
    • 191 4-bit up/down counter
    • 157 quad 2-to-1 mux
    • 164 8-bit parallel output shift register
    • 245 8-bit bus transceiver
    • 151 8-in multiplexer

    Memo to Self: What horror lurks in the box labeled “Old ICs”?

  • IBM Thinkpad 560Z CMOS Battery Connector Polarity

    Thinkpad 560Z Lithium Cell Polarity
    Thinkpad 560Z Lithium Cell Polarity

    Two years ago I converted a $20 Thinkpad 560Z (they’re more expensive now, oddly enough) into a digital picture frame for Mary’s parents, a process documented in two of my late, lamented DDJ columns there and there. It runs a stripped-down Slackware installation that boots directly into a picture viewer, so when you turn it on you get pictures and nothing else. Well, after you get a few screens of the usual white-on-black Linux boot messages, which I think adds a certain geeky charm to a digital picture frame.

    Anyhow, the thing failed just before Thanksgiving with BIOS error messages 161 and 163: its way of telling you that the lithium cell powering the clock chip has gone dead. I hadn’t replaced that cell when I did the conversion and it lasted just about exactly a decade; it was evidently the right size for the job.

    Not being constrained by the confines of the original laptop case, I replaced the coin cell with a grossly oversized CR123A cylindrical lithium cell (having a bunch of them on the shelf and some holders for another project). The connector is in an awkward location, below the IDE socket’s flex-PCB cable, and both wires popped out of the connector shell when I pulled on them. So it goes.

    The top picture shows the proper polarity, as seen inside another 560Z’s lithium cell compartment: red-for-positive on the right, with the circuit board positioned component side down (toward the keyboard). Our daughter did the soldering; she’s since learned about heatshrink tubing and cold joints; it’s good enough.

    This picture shows the CR123A all wired up and ready to go in the picture frame. The circuit board here is component side up, so the connector wires go the other way. Notice the small trace from the red-side pin on the circuit board; that’s your clue that it’s the positive battery connection. Measure the voltage at the backside of the connector to be sure you have those miniature pins properly seated in the connector, too.

    CR123A in 560Z Picture Frame
    CR123A in 560Z Picture Frame

    FWIW, I bought three 560Zs while they were cheap; our young lady installed Puppy Linux on the one in the top picture (hence her soldering) and seems reasonably content. They’re old & slow & cramped by contemporary standards, but just fine for most of the things you’d probably buy a fancy new netbook for.

    Hmmm…

  • Arduino: Slave Select Pin MUST Be An Output in Master Mode

    I’m using hardware-assisted SPI for a project, copied in my own boilerplate code, assigned the bits, and… it didn’t work.

    Jammed hard with mysterious symptoms. Looked like a stack crash, looked like the hardware was broken, looked like a lot of things.

    The final hint, found by stuffing Serial.print() statements in all the usual spots, was that the SPCR register mysteriously changed from the desired 0x71 to 0x61, without any of my code doing the writing.

    Turns out that the Fine Manual has this to say:

    Bit 4 – MSTR: Master/Slave Select

    [snippage] If -SS is configured as an input and is driven low while MSTR is set, MSTR will be cleared, and SPIF in SPSR will become set. The user will then have to set MSTR to re-enable SPI Master mode.

    I planned to use Arduino Pin 10 (PWM10) as the signal to latch the output shift registers, but because I’m developing the code on an Arduino Pro before making the circuit board, I hadn’t gotten around to initializing that pin… which, as you might expect, is also the -SS pin.

    With the pin not set up as an output, it defaults to an input. My cut-n-paste code blipped the pin high and left it low to simulate latching the ‘595 shift registers… but, for input pins, writing a value simulates what would happen when an external signal drives the pin.

    Soooo, I had inadvertently set -SS low, which turned off Master mode, which meant the hardware wasn’t going to send the next byte, which means SPIF wasn’t going to automatically go high when I dropped a byte in SPDR. The code, of course, waited until SPIF was clear before loading SPDR, then hung waiting for it to go high again.

    As always, stupid errors are easy to fix after figuring things out, but ouch did it take a while…

    Moral of the story: always initialize all the I/O pins! (But you knew that, right?)

  • Put Hand Wiring on EAGLE Layer 15

    Hand wiring on Layer 15
    Hand wiring on Layer 15

    Because nearly all of my printed circuit boards are for one-off homebrew projects, I tend to not obsess over getting the last air wire down on the copper. Instead, I route those pesky all-the-way-across-the-board stragglers on Layer 15 with big fat vias on each end, then solder a jumper wire across the board.

    In effect, my Layer 15 is outside the board.

    The screen shot shows a chunk of a board with some Layer 15 wires. I make ’em fat and use swooping semicircular arcs on the ends: they’re easily visible.

    I don’t worry about actually routing the traces; they’re just straight lines and arcs. This generates all manner of overlaps with the rest of the components & wiring, but after I go down through the DRC list and approve ’em all one time, that’s the end of that hassle.

    Two key advantages:

    • All the remaining air wires are genuine unrouted connections
    • I can print out Layer 15 separately to get a hand wiring map

    I make the vias fairly large (here, 100 mils) and a unique shape (octagonal) so that I know each one should get a wire.

    I usually wind up doing the power connections the same way; those vias are square. Conversely, ground vias stitching the top & bottom planes together are round; they get a short Z-wire through the board.

    This probably won’t work if you’re having the boards built by an actual PCB vendor, as they’ll try to make a three-layer board or kick the board out on layout rule violations… but, on the other hand, if you can afford a four-layer board, then most likely you won’t have any trouble routing the wires.

  • Deriving the Logarithm of Photoresistor Resistance From Voltage

    Photoresistor circuit and equation
    Photoresistor circuit and equation

    The general idea is a simple light sensor that can cope with typical indoor illumination, brightening and dimming the digits on a clock so that it’s both visible in the daylight and doesn’t light up the room at night.

    This circuit produces a voltage that varies more-or-less inversely with the photoresistance R. The “decade resistor” DR acts as a range selector: the output voltage will be 2.5 V when DR = R.

    Yesterday I doodled about the voltage-vs-resistance curves and how DR works, showing the equations that spit out V when you know R, which is handy from a circuit-analysis standpoint (if you can say that with a straight face for a two-resistor circuit).

    What you want is the equation that spits out R when you know V, because you can actually measure V. Rearranging the equation in the doodle above produces that equation

    R = DR * (5 – V) / V

    Actually, what you really want is log R, because your sensation of brightness varies logarithmically with the illumination intensity: each doubling of intensity makes the scenery twice as bright. So you could find R, apply a floating-point math package to it, and come up with log R.

    There’s a better way.

    CdS Resistance vs Voltage
    CdS Resistance vs Voltage

    Stand yesterday’s graph on its ear and flip it side-to-side to get this view of the same data points. It’s plotted with a log scale on the Y axis, because the resistance varies over such a huge range.

    The dots represent the values of R produced by the equation above with DR = 1 kΩ. Those are the actual resistance values, at least according to the circuit model.

    The midsection of those dots is pretty straight, so the diagonal line second from the bottom is a straight line “curve fit” with intercepts at

    (0 V, log 10000)

    and

    (5 V, log 100)

    The y = mx + b equation fitting that line is

    log R = (-2/5) * V + 4

    where the (-2/5) comes from the slope of the line:

    (log 10000 – log 100) / (0 – 5)

    and the (+ 4) comes from the intercept at (log 10000), as set by the value of DR. In fact, the intercept is 1+ (log DR), because it’s always a factor of 10 higher than the value of DR.

    Now, what’s nice about that is the equation spits out log R directly, with just some multiply-divide-add action.

    Changing DR by factors of 10 produces the other lines, so (as before) switching DR gives you a low-budget, wide-dynamic-range output.

    DR need not be a power of 10, of course. The dashed line near the middle is DR = 3 kΩ, which puts the more-or-less linear region between about 20 kΩ (fairly dim) and 500 Ω (rather bright). That’s a useful range in my house and it might be close enough for my friend.

    The dashed line approximating those points has an intercept at 1 + log 3000 = 4.5, so the overall equation is

    log R = (-2/5) * V + 4.5

    The approximation gets progressively worse below, say, V = 0.5 and above V = 4.5, so the outline of the algorithm is:

    • V < 0.5 = pretty dark: lowest digit intensity
    • V between 0.5 and 4.5: puzzle over log R
    • V > 4.5 = lots o’ light: max digit intensity

    The Arduino ADC produces a 10-bit integer: 0 through 1023. Call that Vb (“V binary”), which you can scale to V like this

    V = (5/1024) * Vb

    Plugging that into the equation produces

    log R = (-2/5) * (5/1024) * Vb + 4.5

    log R = (-2/1024) * Vb + 4.5

    The useful limits on Vb for the linear approximation are

    • V = 0.5 -> Vb = 1024 * 0.5/5 = 102
    • V = 4.5 -> Vb = 1024 * 4.5/5 = 922

    Checking those limits against the actual formula for R

    • Vb = 102 -> log R = 4.3 (instead of 4.43)
    • Vb = 922 -> log R = 2.7 (instead of 2.52)

    That’s about what you’d expect from the graph: the line is lower than the dots on the dim end (left) and higher on the bright end (right). On the other paw, getting log R without the floating-point math package makes up for that.

    Now, given that you’re going to use a table lookup anyway, you don’t need any arithmetic on Vb at all. Shove all the stuff surrounding Vb to the other side of the equation

    (log R – 4.5) * (-1024 / 2) = Vb

    (4.5 – log R) * 512 = Vb

    Precompute the left side for useful values of R, fill in the corresponding bit pattern to get the desired brightness, then index into the table with the measured Vb: shazam, log R -> brightness bits in one step!

    If you’re exceedingly lucky, the brightness bits will be more-or-less in a binary sequence, in which case you can just right-shift Vb to get that number of bits and send ’em directly to the LED drivers. No table needed: one shift and you’re done!

    So, for example, suppose you want eight brightness levels controlled by three Brightness Bits BB

    BB = Vb >> 7

    What’s not to like?

    Maybe you already knew that and were wondering why it took me so long to get there…

  • Measuring Photoresistor Voltage vs Resistance

    Cadmium sulfide photoresistor
    Cadmium sulfide photoresistor

    A friend wants a digital clock that’s dim when the house lights are low; standard clocks aren’t nearly dim enough. I know how she feels, having added a primary-red filter in front of a blue vacuum-fluorescent clock display to get rid of those garish digits in the middle of the night.

    This job calls for a photosensor of some kind, as you can’t figure it out by time alone.

    After a brief struggle, the parts heap disgorged a 1-inch diameter CdS (cadmium sulfide) photoresistor with a dark resistance over 500 kΩ and a full-sunlight resistance around 50 Ω. Ordinary room light, at least around here, is in the 1-10 kΩ range, more or less, kinda sorta. Down the Basement Laboratory, it’s tens of kΩ.

    Photoresistor circuit and equation
    Photoresistor circuit and equation

    The canonical sensing circuit is a simple voltage divider, with the photoresistor either on the top or the bottom. Putting it on the top means the voltage increases as the light gets brighter, which has a lot to recommend it.

    The resistance varies more or less linearly with the light intensity, to the extent that you can make a very nice linearly variable isolated resistor by bottling up an LED (which has linear intensity with current) with a CdS photoresistor in a light-tight enclosure.

    Anyhow, although the resistance R varies linearly, having the R in the denominator means that the voltage V varies inversely. Worse, because the value of R spans about four decades, there’s a serious range & resolution problem.

    This graph of V against log R shows the situation.

    Output voltage vs log resistance
    Output voltage vs log resistance

    The dots between R=10 Ω and R=1 kΩ are what the circuit spits out, with the “decade resistor” DR = 100 Ω and R values chosen for nice dot spacing. The long tail beyond 1 kΩ shows that for R greater than 1 kΩ, V doesn’t change by very much at all. Ditto for R less than 20 Ω or so, which is beyond the limit for this photocell.

    The straight line through those points is an eyeballometric curve fit to the range from about 20 to 700 and (most crucially) passing through (10 Ω,5 V) and (1000 Ω,0 V). The equation for that line is the usual y = mx + b, albeit with (log R) where you’d expect x. The equation in the lower-left corner is pretty  close to what you want, with D = log DR

    V = (5/2) * ((1+D) – log R)

    Running the photosensor circuit with DR = 1 kΩ would produce an identical series of dots snuggled up along the second line as R varies from 100 Ω to 10 kΩ. Each factor-of-10 change in DR handles another chunk of R’s range, with identical output voltages: when the voltage gets above about 4.5 or below 0.5, just switch to the next value of DR and continue merrily along.

    So that’s a low-budget (if you have cheap relays, like MOSFET analog switches), high-dynamic-range (if you have a good buffer amplifier) light sensor.

    More on how to turn this into a brightness control tomorrow…

    Memo to Self: Can we correlate a digital camera’s exposure at a known ISO with the cell resistance, so I can get some remote light level values?

  • Eagle Polygon Rank Separates Pours

    Shield Amid Ground Plane
    Shield Amid Ground Plane

    Had to look this up again…

    Problem: I needed a shielding plane under a sensitive gizmo that was separated from the ground plane covering the rest of the board. EAGLE poured the ground plane atop the smaller shield polygon, despite the two signals having different names.

    Solution: set the ground plane’s Rank to 2, which means it’s less “important” than the smaller plane. Thus, the smaller plane gets drawn first and the ground plane surrounds it.

    A good ground-plane tutorial is there.

    [Update: That’s a new link location, per the comment below.]

    Memo to Self: The default Rank is, of course, 1 for all polygons.