Waveform Generation

We previously learn about flash memory and how to program it. In this article we build a waveform generator. In that we uses four different switches to generate four different waveform i.e. Saw tooth, square, triangular and sinusoidal. We can get the desire analog signal from the Atmel AVR digital output with the help of DAC (Digital to analog converter).

If we develop at the outputs of the microcontroller an appropriate resistance network have the possibility of developing by the control of the outputs over the resistance an adder with whose assistance, we can produce a proportional tension for the numerical values. Let’s look at the 8bit DAC Ladder circuit bellow-

Here the output value is-

A sinusoidal signal can be define as –sin(X) = Amplitude x sin(2ᴨƒ + Ф) = Asin(2ᴨƒ + Ф)

Assume,

A = Amplitude = 1

ƒ = frequency = 1Hz

Ф = Angle =  

Sample Sinusoidal wave into 8bit, n=8

Since the output vary from 0V to 5V.

DC offset voltage = 2.5V.

So sinusoidal wave output is

#include<avr/io.h>
#include<util/delay.h>
#include<math.h>
#define PI          3.14159265
#define AMPLITUDE   2.5
#define FREQUENCY   1.0
#define DURATION    1.0
#define SAMPLE_RATE 256
#define VREF        5.0
#define MAX_VALUE   255
uint8_t sin_value[256];     //sinewave sample 255 times
uint8_t wave_out;
int main(void)
{
DDRD = 0xFF; //Define for output
int num_samples=(int)(DURATION*SAMPLE_RATE);
double time_step=DURATION/num_samples;
for(int i=0;i<num_samples;i++)
{
	double time=i*time_step;
	double sin_wave=2.5+AMPLITUDE*sin(2.0*PI*FREQUENCY*time);
	sin_value[i]=(uint8_t)((sin_wave/VREF)*MAX_VALUE);
}
while(1)
{
	for(uint8_t i=0;i<256;i++)
	{

		PORTD=sin_value[i];
		_delay_us(78);
	}
}
return 0;
}

Here the variable sin_value[i] has a value-

sin_value[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,0xec,0xed,0xef,0xf0,0xf2,0xf3,0xf5,
0xf6,0xf7,0xf8,0xf9,0xfa,0xfb,0xfc,0xfc,0xfd,0xfe,0xfe,0xff,0xff,0xff,0xff,0xff,
0xff,0xff,0xff,0xff,0xff,0xff,0xfe,0xfe,0xfd,0xfc,0xfc,0xfb,0xfa,0xf9,0xf8,0xf7,
0xf6,0xf5,0xf3,0xf2,0xf0,0xef,0xed,0xec,0xea,0xe8,0xe6,0xe4,0xe2,0xe0,0xde,0xdc,
0xda,0xd8,0xd5,0xd3,0xd1,0xce,0xcc,0xc9,0xc7,0xc4,0xc1,0xbf,0xbc,0xb9,0xb6,0xb3,
0xb0,0xae,0xab,0xa8,0xa5,0xa2,0x9f,0x9c,0x98,0x95,0x92,0x8f,0x8c,0x89,0x86,0x83,
0x80,0x7c,0x79,0x76,0x73,0x70,0x6d,0x6a,0x67,0x63,0x60,0x5d,0x5a,0x57,0x54,0x51,
0x4f,0x4c,0x49,0x46,0x43,0x40,0x3e,0x3b,0x38,0x36,0x33,0x31,0x2e,0x2c,0x2a,0x27,
0x25,0x23,0x21,0x1f,0x1d,0x1b,0x19,0x17,0x15,0x13,0x12,0x10,0x0f,0x0d,0x0c,0x0a,
0x09,0x08,0x07,0x06,0x05,0x04,0x03,0x03,0x02,0x01,0x01,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x02,0x03,0x03,0x04,0x05,0x06,0x07,0x08,
0x09,0x0a,0x0c,0x0d,0x0f,0x10,0x12,0x13,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
};

We store the value in Flash memory using const uint8_t sin_wave[256] PROGMEM. We also developed saw tooth, square and triangle wave variable value. Download the wave.h file. One interesting thing that we can store our variable in .h file and use it our main program. Our main program as follow-

/************************************************************************************************
*************************************************************************************************
This program will genarate different wavefrom according to switch
		PINB0---------Sawtooth
		PINB1---------Square
		PINB2---------Triangle
		PINB3---------SinWave
************************************************************************************************
***********************************************************************************************/
#include<avr/io.h>
#include<util/delay.h>
#include "wave.h"
const uint8_t *Wave[4]PROGMEM ={Sawtooth,Square,Triangle,SinWave};
uint8_t generarion,data;
int main(void)
{
DDRB&=(~((1<<DDB0)|(1<<DDB1)|(1<<DDB2)|(1<<DDB3)));
PORTB|=(1<<PB0)|(1<<PB1)|(1<<PB2)|(1<<PB3);
data=PINB&0b00001111;
DDRD=0xFF;
while(1)
	{
	data=PINB&0b00001111;
	if(data==0b00001110)
	{
		for(int i=0;i<256;i++)
		{
			generarion=(uint8_t*)pgm_read_word(&Wave[0][i]);
			_delay_ms(1);
			PORTD=generarion;
		}
	}
	if(data==0b00001101)
	{
		for(int i=0;i<256;i++)
		{
			generarion=(uint8_t*)pgm_read_word(&Wave[1][i]);
			_delay_ms(1);
			PORTD=generarion;
		}
	}
	if(data==0b00001011)
	{
		for(int i=0;i<256;i++)
		{
			generarion=(uint8_t*)pgm_read_word(&Wave[2][i]);
			_delay_ms(1);
			PORTD=generarion;
		}
	}
	if(data==0b00000111)
	{
		for(int i=0;i<256;i++)
		{
			generarion=(uint8_t*)pgm_read_word(&Wave[3][i]);
			_delay_ms(1);
			PORTD=generarion;
		}
	}
	}
return 0;
}