EAGLE for Circuit Design and PCB Layout

March 21st, 2006 by Keith Neufeld

I’ve been looking for circuit design and PCB layout software for a long time, and in the past couple of weeks I’ve settled on EAGLE. I’ve used it to draw up the most recent schematics here on my blog. Its key advantages for me are:

  • There’s a freeware version. I don’t do enough circuit design to justify paying a lot of money for commercial software–especially software that I haven’t got to try first.
  • It can output netlists from it circuit design module to use with other PCB layout software, and it can output Excellon drill files to use on my friend Joel’s CNC drilling machine.
  • It runs on Windows, Mac, and Linux–and I expect to use all three versions regularly.

To understand why I like it so much, though, it’s worth running through the other software I’ve used.

Electronics Workbench: Multisim and Ultiboard

I got a student copy of Multisim and Ultiboard with my electronics textbooks in 2004. I used it a lot in class, and I think it’s fantastic for doing circuit simulation. It blows me away that it’s even possible to do that level of analysis and simulation on a commodity PC, and I really appreciate Multisim for what it does.

Unfortunately, I also had a not insubstantial list of complaints:

  • The Multisim (circuit design/analysis) UI is pretty glitchy. I had a lot of trouble selecting the component I wanted to move; I’d box-select a group of components and drag them, and parts would get left behind (and disconnected); etc.
  • I had trouble getting the hang of the UI for Ultiboard, the board layout software. I don’t remember exactly what I didn’t like, but I know I gave up in frustration pretty quickly.
  • Worst, though, is that the installation uses a nodelocked license. I installed the software on two PCs in Pittsburg, and when I left, I completely uninstalled it. I’m now within the rights of my license to install it on another PC–but I’ll have to call EWB to get another install code, because I’ve installed it too many times to get a new code automatically.
    So I feel like the next time I install it, I need to be ready to put it onto one PC where I’m going to leave it forever–because how many more times can I call them and tell them (truthfully, but they have no way of knowing that) that I’m moving it to yet a different PC? The offshoot of that is that I’ll probably never install it again.

PCB123

I had used ExpressPCB (next) a long time ago, and while I was searching for it recently, accidentally installed PCB123 instead. Like ExpressPCB, PCB123 is a company that makes small quantities of PCBs for prototyping and hobbyist use, and gives away the software to design the circuit and layout the boards. I don’t even remember what I didn’t like about PCB123–I just know that it took me about five minutes to realize it wasn’t ExpressPCB and I wasn’t willing to learn to use it.

ExpressPCB

LogoChip in Altoids Tin Schematic
LogoChip in Altoids Tin Layout

I had been happy with ExpressPCB for a long time. They’re a board manufacturing house, and they figured out long ago that if they give away circuit design and board layout software, they’ll entice people to use their services.

I think they walk a delicate line trying to decide how much functionality and interoperability to put into their software–too much and people might use their software and then have boards manufactured elsewhere; too little and people will get frustrated using their tools.

In my case, despite finding their UI to be the absolute best I’ve handled, the functionality is too low, and I’ve moved away from their software. With a little more functionality, I’d still be using their software, and I’d turn straight to them when I need a board commercially produce.

First, I have to sing their praises:

  • I found the UI to be fantastic, in both the circuit design and board layout sections. The toughest operation for this type of software seems to be selecting an existing part to move, and I would almost always get exactly the part I was trying to select; it was easy to reselect a different part in the cases when I didn’t get it on the first try.
  • Their board layout software has a netlist checker, so you can see which pins need to be connected. (However, see “ratlines” below.)
  • The UI just has a good “feel” to it–everything handles very nicely.

However, its drawbacks were serious enough for me to move away from it:

  • Foremost, because the software exists entirely to get you to buy boards from ExpressPCB, it has no facility for exporting drill files. I’m drilling boards on my friend’s machine, drawing traces by hand, and etching in a plastic tank–I pose no threat to ExpressPCB’s business–but I can’t use their software to automate my homebrew process. It can’t be made to meet my needs.
  • ExpressPCB doesn’t prepopulate the PCB layout with the components used in the schematic. You have to add and label each component individually. That’s time-consuming and error-prone.
  • ExpressPCB doesn’t support ratlines indicating netlist connections. Yes, it can highlight solder pads that need to be connected–but it’s easier to lay out traces when you have ratlines indicating all of the connections that need to be made.
  • The board layout UI is a little over-eager to merge connections. I’ve had to scroll the entire board off the screen when calling up a new part to add, because with the board on the screen, the part got merged into existing traces before I could even select where the part was to be placed. Similarly, I’ve had entirely unrelated traces merged together because I was dragging a set of parts to a different area of the board, and corners of traces I was dragging (and would have rerouted as the next step) landed on top of other traces.

The biggest issue, of course, was being able to produce the interchange formats I needed–but the other issues served as cautions while looking at other packages.

FreePCB

FreePCB is a really nice-looking package, an amazing programming accomplishment from a single individual, and free of cost but not open source. I like it a lot, and I expect to use it for larger boards in the future. It’ll import component and netlists from other software, and it’s what led me to EAGLE for circuit design.

A few observations:

  • It doesn’t have any corresponding circuit design software. That’s means there’s no way to automate back-annotation when changing a design during PCB layout, and the coupling for forward updates isn’t as tight as with some of the other packages.
  • It’s extremely tedious to lay out a board from scratch without an accompanying parts list from a circuit design package. FreePCB is intended to be used in conjunction with circuit design software, and I’d want to use it that way most of the time. However, I was trying to lay out a one-component, two-connector board without having drawn the schematic, and found it prohibitively difficult to do.
  • It has ratlines, a nice feel, decent export capabilities, etc. It was designed by an engineer–it was made to work well.

EAGLE is a little smoother for me to use, but the free version has some restrictions that I may eventually run into. When I do, I plan to use FreePCB for those boards.

Hand-Created Drill Files

For a 2″ x 2.5″ board with a PIC microcontroller, RJ-45 connector, LED array, lots of sockets, and supporting passives; for the one-component board I mentioned above; and for a couple of other boards I’ve worked on since then; I’ve drawn the circuit (and sometimes the PCB) in one package or another, and then laid out the drill file by hand. It’s not hard–key in a zillion (x,y) coordinates, plot the file in gnuplot to make sure it looks right, use a small Perl script to translate to rudimentary Excellon code, and drill it.

It’s a dumb way to have to do things, but it got me a drill file that I couldn’t get out of ExpressPCB, and it got me a layout that I didn’t have time to figure out how to do in FreePCB. I’d rather not make a lifestyle of it, though.

EAGLE

ADXL202E Carrier Board Schematic
ADXL202E Carrier Board Layout

Which brings me to EAGLE, the software I think I’m going to be using for a long time to come. It outputs the formats I need, it runs on all the OS platforms I use, and a slightly restricted version is available at no cost. The freeware limitations won’t impact me for quite a while: only one-sheet schematics, only two-layer PCBs, and PCBs no larger than 4″ x 3.2″. I’ll hit the last one first, and I’ll use FreePCB for layout when it happens.

I do have a few complaints about the UI:

  • It’s often very difficult to select an onscreen part to move to a different location. I’m starting to resort to drawing a select box around the interior of the part in order to select it and nothing else; I much prefer the click-click-click to cycle through overlapping parts. I think there’s a right-mouse trick to cycle in EAGLE, and I need to learn it.
  • Speaking of right-mouse, too much of EAGLE’s functionality depends on it. I use the right mouse button nonstop when I have one, but my PowerBook doesn’t.
  • The screen doesn’t automatically refresh objects when other objects have been covering them and are removed, at least not in the X11 versions. Yes, I can hit F2 to redraw the screen, but it’s often really messed up until then.
  • EAGLE seems to have serious problems performing unintended merges during component rotation operations–I have PCB traces that get stuck together and I have to reroute by hand. Worse, that situation seems to corrupt the netlist, because it changes the ratlines. I’m stuck with leftover ratlines that disagree with their traces, and no way to correct them. This is very problematic.

But mostly gratitude at finally finding software that does so many things right:

  • Pretty good coupling between the schematic and board layout sections, including prepopulating components and ratlines
  • The ability to export a netlist to use in a separate board layout program
  • The ability to export drill files in Excellon format to drill my own holes

LogoChip and PWM: Bidirectional Motor Speed Control

March 21st, 2006 by Keith Neufeld

Early last week, I was working on expanding my PWM motor speed control to be able to reverse directions. I had the PWM output from my LogoChip’s PWM subsystem, and I wanted to add another line to indicate whether to spin the motor forward or backward.

Because I’m using the 754410 motor driver chip, I need to apply the PWM signal to the pin corresponding to the direction I want the motor to turn, and keep the other 754410 input pin grounded. That means I needed to translate from (speed, direction) to (move forward, move backward). I have lots of digital logic chips lying around, so I knew I could put something together.

Ideal Schematic

Ideally, if I had all the gates I wanted on a single chip, it’s this simple:

Ideal Motor Direction Control Schematic

(Pardon the truncated labels on the right side–EAGLE did that for me in the PNG export.)

I’m using a direction of 1 to mean forward and 0 reverse. So here’s what the schematic means:

  • If the PWM speed signal is on and Direction is 1 (forward), activate the Forward output.
  • If the PWM speed signal is on and Direction is 0 (reverse), activate the Reverse output.

I could have done this with a 74*08 quad AND gate and a 74*04 hex inverter, but that’s two chips. It offends my sensibilities to use two chips when one would suffice, plus I don’t have a lot of room to spare on my LogoChip breadboard. So I looked for something better.

74LS138

I was looking for a chip with a data input and address input(s) to select which output line the data was routed to, and the closest I could find was the 74*138. The ’138 is 3-to-8 decoder/demultiplexer, meant to decode three lines of an address bus into eight enable inputs for memory or other chips: You supply a three-bit address to its inputs, and it activates the corresponding one of its eight outputs.

This wasn’t exactly what I needed, but there’s a trick I figured I could use. I applied the Direction signal to an address input, to select which output would receive the PWM signal; then I applied the PWM signal to one of the enable inputs. In theory, that means that both outputs would be inactive any time the PWM speed signal was off, and the appropriate output would be active when the PWM speed signal was on.

Motor Direction Control with 74LS138

Unfortunately, EAGLE’s circuit symbol for the ’138 is a block diagram that doesn’t illustrate the internal logic, but here’s what’s going on. Direction is applied to address line A, which will select output Y1 (Forward) when Direction is 1 (forward) and output Y0 (Reverse) when direction is 0 (reverse). And the PWM speed signal is applied to active-high enable line G0, to activate the appropriate output whenever it’s high. The other enable lines are active-low, so they’re tied to ground to be active all the time.

But you’ve probably noticed that it’s still a two-chip design–there are two inverters off to the right. Unfortunately for this project, the ’138′s outputs are active-low. Most memory chips have active-low enable inputs (it makes it easier to gang together open-collector selection circuitry), so naturally the ’138 provides an active-low output. In order to get the active-high signals that I wanted to feed into the 754410 motor driver chip, I had to invert the ’138′s outputs, and that meant adding another chip. I did build and test this circuit as a proof of concept, but I still wasn’t satisfied, and kept looking.

As a bit of an aside–I could have used active-low signalling to drive the 754410. It’s an H-bridge driver chip, so it powers the motor whenever it has different inputs. When the inputs are the same–low or high–the motor doesn’t run. However, I’m guessing there’s slightly more power consumption when both inputs/outputs are high, and I wanted it to draw as little power as possible in the quiescent state, so I was determined to come up with a circuit that would provide active-high signalling.

One other note–I tied both inputs to ground with pull-down resistors. As long as the LogoChip is providing outputs, these are irrelevant–but when the LogoChip first powers up, its ports are configured as inputs and don’t provide a valid TTL signal to the ’138. The motor was freaking out (that’s the technical term) when I’d reset the LogoChip, so I added the pull-downs for power-up sanity.

74LS153

The 74LS153 is my final, one-chip solution. It’s a dual 4-line to 1-line data selector/multiplexer, meant to do exactly, uh, the opposite of what I need: It picks which of four inputs to send to the output. But that’s okay–there are two selector/multiplexers in one package. That means I can use one multiplexer to select whether the PWM or nothing goes to the Forward output, and the other to select whether nothing or the PWM goes to the Reverse output. Looks a little somethin’ like this:

Motor Direction Control with 74LS153

Again, EAGLE renders the ’153 as a block without exposing its inner workings, so explanation is in order. Inputs A and B are the address lines (think A0 and A1) to select which data input will be delivered to the output. Note that A and B select for both multiplexers at the same time, so I don’t have to wire to separate address lines for the two multiplexers. Input B (address line 1) is tied to ground because I always want it 0–I’m only working with the first two possible inputs. And the active-low enable inputs are tied to ground, because I always want the chip enabled.

The first selector has the PWM signal at its 0 input (1C0), ground at its 1 input (1C1), and its output (1Y) feeding the Reverse driver. So when Direction is 0 (reverse), the first selector will pick input 0 (PWM) and feed it to the Reverse input of the motor driver. When Direction is 1 (forward), the first selector will pick input 1 (ground, or nothing) and feed it to the Reverse input of the motor driver.

Likewise, the second selector has ground at its 0 input (2C0), the PWM speed signal at its 1 input (2C1), and its output (2Y) feeding the Forward driver. When Direction is 1 (forward), the second selector routes input 1 (PWM) to the Forward motor drive pin. When Direction is 0 (reverse), the second selector routes input 0 (ground) to the Forward motor drive pin.

Because human minds are forward-centric (there’s a very interesting section of linguistics that studies which word out of pairs of opposites has connotations of dominance: forward/reverse, up/down, hot/cold, etc.), it would seem to make more sense to use the first selector for the forward drive and the second selector for reverse. But I wanted Direction == 0 to activate the first selector and Direction == 1 to activate the second, and because I made Direction == 1 for forward, it worked out like this.

I added pull-down resistors again–different values this time, based on the datasheet and application notes. And the circuit works, in a single chip! Yeah, the ’153 is overkill for this application–but I can’t find a simpler single chip that’ll do the job. I could do it with a PAL and have room left over for other tasks; but in the absence of a need for other logic in this project, that’s even more overkill.

Finis.

DIY Logic Probe

March 13th, 2006 by Keith Neufeld

Over the weekend I was working on a bidirectional PWM motor speed control circuit with the LogoChip, and I ended up using a 74LS138 demultiplexer to route the PWM signal to the appropriate H-bridge input. (It’s what I had on hand.) Because I wasn’t that familiar with the ’138, I wanted to test it carefully before connecting it to the motor driver. I needed a logic probe, and I didn’t have one.

A logic probe is a tester–usually a small, handheld tester–with a probe that you poke into different parts of your circuit. When you touch a logic connection, the probe lights up an LED to indicate whether the connection is at a high or low logic level. Radio Shack used to sell one for about $30, although I think they’ve discontinued it and I can’t find it in their catalog any more.

In principle, it sounds simple–something that could be built with two TTL buffer gates, one inverting and one non. In practice, there’s a snag that has to do with the definition of TTL logic voltages: a voltage below .5 – .8V is considered a low signal, a voltage above 2.0 – 2.7V is considered a high signal, and a voltage in between is undefined. (Output voltage specifications are stricter and input voltage specs more generous, to account for lossy transmission.)

The obvious implementation–feeding the input into a TTL buffer–would always indicate either high or low, because the buffer will always produce a valid output even if the input is in the “dead zone.” But the probe needs to have both LEDs off when it’s not touching anything or touching something that’s not a high or low logic signal (like a tristated connection, something that isn’t digital logic at all, an output that’s broken, two outputs mistakenly wired together, etc.). Ironically, to indicate the state of a digital signal correctly, you have to use analog electronics.

I’ve wanted a logic probe for years, and although at $30 I could certainly afford one, I never felt it was quite worth buying one. After building my own, I’d have to concur with my previous opinion. :-)

Different Designs

I searched online and found several logic probe designs, but wasn’t satisfied with any of them. My dissatisfaction fell into two categories:

  • Several of the circuits reported whether the input voltage was above or below 2.5V. That’s doubly wrong: they never go dark to indicate absence of a valid signal; and if you’re going to make that mistake, make it around 1.6V, the middle of the “dead zone.”
  • Other circuits purported to remain dark when the input was in the TTL dead band, but their schematics were beyond my ability to confirm correct operation. They did things like play tricks with pull-up and pull-down resistors between the probe input and TTL inverter inputs, presumably to try to pull dead-band voltages out of the input range of the buffer. I just wasn’t comfortable with this.

So I designed my own around an LM339 quad comparator chip and some resistors, all from my parts bin.

The Circuit

The key to understanding the circuit is to understand the operation of the LM339. A comparator is an op-amp designed to be used open-loop, to indicate which of two input voltages is higher than the other. The inverting input (labelled -) is subtracted from the non-inverting input (labelled +), and if the resulting voltage is positive, the comparator’s output is high; if the resulting voltage is negative, the comparator’s output is low. That is, if the signal provided to the + input is larger than the one provided to the – input, it indicates high; if the signal provided to the – input is larger, it indicates low. In effect, it compares the two voltages.

Then keep in mind a small trick: Most transistor and IC outputs can sink more current than they source, so I wanted to wire the indicator LEDs from +5V to the comparator output, rather than from the comparator to ground. That means I had to use inverted logic on the outputs, which is accomplished by swapping the inputs. It’s easily done; it just messes with the brain a bit.

Logic Probe Schematic

Going through the schematic from left to right, the signal under test is received at the probe input. It’s attached to a high-impedance voltage divider to bias the circuit into the TTL dead band (1.67V) when the probe isn’t touching anything or is touching a high-impedance connection, but which is easily overridden (the bias current is only a few microamps) when a real signal is present.

I built a voltage divider to provide the reference voltages for the TTL low and high voltage levels. I was aiming for .8V and 2.4V; common resistor values of 3.9kΩ, 8.2kΩ, and 13kΩ gave me actual voltages of .78V and 2.41V. Close enough for jazz.

Looking first at the logic-low indicator (which is the lower section on the schematic), the input signal feeds to the non-inverting (+) input of the comparator, with the low reference voltage (.8V from the divider) feeding the inverting input. That means the reference voltage is subtracted from the input voltage, so when the input signal is higher than .8V, the comparator output is high–which leaves the red LED off. (Inverted outputs, remember?) When the input is lower than .8V, the comparator output is low, and the red LED lights.

In contrast, in the logic-high section of the circuit (the upper part of the schematic), the input signal feeds the inverting input of the comparator and the high reference voltage (2.4V) feeds its inverting input. Here the input is subtracted from the reference voltage, so when the input signal is higher than 2.4V, the comparator output is low, lighting the green LED. When the input is lower than 2.4V, the comparator output is high, and the green LED stays off.

The rest of the schematic is housekeeping. Because the LM339 runs as an “infinite-gain” amplifier in an open-loop configuration, it’s subject to self-oscillation, and the datasheet recommends wiring all unused inputs and outputs to ground. And the probe takes its power (and reference VCC) from the circuit under test, so it needs wires to connect to +5V and ground–the jumper at the far right.

Success!

It works like a charm! Because of the inverted logic on the LED-driving outputs, I confused myself about the placements of the inputs a couple of times. But after straightening that out, I haven’t had any problems. It correctly identifies logic levels (and un-identifies non-logic signals), and proved invaluable while troubleshooting my 74LS138 PWM circuit (which will be the subject of another post).

Right now, the probe is built into the rightmost end of the breadboard with my LogoChip, 74LS138, and 74LS04. I’m planning to drill and etch a few dedicated PCBs to make logic probes for myself and some friends, and I’ve just learned to use the Eagle circuit design software–which runs on Mac OS X (among others–another ‘nother post?). W00T!

What’s Missing?

Commerical logic probes have two things that mine doesn’t (not counting a fancy case and a higher price tag): audible output and pulse stretching.

Audible output

Audible output is just what it, er, sounds like: high/low tones played through a little speaker (in conjunction with the LEDs), to indicate high/low logic signals. I don’t think it’d be a big gain for me, but a friend who has one says it’s really handy to be able to focus on keeping the probe tip from slipping off the pin you’re measuring and not have to glance over at the LEDs to check the logic level. I may add that in a future version, or swap probes with him long enough to find out how much it matters to me.

Pulse Stretching

Pulse stretching has to do with the handling of very short pulses. A single bump from low to high of 1ms duration will be detected by the probe and send appropriate current through the high LED, but it’ll probably be so short it can’t be detected (or registered) by the human eye. Pulse-stretching circuitry adds a short-duration timer (say 1/4 second) to the high and low indicators, so that every time a high signal is detected, the indicator lights (and/or sounds) for at least a minimum amount of time (e.g. 1/4 second)–and then for as long as the signal remains at that level. It just gives your eye longer to detect very rapid pulses.

I’m undecided on the topic for my own use, though. I know it’d be annoying to have short pulses coming through and miss them because they were too brief to see. On the other hand, since a lot of what I’m interested in testing right now is PWM signals, I don’t want pulses stretched. PWM is all about repeating rapid pulses, and I prefer to have variable (perceived) LED brightness as an indicator of PWM duty cycle.

I suppose the right answer is to add a switch to select the behavior. Pulse stretching isn’t difficult–it’s just a couple of monostable multivibrators, and the LM339 datasheet shows how I could build them from the two unused gates on the chip I’m already using. That dashes my hopes of dropping from a 14-pin quad comparator to an 8-pin dual comparator and making my logic probe extra slimmy; but sometimes that’s the price you have to pay for greatness.

Voltage Supply

One last consideration is that my circuit “trusts” the voltage supply from the circuit under measurement. The logic probes that I’ve seen all take their power from the test circuit–but mine also divides the circuit’s voltage to get its reference voltages. That means that if the test circuit’s voltage is nonstandard or faulty, my probe will behave differently than expected. It’s unlikely to be damaged–the LM339 can run on a supply voltage of 3-18V–but it wouldn’t necessarily deliver accurate results.

And there’s not much I can do about it without getting a lot fancier–a 7805 regulator needs something like 2.5V of headroom to maintain regulation, and even the more efficient regulators need some headroom. So when the probe is receiving the expected 5V supply, adding a regulator would potentially make it behave worse. I could do something clever stacking diodes to construct a reference voltage, but I’m not sure it’s worth it to me. Guess I might play with it for V2.

LogoChip: PWM Motor Control

March 9th, 2006 by Keith Neufeld

Built-In PWM

A while back, John sent me some code that he and Tom had been using to test the pulse-width modulation (PWM) capabilities of the hardware underlying the LogoChip. I read through the PIC18F2320 datasheet over the weekend and learned how it does PWM; and between John and Tom’s sample code and the information in the datasheet, tonight I got a motor running at variable speed under software control.

To use the PIC’s PWM, you configure the Timer 2 counter for the modulation frequency (period, actually), then set the output port into PWM mode and configure the duty cycle. Sounds simple; it’s really just a matter of finding all the control registers and the proper bits. Because the PWM is implemented in the chip’s hardware, it keeps running at the last-set duty cycle (== motor speed) even if you’re doing something else or your program stops running, so you can set and forget.

I’d like to measure the PWM output frequency and confirm what the Timer 2 counter and prescalar are doing, but my frequency counter is giving me weird results and I have no idea how far out of calibration my scope is, so that’ll have to wait for another day. When I hook a speaker to the output, it sounds well below 440Hz, but the frequency counter is trying to tell me it’s 2+kHz. Feh.

Huh, when I calculate the frequency (if I’m doing it right), I come up with ~2.4kHz. My speaker is a piezo and it sounded funny, so maybe that’s outside its range and the frequency counter was right on?

The Code

After I got over the excitement of just getting it to work at all, I wanted it to do more than let me manually set a speed for my motor, so there are a couple of extra procedures at the bottom (pwm-speedup and pwm-slowdown) to ramp the speed from slow to fast and back down to slow. They add to the code length, but they’re not critical for implementing PWM.

Here’s the program:

Here’s the code:

;   Keith Neufeld
;   08-Mar-2006
;
;   LogoChip program to demo motor speed control with PIC PWM output.
;   Uses PWM channel 1 on port C2.  Duty cycle values determined with
;   NPN transistor driver with 9V motor supply.

constants [
    [CCP1CON $fbd]                      ;   capture/compare/PWM 1 control reg
    [T2CON $fca]                        ;   timer 2 control register
        [TMR2ON 2]                              ;   timer 2 enable bit
        [T2CKPS1 1]                             ;   timer 2 prescale bit 1
    [CCPR1L $fbe]                       ;   C/C/P 1 register low byte
    [PR2 $fcb]                          ;   timer 2 period register

    [pwm-port-ddr portc-ddr]            ;   PWM 1 outputs on port C2
    [pwm-bit 2]

    [period 255]                        ;   default timer period to use
    ;[low-duty 110]                     ;   lowest duty cycle for my motor to
    [low-duty 10]                       ;   start from a stop
    [high-duty 255]                     ;   highest possible cycle
]

;   Initialize PWM by configuring timer 2 for PWM period and enabling PWM mode.
to pwm-init
    clearbit pwm-bit pwm-port-ddr       ;   set PWM port to output

    ;write T2CON 6                      ;   set timer 2 on, prescalar 16
    setbit T2CKPS1 T2CON                ;   set timer 2 prescalar to 16
    write PR2 period                    ;   set timer period highest possible
    setbit TMR2ON T2CON                 ;   turn on timer 2

    write CCP1CON 12                    ;   set PWM mode
    ;write CCPR1L 128                   ;   set 50% duty cycle
end

;   Set PWM period and duty cycle.
to pwm-set :period :duty
    write PR2 :period                   ;   set timer period
    write CCPR1L :duty                  ;   set PWM duty cycle
end

;   Disable PWM by shutting off timer 2.
to pwm-off
    pwm-set 0 0                         ;   disable PWM by setting duty cyc to 0
    clearbit TMR2ON T2CON               ;   and turn off timer 2
end

;   Enable PWM and ramp up to highest speed at :increment / 255ths
;   per 1/10 second.
global [duty]
to pwm-speedup :increment
    setduty low-duty
    pwm-set period duty
    repeat ((high-duty - low-duty) / :increment) [
        wait 1
        setduty duty + :increment
        pwm-set period duty
    ]
    setduty high-duty
end

;   Enable PWM and ramp down from highest speed at :increment / 255ths
;   per 1/10 second.
to pwm-slowdown :increment
    setduty high-duty
    pwm-set period duty
    repeat ((high-duty - low-duty) / :increment) [
        wait 1
        setduty duty - :increment
        pwm-set period duty
    ]
    setduty low-duty
end

LogoChip: Small Motor Control

March 8th, 2006 by Keith Neufeld

LogoChip Motor Control

Yesterday after class, Steve Atwood and John were talking about controlling a small motor from one of the LogoChip’s output ports. Steve had wired the motor from the LogoChip to ground, and when he activated the output port, the motor would barely spin.

The problem is that the chip on which the LogoChip is based can’t source a lot of current, so it can’t provide enough power to run the motor (even a small one). There are a couple of other ways to wire the motor that work better (which I’ll show below), but first, let me try to explain why it doesn’t work when it’s wired the simple way.

Source and Sink

Imagine a T-fitting attached to a faucet, with the bottom draining into the sink and the side leg connected to a hose. (This is almost exactly like the faucet fitting on a roll-up dishwasher, except the dishwasher has two hoses and we have only one.)

The T-fitting has a valve in it that you can turn, which connects the hose to either the faucet or the sink. So if you turn the valve to the faucet position, you can supply (“source”) water to the hose; if you turn the valve to the other position, you can put water in the other end of the hose and have it drain out into the sink.

One last complication: You only open the faucet enough to supply a trickle of water, not a torrent. But the bathtub is nearby, and you can open its faucet all the way to get as much water as you want.

If you wanted to use the water to spin a water wheel, what would you do? Your first instinct would be to set the valve so that the faucet supplies water to the hose, and hold the hose over your water wheel. That would work–sort of. Because the faucet will only supply a trickle of water, you only get a trickle into your wheel, and it doesn’t turn very fast.

Although it’s counterintuitive, you can actually spin the wheel faster by running a hose from the bathtub faucet (open wide) to your water wheel, then holding that over a funnel into the hose to your sink, with the valve (remember the valve?) set to drain water from the hose into the sink. The bathtub supplies all the water you want, the wheel spins, and the valve drains water down the sink as fast as the bathtub supplies it.

That’s a reasonable parallel for how the circuitry works on the output pins of our LogoChips. They’re not able to source a large amount of current (a trickle of water from the faucet), but they can sink quite a bit (sending the bathtub’s water down the drain).

Active High

Last night, I tested controlling a small motor in three different ways from my LogoChip. First, I hooked it directly to the LogoChip pin and to ground, so that when the pin was on, the motor ran. This type of arrangement is called “active high,” because when you want the motor to be active, you make the voltage on the chip’s pin high.

Motor Driven from PIC Port, Active High

To turn on the motor, I set the port’s value to 1 (setbit). This made the port output +5V, causing power to flow from the pin through the motor to ground. (Engineers, pardon me for using positive current flow, but there’s no point in getting into that much detail in this class.) The motor spun, but weakly.

Active Low

Next, I tried a configuration called “active low,” in which you set the chip’s pin to a low voltage to make the motor active. To set this up, I wired the motor from the pin to the +5V power connection, instead of to ground.

Motor Driven from PIC Port, Active Low

Then to activate the motor, I set the port’s value to 0 (clearbit), so that the pin’s voltage dropped to 0 and power was coming from +5V through the motor to the pin. The motor spun much faster, demonstrating that the chip is able to sink more power than it can source.

Transistor Driver

Finally, I tested using a separate transistor to power the motor. I had a suspicion that even though the motor ran faster in an active-low configuration, I might be able to get yet more performance using a separate transistor.

Motor Driven from PIC Port, NPN Transistor Driver

In this circuit, the LogoChip port goes high (+5V) and sends a small current (5mA) through the base-collector (B-C) junction of the NPN transistor. The transistor has a beta (amplification factor) of about 200, so that permits an emitter-collector current (E-C) of about 1A–enough that I’m pretty sure the transistor is in saturation, even though I haven’t checked the datasheet.

In non-geeky-electronics terminology, the transistor is working like a relay. A small amount of power through the relay coil controls a large amount of power through the relay’s contacts. In the case of the transistor, one wire (the collector) is shared between the low-power coil circuit and the high-power contact circuit. All the stuff with the numbers is just calculating the right value(s) of resistor(s) to use based on your circuit and the characteristics of your transistor.

And it worked as expected. The motor spun noticeably faster with the transistor driver than it did even in the active high configuration.

Stuff for Steve

I dug a couple of salvaged transistors and resistors out of my parts bins, soldered longer leads onto them, and brought them to work today for Steve to try out. I’ll be interested to see how much difference it makes for his motor. And like Tom McGuire, I have plenty of stuff saved up, so the offer’s open to anyone in class if you need help with circuits or components.

LogoChip: Audio Playback Demo

February 28th, 2006 by Keith Neufeld

Over the weekend and last night, I’ve put together a demo of using sensors and triggers with the LogoChip. The demo uses one of the built-in A/D converters to monitor a CdS photocell, and then trigger audio playback on a Radio Shack 276-1323 recording module.

The code watches for the light level to dim and then triggers one of two recordings, the idea being that someone is probably standing over the box looking into it. It’s actually a bit complex, because I keep a running average of the recent brightness, to make it easier to tell whether a sudden drop is a significant event or just noise variation on the sensor. LogoChip Logo doesn’t have terribly good support for arrays, and it was fairly interesting writing ring-buffer code.

Adapting the Playback Modules

[INSERT PHOTO OF CIRCUIT IN BOX]

The little PCBs on the sides are the Radio Shack audio playback modules. Each has an offboard record button and an onboard playback button. I desoldered the 9V battery clip that came with the units and soldered on leads to take power from my PCB, to cut down the number of batteries I had to install. I just now realized I had mistakenly plugged the power into the regulated 5V instead of the unregulated 9V, so that may explain why the playback was relatively quiet. It also speaks well for a wide supply voltage range on the modules.

The playback buttons are NO with pullup resistors, and ground their line when closed. Because they’re rubber pushbuttons with graphite contacts the press directly onto the PCBs, there were no leads to solder my remote trigger wires onto, so I wrapped them around the lower leads (toward the middle of the PCB) of the pullup resistors, R3.

[INSERT CLOSEUP PICTURE OF MODULE PCB]

Then I plugged the remote triggers into ports C6 and C7 on the LogoChip. Since the playback buttons on the modules are active low, I had to reverse my software logic and set the ports high on initialization, then pull them low to activate.

;   Configure the audio trigger I/O port.
to init-squawk-port
        ;   Set left and right triggers off (active low, so set high)
        setbit squawk-left-bit squawk-port
        setbit squawk-right-bit squawk-port

        ;   Set left and right triggers as outputs
        clearbit squawk-left-bit squawk-ddr
        clearbit squawk-right-bit squawk-ddr
end

;   Trigger the external playback modules
;   Parameter: which module to trigger
to squawk :squawk-bit
        ;   Trigger it (active low, so set low)
        clearbit :squawk-bit squawk-port

        ;   Wait a smidge to be sure it registers
        wait 1

        ;   Clear the trigger (active low, so set high)
        setbit :squawk-bit squawk-port
end

The Software

[INSERT DETAILED DESCRIPTION OF RUNNING AVERAGE FUNCTION]

I learned several important lessons from this programming exercise:

  • The A/D converter needs longer than .1 seconds between readings–at that repeat rate, I was getting garbage every time. .2 seconds appears to have been working reliably.
  • The LogoChip Language Reference gives the positions of global variables m and n incorrectly, which led to a buffer overflow in my code. Global n is actually position 0 and m is 1, not 1 and 2 as stated.
  • LogoChip Logo does bizarre things to arithmetic expressions. I have no idea how it was evaluating

    setsum-bright sum-bright - global (array-base + array-index) + bright

    because I couldn’t figure out any sequence of evaluation that led to the results it was giving me. I solved it with parentheses:

    setsum-bright (sum-bright - global (array-base + array-index)) + bright

    but it’d be nice to understand what was happening.

The Code

Here are the programs:

  • squawk.txt – Test code to play back sound samples
  • light-level.txt – Test code to monitor and report light levels
  • light-demo.txt – Program to monitor light levels and trigger audio playback

Here’s the code:

;   Keith Neufeld
;   27-Feb-2006
;
;   LogoChip program to demo measuring ambient light level
;   with CdS photocell wired from LogoChip port A1 to +5V
;   and 1K resistor wired from A1 to GND.
;
;   When light level suddenly becomes dimmer, trigger audio playback
;   using Radio Shack 276-1323 20-second recording modules
;   with play buttons wired to LogoChip ports C6 and C7.
;   Play buttons are active low.

;   Port assignments for the photocell and audio units
constants [
        [cds-port porta] [cds-ddr porta-ddr] [cds-bit 1]
        [squawk-port portc] [squawk-ddr portc-ddr]
                [squawk-left-bit 6] [squawk-right-bit 7]
]

;   Array for averaging brightness
global [array0 array1 array2 array3 array4 array5 array6 array7 array-index]
constants [
        [array-base 2]
        [array-len 8]
]

;   Current brightness, sum of recent brightness, average recent brightness
global [bright sum-bright avg-bright]
;   Calculated brightness values that indicate dimming
global [threshold-shady threshold-dark]

;   At powerup, run the main program.
to powerup
        startup
end

;   At startup, clear the array storage space, initialize some
;   global variables, and configure the I/O ports.
to startup
        init-array
        init-vars
        init-squawk-port
        init-cds-port

        prs "starting
        watch-brightness
end

;   Loop forever, taking samples and watching for dimming.
global [already-shady already-dark]
to watch-brightness
        loop [
                ;   Calculate what fractions of previous brightness
                ;   constitute being dim
                calc-thresholds

                ;   Get current brightness
                read-bright

                ;   The following logic for different brightness conditions
                ;   is carefully arranged to make a successful test exclude
                ;   success on subsequent tests.  I would have preferred to
                ;   write this using
                ;
                ;   if  [ block 1 ]
                ;   elseif  [ block 2 ]
                ;   elseif  [ block 3 ]
                ;
                ;   but LogoChip Logo doesn't support that, and I got cranky
                ;   nesting the conditional blocks three deep using the syntax
                ;   that _is_ supported.
                ;
                ;   Caveat maintainer.

                ;   If we're getting brighter,
                if bright > avg-bright [
                        ;   Start paying attention to getting dimmer again
                        setalready-dark 0
                        setalready-shady 0
                ]

                ;   If we're significantly darker than before,
                if bright < threshold-dark [
                        ;   And we haven't already done something about it,
                        if not already-dark [
                                ;   Then cause an event
                                dim-a-lot-event

                                ;   And remember that we're already dark
                                ;   and don't need to trigger another event.
                                setalready-dark 1
                                setalready-shady 1
                        ]
                ]

                ;   If we're a little darker than before,
                if bright < threshold-shady [
                        ;   And we haven't already done something about it,
                        if not already-shady [
                                ;   Then cause an event
                                dim-a-little-event

                                ;   And remember that we're already shady
                                ;   and don't need to trigger another event.
                                setalready-shady 1
                        ]
                ]
        ]
end

;   Event routine for when slight dimming is detected
to dim-a-little-event
        prs "|dimming a little|

        ;   Play the message from the right speaker.
        squawk squawk-right-bit

        ;   Give it a couple of seconds to finish.
        wait 20
end

;   Event routine for when significant dimming is detected
to dim-a-lot-event
        prs "|dimming a lot|

        ;   Play the message from the left speaker.
        squawk squawk-left-bit

        ;   Give it a couple of seconds to finish.
        wait 20
end

;   Clear the array.
to init-array
        setarray-index 0
        repeat array-len [
                setglobal (array-base + array-index) 0
                setarray-index (array-index + 1) % array-len
        ]
end

;   Initialize global variables.
to init-vars
        setsum-bright 0

        setalready-shady 0
        setalready-dark 0
end

;   Configure the audio trigger I/O port.
to init-squawk-port
        ;   Set left and right triggers off (active low, so set high)
        setbit squawk-left-bit squawk-port
        setbit squawk-right-bit squawk-port

        ;   Set left and right triggers as outputs
        clearbit squawk-left-bit squawk-ddr
        clearbit squawk-right-bit squawk-ddr
end

;   Configure the photocell I/O port.
to init-cds-port
        ;   Set photocell port as input
        setbit cds-bit cds-ddr

        ;   Give time for the operator to get their hand out of the way
        ;   and find out how bright the room can be
        repeat 10 [
                ;   Read the current brightness and store rolling average
                read-bright
                ;prs "average
                ;print avg-bright
        ]
        ;prs "|final average|
        ;print avg-bright
end

;   Trigger the external playback modules
;   Parameter: which module to trigger
to squawk :squawk-bit
        ;   Trigger it (active low, so set low)
        clearbit :squawk-bit squawk-port

        ;   Wait a smidge to be sure it registers
        wait 1

        ;   Clear the trigger (active low, so set high)
        setbit :squawk-bit squawk-port
end

;   Read the brightness and work it into a rolling average.
;   Uses a ring buffer to compute the rolling average.  If you know what
;   that means, there's not much I can teach you about LogoChip Logo.
to read-bright
        ;   Read current brightness
        setbright read-ad cds-bit
        ;prs "|current brightness|
        ;print bright

        ;   Roll off oldest value from rolling average and add current
        ;   Parentheses around first two operands are necessary--
        ;   returns random result without
        setsum-bright (sum-bright - global (array-base + array-index)) + bright

        ;   Save current brightness and advance history pointer
        setglobal (array-base + array-index) bright
        setarray-index (array-index + 1) % array-len

        ;   Calculate recent average brightness, rounding the fraction
        setavg-bright (sum-bright + (array-len / 2)) / array-len

        ;   A/D converter seems to require .2 sec between readings
        wait 2
end

;   Calculate thresholds of dimming based on recent average brightness.
;   Multiply then divide because fractions become 0 in integer arithmetic.
to calc-thresholds
        setthreshold-shady (9 * avg-bright) / 10
        ;prs "|shady threshold|
        ;print threshold-shady
        setthreshold-dark (5 * avg-bright) / 10
end

LogoChip Desktop Serial Port Configuration

February 21st, 2006 by Keith Neufeld

After learning of the ! print portnames command from John, I finally got my PowerBook’s LogoChip Desktop Software talking over my USB serial to my LogoChip.

Turns out the Classic mode support and the Java serial communications driver installation error were red herrings. The problem was simply that LogoChip Desktop was defaulting to the first serial driver in the list–which was the IrDA driver. Since my desktop computer doesn’t have IrDA, it picked the USB driver–the only one in the list.

The solution was simply to update my config.txt to read:

com-port: /dev/tty.usbserial0

I had previously tried changing it to usbserial0, but it didn’t recognize that format. It was the ! print portnames command that led me to the device-file syntax.

And it works. Hooray!

Detailed instructions on the class wiki.

Project Idea: Flash Subliminals

February 20th, 2006 by Keith Neufeld

(Originally sent to the class mailing list)

Here’s a project to carve up single-use cameras and make their flash project a very short message through the lens onto a surface:

http://www.hactivist.com/flashpoint/

If this actually works, it could be kinda interesting to have in the gallery. And I have a box of these at home that I could contribute.

Question for someone who knows ShiftSpace: Would there be somewhere we could have a light-colored wall (or projector screen), dark lighting, and a box sitting in front of it that randomly flashes messages onto the wall?

Question for everyone: Let’s say we could have four different frames, sequenced somewhat randomly. The flash will be so quick, you won’t be able to see the images long enough to read or distinguish them consciously–if words, say a limit of ten letters; if images, then something simple. What messages or images would you like to project?

Project Idea: Cell Phone Abuse

February 17th, 2006 by Keith Neufeld

(Originally sent to the class mailing list)

I know it’s a little late to be adding more ideas, but I just had another one walking back from class. Kinda jumped out at me, in fact, for reasons that’ll be obvious once you read it.

Cell phones have ushered in all kinds of new inconsiderate behavior–erratic driving; loud, personal conversations in quiet public spaces; etc. But my personal favorite most hated behavior is when you pass someone on the sidewalk and they say, “HEY! HOW ARE YOU!,” and you look at them like who the heck are you, and then you see they have a freakin’ borg implant on the side of their head and they were talking on the darn phone.

Project idea: Make a display with a few heads that illustrate the worst cell phone abuses. They wait until people get close and then carry on conversations, they shout things but they’re really to someone on the other end of the phone, etc. I dunno, several heads clustered together apparently talking to each other but then the conversations diverge and you realize they were sitting together but talking to other people. You could have three in one part of the gallery and two in another and once in a while they’re talking to each other (which would take a fairly clever viewer to figure out).

If you made enough rude behaviors, it could take a long time (15-30 minutes) to cycle through them all. Most viewers probably wouldn’t stay for the whole thing, so everyone who saw it would witness a slightly different portion and get different things to talk about with their friends.

Mini Pumps

February 11th, 2006 by Keith Neufeld

Serendipity strikes again! After thinking up the idea for a dancing water fountain, I was stumped on where to find pumps to circulate the water, but remembered that Harbor Freight somtimes has pumps for outdoor waterfall displays. I checked their flyer that I had just received, and they had not one but two different small pumps on sale this week, for $5 and $10! One of them even specifically listed tabletop fountains among its applications!

I dropped by Harbor Freight last night and bought both pumps. After trying them out in the sink, I’m pretty sure the larger one will work for my fountain, although the smaller one sure is cute. :-)

Smaller Pump

The smaller pump is Harbor Freight item number 45303, rated for 66 gallons per hour. It has a 1/2″ outlet and a 1/4″ adapter, which makes a stream barely larger than what I’d like for one of the jets in my fountain. It was on sale for $4.99, regularly $9.99.

Harbor Freight Mini Pump #45303

When I first tested it, I had it stuck flat on the bottom of the sink, and its own water splashing down on top of itself disturbed the surface of the water enough that it was trying to suck in air, and the water stream “lurched” as it got water, didn’t get water, got water again, etc. Then the suction cups on one side popped loose (mental note: don’t expect the pump to stay in place under power of its suction cups alone) and it leaned to one side, making an arc of water that was much less disruptive and more photogenic.

Not large enough to power eight (or sixteen) jets, though.

Larger Pump

Perfection! Harbor Freight item number 41287 is rated for 190 gallons per hour, which turns out to be more than I think I’ll need, but it’s adjustable. It has a 1/2″ outlet that makes quite a stream! It was on sale for $10, regularly $17.99.

Harbor Freight Mini Pump #41287

The inlet has a rotating “switch” (visible in the photo on the Harbor Freight web site) to limit the amount of water taken into the pump. The photo above shows the amount of output at the second-lowest setting, which is about as far as I wanted to go in the sink–but it can put out a lot more water if it turns out that I need it. This is definitely the right pump for this project, and it was CHEP! Hooray!

Several observations:

  • I think I’ll want to build a completely submerged enclosure for the pump. That presents the complication of making good enough seals to get the power cord and the outlet tubing through the enclosure without leakage. It also complicates replacing the pump if/when it fails.
  • While prototyping, I’ll need to be able to access the inlet “switch.” That means that I can’t seal the pump into its enclosure until I’m sure I know which setting will provide the right amount of water.
  • From what I can see of the impeller design, the pump won’t suffer if its output is constricted or cut off entirely. That reduces the need for a bypass valve and simplifies my work.
  • I looked for clear tubing in the store to go with the pump and couldn’t find any, so I’m kind of annoyed that they list it for cheap (25′ for $3) on the web page right next to the pump.