PWM timing

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

I have been working on a project to make a 100 Hz sine wave output using fast PWM and a sine look up table in an ATtiny45.  The ATtiny45 is running on an external 3.276 MHz crystal.  The output of pin 5 (PB0) is connected to an RC filter.  The program I've attached produces a nice sine wave at the output of this filter but the 50 Hz frequency is much different than I had expected.

 

According to my calculations a 3.276 MHz oscillator frequency divided by 16 followed by a counter prescaler division of 8 should give an output of 100 Hz, since one complete output cycle should require a further 256 values from the sine table.  That is: 3.276 MHz/16/8/256 = 100 Hz.  When I set the appropriate fuses for the clock divide by 16 and counter prescaler divide by 8, however, the frequency was much lower than 100 Hz.  With the settings shown in the attached program the RC filter output frequency is 50 Hz and the counter frequency is 12.8 kHz.  In the attached version the clock and prescaler are both set to divide by 1 instead of the 16 and 8 I had thought would be required.

 

I have tried changing fuses and the counter prescaler and the changes I've made affect the frequency.  What I don't understand is why the frequency is so different from the 100 Hz I expected from the calculations I made.  Is it that I am overlooking something in my calculations or doing something wrong with the programming?  I would appreciate advice.

 

.DEF A = R16 ;GENERAL PURPOSE ACCUMULATOR
.ORG $0000 ;STARTUP VECTOR
RJMP ON_RESET
.ORG $000A ;COMPARE MATCH VECTOR
RJMP TIM0_COMPA
ON_RESET:
ldi A, 0b1000_0000  ;set external clock divide by 1
out CLKPR, A
ldi A, 0b0000_0000
out CLKPR, A

ldi A, low(RAMEND)                    ; Initiate Stack pointer
out SPL, A
ldi A, high(RAMEND)
out SPH, A

SBI DDRB,0 ;SET PORTB0 FOR OUTPUT
LDI A,0b1000_0011 ;PWM MODE 3
OUT TCCR0A,A
LDI A,0b0000_0001 ;SET PRESCALER/DIVIDER TO /1
OUT TCCR0B,A
LDI A,0b0001_0000 ;ENABLE COMPARE INTERUPT
OUT TIMSK,A
SEI ;ENABLE INTERUPTS GLOBALLY
MAIN_LOOP: RJMP MAIN_LOOP;A DO-NOTHING LOOP

TIM0_COMPA:
ldi ZH, high(sine_table*2)            ; Set up Z to point to the beginning of sine_table
ldi ZL, low(sine_table*2)
add ZL, r19                            ; Offset Z by r20:r19
adc ZH, r20
lpm                                    ; Load sine_table[Z] into OCR1A
out OCR0A, r0                        ;set OCR0A value for PWM
inc r19                                ;increment r19 to take the next value from the sine table
clr r20

RETI

 sine_table:                                ;from AVR App Note 131
.db 128,131,134,137,140,144,147,150,153,156,159,162,165,168,171,174
.db 177,179,182,185,188,191,193,196,199,201,204,206,209,211,213,216
.db 218,220,222,224,226,228,230,232,234,235,237,239,240,241,243,244
.db 245,246,248,249,250,250,251,252,253,253,254,254,254,254,254,254
.db 254,254,254,254,254,254,254,253,253,252,251,250,250,249,248,246
.db 245,244,243,241,240,239,237,235,234,232,230,228,226,224,222,220
.db 218,216,213,211,209,206,204,201,199,196,193,191,188,185,182,179
.db 177,174,171,168,165,162,159,156,153,150,147,144,140,137,134,131
.db 128,125,122,119,116,112,109,106,103,100,97,94,91,88,85,82
.db 79,77,74,71,68,65,63,60,57,55,52,50,47,45,43,40
.db 38,36,34,32,30,28,26,24,22,21,19,17,16,15,13,12
.db 11,10,8,7,6,6,5,4,3,3,2,2,2,1,1,1
.db 1,1,1,1,2,2,2,3,3,4,5,6,6,7,8,10
.db 11,12,13,15,16,17,19,21,22,24,26,28,30,32,34,36
.db 38,40,43,45,47,50,52,55,57,60,63,65,68,71,74,77
.db 79,82,85,88,91,94,97,100,103,106,109,112,116,119,122,125

 

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

r19  r20 are not set the first time used.

 

Also r20 does not need cleared each time in the IRQ.

 

what is the freq of the fast PWM?

 

The data in the table (256 entries) produces one full cycle, 360 degrees of waveform

bottom line--you need a 26500 Hz IRQ to get a 100 Hz sine

 

but the 50 Hz frequency is much different than I had expected.    ...how are you measuring freq?  It is easy to also make a 2x measuring mistake, unless you are using a freq counter

 

a minor point 

Load sine_table[Z] into OCR1A

its going into r0 then to OCR0A

 

Does the wave look clean? Do you get a steady IRQ interrupt rate?

 

 

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

Last Edited: Thu. Mar 26, 2020 - 08:13 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I suspect that the fuse setting for the clock is wrong and the system is running at @1.2MHz on internal RC clock.

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

Thank you avrcandies and Simonetta for taking the time to look over my question.  Unfortunately, I am still unclear about the answer to it.

 

First: 

The data in the table (256 entries) produces one full cycle, 360 degrees of waveform

bottom line--you need a 26500 Hz IRQ to get a 100 Hz sine

 

As I mentioned, the frequencies 12.8 kHz, not 26500 Hz and that is why the sine wave has a frequency of 50 Hz, half of what I would like.  Both frequencies were measured with an oscilloscope and they are accurate within 1 Hz.  If I set the clock division to 2 instead of 1, I get a sine wave frequency of 25 Hz.

 

Second:

I suspect that the fuse setting for the clock is wrong and the system is running at @1.2MHz on internal RC clock.

 

I don't think this is the problem because I can't see how I could get exactly 50 Hz from the 1.2 MHz internal RC clock.  Also, I know the chip is running on the 3.276 MHz crystal because I checked it with an oscilloscope.  The frequency was measured as 3.276 MHz.  As well, I don't think it is possible to divide 1.2 MHz by powers of 2 to produce 100 Hz.

 

When I set the clock division to 16 and the prescaler division to 8 there was an output on pin 5 (PB0) but its frequency was too small to measure.  I presume it was 50 Hz/16/8 (since by taking out the 16 and 8 divisors I get a 50 Hz sine wave).  But I still don't understand why I don't get 100 Hz if I am using a 3.276 MHz clock/16/8 and then have a count of 256 to get one cycle.

 

 

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

After giving more thought to my question I think I have discovered the answer.  The clock is running at 3.276 MHz.  I forgot to include the 256 clock counts required for each counter output. The result is that 3.276 MHz/256 = 12.8 kHz and when this is divided by the 256 values required for one cycle of the sine wave the result is 50 Hz, which is what I found.  I am very glad to have this sorted out because although I was able to get the desired 100 Hz output by cycling through every second value of the program's sine table twice, I really wanted to understand what was happening.

 

Thanks again to avrcandies and Simonetta.