Sunday, November 1, 2009

No-DDS DDS





A DDS using a PIC and a DAC chip ...

First, I apologize for having all the pictures piled up at the top. Someday I'll figure out how to insert them at the proper locations in the flow of the text.

Frequency synthesizers using the DDS (Direct Digital Synthesis) technique are lots of fun and I’ve built, let’s see … , four of them as stand-alone boards. I thought it would be fun to build one not by using an integrated DDS chip, but rather by using a microcontroller (PIC) and a DAC chip. Obviously I wouldn’t be achieving RF speeds, but this is just for the learning experience.

How does a DDS work?

Let’s start with the output device, which is a DAC or digital to analog converter. It takes as input a binary number with a maximum value depending on the number of bits and outputs a voltage proportional to that number. In my case it’s an 8 bit number having a range of 0 to 255, so my DAC has an output range of 256 discrete voltages in equal steps.

Within my PIC’s program, here’s the task at hand: The program runs in a loop that sends the proper voltage info (0 to 255) to the DAC each time through. One run through the loop always takes the same amount of time, 4 microseconds in my case. I want to produce a sine wave of a specified frequency. So I need to know, for each 4 microsecond advance in time, where I am in the 360 degree period of a sine wave of the desired frequency. Knowing that, I can look up the closest value of the sine wave in a table (there’s not enough time to calculate it) and put that out to the DAC. This is how any frequency up to the upper limit can be generated even though the loop is outputting numbers at a constant rate.

That upper limit is the based on sampling theory which says that with a minimum of two samples per cycle, the sine wave can be recovered. In practice a bit more than two is considered the actual limit. With my 4 u-sec loop time, I’d need 8 u-sec to send out two samples and my theoretical limit would be 1/8E-6 or 125,000 Hz.

Cutting to the chase on the mechanics of this thing … I need a number called the Phase Increment which I call “PI”. It’s how much the phase angle of the sine wave advances with each trip through the loop in the PIC. (Don’t confuse it with pi = 3.14159 …)

The data (for a sine wave) is a 256 sample look-up table. Therefore, 256 = 360 degrees. For greater accuracy, 24 bits are used to allow a high precision phase increment.

The frequency of operation for the DDS is

f = PI*fclock/2^24 where fclock is the effective "frequency" of the program loop which is 1/T, where T is the time it takes to execute it, or 250,000 Hz in my case.

So, PI = f*2^24/fclock

I have to use the above to calculate a new PI every time I change the DDS output frequency. The PI is added to a phase accumulator in each passage through the loop. Since there are only 256 samples, only the most significant byte is examined to point to a sample in the table. Consider my 24-bit phase accumulator to be an integer plus fraction where the high byte (MSD) represents a full cycle (360 degrees) and the other 16 bits are fractional parts of a cycle.

To write the DDS loop, I need a 3-byte accumulator and a 3-byte PI. Calculation of the PI is done outside the loop, so assume it's known. Here's what the main loop does:

  • Add the PI to the accumulator. The MSD will be the current phase angle of the sine wave to 8-bit accuracy. (MSD is the most significant digit, also known as the high byte of the 24-bit number.)
  • Take the MSD of the accumulator and use it to look up the corresponding value of the sine wave in a table.
  • Put that value out to the DAC
  • Repeat

So the only bit of information supplied from outside the loop is the PI. When the external control routines want to change the frequency of the DDS, it just alters the PI.

Hardware details -

I decided to use a DAC chip I have in my junkbox, which is an AD7530 10-bit ADC. ($1.35 from B.G. Micro.) I'll tie the two highest bits to ground and my maximum output will be 1/4th of what it would be using all bits. Yes, I had enough bits in my calculation to use all 10, but that would make my update routine take longer and lower my maximum frequency.

I wasn’t sure how to apply this chip. The data sheet shows using an inverting op-amp on the output, which it appears is really necessary. This means I need a negative supply, unfortunately. Plus the chip needs +15V to power it. So now I need +15V, +5V (PIC) and negative for Vref. Vref can be positive or negative, but since the op-amp inverts it, I'm going with negative so I'll have a positive output. I'll also us the negative Vref on the negative op-amp supply so I won't require a rail-to-rail op-amp to get to 0 volts.

For the negative supply, I took a wall wart rated 9V at 200mA which puts out 14.5 V no load. Took that through 200W to a 10 V zener to get about -9.79 volts as a reference. Experimenting on a breadboard, I get +2.45 volts out with all 8 lines high, close to the expected value. The step is about 10 mV per bit. My op-amp is currently a 4558. It's GBP is over 3 MHz, but open loop gain goes from 100 dB at low frequency down to 30 dB at 100,000 Hz, so I'm not sure if it's fast enough or not.

The 2.45 volt maximum output might need a little boost, so I could use the other half of the 4558 for that, with a gain of 2.

I'll add a photo of the board here ...

Well, guess I can't add it here. Everything goes to the top it seems.

Schematic -

Which is no doubt going to happen to the schematic when I add it too ... I keep reading the "help" on this Google Blogger thing but it's not much help to me. But it's free and it works, to a degree.

Anyway, the schematic is in here somewhere. Mostly it's a connection diagram, but some details are presented in schematic form.

One of my favorite parts isn't part of the No-DDS at all but is the RS-232 to TTL interface. This is the two 2N7000 MOSFET circuits shown at the bottom. I've fooled with a lot of level translation circuits, especially the MAX232 chips and that family. I like this one because it uses a two dime active devices and two resistors and takes less connections than a MAX232, though to be fair, the chip does two conversions in each direction. One drawback of the circuit is that the signal out to the RS232 device doesn't go negative. Maybe I could have made that happen in the No-DDS circuit, since I do have negative voltage available.

Controlling it - the PC software interface ...

I needed a way to tell the PIC what frequency to generate, so I altered an old piece of DOS software I'd written earlier. A slight problem was in how to get the PIC's attention. The update loop needs to be as tight as possible, so it can't afford to poll for external input. The logical thing then is to use an interrupt. But I discovered that all the lines that were interrupt capable, I'd already used for I/O with the DAC. So I wondered if using the -MCLR line would work. This effectively forces the PIC to re-boot every time that line is actuated. It turned out to work OK. When the PC software wants to get the PIC's attention, it bangs the -MCLR line. The PIC restarts and part of the start-up code is for it to check its serial port for incoming data. That data will be the new PI, which will be stored before the PIC goes permanently (until the next restart) into the update loop.

I'm putting in a picture of the DOS screen. Some of the fields aren't used, since this program was developed to control full featured RF DDSs that were used as VFOs. I wrote this program in 8088/8086 assembly language using the A86 shareware assembler.

Conclusions

It worked pretty well. That rope-like waveform appearance was due to my scope acting up a bit. Like the 1-bit sine generator, I built this thing but am not sure why. I think I thought it would be fun, and I guess it sort of was. I combined a little electronics, a little PIC programming, and a little PC programming to produce a circuit that worked as imagined.

-Nick




Thursday, October 1, 2009

1-bit PIC sine wave generator
































Above is the digitally synthesized sine wave.

This is one of those “because I can” projects. Can I generate a sine wave using a simple PIC employing no PWM and no DAC, no software timers or interrupts, just turning an output pin on and off? We all know it can be done because our music players boast of the 1-bit DACs inside.

Simplistically, we know if our output pin puts out 5 volts when ON and 0 volts when OFF, a 50% duty cycle should give us an average output voltage of 2.5. But the actual method is a little cleverer than that, which is what makes it fun. I picked it up from Glen Leinweber, VE3DNL, a great ham tinkerer in the realms of RF and programming.
The sequence of ones and zeroes is first calculated “off line” using a simple program in a high level language, QBASIC in my case. Variables track the integral under the sine (actually cosine in my case) curve and the integrated value of all the bits generated previously. If the value of the integrated bits is less than that of the cosine curve, the next bit is made a 1 and if it is more, the next bit is a 0. In this way, the average value of the bit stream is tracking the value of the cosine wave as closely as possible. Glen says this technique is an example of something called “sigma-delta coding”.
There are some practical considerations related to our MCU chip, a 12F629 in my case. My processor is running at 1 MHz and it can toggle my output pin in one execution cycle or 1 microsecond. Naturally, I want my bits as narrow as possible for fine resolution. The limitation is on the amount of program memory I have, which is 1024 bytes for the 12F629. The program will simply output all the bits for one cycle and then repeat. So the period of the cycle determines the program’s length. Say I wanted a 1,000 Hz output. The period is 1 millisecond, so I’d need roughly 1,000 instructions plus a little overhead. You can see that lower pitched tones require more memory as their period is longer.
I wanted to do an “A” musical note at 440 Hz but it wouldn’t fit so I wound up at “D” (587 Hz). Even this wouldn’t fit without a little trickery since its period is 1,703 microseconds. Turns out that there are long streams of 1s or 0s where the sine wave is at its positive and negative peaks. So I can save memory by calling delay routines repetitively. Actually, one routine with multiple entry points is even better.
Want to write a ~1000 line program by staring at a printout of 1,703 ones and zeros and writing the code to produce them? Me neither. So my QBASIC program also gets to write the bulk of the source code. After the bit sequence is stored in an array, the program then examines it for repeats and writes the code to implement the bit sequence efficiently.
I also wanted a way to turn the output on or off in response to user input (telegraph key?) on another pin. To do this, I just wrote the code to sense the pin and if its state tells me to turn the sound off, I configure the output pin to be an input instead of an output. Each time through the code, it reads the control pin and configures the output pin accordingly. The sound generating code continues to run as always. I had to count the number of cycles this code took and then insert it in place of an equal number of “time wasting” cycles in an area where the output pin is not changing.
OK, say I get it running. How do I look at the output and verify that I’ve achieved my goal? If I just look at the output pin with my o’scope, I’ll see a pulse train of varying density. So just as I did in software, I have to integrate the pulse train in hardware by connecting a resistor and capacitor to the pin. Here’s the tricky part: the R/C network is a low pass filter, and with enough filtering even a square wave can be turned into a perfect sine. So to make sure I’m not “cheating”, I make sure the corner frequency of my filter is much higher than my fundamental frequency. The proof is in the pictures, with a shot of several cycles showing a nice sine wave, but a close-in zoom of part of the cycles show the jaggies caused by the individual bit transitions.




In this "magnified" view, you can see the jaggies that betray the sine wave's digital origin


A fun variation might be to do a more complex waveform – say the sum of sine waves of 1,000 Hz and 1,500 Hz. The period would be that of the difference frequency, 500 Hz and the resultant would be something you couldn’t fake with low pass filtering. Combining two musically related notes would be even better – easier on the ears.
One more relevant bit of info. Most PICs these days include high speed and fairly accurate internal oscillators you can use and save the price of a crystal and two I/O pins. The thing is pretty accurate, but has frequency trimming registers if you want to get closer. My ‘D’ note started off 8 Hz low with the factory value and I was able to trim it to within 1 Hz.
What’s it good for? Don’t you hate that question? But I guess it’s a stable audio sine wave source for the price ($2 or so?) of a simple PIC chip. Not too flexible though – to change the frequency you have to re-run your QBASIC program to generate revised source code and then re-program the chip.
Update: I decided I should make my PIC program and my QBASIC program accessible, which was easier to do on my web page than in this blog. So go to my site using this link and near (or at) the bottom of the table of stuff is the link to my 1-bit sine page. Scroll down through all the text you've already seen and you see the links to the two files.








Sunday, September 27, 2009

My Nixie Clock


I bought a digital volt-ohm meter for $5 at a ham flea market years ago. It is probably about 1970 vintage and uses old fashioned Nixie display tubes. These tubes have long since been replaced with 7-segment LEDs and then LCDs, and then pixel based LCDs.

Nixies are a favorite among hobbyists who like archaic parts because of the visual appeal of the display. Each numeral is individually "drawn" from a gas discharge tube, rather than being crudely constructed from segments or dots. The VOM has three Nixie tubes with 0-9 plus decimal point, plus a single neon tube for the MSD (1 or off). So it is a 3-1/2 digit device with range from 0000 to 1999.

A. Hardware approach ...

Plan 1 was to let the PIC generate a DC voltage equivalent to the time in millivolts, for example 10:35 is 1035mV, and input that to the meter. The PIC would use its PWM module to generate voltages. Unfortunately, the PWM is only 10 bits, a resolution of one part in 1024. I need one part in 1259 so I couldn't be accurate right to the minute. Also there would be some accuracy issues resulting in a little uncertainty in the 1's minute digit. The advantage would be that there would be no modification to the VOM at all.

Plan 2 required investigating how the VOM works. I could have the PIC put BCD data right to the three Nixie driver chips (if I have their data), but it might be nice to have an easier way that doesn't require 12 data lines and cutting a bunch of traces.

Each Nixie has three chips in front of it. First is a 7441B Nixie driver, fairly standard. Next is a SN7075N and behind it is a SN7090N. Probably TTL chips 7475 and 7490 before the industry standardized on 7400 series numbering for TTL devices.

The VOM works this: It clears the counters to zeroes, then starts a ramp generator and at the same time gates on a string of pulses to the units digit counter. The ramp generator and unknown voltage both go to a comparator. When the ramp voltage becomes equal to the unknown voltage, a logic signal is generated which gates off the pulse train to the counter. At the same time or just after, the latch signal is given to the 7075 to update the display.
Next, a clear signal is given to the counters and the next measurement starts.

Initially, I was going to monitor the DMM's "clear" line, and after it was asserted, I would substitute my pulse string, virus like, for its own, in the available window. For example, if it's 8:37 AM (or PM), I send 837 pulses and the DMM is none the wiser. I'd have to sneak them in fast enough to be finished before the DMM generated its "latch" pulse. Due to technical difficulties too tedious to describe here, I wound up having to take control of both the clear and latch lines form the PIC. Easy enough except my idea of keeping things minimalist by using an 8-pin 12F629 chip severely challenged me for my I/O needs as the project progressed.

B. The software ...

I was initially going to use a 32,768 (2^15) hertz "watch crystal" for my PIC's timebase, just because that approach seems to go with clocks. You divide it down to 1 Hz and -- Bob's your uncle -- you're there. But that speed was too slow to allow me to jam my train of pulses (maximum of 1259) into the available window. So I went to a 455 kHz crystal and to a method of calculating 1 second intervals that's lots cooler. Here we go ...

This uses a technique I found on the web described by
Roman Black, based on an idea by Bob Ammerman. It uses a
method based on the Bresenham algorithm which produces
intervals that average exactly a second, although there
may be some small jitter (which can be calculated) in each
second's time.

It will work like this. My clock speed is 455,000/4 or
113,750Hz. I put that number into a 24 bit variable. I set
timer 0 to interrupt every 256 counts. At each interrupt,
I subtract 256 from the variable. When the variable becomes
less than 256, I add 113,750 to it and increment the seconds
count.

Obviously, over time my *average* second takes 113,750 counts,
which would be perfect. But each individual second could be
off by as much as 256, so my maximum jitter is 256/113,750 or
0.23%. If I used a 1MHz clock and interrupted every 128
counts, jitter would be 0.0128%, but 0.23% is plenty good for
this application. My Nixie clock won't show individual
seconds and over 60 seconds the errors should cancel pretty well.
(What's the accuracy over longer periods, assuming a perfectly
accurate crystal? Well, the uncertainty is never larger than
256 counts at any given time. So for a full minute, the jitter
would be 0.23% / 60, for an hour, it's 0.23% / 3600, and so on.
That's why it's said to approach perfect accuracy over time.)
Black said you can do this for any crystal frequency. I'd
say that's true, but since the PIC clock is Fxtal / 4, if
that division didn't yield an integer, you'd want to trim
the crystal's frequency (+/-3 Hz maximum) to produce an integral
count.


C. Summary ...

Nick's Law says that any programming or hardware project will be two to ten times more complicated than originally envisioned. This one fell comfortably within those boundaries. The clock works great. A clock doesn't have to do much, right? But it keeps good time and doesn't lock up or show any strange behavior. At least not any more.

A few things are missing or not fully developed. First, there's no colon. I can manipulate a decimal point into that position if I want a delimiter. I've considered using a long neon tube painted black except for two dot-sized openings on each end, and possibly using two small yellow LEDs, but I decided it was time to call this project to a halt.

Another sort of clunky part is that my setting routines aren't very well human engineered, but they do work. I added small surface mount SET and ADVANCE pushbuttons on the rear of the case.

Finally, I wanted battery backup. The PIC board should pull less than 1 mA so a tiny battery should maintain the time even during long outages. I mounted a little 3-cell nicad pack in the box, diode auctioneered with the main 5 VDC supply, but I abandoned it when I had startup problems. I found that the PIC needs a clean RESET signal, which here means pulling the supply voltage all the way to zero. So to use the battery, I'd need a third button on the back of the box, labeled RESET. But I've declared this project finished.

Nixie mania? Just this month (September, 2009) I found another Nixie based DMM at a hamfest for $5. It's a Bell & Howell unit made by Heathkit for an electronics class. But it has only 2 & 1/2 digits so isn't suitable for use as a clock. I should consider myself lucky.

Friday, August 14, 2009

Update on the multi-turn loop effort

In my first post on the subject, I was flushed with the success of actually making two QSOs with the loop. But on further examination, I was having trouble keeping a good stable match or even getting back to where I had been. Now I was seeing minimum SWRs (at resonance) of 3:1 or higher.
I thought the problem might be my use of single conductor wire as opposed to Newkirk's zip cord. I taped and tied my conductors to increase coupling but without much effect. So I decided to rebuild the antenna with zip cord, in my case 2c/#18 speaker wire with clear plastic insulation. I loosely wove the two lengths of cord together as the author had reported that his were "entwined" (sounds romantic - he's a flowery writer).
My initial trails with the new version were disappointing. I tried a number of different fixed capacitors, including 20 pF dipped silver micas, 33 pF postage stamp micas, and 25 pF "doorknob" HV capacitors. In each case I could tune to a resonance but could not get to a low SWR. I even installed a compression mica trimmer in place of the split stator variable with no improvement. Sometimes I could get a low SWR at some point, but tuning to resonance on my desired 40 meter frequency gave a much higher SWR value.
One tangent I got off on concerned the existence of the fourth wire. Mr. Newkirk said he used two loops of zip cord but on 40 meters he just used three wires (turns), sparing the fourth for a future conversion to 80 meters. The article didn't describe whether the spared conductor was broken only at the top or in two places (top and at the matching capacitors at the bottom). Would it make any difference? I had originally cut the condutor in both places, so I jumpered it together at the bottom and found that it made a big difference in the resonance point. The resonant frequency dropped about 1 MHz and the SWR at resonance was well under 2:1. So the spare isn't just hanging around minding its own business.
Too many variables - the quality of the capacitors, the disposition of the spare wire, -- what about balance, which Mr. Newkirk emphasized? Currently I'm having to tune my variable to minimum capacitance to reach 40 meter resonance. That might mean my fixed capacitors (lowest tried - 20 pF) are too large. So I put in two 14.7 pF silver micas. Much better! Now my variable is partially meshed for resonance at 7040 kHz and my SWR is well under 2:1. It seems stable too, and not sensitive to body capacitance.
So that's where I am at this point. No more QSOs yet -- not much activity on 40 and no contests to exploit. I think I'd like to put the antenna on the second floor or even outside to give it a better chance.
It's interesting to note the big difference in capacitor values I wound up with as opposed to those in the article: 14.7 pF for me versus 40 pF for Rod Newkirk.
So now I'm happy with it again. I think it might make a good hotel room antenna. And it's now much easier to fold up due to the superior flexibility of the zip cord.


Tuesday, August 4, 2009

Multi-turn small 40 meter loop antenna

Here's the loop hung from the ceiling with string.
The feed is at top, capacitors bottom center.
I've had an interest both in compact loops and in in-room hotel antennas for a while, but really hadn't gotten far. So I finally got around to trying a multi-turn design by Rod Newkirk, W9BRD in the July 1993 QST article called, "Honey, I Shrunk the Antenna". (Guess what movie was new at the time.) According to the author, the multi-turn design raises radiation resistance significantly, and a resonating capacitor in each turn, along with the multi-turn design, calms down the extremes of voltage and current seen in single turn loops.

The antenna is a rectangle 4.5 feet by 3.5 feet, three turns, each turn cut at the bottom (one 4.5 foot side) with a 40 pF capacitor inserted, one of them variable, and fed at the center of the opposite side, which is the top in my case.

I used #14 AWG THWN house wire, stranded (it's a little springy). I made a little circuit board for inserting the three capacitors and another one for the feed line connection "insulator" at the top. Instead of etching, I just scored traces with my Dremel tool abrasive wheel. I mounted the variable capacitor on the opposite side of the (singled sided) board, using nylon screws so's not so short anything out. The capacitor is a dual section, unequal values (80 pF and 150 pF or so) in series. This is standard practice so current doesn't have to flow through the shaft to frame bearings. In the photo below, the variable cap is on the back side and connected to the center traces.

Circuit board material for series capacitor connections

The wire generally is bunched up, even tie-wrapped or taped in a few places, in keeping with how the author did it. In fact, he used a couple turns of 2/c zip cord and spared one pass of the resulting four.

The article called for 40 pF capacitors with the variable used for fine tuning. I put two 20.5 pF silver micas in parallel to get 41 pF with lower current in each. In the photo, I'm experimenting with just one capacitor. I'm publishing this a little prematurely as I'm still not satisfied with my values and possibly the quality of the capacitors. I got the SWR down to a fairly stable 2:1 and let the K3's ATU finish the job. I actually made two QSOs at 5 watts with the top of the antenna barely above head height. Note that my shack is on the ground floor.

More to come, maybe, if I make some improvements.

Nick, WA5BDU
August 4, 2009

Saturday, May 23, 2009

Si570 Synthesizer


Lately I've been playing with a different kind of frequency synthesizer chip -- instead of DDS, it uses a built in crystal and a voltage controlled oscillator and dividers. I'm sure that's over-simplifying a great deal. The chip is the Si570--it's the little silver rectangle in the center of the vertical board in the photo. The major excitement (to me) is that they make versions that go up to the GHz range. I'm currently limited to about 60MHz with the Analog Design DDS chips I use. My Si570 only goes to 160 MHz, but that would allow direct conversion at 2 meters and lots of other interesting stuff.
The fun in this is learning to program a new chip from a microcontroller. It's not nearly as straightforward as an AD DDS chip. You set two front end dividers to set the rough range and then a 38 bit divider for the exact frequency. It's not deterministic in that there may be more than one combination of the three to get to the same frequency. Also, you can't just jump anywhere in the range. Large jumps impose a little delay and some additional programming steps.
But per the data sheet you can move plus or minus 3500ppm by just sending a new 38 bit divider number. I assumed this meant that on 14 MHz, I could move +/- 49kHz, but experimentally I could go +/- about 330kHz. Hmm ... You can tell you've gone too far because the thing freaks out and resets itself to its startup frequency, 56.32MHz in my case. Using the more complex frequency change process always works though. It's just not well suited to continuous tuning.
I got my Si570 on a little board with the same form factor as the NJQRP DDS-30 and DDS-60 after reading about the thing in a recent QEX article. See the softrock receiver page and/or Yahoo group to track it down.
You control or program it over a two-wire bi-directional bus called I2C, which is a protocol for talking chip-to-chip. Assembly language programmers always want to do things the hard way, so I was going to bit-bang the thing thru ordinary I/O pins, but it turns out that my Arduino development board (ATmel 168) has I2C built in to its C-based language so I figured I'd do my initial experiments there. The Si570 is plugged into the Arduino board in the photo, or into a proto board atop the Arduino board.
I'd like to give some tutorial and "lessons learned" stuff, but I've rambled on just in this overview. Maybe more details later. I see some fun potential for this thing. Direct conversion on 144 MHz, or even 220 MHz for the chip just one speed grade up. An LO for a 2-meter FM rig (not a lot of homebrew there, eh?). SDR (software defined radio) types like it because they need an LO four times the mixer frequency. That's why this thing starts up on 56.32MHz -- that's four times 14.080MHz. I still need to do stuff like measure its output level over the frequency range and so on.