Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

how to vary the voltage of spwm signal

Status
Not open for further replies.

mobinmk

Full Member level 2
Joined
May 27, 2010
Messages
140
Helped
4
Reputation
8
Reaction score
4
Trophy points
1,298
Location
Kollam (Quilon),kerala, India
Activity points
2,484
hi frnds

i succesfully generated spwm signal by arduino using dds technique, sine look up table, timer, interupt,

then i fed into low pass filter.

now i got sine wave.

i can vary the fequency of sine wave from 1 hz to 1024 hz.

i wana to vary the voltage of sine wave ,in program .

any idea ??

which code will add to my program.
#include "avr/pgmspace.h"

// table of 256 sine values / one sine period / stored in flash memory
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124

};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int ledPin = 13; // LED pin 7
int testPin = 7;
int t2Pin = 6;
byte bb;

double dfreq;
// const double refclk=31372.549; // =16MHz / 510
const double refclk=31376.6; // measured

// variables used inside interrupt service declared as voilatile
volatile byte icnt; // var inside interrupt
volatile byte icnt1; // var inside interrupt
volatile byte c4ms; // counter incremented all 4ms
volatile unsigned long phaccu; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m

void setup()
{
pinMode(ledPin, OUTPUT); // sets the digital pin as output
Serial.begin(115200); // connect to the serial port
Serial.println("DDS Test");

pinMode(6, OUTPUT); // sets the digital pin as output
pinMode(7, OUTPUT); // sets the digital pin as output
pinMode(11, OUTPUT); // pin11= PWM output / frequency output

Setup_timer2();

// disable interrupts to avoid timing distortion
cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt

dfreq=1000.0; // initial output frequency = 1000.o Hz
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word

}
void loop()
{
while(1) {
if (c4ms > 250) { // timer / wait fou a full second
c4ms=0;
dfreq=analogRead(0); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz

cbi (TIMSK2,TOIE2); // disble Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt

Serial.print(dfreq);
Serial.print(" ");
Serial.println(tword_m);
}

sbi(PORTD,6); // Test / set PORTD,7 high to observe timing with a scope
cbi(PORTD,6); // Test /reset PORTD,7 high to observe timing with a scope
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);

// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);

sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}

//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect) {

sbi(PORTD,7); // Test / set PORTD,7 high to observe timing with a oscope

phaccu=phaccu+tword_m; // soft DDS, phase accu with 32 bits
icnt=phaccu >> 24; // use upper 8 bits for phase accu as frequency information
// read value fron ROM sine table and send to PWM DAC
OCR2A=pgm_read_byte_near(sine256 + icnt);

if(icnt1++ == 125) { // increment variable c4ms all 4 milliseconds
c4ms++;
icnt1=0;
}

cbi(PORTD,7); // reset PORTD,7
}
 

To change the output voltage you have to divide the numbers in your look up table by a suitable factor, i.e. 2, to half the output voltage.
I see you are storing the whole of the sinewave, you could store half of it, then phase invert the second half, or store 1/4 of it and , first read the table forward, then back ward, then repeat with the invert. This would give you a better sinewave, though it does depend on your micro being fast enough compared to the wanted output frequency.
Frank
 

I would consider to multiply the table entries with a magnitude factor. Presently the number representation is offset binary (0 = lowest value, 255 highest). To scale symmetrical to zero output voltage, you would e.g. use 2's complement format. Or have a single quadrant table with unsigned numbers only (following chuckey's suggestion) and generate the negative halfwave when calculating the four-quadrant value.

Asking how to write the spwm code is another word for how do I write non-trivial C programs. You need to become familiar with the language and also with number crunching. There are of course "tons" of spwm example codes on the internet. But I believe that it's not really fruitful to use a code that you don't fully understand.
 

pls optimize this program,

serial monitor is not working,

i wana to add code for interface lcd with arduino
 

Attachments

  • finaloptimize.zip
    2.3 KB · Views: 73

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top