DDS sinewave generator with PIC

Status
Not open for further replies.

atferrari

Well-Known Member
Most Helpful Member
Two sinewave generators, each one implemented with a PIC 16F84A, its own keypad and the output via PORTB, going to an R-2R network. A 4 pole filter completes the circuit. Both driven by a common 4 MHz clock and both running EXACTLY the same software.

In each generator, following the principle of of DDS, one value, PHASE_INC (3-bytes), is repetitively added to a PHASE_ACCUMULATOR (3-bytes as well). The bits b6:b0 of the accumulator's MSB are used to read a look up table with sine values from 1 to 128 and b7 of that MSB is used to know when to calculate the complement.

To change the frequency, withs keys "FREQ-UP" and "FREQ_UP", I can increase / decrease PHASE_INC value in unitary steps (yes, one unit at a time).

Everything works as expected except one thing: If I vary PHASE_INC in one of them to any axtent and then try to bring it to its original frequency by increasing / decreasing PHASE_INC, it is close to impossible getting the orginal value again, albeit VERY VERY close.

Just in case, please note:

a - Both generators , independently checked proved to be stable enough in the long term. They start with the same PHASE_INC value, thus their frequencies match each other 100% and stay like that forever. That's the reason for the common clock and it works OK.

b - According to theory, using UNITARY steps, sooner or later I should get again the PHASE_INC initial value where I started from, that is the initial frequency (mathcing again the other generator). In software I included enough delays to make the unitary changes of PHASE_INC painfully SLOW ensuring to have a smooth control of the changes. Simulation shows that PHASE_INC is increased/decreased by one, every time. (?)

c - I have an option, via keypad where I can change the PHASE_INC to different fixed values. Doing that to both generators, I get again matching (and stable) frequencies at the output. It's the up / down thing that ruins everything.

Please, can anyone tell me if I am overlooking something too obvious regarding the DDS principle, considering that the problem shows up only when I change one of them whether Up or Down.

Help really appreciated. (I wish I could explain this in a shorter text!! - Sorry)
 

What do you mean by "original value"? The numerical value of PHASE_INC variable?

If what you meant by the "original value" was the display of these two waves on CRO being shifted in phase, then it is as expected.

When your software "handles" the shift in frequency by changing the value of the PHASE_INC, it will take some cycles while the other PIC runs as usual. This introduces phase differences to the existing wave. The resultant change in frequency also introduce another shift in output. More changes when you tried to "undone" the frequency changes.

With the same PIC clocking, the output frequency depends only on the value of PHASE_INC and nothing else. This is not sure for the phase difference though.

Edited: How do you know (or what have you observed) that they are close but not exactly the same?

P.S. Atferrari, can you also count the number of PIC clock cycles(instruction cycles x 4) between two sucessive port change instructions in your asm code.
 
Last edited:
To clarify

Hola L. Chung,

Phase is NOT a problem and I control it well and easily.

Initial value means "initial value of PH_INC registers" what euqates to "initial frequency".

After thinking a lot of all this I concluded that I should revise my software (the increase / decrease) of the three registers.

Theory is basically simple so, I feel I am implementing that part in a wrong way. Not bein at the bench I can not tell but suspect it is the LSbyte of PH_INC improperly handled.

Will revert with the outcome
 
Problem identified

Problem not solved, but clearly identified.

After adding the missing testing of the LSB of PH_INC now I know that I have to increase the delay to avoid multiple "increase" or "decrease" actions per pushing of the button.

I am happy in knowing it is not my failure in understanding the DDS principle but just software to be improved.
 
I have asked for this in the previous postings.

Please counts how many clock cycles(instruction cycles x 4) your program runs between sucessive table lookups because I'm interested to know the highest frequency one can possibly generate using PIC running at 4MHz, with 8-bit DAC via a port. Ignor the question if you are using C to code the routine.
 
Two different countings

The simplest loop takes 29 usec (steps) to repeat. "Simplest" means with nothing else than what is needed to increase regularly PHASE_INC, read the table, pass the values to the port and be ready to repeat the loop.

My current loop, with keypad service, takes 92 usec (steps). Enough to go up / down in frequency or change frequency steplike between 10 different fixed values already in program memory.

Intended final ends = 10 Hz to 550 Hz.
 
atferrari said:
The simplest loop takes 29 usec (steps) to repeat. "Simplest" means with nothing else than what is needed to increase regularly PHASE_INC, read the table, pass the values to the port and be ready to repeat the loop.

Ok, so each table lookup takes 29us and your table is 256 entries. That would means a complete cycle of one sinewave in 7.42ms. This works out to be 134.7Hz if the table is stepped through without skipping.

Usually, one can let the table lookup skips so that there is ten or more lookup entries per waveform cycle and still get a fairly good waveshape output. So practically, your circuit can output a max of 134.7x25 = 3367Hz.

You should have no problem meeting your target of 10-550Hz. If you wants higher frequency output, you can either shortening your loop time(which is difficult) or use crystal with higher frequency.
 
Last edited:
128 steps

Originally I posted:

a look up table with sine values from 1 to 128 and b7 of that MSB is used to know when to calculate the complement.

Not 256 steps.

I dare to say that shortening is impossible in that micro.
 
atferrari said:
Originally I posted:

a look up table with sine values from 1 to 128 and b7 of that MSB is used to know when to calculate the complement.

Not 256 steps.

I dare to say that shortening is impossible in that micro.

That's 256 steps, but with half the steps in the opposite direction using data from the same table.

Does it not take 256 table lookup loops to generate a complete sinewave? OK, your table has 128 entries but you still have to look it up 256 times.
 
Status
Not open for further replies.
Cookies are required to use this site. You must accept them to continue using the site. Learn more…