Yesterday, that meant Phase-Locked Loops (PLLs).
It occurred to me that a PLL might be the key to a couple of other things I wanted to try:
- Layering a digital data signal onto a DC power signal or current loop, so I could power and communicate with a sensor or other small embedded system over a single pair of wires.
- Doing something cool with the Sci-Toys Freespace Laser Communicator.
Let's abstract away the physical layer, and just assume that we want to send a bitstring over a carrier signal somewhere in the 25 kHz to 1MHz range. We can use a PLL chip, e.g. a 74HC4046, to lock on to the carrier signal. When we capacitively couple the input signal to the '4046, we can size the capacitor for a high-pass filter to get rid of low frequency noise. If we're lucky, interfering signals will be much lower frequency than the signal we're sending (e.g. 60 Hz hum, fluorescent lighting, nearby LED multiplexing, etc.), so we can get away without needing to build a highly-selective bandpass filter.
Frequency-shift keying (FSK) would be a natural choice for the modulation scheme, as used in early modems. We'd pick a pair of frequencies close enough that the PLL can switch from one to the other quickly, and assign them to 0 and 1. The demodulator circuitry would determine which frequency was received by looking at the VCO (voltage-controlled oscillator) control signal from the PLL chip. Generating the signal on the sending end would be easy, using another VCO or a PWM (pulse-width modulated) output from a microcontroller.
Simple FSK has some downsides, though:
- It isn't naturally self-clocking: you'd need a synchronizing mechanism, and an encoding layer on top of FSK that ensured enough frequency transitions to stay in sync.
- The PLL has to re-lock with every bit change; making it agile enough for an acceptable bit rate might compromise its stability and noise resistance.
Ideally we'd read the duty cycle by checking the signal input at the time the PLL output falls: the PLL always outputs a 1/2 duty cycle. But there's a catch: the '4046 PLL chip doesn't output the amplified version of the signal, so we don't have direct access to it. We could do out own amplification and buffering before passing the signal to the '4046, but that seems like a waste of circuitry.
Instead, we can kludge it by repurposing the unused "Phase Detector I" output from the PLL, which gives [ signal XOR vco ]. This output will produce a pulse that either falls (receiving logical 0) or rises (receiving logical 1) at the time that the VCO output falls. It's unfortunate that it's changing at the same time as our clocking VCO signal (we'd much rather have the original signal, which is stable for a long time around this transition), but we can work around that with an RC (resistor capacitor) low-pass filter to delay the pulse a bit, and a Schmitt trigger to clean it up: that'll give us an sigal which is high for logical 0 and low for logical 1, and which stays valid for some appropriate number of nanoseconds after the underlying transition (to let the subsequent gates and latches get set up). The RC might be unnecessary, but it depends on the delays inside the PLL and I wouldn't want to bet on it (at least not without an oscilloscope to confirm all the timings).
At this point we have 3 outputs from the PLL section:
- LOCK - digital ouput indicating PLL lock (cleaned up with comparator or Schmitt trigger)
- VCO - local oscillator square wave, rises in sync with input signal, falls to clock bit
- BIT - bit read from duty cycle indicator, clocked by falling VCO
Well, we could feed it into a microcontroller (µC), but that's kind of boring; since we're having fun with discrete logic, let's see how far we can take it.
Let's feed the BIT input into a series of two 74HC164 serial-in/parallel-out 8-bit shift registers, so we can recognize 16-bit command words in the input stream. That ought to be long enough (if we pick our command words well) that we won't see too many commands in noise if the PLL locks onto a spurious signal and starts spouting garbage bits.
To recognize some constant words, we'll use a pair of 74HC688 identity comparators. Some really interesting combinatorial analysis would probably yield a vocabulary of codewords with maximal robustness against errors, but (for once) I don't feel like doing the analysis.
Let's try a simple scheme like '01110101WWXXYYZZ'. We get 16 commands, with redundancy to protect again single-bit errors (and many double-bit errors), and no translation collisions. One '688 can match the first byte, the other one can test the redundancy coding in the second byte (with 4 comparisons to spare, in case other constraints are needed).
Finally, let's do something stateful with these commands; since there's no handshaking, the sender will need to send a command many times to make sure it's received, so we want to make them idempotent operations. With 16 commands, we can control 8 on-off outputs, and the 74HC259 8-bit addressable latch is just what we need. Handily, we can clock the '259 from the rising edge of VCO, with no worries about set up time or propagation delay. By setting up capacitors appropriately, we can make sure the '259 is cleared on power up.
I think that's it for the digital logic. We've sketched an 8-channel on/off command receiver using:
- 1 x 74HC4046 PLL
- 1 x 74HC132 quad Schmitt-trigger NAND (used diversely for delay buffering, AND, and inversion)
- 2 x 74HC164 8-bit SIPO shift register
- 2 x 74HC688 8-bit identity comparator
- 1 x 74HC259 8-bit addressable latch
Will I build one? Doubtful at this point, given the existence of much simpler IR remote control circuits. If I get a chance to play with an oscilloscope it might be a good test project.
Update: Keith's Electronics Blog covers a similar PLL application, with diagrams.
No comments:
Post a Comment