variable sine wave generation

Go To Last Post
10 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello All, 

 

I am trying to generate variable frequency sine wave using DAC0800 by lookup method. For fixed frequency there is no problem. But I want to vary frequency in step of 0.5 hz. I found this code given in link " https://codeandlife.com/2012/03/13/fast-dds-with-atmega88/ " and made some modification. But when I run the program I getting 5 volt output.  So please help me to find what is wrong.

 

My microcontroller is ATMEGA32

Clock-11059200

AVR Studio 7

Winavr-20100110

 

#include <avr/io.h>
#include <avr/interrupt.h>
#include <avr/sleep.h>
#include <util/delay.h>
#include <math.h>
#include <avr/pgmspace.h>

 

 

const unsigned char sine_255[256]={
0x80,0x83,0x86,0x89,0x8c,0x8f,0x92,0x95,
0x98,0x9c,0x9f,0xa2,0xa5,0xa8,0xab,0xae,
0xb0,0xb3,0xb6,0xb9,0xbc,0xbf,0xc1,0xc4,
0xc7,0xc9,0xcc,0xce,0xd1,0xd3,0xd5,0xd8,
0xda,0xdc,0xde,0xe0,0xe2,0xe4,0xe6,0xe8,
0xea,0xeb,0xed,0xef,0xf0,0xf2,0xf3,0xf4,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfb,0xfc,
0xfd,0xfd,0xfe,0xfe,0xfe,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfd,
0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,0xf6,
0xf5,0xf4,0xf2,0xf1,0xef,0xee,0xec,0xeb,
0xe9,0xe7,0xe5,0xe3,0xe1,0xdf,0xdd,0xdb,
0xd9,0xd7,0xd4,0xd2,0xcf,0xcd,0xca,0xc8,
0xc5,0xc3,0xc0,0xbd,0xba,0xb8,0xb5,0xb2,
0xaf,0xac,0xa9,0xa6,0xa3,0xa0,0x9d,0x9a,
0x97,0x94,0x91,0x8e,0x8a,0x87,0x84,0x81,
0x7e,0x7b,0x78,0x75,0x71,0x6e,0x6b,0x68,
0x65,0x62,0x5f,0x5c,0x59,0x56,0x53,0x50,
0x4d,0x4a,0x47,0x45,0x42,0x3f,0x3c,0x3a,
0x37,0x35,0x32,0x30,0x2d,0x2b,0x28,0x26,
0x24,0x22,0x20,0x1e,0x1c,0x1a,0x18,0x16,
0x14,0x13,0x11,0x10,0xe,0xd,0xb,0xa,
0x9,0x8,0x7,0x6,0x5,0x4,0x3,0x3,
0x2,0x2,0x1,0x1,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x1,0x1,0x1,0x2,0x2,
0x3,0x4,0x4,0x5,0x6,0x7,0x8,0x9,
0xb,0xc,0xd,0xf,0x10,0x12,0x14,0x15,
0x17,0x19,0x1b,0x1d,0x1f,0x21,0x23,0x25,
0x27,0x2a,0x2c,0x2e,0x31,0x33,0x36,0x38,
0x3b,0x3e,0x40,0x43,0x46,0x49,0x4c,0x4f,
0x51,0x54,0x57,0x5a,0x5d,0x60,0x63,0x67,
0x6a,0x6d,0x70,0x73,0x76,0x79,0x7c,0x80    
};

 

void cloop (unsigned int  step);

 

int main(void)
{
    unsigned int i=255,j=00;
    long count=0;
    
    PORTB=0XFF;
    DDRB=0XFF;    
    
    PORTC=0XFF;
    DDRC=0XFF;
    /* Replace with your application code */
    while (1) 
    {
     cloop(4);
    }
}

void cloop (unsigned int  step)
{
    unsigned int  counter = 0;
    while(4) 
    {
                
         if (counter<=255)
         {
             counter += step;
         }
         else
         {
          counter=0;           
         }
        
        
        PORTB = sine_255[counter>>8];
     
    }
}
 

 

 

 

Last Edited: Mon. Nov 11, 2019 - 04:40 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Have you tried just stepping through the code using pencil and paper?

 

What do you intend this to do:

while(4) 

 

See Tip #1 for how to properly post source code.

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

The variable "counter" never gets beyond 255.  So when "counter" gets shifted right eight times, it always becomes zero.  The value sine_255[ 0] is always sent to PORTB.  Take out the >>8.

 

Plus, if your AVR is running at  @11MHz system clock, then you are going to getting a 64 point sine wave at about 8000 - 10KHz out of PORTB (and the DAC).  There are 64 points because you are stepping through a 256 byte table and skipping 4 on each step.  Assuming about 20-30 instructions per pass through the C_loop. 

There's no way that you are going to be able to make 0.5Hz adjustments with this configuration.

 

As I roughly understand, DDS is done by stepping through a waveshape table with an extremely fast clock.  The time between each step is adjusted by dividing this fast clock by a 16-bit value.   Changing this 16-bit value by small amounts allows fine graduations in the final waveform (sine in most cases) frequency.

Last Edited: Mon. Nov 11, 2019 - 07:10 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Also, look up Jespers DDS  for more tips

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 1

Simonetta wrote:
The variable "counter" never gets beyond 255.  So when "counter" gets shifted right eight times, it always becomes zero. 

Indeed - which should have been obvious from stepping through the code.

 

See: https://www.avrfreaks.net/commen... and replies

Top Tips:

  1. How to properly post source code - see: https://www.avrfreaks.net/comment... - also how to properly include images/pictures
  2. "Garbage" characters on a serial terminal are (almost?) invariably due to wrong baud rate - see: https://learn.sparkfun.com/tutorials/serial-communication
  3. Wrong baud rate is usually due to not running at the speed you thought; check by blinking a LED to see if you get the speed you expected
  4. Difference between a crystal, and a crystal oscillatorhttps://www.avrfreaks.net/comment...
  5. When your question is resolved, mark the solution: https://www.avrfreaks.net/comment...
  6. Beginner's "Getting Started" tips: https://www.avrfreaks.net/comment...
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Actually why does:

         if (counter<=255)
         {
             counter += step;
         }
         else
         {
          counter=0;
         }

even exist at all? Surely you just keep adding 'step' to counter forever? 

             counter += step;

It's going up in 4's so will count 0, 4, 8, 16, 32 .. 65524, 65528, 65532 and at the next +4 it will be back to 0 (because of integer overflow).

 

If 'step' were 7 the the count would be 0, 7, 14, 21, 28... 65520, 65527, 65534 then it would wrap around to 5, 12, 19 etc.

 

PS I just followed the link you gave in #1:

 

https://codeandlife.com/2012/03/13/fast-dds-with-atmega88/

 

and this actually has:

void cloop(uint16_t step) {
    uint16_t counter = 0;

    while(1) {
        counter += step;
        DAC_PORT = waveform[counter >> 8];
    }
}

So why did you actually change this at all? Even their use of "uint16_t" is better than the "unsigned int" you changed it to !

Last Edited: Tue. Nov 12, 2019 - 10:54 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

As you I try this but with 8 bit 255 point table but I getting high. And as other suggest, first I try with jespers dds.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

samic45mit1 wrote:
As you I try this but with 8 bit 255 point table but I getting high. And as other suggest, first I try with jespers dds.
You've missed the whole point of DDS. In DDS the "counter" is wider than the sample table. That is the reason for the >>8 in:

DAC_PORT = waveform[counter >> 8];

It's saying "ignore the low end noise - I'm only interested in the upper bits to index the table". As the counter is uint16_t and an >>8 is performed then you are left with 8 bits which is fine for indexing a 256 entry table.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

samic45mit1 wrote:

I am trying to generate variable frequency sine wave using DAC0800 by lookup method. For fixed frequency there is no problem. But I want to vary frequency in step of 0.5 hz.

What Frequency range do you target ?

 

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

quick comments:

you need to read more about DDS's :)

1) The code have an error in the lookup table, element 0 and 255 are both 0x80 (looks like you have a sine wave with a period of 255 not 256) 

2)With a DDS never do any checks (it't the carry's that is its strength), you and away unwanted bits (shifts will sometimes do the same job, and with 8 16 24 32 bit counter and 8 bit output you just select the byte you want (normally the high byte)).

3)You need to time the update rate (Timer ISR) if you want a constant freq.