No announcement yet.

sine wave tables

  • Filter
  • Time
  • Show
Clear All
new posts

  • sine wave tables

    I'm pretty lost here. What I need to do is build some sinewave tables. The end result is to use these tables in a PIC micro to send the values to a 14 bit DAC. Basically I want to input a frequency and build a table for it. For you people great in math the ability to mix two frequencies would be great but I think a summing opamp will solve that problem

    I just need pointed in the right direction, not asking for someone to write the code for me

    an example table:

    ' table for DAC sine wave 8 bit I think
    DAC_Table: CData $80,$00,$81,$C9,$83,$92,$85,$5B,$87,$24,$88,$EC,_

    Thank you
    Doug McDonald

  • #2
    Here's a thought,

    to mix the freq's is freq1 + freq2 per table index

    with the DAC at a 2.5v reference I'd adjust the sum of the freq's from full scale to produce the required RMS voltage (amplitude) above and below the 2.5v

    It can't be that simple is it?

    I still would like to know how to build the tables in PB

    BTW the above table is 16bit broken up into 8 bit chunks

    Just thinking out loud

    Last edited by Doug McDonald; 31 Dec 2007, 07:00 PM. Reason: error in post
    Doug McDonald


    • #3
      For a 14 bit DAC, I'd think you'd want limit the table to 14 bit values, even if they are stored as 2 bytes (16 bits).

      center (sine zero) = 10000000000000 binary, 2000 hex
      positive peak = 11111111111111 binary, 3FFF hex
      negative peak = 00000000000001 binary, 0001 hex
      (I originally put negative peak at 0000, but that wouldn't be symetrical.
      3FFF - 2000 = 1FFF; 2000 - 1FFF = 1, not zero)

      Amplitude domain for 2 frequencies:
      current sine for freq1 plus current sine for freq2 divided by 2
      Why divide by 2? Because when both positive peaks happen at the same time the sum is 15 bits.

      3FFF + 3FFF = 7FFE (111111111111110)
      then shift right 1 bit (same as divide by 2)

      Or, build the table to 13 bits in the first place, then no need to divide.

      Time domain for 2 frequencies:
      I've got thoughts going around in my head, but I've only had one cup of coffee so far this morning and can't organize them. Maybe later.

      Last edited by Dale Yarker; 1 Jan 2008, 12:12 AM. Reason: correct negative peak


      • #4
        Computing Sine Table Values

        Computing the sine wave table values is pretty easy. You can use something like:

        TWOPI = 710/113
        FOR I = 0 TO (NrSamples -1)
        Sample(I) = INT(8191* SIN(TWOPI/NrSamples * I)) + 8191 (use for offset binary DAC)
        Sample(I) = INT(8191 * SIN(TWOPI/NrSamples * I)) (use for 2's complement DAC)
        NEXT I

        I know with a little bit of logic you could use the full span (0 to 16383) but I have found that it isn't worth the headaches to pick up one or two more counts.

        Just use the lower 14 bits of the result for either equation and you will be fine.

        Where your request gets tricky is how you supply these values to the DAC. Obviously, the rate the samples are sent will set the frequency of the DAC output. One of the simplest ways to approach the problem is to use a variation of DDS (direct digital synthesis) in the PIC code.

        The theory is something like this:
        You store the samples for one cycle of the sine wave in the PIC memory. It is easiest if you use some power of two for the number of samples. Let's assume that you use 128 samples for the sine wave.

        You then set up an accumulator (say 16 bits) whose upper byte will address the sinewave table. You also set up a 16 bit phase increment register that will hold a number that will ultimately set the output frequency.

        When you want to output a frequency, you clear the accumulator and add the value in the phase increment register to the accumulator. You then use the upper 8 bits of the accumulator to index into the sine table and send that value out to the DAC. You then loop back and repeat the addition to the accumulator and output to the DAC. If the value in the phase increment register is small, it will take longer to read the sine table out and thus you will obtain a lower frequency. Larger values will yield higher frequencies. Obviously, there will be an upper limit to the frequency and the sine wave will look worse as you start to use more bits in the upper byte of the phase increment register.

        The highest frequency will be set by how fast the PIC can loop through the "accumulate and send" code. If you are using a parallel DAC it should be pretty fast, but if you are using a SPI or I2C DAC, you may not be able to loop fast enough to get the frequency you want especially if you are bit-banging the communications. I don't know how you are using the output, but you should have at least 16 samples per cycle to keep things looking reasonable. I have seen as few as 8 samples per cycle, but the waveforms start looking pretty chunky.

        Also, you mentioned "mixing" frequencies. To those of us who have worked in the radio world this means heterodying two frequencies to obtain new frequencies. I assume you mean that you wish to combine or superimpose two frequencies similar to touch-tone codes.

        If this is what you want to do, then compute the sine wave samples to 13 bit resolution and run two accumulators in parallel. After they have both been updated, read one sample for each accumulator output, add them and then send that to the DAC.

        I have used this technique in microcontrollers and FPGAs and it works pretty well.
        Last edited by Jeff Burrell; 1 Jan 2008, 12:49 AM. Reason: corrected FOR loop upper limit
        Understanding is a three edged sword.
        (Old Vorlon saying)


        • #5
          I counted the number of entries in sample while Jeff was posting and got 89. (I think there should be 90 but doesn't matter.) It would easier in PIC coding if the number of table entries is a power of 2, like 64, 128 or 256. 16384 is max because there is no point in having more values in table than steps in the DAC. The practical max table size will be limited by memory size of the PIC.

          (I think I just reworded part of what Jeff said.)

          For a 128 entry table, each step would be 90 / 127 = 0.708661 degrees.

          I do disagree with Jeff on storing a full cycle. You were right with entries for 0 to 90 degrees, because sine of 91 equals sine of 89, etc etc., sine of 181 equals 0 minus sine of one, etc etc. Table only needs to cover one quadrant. (Darn, that messes up what I said above about max table size. Change 16384 to 8192.)

          For a different approach to sine waves from a PIC, start here:

          "Magic Sine Waves" are generated by PWM instead of DAC.

          Last edited by Dale Yarker; 1 Jan 2008, 01:53 AM.


          • #6
            Symmetries In The Sine Table

            Dale is correct about using symmetries in the sine function to reduce storage space. The question is whether the extra code is smaller/faster than using a full table. Sometimes it's better to sacrifice ROM for speed or vice-versa. Most of my programming now is in VHDL on FPGAs, so I can play more tricks and make more trade-offs than is usually possible with a microcontroller.
            Understanding is a three edged sword.
            (Old Vorlon saying)


            • #7
              Thank you all Very much. great info and insight
              Doug McDonald