Forum Menu




 


Log in Problems?
New User? Sign Up!
AVR Freaks Forum Index

Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Author Message
Analog_guy
PostPosted: Mar 20, 2012 - 05:31 PM
Rookie


Joined: Jun 16, 2011
Posts: 31


I'm trying to get a sinewave out by modulating the pwm with a sine table but get no modulation, just expected pulse. I'm using avr studio 4.14, atmega8 chip on a dragonrider. Code is:

Code:
#include <avr\io.h>
#include <avr\interrupt.h>
#include <avr/pgmspace.h>
const uint8_t sinewave[] PROGMEM= //256 values
{
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
};
uint8_t i=0;
ISR(TIMER1_COMPA_vect)
{
OCR1A=pgm_read_byte(&sinewave[i]);
i++;
}
int main(void) {
//Port D pins as input
DDRD=0x00;
//Enable internal pull ups
PORTD=0xFF;
//Set PORTB1 pin as output
DDRB=0xFF;
// initial OCR1A value
OCR1A=80;
//Output compare OC1A 8 bit non inverted PWM
TCCR1A=0x91;
//start timer without prescaler
TCCR1B=0x01;
//enable output compare interrupt for OCR1A (TIMSKI=0x10 for ATmega8)
TIMSK=0x02; // OCIE1A = 1
//enable global interrups
sei();
while (1) {
//loop forever. Interrupts will do the job.
}


I checked and it looks correct. Any ideas?
 
 View user's profile Send private message  
Reply with quote Back to top
js
PostPosted: Mar 20, 2012 - 10:13 PM
10k+ Postman


Joined: Mar 28, 2001
Posts: 20637
Location: Sydney, Australia (Gum trees, Koalas and Kangaroos, No Edelweiss)

What does your filter look like? Also I would make i volatile, maybe it's not needed but it won't hurt.

_________________
John Samperi
Ampertronics Pty. Ltd.
www.ampertronics.com.au
* Electronic Design * Custom Products * Contract Assembly
 
 View user's profile Send private message Visit poster's website 
Reply with quote Back to top
Analog_guy
PostPosted: Mar 20, 2012 - 11:47 PM
Rookie


Joined: Jun 16, 2011
Posts: 31


Filter doesn't matter since I don't see any variation in pulsewidths to filter out. I did try a rc filter with fc=1000, but no sinewave.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 21, 2012 - 09:30 AM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62952
Location: (using avr-gcc in) Finchingfield, Essex, England

Why write code like this:
Code:
// initial OCR1A value
OCR1A=80;
//Output compare OC1A 8 bit non inverted PWM
TCCR1A=0x91;
//start timer without prescaler
TCCR1B=0x01;
//enable output compare interrupt for OCR1A (TIMSKI=0x10 for ATmega8)
TIMSK=0x02; // OCIE1A = 1

when it could explain itself like this:
Code:
// initial OCR1A value !!!! Bet this is supposed to be 0x80 !!!
OCR1A = 80;
//Output compare OC1A 8 bit non inverted PWM
TCCR1A = (1 << COM1A1) | (1 << COM1B0) | (1 << WGM10);
//start timer without prescaler
TCCR1B = (1 << CS10);
//enable output compare interrupt for OCR1A (TIMSKI=0x10 for ATmega8)
TIMSK = (1 << undefined);

Having done that, if this is really for mega8, several problems become immediately obvious:

1) trivial but your OCR1A start value is supposed to be 0x80

2) trivial but your comment on setting TCCR1A does not match what's actually being done - why even bother with COM1B0 if you don't use OC1B?

3) most important is the 0x02 you are setting in TIMSK. bit 1 is undefined. The comment even says "(TIMSKI=0x10 for ATmega8)" The bit that enables the COMPA1 interrupt is:
Code:
TIMSK = (1 << OCIE1A);

which I guess you'd write this as:
Code:
TIMSK = 0x10;

So why are you setting the register to 0x02?

Also do you really want to change OCR1A on a compare match anyway? Personally I'd enable the overflow interrupt and change OCR1A in that.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Analog_guy
PostPosted: Mar 21, 2012 - 05:55 PM
Rookie


Joined: Jun 16, 2011
Posts: 31


I'm an older analog engineer who's slowly learning how to program a microcontroller. So, it takes me a while to get something working.
I started with a butterfly and Smileys book and then got a dragon and put it on a dragonrider. Anyway, Smiley likes to use the technique of
TIMSK = (1 << OCIE1A) while others use TIMSK = 0x10. I wish I had looked closer at the code, because I would have noticed that TIMSK = 0x10 is wrong! I used TIMSK = (1 << OCIE1A) and got the sinewave output!!

I copied the code from a pdf file "sine_wave_generator" where the code was copied from :

http://www.scienceprog.com/generate-sin ... ontroller/

so I was sure the code was correct.

Thanks for your help!

Actually 'OCR1A = 80' was correct. 256 would have been 100% while 80 gives ~1/3 duty cycle.
 
 View user's profile Send private message  
Reply with quote Back to top
clawson
PostPosted: Mar 21, 2012 - 06:54 PM
10k+ Postman


Joined: Jul 18, 2005
Posts: 62952
Location: (using avr-gcc in) Finchingfield, Essex, England

Quote:

Actually 'OCR1A = 80' was correct. 256 would have been 100% while 80 gives ~1/3 duty cycle.

You sure? On the very next interrupt after initialisation the table data has:
Code:
const uint8_t sinewave[] PROGMEM= //256 values
{
0x80,

So the 80 will almost immediately be replaced by 0x80.

Actually, to be honest, I don't suppose it matters and there's not really much point setting an initial value anyway as the interrupting will start so soon after power on that it's moot.

_________________
 
 View user's profile Send private message  
Reply with quote Back to top
Display posts from previous:     
Jump to:  
All times are GMT + 1 Hour
Post new topic   Reply to topic
View previous topic Printable version Log in to check your private messages View next topic
Powered by PNphpBB2 © 2003-2006 The PNphpBB Group
Credits