DDS (generating sine waves) with onboard DAC using latest PIC 16F chips?


Closed Thread
Results 1 to 40 of 77

Hybrid View

  1. #1
    Join Date
    Oct 2005
    Location
    Sweden
    Posts
    3,612


    Did you find this post helpful? Yes | No

    Default

    Hi Hank,
    I've never played with them but I'd say it depends on what kind of resolution you need as the DAC in the 16F1824 only has 5 bits of it. This means that you will only be able to get 32 discrete voltage levels which may, or may not, be enough.

    /Henrik.

    Edit: Don beat me to it, I was reading the datasheet while writing.

  2. #2
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Quote Originally Posted by HenrikOlsson View Post
    Hi Hank,
    I've never played with them but I'd say it depends on what kind of resolution you need as the DAC in the 16F1824 only has 5 bits of it. This means that you will only be able to get 32 discrete voltage levels which may, or may not, be enough.

    /Henrik.

    Edit: Don beat me to it, I was reading the datasheet while writing.
    Actually 5 bits would probably ok for my needs, but I need to be able to resolve the frequency to 0.1% (eg plus or minus 1Hz @1khz & so on)

    I can see now that is's a very very basic DAC (just a 32 step pot really)...hey, ho.

    Thanks for your input though.

  3. #3
    Join Date
    Oct 2005
    Location
    Loveland CO USA
    Posts
    83


    Did you find this post helpful? Yes | No

    Default

    The DAC is very high impedance. You will need a buffer. Normally I use a 2 pole low pass filter to remove the digital noise.

  4. #4
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Hi Hank,

    Not exactly what you asked for, but... have you considered using the PWM module with a low pass filter on the CCP1 output? You may need to amplify the signal as well.

    I was toying with this idea a while back for a CTCSS Access Tone Generator but I never got around to building and testing it.

    This example (free/lite version of BoostC) uses a 12F683 and an 8.388608-MHz crystal to generate CTCSS sine wave tones spanning 100 to 250-Hz with 0.000625-Hz frequency resolution. If you were to use a 12F1822 with that crystal and 4xPLL, or any other device with 4xPLL, you could bump the upper frequency range to about 1000-Hz with 0.0025-Hz frequency resolution.

    Food for thought.

    Cheerful regards, Mike McLaren, K8LH


    PS: A quick search came up with this interesting old thread; Generating tones with decimals using PWM

    Code:
    /********************************************************************
     *                                                                  *
     *  Project: CTCSS 12F683                                           *
     *   Source: CTCSS_12F683.c                                         *
     *   Author: Mike McLaren, K8LH                                     *
     *     Date: 26-Nov-10                                              *
     *  Revised: 26-Nov-10                                              *
     *                                                                  *
     *  untested 12F683 DDS(PWM) CTCSS Tone Generator with 24-bit       *
     *  Phase Accumulator (Fosc = 8.388608-MHz)                         *
     *                                                                  *
     *      IDE: MPLAB 8.56 (tabs = 4)                                  *
     *     Lang: SourceBoost BoostC v7.01, Lite/Free version            *
     *                                                                  *
     ********************************************************************
     *
     *    CTCSS tone frequencies
     *
     *     67.0 Hz    69.3 Hz    71.9 Hz    74.4 Hz    77.0 Hz
     *     79.7 Hz    82.5 Hz    85.4 Hz    88.5 Hz    91.5 Hz
     *     94.8 Hz    97.4 Hz   100.0 Hz   103.5 Hz   107.2 Hz
     *    110.9 Hz   114.8 Hz   118.8 Hz   123.0 Hz   127.3 Hz
     *    131.8 Hz   136.5 Hz   141.3 Hz   146.2 Hz   151.4 Hz
     *    156.7 Hz   159.8 Hz   162.2 Hz   165.5 Hz   167.9 Hz
     *    171.3 Hz   173.8 Hz   177.3 Hz   179.9 Hz   183.5 Hz
     *    186.2 Hz   189.9 Hz   192.8 Hz   196.6 Hz   199.5 Hz
     *    203.5 Hz   206.5 Hz   210.7 Hz   218.1 Hz   225.7 Hz
     *    229.1 Hz   233.6 Hz   241.8 Hz   250.3 Hz   254.1 Hz
     *
     */
    
    #include system.h
    
    #pragma DATA _CONFIG, _MCLRE_OFF, _WDT_OFF, _HS_OSC
    
    #pragma CLOCK_FREQ 8388608      // using an 8.388608-MHz crystal
    
    //--< function prototypes >------------------------------------------
    //--< type definitions >---------------------------------------------
    
    typedef unsigned char u08;
    typedef unsigned int u16;
    typedef unsigned long u32;
    
    #define r08 rom char*
    
    //--< variables >----------------------------------------------------
    
    u32 accum;                  // phase accumulator
    u32 phase;                  // phase offset (DDS tuning word)
    
    r08 sinetbl =   { 100,102,104,107,109,112,114,117,119,121,
                      124,126,129,131,133,135,138,140,142,144,
                      147,149,151,153,155,157,159,161,163,165,
                      167,168,170,172,174,175,177,178,180,181,
                      183,184,185,187,188,189,190,191,192,193,
                      194,194,195,196,197,197,198,198,198,199,
                      199,199,199,199,200,199,199,199,199,199,
                      198,198,198,197,197,196,195,194,194,193,
                      192,191,190,189,188,187,185,184,183,181,
                      180,178,177,175,174,172,170,168,167,165,
                      163,161,159,157,155,153,151,149,147,144,
                      142,140,138,135,133,131,129,126,124,121,
                      119,117,114,112,109,107,104,102, 99, 97,
                       95, 92, 90, 87, 85, 82, 80, 78, 75, 73,
                       70, 68, 66, 64, 61, 59, 57, 55, 52, 50,
                       48, 46, 44, 42, 40, 38, 36, 34, 32, 31,
                       29, 27, 25, 24, 22, 21, 19, 18, 16, 15,
                       14, 12, 11, 10,  9,  8,  7,  6,  5,  5,
                        4,  3,  2,  2,  1,  1,  1,  0,  0,  0,
                        0,  0,  0,  0,  0,  0,  0,  0,  1,  1,
                        1,  2,  2,  3,  4,  5,  5,  6,  7,  8,
                        9, 10, 11, 12, 14, 15, 16, 18, 19, 21,
                       22, 24, 25, 27, 29, 31, 32, 34, 36, 38,
                       40, 42, 44, 46, 48, 50, 52, 55, 57, 59,
                       61, 64, 66, 68, 70, 73, 75, 78, 80, 82,
                       85, 87, 90, 92, 95, 97 };
    
    //--< defines >------------------------------------------------------
    
    //--< isr >----------------------------------------------------------
    
    /*
     *  12F/16F1xxx DDS-PWM CTCSS "Access Tone Generator" Notes
     *  =======================================================
     *
     *  using an 8.388608 MHz crystal
     *
     *    Tcy = 1 / 8388608 * 4 = 476.837158203125 nsecs
     *
     *  using a 200 cycle PWM period provides a DDS frequency of
     *
     *    Fdds = 1 / (200 Tcy) = 10,485.76 Hz
     *
     *  frequency resolution using a 24 bit phase accumulator is
     *
     *    Fres = Fdds / 2^24
     *    Fres = 10485.76 / 16777216 = 0.000625 Hz
     *
     *  dds tuning word (phase offset) can be calculated a couple
     *  different ways.  since the dds frequency resolution (Fres)
     *  is basically 0.01-Hz divided by 16, you can calculate the
     *  phase offset by mulitplying desired Fout output frequency
     *  by 1600.  the phase offset for an Fout of 254.1-Hz is;
     *
     *    phase = (Fout  * 100) * 16
     *          = (254.1 * 100) * 16 = 406560
     *
     *    phase =  25410 << 4 = 406560
     *
     *  or you can also calculate phase offset like this (yuch!);
     *
     *    phase = Fout / Fres
     *          = 254.1 / 0.000625 = 406560
     *
     *    phase = Fout * 2^24 / Fdds
     *          = 254.1 * 16777216 / 10485.76 = 406560
     *
     *  the highest CTCSS frequency (254.1 Hz) will produce the
     *  smallest number of sine wave D/A output points per cycle;
     *
     *    INT(10485.76 / 254.1) = 41 output points per cycle
     *
     *  use the most significant 8 bits of the 24-bit phase
     *  accumulator as the sine table index.
     *
     */
    
    void interrupt()                // 200-cycles (10485.76-Hz)
    { pir1.TMR2IF = 0;              // clear TMR2 interrupt flag
      accum += phase;               // add phase offset to accum
      ccpr1l = sinetbl[accum>>16];  // sine duty cycle value for
    }                               // next PWM period
    
    //--< main >---------------------------------------------------------
    
    void main()
    {
      cmcon0 = 7;                   // comparator off, digital I/O
      ansel = 0;                    // a2d module off, digital I/O
      trisio = 0b00111011;          // GP2 output, all others input
     /*
      *  setup PWM module for 200 cycle interrupts (10485.76-Hz using
      *  an 8.388608-MHz clock)
      *
      */
      ccp1con = 0b00001100;         // 00001100
                                    // --00---- DC1B<1:0>, duty cycle b1:b0
                                    // ----1100 CCP1M<3:0>, pwm mode
      t2con = 0b00000000;           // 00000000
                                    // -0000--- TOUTPS<3:0>, postscale 1
                                    // -----0-- TMR2ON, timer off
                                    // ------00 T2CKPS<1:0>, prescale 1
                                    // for 476.837158203125 nsec 'ticks'
      pr2 = 200-1;                  // for 95.367431640625 usec interrupts
      ccpr1l = 0;                   // 0% duty cycle
      pie1.TMR2IE = 1;              // enable Timer 2 interrupts
      pir1 = 0;                     // clear all peripheral interrupt flags
      intcon.PEIE = 1;              // enable peripheral interrupts
      intcon.GIE = 1;               // enable global interrupts
      t2con.TMR2ON = 1;             // turn TMR2 on
    
      phase = 25410 << 4;           // phase offset for 254.1-Hz tone
    
      while(1);                     // loop forever
    }
    Last edited by Mike, K8LH; - 15th January 2011 at 18:36.

  5. #5
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default

    Hi Mike,

    yes I've done that....I just got a bit over excited at the prospect of an onboard DAC, but I now realise it's pretty poor....looks as if it's meant to generate a ref voltage, but being high impedance, I'd be better off using two resistors and an opamp!

  6. #6
    Join Date
    Aug 2005
    Location
    Michigan, USA
    Posts
    224


    Did you find this post helpful? Yes | No

    Default

    Do you think it might be possible to add 2 (or more) bits of precision to the DAC?

    Code:
    Interval  #1  #2  #3  #4
         DAC  00  00  00  00  -> 0.00v
         DAC  00  00  00  01  -> 0.04v
         DAC  00  00  01  01  -> 0.08v
         DAC  00  01  01  01  -> 0.12v
    
         DAC  01  01  01  01  -> 0.16v
         DAC  01  01  01  02  -> 0.20v
         DAC  01  01  02  02  -> 0.24v
         DAC  01  02  02  02  -> 0.28v
    
         DAC  02  02  02  02  -> 0.32v
         ........

  7. #7
    Join Date
    Mar 2009
    Posts
    653


    Did you find this post helpful? Yes | No

    Default Re: DDS (generating sine waves) with onboard DAC using latest PIC 16F chips?

    Quote Originally Posted by Mike, K8LH View Post
    Do you think it might be possible to add 2 (or more) bits of precision to the DAC?

    Code:
    Interval  #1  #2  #3  #4
         DAC  00  00  00  00  -> 0.00v
         DAC  00  00  00  01  -> 0.04v
         DAC  00  00  01  01  -> 0.08v
         DAC  00  01  01  01  -> 0.12v
     
         DAC  01  01  01  01  -> 0.16v
         DAC  01  01  01  02  -> 0.20v
         DAC  01  01  02  02  -> 0.24v
         DAC  01  02  02  02  -> 0.28v
     
         DAC  02  02  02  02  -> 0.32v
         ........
    This must have slipped past me - I'm not understanding what you're getting at?

    I was actually wondering myself whether it's possible in practise to squeeze another 2 bits of effective' resolution by switching the fixed voltage reference supply into the DAC resistor divider chain (ie feed 1.024V in for the first 32 voltage level steps, then 2.048, then 4.096V) - it might be a bit spikey (due to the FVR switching voltages), but if not that should mean we can squeeze 7 bits out of the PIC's DAC pin.

Members who have read this thread : 1

You do not have permission to view the list of names.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts