Friday, May 23, 2014

An Updated Memory Module : Part 2 - A Bare-Bones Prototype

Since I said in Part 1 that knowing most of the the detail of how the memory module works was unnecessary, and reckoned you could just about build a memory module knowing nothing more than the basic inputs and outputs, I suppose I'd better put my money where my mouth is.

Well, here we go…

To recap the basics:
  • There's a bunch of input pins - 8 for the memory location, 6 for the band, 3 for the antenna filter, and 2 for the VCO - that go high (+5v) or low (0v) to indicate the position of the memory & band switches. The memory module need to read from these pins.
  • There's a bunch of output pins - 6 for the band, 3 for the antenna filter, and 2 for the VCO - that need to be driven high or low to control the radio. The memory module needs to write to these pins.
  • There's a common input / output for the VFO (tuning knob) - when tuning normally the VFO signal (sine wave) appears here; when in memory mode the VFO signal (from the memory unit) needs to be sent here. The memory module needs to be able to both read/count this signal and generate a new one.
  • There's a few other input pins - "M" and "MR" that go low to indicate the respective front-panel buttons have been pressed, and "Clarifier" which is connected to the front-panel Fine Tune knob - that need to be read. But, to keep things simple, let's ignore them for now…
So our memory module needs to handle all that.

Actually, I lied a little up there. The band/filter/VCO input pins don't actually go low / 0v, but instead go open-circuit. This causes problems when we hook something up to them - even high-value pull-up resistors are enough to interfere with the open-circuit pins, making the radio think they're being pulled to +5v and switching it into a mode which doesn't exist. Additionally, between the various inputs and outputs, we need to be able to configure 30 pins (19 in + 11 out) to be high (+5v), low (0v), or open circuit (high-Z), with additional pull-up or pull-down resistors as required.

The easiest way to handle that many pins is with an I/O expander IC. These typically have 8 or 16 pins that can be configured as inputs, outputs, or any combination of both. The problem with most of them is that input pins usually have fixed pull-up (or, less commonly, pull-down) resistors, and output pins can only either pull-up or pull-down - not both. However, after a bit of head-scratching I remembered a suitable IC - TI's TCA9535 "Remote 16-Bit I2C and SMBus, Low-Power I/O Expander With Interrupt Output and Config Registers" - which has both high-Z inputs and push/pull outputs (can be driven both high and low). As it happens, it's also nice and cheap (~AU$3 in one-off quantities) and is readily available from places that don't also sell farting toys…

(Yes, blatant plug for TI there. Any why not? They produce good parts which are widely available, and they're happy to provide samples to genuine end-users [btw the parts used here were bought - after I'd obtained a couple as samples for an earlier work project]. What's not to like? The similar PCA9535 [note: not the PCA9535C; it doesn't have push-pull outputs] is available from other vendors, though I haven't tried it. It should work, but has slightly lower specs.)

Since the TCA9535 is only available in SMD packages, for this proof-of-concept prototype I built a small board to carry the ICs and connections. It's pretty simple - the 2 ICs, a bunch of 100k pull-down resistors on the inputs, and most of the rest is connectors. The cables from the radio connections (with the exception of P33/J06, the VFO signal) connect to this interface board, and 2 small cables (SV1 and SV2) connecting the I2C bus and M/MR/clarifier controls to the rest of the circuit.

The rest of the circuitry is only slightly more complex, at least for the moment. Currently it's nothing more than an Arduino, a cheap AD9850 DDS module, and a simple buffer amp connected together on a breadboard. Everything is powered from the breadboard's +5v supply (not shown) - the Arduino, the DDS module, the interface board, and the buffer.


The I2C bus from the interface board connects to the Arduino's hardware I2C port (shared with A4 & A5), allowing the settings of the radio to be read/controlled by software. The M & MR buttons are hooked up directly to digital inputs 2 & 4 (0&1 are necessary to use the serial/USB port for testing/development, and I kept away from the PWM-capable pins because the associated hardware interrupts are used elsewhere). A single transistor buffer amplifies the incoming VFO signal on J06 to drive the frequency counter on Arduino pin 5. The DDS module (which generates the VFO signal in memory mode) is connected in serial mode to the Arduino, and its sine wave output is connected back to P33/J06.

It works - but, since this is still in the prototype stage, there's a few things to sort out:
  • The VFO input buffer is borderline, and will need improvement. At the moment, my prototype is only just barely able to handle the incoming VFO signal and drive the Arduino's input pin, so it's probably a 50-50 chance whether it'll work for anyone who slavishly copies my design. The Arduino at 16MHz is quite capable of counting a 5vp-p square wave at 5MHz, and the VFO only tunes from ~2.5MHz to ~3.5MHz - but, with the buffer as shown, the frequency counter fails at about 3.56MHz. Since it was basically knocked up quickly to prove the point and was always going to need a proper redesign, I've never even bothered to find out why - I suspect the gain is falling off rapidly with frequency, mainly due to the breadboard construction. It'll probably end up as a 2 stage fet-bipolar or single comparator design.
  • The DDS output level (~1v p-p) needs attenuation to match the normal VFO level (~0.6v p-p). It works fine as a proof-of-concept, but probably results in decreased performance when running on the DDS signal. Since I haven't decided what I'll use as a VFO in the next (& hopefully final!) design - stick with an eBay/DX style AD9850 DDS module, roll my own on-board DDS, or use a high-resolution silicon oscillator (e.g. something like a Si570) - I haven't bothered to match the signal levels yet. Once I decide on what I'll use, a simple voltage divider should suffice.
  • The biggie (though it's really not that big) - implementing fine tuning. "Not a problem!" I originally thought, "the fine tune control is obviously varying the voltage to a varicap, so I can just hook it up to one of the Arduino's ADCs and use it to tune the VFO by ± 2kHz or so". Yeah, I was a bit wrong. It is just varying the voltage - the problem is, it's varying the voltage between ~1.5v & ~6.5v. Oh, and it's derived from an 8v rail (I think) that is itself probably not terribly accurate. Ideally, that needs to be re-scaled and limited to between 0 and 5v to suit the ADC and ensure we get the maximum resolution / smallest tuning steps out of the fine tune control. A rail-to-rail single supply difference amp should solve the problem, but I'll need to think a bit about that...
  • Improvements / Extensions: The ATmega328 in the Arduino has more than enough non-volatile memory to store the default 12 memories, but I'm thinking bigger. Adding memory is easy - I2C EEPROM chips are cheap and can simply hang on the I2C bus. One obvious improvement would be to segment the 12 switch positions into something like 4 per-band memories & 8 all-band memories (for a total of 128). Another idea would be to add a keypad and display for direct frequency entry and potentially 1000's of memories; that too can be easily connected to the I2C bus. Hmmm…
Regardless of all that, I think the proof-of-concept prototype is working pretty well - in fact, in some ways it exceeds expectations. For example the frequency counter routine, once calibrated, is accurate to within ±5Hz, which was a pleasant surprise - to minimise delay in counting the frequency on storage, it only counts with 5Hz resolution to start with! At the moment the software is far enough advanced that I've tested and proved all the functions in isolation - all the switches can be read, all the settings can be controlled, the VFO frequency can be read, the DDS can output the requested frequency, and I can even tune the radio by hard-coded settings to any frequency desired.

Coming up next: Software. Hopefully, in the next few days I have a version that's "minimally fully-functional" (if that makes sense!) with the current breadboarded prototype e.g. functions the same as the original MU-7700 memory unit. Once that's done I'll start work on the final hardware & software design…

No comments:

Post a Comment