Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Xtal-locked DDS audio sine generator with just a PIC 18F1320

Status
Not open for further replies.

Mr RB

Well-Known Member
Hi everybody, here is a PIC-based nice accurate audio sine generator with a good range 5Hz to 20kHz.

It should be very cheap and easy to build and is a project I was meaning to attempt for a while now (since I posted my "high-accuracy 1kHz sine generator" some months back).

It is finished and tested. All you need is the PIC, 10MHz xtal and a couple of discretes to make the RC filter.

**broken link removed**

The output sine is very nice (due to the 400kHz DDS and PWM), and so is frequency stability especially as you can set the frequency with buttons then it remains very stable.

My web page;
https://www.romanblack.com/onesec/SineDDS.htm
has the complete project details and a free HEX file for anyone that wants to build one.

I'm also appreciative of filter suggestions (like last time!) as this project is probably worth having a nice adjustable low-pass filter to give a really good sine output.

Merry Christmas! :)
 
Last edited:
Xtal shown as of 20 MHz. Is it 10, isn' it?
 
How does your project compare with the DDS generator IC by Fairchild?
 
To Atferrari; you are correct the xtal is actually 10MHz. I found the mistake and corrected it on the schematic image on my web page, but the image above must be cached on the forum so it shows the 20MHz xtal error.

To Audioguru; That's not really a fair comparison. The specialised DDS chips are much better as they can generate very high frequencies (up to radio frequencies) where mine is limited in software to a max of 20kHz. But in the audio range they both give a similar level of performance, I used a 32bit DDS which gives quite a good level of sine generating performance.

Keep in mind mine is a complete signal generator project, using just a $2 PIC. If you are using a commercial DDS IC they cost maybe $15 to $20, are very fiddly SSOP SMD package that needs a carrier PCB, then the DDS IC still needs another microcontroller to send it the serial data to set its parameters and output frequency.

I was aiming for a beginner level project to replace something like the XR2206 or MAX038 signal generator ICs as they are becoming obsolete and hard to find. It keeps the same one-IC ease of building. And being digital this is a lot better than those signal generator ICs as the freq is very stable, xtal locked in real Hz steps and the sine quality is much better too. :)
 
Hi Roman,

After you detect a switch press within your 25 cycle DDS loop, do you need extra cycles to process the switch press (when you add or subtract some value from the phase offset variable), and does that interfere with the DDS loop timing?

Regards, Mike
 
Hi Mike, yeah it's unavoidable to do some math processing outside the DDS loop (as it needs some big math with 32bit LONG and DOUBLE divisions etc to get real Hz steps in adjustment), however I tried to minimise the time outside the loop and also minimise how often the loop is broken while the button is held.

When there are no buttons pressed the DDS sine is rock solid and the loop is never broken, but when holding a button down to adjust the frequency there will occasionally be some small glitches, although the overall effect to the ear is a gradually changing frequency. So in its intended purpose as a audio sine generator it works fine, but if you were to try to "sweep" the frequency by holding a button down the sweep will be through accurate frequencies but there will be some occasional small glitches when sweeping.

It was a tradeoff of using the large math code needed to give actual accurate Hz steps in the user adjustment rather than just sweep the DDS freq smoothly and not have real Hz steps. :)
 
Last edited:
Hi Roman,

Thanks for the info'. I believe I may have come up with a simple and elegant 20 cycle DDS routine which would allow me to achieve the same 400 kHz DDS performance you're getting on a 40 MHz 18F1320 but using the less expensive 32 MHz "enhanced mid-range" devices (12F1822, 16F1827, etc.).

It was a tradeoff of using the large math code needed to give actual accurate Hz steps in the user adjustment rather than just sweep the DDS freq smoothly and not have real Hz steps. :)

Could you improve math overhead without affecting performance? For example, I would like to try using an 8.388608 MHz crystal with 4xPLL, a 24 bit phase accumulator, and a 20 cycle DDS loop to produce FDDS = 419,430.4 Hz with 1/40th Hz frequency resolution (FRES = 419430.4/2^24 = 0.025 Hz). That would make it relatively easy to maintain a 'display' variable with a value of frequency*10 (like 2541 for 254.1 Hz or 15000 for 1500.0 Hz). Bumping the frequency output up or down by 1, 2, 5, or 10 Hz would simply involve adding or subtracting integer 10, 20, 50, or 100 from the display variable and adding or subtracting integer 10*4, 20*4, 50*4, or 100*4 from the DDS tuning word (phase offset) variable. What do you think?

Cheerful regards, Mike
 
Last edited:
...
Could you improve math overhead without affecting performance?
...

Not really. Going to a 24bit accumulator rather than a 32bit one will make the DDS loop faster (as you said) but you lose a heap of frequency accuracy. My 32bit version produces a real Hz frequency within a few PPM frequency accuracy. A 24bit version is 256 times less accurate as you know, although is faster to implement.

...
For example, I would like to try using an 8.388608 Hz crystal with 4xPLL, a 24 bit phase accumulator, and a 20 cycle DDS loop to produce FDDS = 419,430.4 Hz with 1/40th Hz frequency resolution (FRES = 419430.4/2^24 = 0.025 Hz). That would make it relatively easy to maintain a 'display' variable with a value of frequency*10 (like 2541 for 254.1 Hz or 15000 for 1500.0 Hz). Bumping the frequency output up or down by 1, 2, 5, or 10 Hz would simply involve adding or subtracting integer 10, 20, 50, or 100 from the display variable and adding or subtracting integer 10*4, 20*4, 50*4, or 100*4 from the DDS tuning word (phase offset) variable. What do you think?
...

That is similar to what I did, using a "display" variable in actual Hz and a second value that is used in the accumulator. But for the highest freq accuracy in real Hz I kept the Hz variable large, and used large math to convert it to the dds variable with accurate rounding giving the least dds error for any value of the Hz variable. Basically the decisions were made so if the user selects 1Hz or 1kHz or 10kHz etc the system makes the best possible freq accuracy it can to match what the user wants.

What you are suggesting which is a simple addition to the dds per Hz unit was a system I considered but did not implement because although it is faster and easier when setting frequencies it carries a huge penalty in freq accuracy. But if you can source a binary divisible xtal (like a 8.388608 Hz xtal you mentioned) so the dds value becomes in real Hz then it should be workable and makes life a lot easier! :) But again this rules out standard junkbox 10MHz xtals and HAM guys etc who already have accurate 10MHz frequency generators, and TCXO/OCXO/GPS etc where 10MHz is a standard freq output value.

But a binary divisble xtal does solve both issues, it means the 24bit accumulator won't cost freq accuracy and neither will using a very coarse math.
 
Mike said:
Could you improve math overhead without affecting performance?
Not really. Going to a 24bit accumulator rather than a 32bit one will make the DDS loop faster (as you said) but you lose a heap of frequency accuracy. My 32bit version produces a real Hz frequency within a few PPM frequency accuracy. A 24bit version is 256 times less accurate as you know, although is faster to implement.

I was asking that question in the context of using an 8.388608 MHz crystal with a 20 cycle DDS engine.

I understand that with FRES = 400000/2^32 = 0.0000931322574615478515625 Hz for your 400 kHz 32-bit DDS that you're forced into some considerable math in order to provide a DDS tuning word (phase offset) for any particular frequency.

But if you can source a binary divisible xtal (like a 8.388608 MHz xtal you mentioned) so the dds value becomes in real Hz then it should be workable and makes life a lot easier!

So it sounds like you might agree that spending 49 cents for an 8.388608 MHz crystal may be a worthwhile investment when you consider that, when coupled with a 20 cycle DDS engine and a 24 bit phase accumulator, it allows the use of simple integer math for accurate and trouble-free operation with 0.1 Hz frequency resolution. Not to mention that now you can use any 32-MHz "enhanced mid-range" chip, like an 8-pin 12F1822 or a 14-pin 16F1824, instead of the more expensive 18F1320. Cool!
 
Last edited:
...
So it sounds like you might agree that spending 49 cents for an 8.388608 MHz crystal may be a worthwhile investment when you consider that, when coupled with a 20 cycle DDS engine and a 24 bit phase accumulator, it allows the use of simple integer math for accurate and trouble-free operation with 0.1 Hz frequency resolution. Not to mention that now you can use any 32-MHz "enhanced mid-range" chip, like an 8-pin 12F1822 or a 14-pin 16F1824, instead of the more expensive 18F1320. Cool!

Absolutely! I understood from the start that the job would be easier with a binary divisible xtal, just that I didn't think it was the best way to go. :)

The 18F1320 is a couple of dollars more expensive than the 12F1822, but is very popular and most PIC hobbyists have 18F1320 (so its practically free, people have them with their Junebugs etc) where the cheaper 12F1822 means a parts order with costs of postage etc. The 18F1320 can be programmed on pretty much any programmer, where the 12F1822 is very new and won't be supported on many beginner's programmers. It's not even supported on many people's compilers due to the new enhanced instruction set, another reason people at hobby level may not keep stocks of 12F1822.

Likewise the 10MHz xtal is very popular in junkboxes, especially popular with people who use 18F PICs. So again practically free compared to a specialty xtal order, and the 10MHz is the standard output for signal generators,OCXO,TCXO,GPS and HAM guys etc.

Then there are some performance differences, the 100 unit vert resolution from 25 cycles is better than 80 units from 20 cycles, and the 18F1320 has dual complimentary outputs (so it generates dual push-pull sines if desired) where the 12F1822 will only give one output if using the same 3-button control. Also with the 24bit DDS you get a 0.025Hz freq resolution but the 32bit DDS with the 10MHz xtal gives a freq resolution of just better than 0.0001 Hz.

Please don't think I'm belittling your work with the smaller PIC Mike, I'm a minimalist at heart so it's really made me smile seeing you create a 12F1822 sine generator with such enthusiasm, and I sincerely congratulate you on the great achievement of getting the little 12F to do it! That's very cool! :D

But decision wise I still think I made the best "hobby project" choices for 18F1320 and 10MHz xtal. ;)
 
Hello Roman,

Nice project thank you for sharing ...
What kind of modifications are required to the actual circuit ( code ) to have a square wave generator for the same frequency range ?
Is your DSO a Rigol one or something more exotic ?
 
Hi Hugo, a square wave generator is a lot easier, the hard part was getting something to make good quality sines throughout the entire audio range.

The obvious option would be to add a comparator to the sine output after the filter, and reduce the filter to a simple RC of R=1k C=10nF. The comparator gives you a square wave output from the project as it is. Or if you keep the filter as shown (to make a good sine) then add a comparator you have both a sine and a squarewave available.

The digital 'scope is a cheap Hantek brand, I chose because it has a 800x480 display. The pixely display is the most annoying thing about digital scopes and even with the large 800x480 display it is still not showing all the detail visible on a decent analogue CRO, nor is it as fast or convenient to use. I've always had good results from analogue CROs but had wanted to add a DSO to my bench for a few years and was waiting for better screen resolution. But one of the commercial projects I'm doing needed a storage capture to analyse some non-synchronous events so the Hantek fit the bill. Of course in 6 or 12 months there will be still better and cheaper DSOs on the market. ;)
 
Firmware v2 - now has 4 waveforms

I got a spare hour tonight and added some more wavetables. With nothing connected to pins RB7 and RB6 the PIC will default to sinewave and give the same functionality as v1.

But if you connect two switches, between RB7 and GND and RB6 and GND, these select between 4 waveforms; Sine, Square, Sawtooth, Triangle.

Details are on the project web page;
https://www.romanblack.com/onesec/SineDDS.htm
 
Last edited:
That's great. Roman what if you are using the 18F1320 just for DDS routine ( for max speed -> less than 25 PIC instructions ) and add another PIC ( 16F628 int osc ) for driving a LCD display , some push buttons or a rotary encoder and send the data serially to the 18F1320 ?
 
Last edited:
Hi Hugo, the 18F1320 can drive a LCD fine as is, I did not add LCD function as it really increases complexity and makes it a much more complicated project for beginners to assemble. Connecting all the wires to an LCD is a common stumbling block for beginner projects, so the way this was designed was basically just a PIC and a xtal and the output filter. :)
 
Status
Not open for further replies.

New Articles From Microcontroller Tips

Back
Top