Is my calculation right for generating 3.8 kHz PWM ?

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

Guys,

Is my calculation right for generating 3.8 kHz PWM ?

PWM wave frequency is f= 16000000/(2*8*256) = 3.8 kHz

I want to put the output into OC1A,

Is my init code right ?

timer_init()
{
	
	//page 136 ATMEGA128A datasheet
   TCCR1A = 0xA7;  // PWM, Phase Correct, 8-bit set OC1A on compare match, clear them at top,set OC1B on compare match, clear them at top
    TCCR1B=  0x12;
}

int main(void)
{
	DDRB=0xFF;
	timer_init();
    while(1)
    {
		OCR1A = 100; //beep on

		//sound for 500ms
		_delay_ms( 500 );

		OCR1A = 0; //turn beep off

		//wait 1s between beeps
		_delay_ms( 1000 );
        //TODO:: Please write your application code 
    }
}

Thank you

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

Don't hard code numbers like A7 and 12. Use symbolic bit names so the reader does not need to dig out the datasheet to work out what those bit patterns mean.

BTW why "phase correct" (which halves the PWM frequency available)? It's almost never actually required.

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

I put a hard code because I read from datasheet,
I'll have a look and put it as symbolic bit names
Please correct me if I'm wrong

Probably :

pwm_init()
{
	TCCR1A = _BV(WGM10)  // PWM, Phase Correct, 8-bit
	| _BV(COM1A0)   // set OC1A on compare match, clear them at top
	| _BV(COM1A1);   // set OC1A on compare match, clear them at top


	
	TCCR1B |= _BV(CS11) ;//| _BV(CS10);
	//page 136 ATMEGA128A datasheet
 
}

Clock equal to 16Mhz

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
int main(void)
{
	DDRB=0xFF;
	pwm_init();
    while(1)
    {
		OCR1A = 100; //beep on

		//sound for 500ms
		_delay_ms( 500 );

		OCR1A = 0; //turn beep off

		//wait 1s between beeps
		_delay_ms( 1000 );
        //TODO:: Please write your application code 
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0
A7 = _BV(COM1A1) | _BV(COM1B1) | _BV(COM1C0) | _BV(WGM11) | _BV(WGM10)

That is clear OC1A/OC1B on compare, toggle OC1C on compare.

12 = _BV(WGM12) | _BV(CS11)

The WGM bits in the TCCR registers together select Fast PWM 10-bit and the CS11 bit starts the timer with /8 prescaling.

Some of that matches your comments - some doesn't.

So what exactly is your intention here? Why the /8 (usually you are aiming to run PWM as fast as possible) for example? Why the different setup of COMC compare to A/B? Are you erally using all three pins?

EDIT: OK, while I worked out your bit patterns you posted completely different code. Are you trolling?

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

I got

on PB5, am I doing the right thing ?
thanks

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

What do you think?

(I still wonder what you are doing setting COM bits for B and C if you are never going to touch OCR registers for B and C?)

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

I'm doing experiment with bit combination in datasheet...so keep changing all the time...

I haven't heard the beep, may be my LM386 doesn't work properly yet....

Because I'm doing experiment and trying to understand all the bits there on the register and experimenting...

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

The purpose of an experiment is to perform the tests, observe the results and form a conclusion. By asking our opinion , you've missing out on the experience. Pretend there is no internet.

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

There are code generators for timers and pwms. One comes with codevision, one comes with imagecraft. Maybe there is one for gcc?

Imagecraft compiler user

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

bobgardner wrote:
There are code generators for timers and pwms. One comes with codevision, one comes with imagecraft. Maybe there is one for gcc?

are there any with Atmel studio ?
thanks

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

Quote:

I haven't heard the beep, may be my LM386 doesn't work properly yet....

Are you sure you don't want to modulate the duty to produce the noise?!? That's the way PWM playback of sound samples usually works. It's also why you want the PWM frequency out of the human audio range so it can be removed by filter.

I'm guessing you maybe just want to produce square waves in which case forget PWM - use CTC and use the "TOP" register to vary the frequency of the "note" produced.

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

That's right, I want to produce squarewave only, but next time I want to produce multiple different frequency of squarewave....it's modulation of duty isn't it ?

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

Back in '70 I saw one of the first MiniMoogs at Lipham Music in Gainesville. Met Bob Moog too. The oscillators had a width control on the square wave setting, and making the pulse width skinnier made the tone fatter with more hi harmonics. A wave that is symmetrical horizontally (50% duty) has only even harmonics. So for simple beeps at different freqs, I'd just set the channel to toggle and set the top to the period of half the waveform freq.

Imagecraft compiler user

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

do you mean by this one ?

OCR1A = 200; //beep on

		//sound for 500ms
		_delay_ms( 500 );

		OCR1A = 0; //turn beep off

		//wait 1s between beeps
		_delay_ms( 1000 );
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

What should I do, if I have multiple frequency but still want to use 1 timer ?
for example tone c d e and so on ?

thanks guys

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

bianchi77 wrote:
What should I do, if I have multiple frequency but still want to use 1 timer ?
for example tone c d e and so on ?
Do you mean multiple frequencies at the same time (polyphonic)? Difficult to do with one timer. It's possible, but you're probably looking at DDS, which is much more complicated than simple PWM with a timer.

If you mean multiple frequencies one after the other, simply re-configure the timer for each frequency. If you want to 'play' a frequency for a certain amount of time, configure the timer and then use _delay_ms() (or other timing mechanism) to set the length of the 'note', then lather/rinse/repeat for the remaining frequencies.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

bobgardner wrote:
Back in '70 I saw one of the first MiniMoogs at Lipham Music in Gainesville. Met Bob Moog too. The oscillators had a width control on the square wave setting, and making the pulse width skinnier made the tone fatter with more hi harmonics. A wave that is symmetrical horizontally (50% duty) has only even harmonics. So for simple beeps at different freqs, I'd just set the channel to toggle and set the top to the period of half the waveform freq.
This is OT, but a 50% square wave contains only odd harmonics. As you move away from 50%, even harmonics come in.

Attached are spectral plots of a 1kHz 50% square wave, and a 10% square wave.

JJ

Attachment(s): 

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

so just create another function with different frequency (different configuration of timer) and then call it when I want to play it ?

for example I want to create specific frequency, outside the pre scaler, is that possible ? how to do that ?

thanks

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

Merely a test to see if you know your Fourier Analysis. I was proud of myself for remembering that one set of harmonics disappeared. Sorry I got the even and off mixed up yall.

Imagecraft compiler user

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

@bianchi,

You write down a complete list of requirements on a piece of paper. You will soon see what an AVR can do. The mega128 has plenty of ports and timers.

If you are still worrying, post your complete list of requirements (with typical numbers). I am sure that you will get useful advice.

After you have spent ten minutes with pencil and paper, the answers become obvious. Considerably quicker than farting about from one subject to another (for days on end).

David.

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

bianchi77 wrote:
so just create another function with different frequency (different configuration of timer) and then call it when I want to play it ?
If you like. How many frequencies do you need to produce? Do you really want to write a separate function for each frequency?

I'd think it would be better to write a function that takes a frequency as an argument, and configures the timer for you.

JJ

"Experience is what enables you to recognise a mistake the second time you make it."

"Good judgement comes from experience.  Experience comes from bad judgement."

"Wisdom is always wont to arrive late, and to be a little approximate on first possession."

"When you hear hoofbeats, think horses, not unicorns."

"Fast.  Cheap.  Good.  Pick two."

"We see a lot of arses on handlebars around here." - [J Ekdahl]

 

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

that's good idea on writing a requirements, and it's growing from day by day since I like to do experiment,
and I like to ask from other people which I believe have a better experience than me...one reason why I have a lot subjects because I like to try it....and unleashed the power of AVR..

Last Edited: Wed. Sep 25, 2013 - 10:37 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

If you like. How many frequencies do you need to produce? Do you really want to write a separate function for each frequency?

I'd think it would be better to write a function that takes a frequency as an argument, and configures the timer for you.

Probably I need to produce 8 different frequencies. ( 1 octave ) and some more for experiment

That's a good consideration, thanks

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

Do you have a speaker? If it a piezo, they tend to resonate at about 2KHz so they can only beep at this frequency. A regular old paper cone speaker will have a wider range and you can play different frequencies. You used the word octave... which to me means musical notes. Do you want to generate the 12 notes in an octave of musical notes? Or just some beeps and boops?

Imagecraft compiler user

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

Yea, I want to generate 12 notes in octave, but base on beeper, I'm currently using speaker and LM386....

Any ideas ?
thanks

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

Yep. Look up the equation for the freq of each musical note. A440 is a standard frequency. The amount to multiply by is the twelfth root of the frequency ratio of hi freq to lo freq.In this case the twelfth root of 2, because an octave is a freq ratio of two. You can now calc each of the 12 freqs. Find the equation in the datasheet for freq as a function of xtal freq, prescaler and timer OCR register. Make a table of which timer divisor to use for each of the twelve nots. Good clear advice so far?

Imagecraft compiler user

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

yes it's clear, I'll make it and get back to you..
so the lowest frequency from the note is 440Hz for c ?

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

is it right ?

//f= 16000000/(2*64*256) = 480 Hz pre scale 1:64
	
	TCCR1A = _BV(WGM10)  // PWM, Phase Correct, 8-bit
	| _BV(COM1A0)   // set OC1A on compare match, clear them at top
	| _BV(COM1A1);   // set OC1A on compare match, clear them at top

//	| _BV(COM1B1);  // set OC1B on compare match, clear them at top
	
	TCCR1B |= _BV(CS11) | _BV(CS10);

Thank you

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

Quote:

so the lowest frequency from the note is 440Hz for c ?

Eh?

440Hz is the frequency of "international A"

See this:

http://www.phy.mtu.edu/~suits/no...

and this:

http://www.phy.mtu.edu/~suits/No...

The scale is created using A4 = 440Hz then going up/down from there in steps of 2^1/12. That is multiplying or dividing by 1.059463094359. This produces the "even tempered scale".

The key thing for you is simply the frequency column in that table. Either hard-code those values as an array in your code (and use to set the timer TOP value) or calculate them at run time using the 1.059463094359 value (though this will cost computation time).

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

Thanks for the link, I appreciate that,

Is my function correct ?
Please correct me if I have mistake, thanks

void play_note(unsigned int note,unsigned int duration)
{
	// Reset the 16 bit Counter
	TCNT1H = 0;
	TCNT1L = 0;

	// Set the Counter TOP
	ICR1H = ( note >> 8 ) & 0x00FF;
	ICR1L = note;

	// Turn on the Prescaler
	TCCR1B |= (1<<CS11);
	_delay_ms(1000);
	//_delay_ms(duration);

	// Turn off the Prescaler
	TCCR1B &= ~(1<<CS11);
	_delay_ms(1000);
}
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Quote:

Is my function correct ?

That sort of depends on what timer_init() is doing these days.

I sort of assumed you would use CTC mode. If you use mode 4 then it is OCR1A that sets TOP not ICR1. But if you are using mode 12 it could well be right.

BTW don't set ICR1H and ICR1L separately - there's no need to split things like that. Replace:

   // Set the Counter TOP
   ICR1H = ( note >> 8 ) & 0x00FF;
   ICR1L = note;

with

   // Set the Counter TOP
   ICR1 = note;

to achieve the same thing.

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

which one is better and easier mode 4 or mode 12 ?
frequency will start from here :
C4 261.63Hz ?
based on :[url]
http://www.phy.mtu.edu/~suits/no...

Last Edited: Thu. Sep 26, 2013 - 01:49 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

currently I'm doing the beeper with mode 2....

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

Quote:

currently I'm doing the beeper with mode 2....

Stop spouting rubbish and show your code. You cannot possibly be using mode 2. That is PWM phase correct 9 bit with TOP fixed at 0x1FF (hence 9 bit). That mode wouldn't let you vary the frequency which is surely the whole purpose of the exercise?

The modes with variable frequency are 4,8,9,10,11,12,14,15.

If you just want to play square waves with 50:50 duty there's no point using a PWM mode. So that would reduce your choice to modes 4 or 12.

There is another way to make sound and it does involve PWM. Read AVR335 to understand more about that technique but note that in this case your frequency will be fixed (as high as you can get it usually) and then you load the compare register with "sound samples (for example from a WAV) file at the same frequency as the sound was originally sampled. Making sounds this way does, however, use huge amounts of storage space for the sound samples so you'd usually employ an external memory such as an SD/MMC to store the audio files.

For now stick to making monophonic square waves with CTC and see how you get on.

Last Edited: Fri. Sep 27, 2013 - 08:58 AM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

2 Clawson, thank you for the application note, give me time to ponder it...
and thank you for CTC idea to, I'll try it and get back later....

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

Is it right for CTC 1:64 :

 TCCR1A =  // Mode 4 CTC 1:64 Prescaler
     _BV(COM1A0)   // set OC1A on compare match, clear them at top
    | _BV(COM1A1);   // set OC1A on compare match, clear them at top
 
TCCR1B |= _BV(CS11) | _BV(CS10) | _BV(WGM12);

OCR1A = 100; //beep on

		//sound for 500ms
		_delay_ms( 500 );

		OCR1A = 0; //turn beep off

		//wait 1s between beeps
		_delay_ms( 1000 );

I can hear a beep but very very soft almost nothing....any ideas ?
from my calculation it's
1237.623762376238 Hz
Please correct me if I'm wrong...
I saw nothing in my logic analyzer.....

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

Quote:

from my calculation it's
1237.623762376238 Hz
Please correct me if I'm wrong...
I saw nothing in my logic analyzer.....

If you own a logic analyzer why on earth are you asking that question? Surely it can tell you exactly what the output frequency is?

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

is my timer configuration right for Mode 4 on Timer 1 ? and the code as well ? So I'm sure that I'm doing the right thing on my code.. :?:

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

Get one of those timer calculators. There is one in the imagecraft demo. Run that.

Imagecraft compiler user

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

I want to generate 430Hz with ctc,
I followed this link :[url]
https://www.avrfreaks.net/index.p...

code :
timer1_ctc_init()
{
	TCCR1A =  // Mode 4 CTC 1:64 Prescaler
	_BV(COM1A0)   // set OC1A on compare match, clear them at top
	| _BV(COM1A1);   // set OC1A on compare match, clear them at top
	
	TCCR1B |= _BV(CS11) | _BV(CS10) | _BV(WGM12);
}

.
.
 while(1)
    {
		lcd_cmd(0x01);
		lcd_string("Beeping...");
		
		OCR1A = 583; //beep on

		//sound for 500ms
		_delay_ms( 100 );

		OCR1A = 0; //turn beep off

		//wait 1s between beeps
		
		_delay_ms( 1000 );

why can't I hear the tone ?
thanks

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

I got it
TCCR1A = // Mode 4 CTC 1:64 Prescaler
_BV(COM1A0);

Thanks for helping folks

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

Does anyone know where I can find Advance Australia Fair note ?
I got only :
http://www.musicnotes.com/sheetm...
I want to find the free one for experiment

Thank you

Octave test :
http://www.youtube.com/watch?v=3FPBg-iR1sQ&feature=share&list=UUXJgKmAuT1OlkYg-xq7BiNw

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

Quote:

Advance Australia Fair

When I put those three words into Google and add the additional word "MIDI" the top hit is:

http://www.hamilton.net.au/advan...

now just load that MIDI into any sequencer to see the "music".

EDIT: actually I found an online MIDI to RTTL converter so I took one of those files and used this:

http://midi.mathewvp.com/midi2RT...

and got this:

advance_pi:d=4,o=5,b=100:2p.,2p.,g,p,480c,480p,8c3,8p,p,p,480g3,8g2,8p,p,240e4,240p,8e3,8p,p,p,p,8g3,8p,p,480c,
480p,480c4,8d,p,p.,p.,p.,9c3,9p,480c,480p,120c3,p,p,p,480e,480p,8c3,8p,480d6,480p,480p,480g,480p,8g2,8p,480c6,480p,480
p,p,p,p,240d,240p,240p,8g2,8p,p,480c,480p,8g,8p,480d6,480p,480p,480g,480p,8g3,2p,2p.,8g3,8p,p,p,p,8c4,8p,p,240g3,8g2,
8p,240e,240p,8e3,8p,p,480c4,8c3,8p,480g,480p,480p,8g2,p,p.,p.,p.,9g,9p,9p,9p,120g4,p,p,p,p,p,480c3,8c4,8p,p,480d,480p,
480p,480p,8d3,8p,p,p,p,480c,480p,8e3,8p,p,p,480d,480p,480p,8d3,8p,p,p,p,8f#,8p,p,p,p,480g3,g.2,p.,2p.,2p.,2p.,480g4,
8e4,8p,p,p,p,480f4,8f3,p,p.,480c,9g,9p,9p,480c6,480p,480f3,240f,p,p,p,8c,8p,p,p,480c,480p,c3,8p,p.,480c,8e,8p,8p,p.,
p.,p.,240g4,240p,8e3,8p,p,p,240f,240p,8f3,8p,p,p,480g,480e4,8e3,8p,p,p,p,p,8d3,480p,8b,480p,8p,8p,8p,480e,480p,8e3,
240p,8p,8f4,160p,8p,8p,8p,8p,480g4,g3,2p,2p.,2p.,2p.,480g4,8e3,8p,p,p,480f,480p,8f4,p,p.,p.,9g,9p,480c,480p,480p,120f2,
p,p,p,8f,8p,p,p,p,480c3,c4,8p,480c6,480p,480p,9g,9p,9p,9p,120c,p,p,p,p,480g,480p,8b2,8p,p,p,p,480e,480p,8c4,p,480c6,
480p,9e,480b,480p,480p,480p,480p,240f,p.,p.,p.,p.,9g,9p,9p,9p,9p,480c4,240c3,2p.,2p.,2p.,2p.,480g,480p,8c3,8p,p,p,480f6,
480p,8b3,8p,p,p,480g,480p,8c4,8p,p,p,p,p,p,8d3,8p,p,p,p,480e4,8e3,8p,480b,480p,480p,480p,160f3,9f#3,8p,p,p,p,p,8f#4,
8p,p,p,p,480g3,2g4,p,2p.,2p.,2p.,480g,480p,8c4,8p,p,p,p,p,p,8g2,p,p.,p.,8g,8p,8p,8p,480d6,480p,480g3,p.,480b,480p,480p,
9f,9p,9p,480e,480c,480p,480c4

Decoding that is left as an easy exercise for the reader.

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

what do you mean by "sequencer" somekind a software ?
Like this ?[url]
http://en.wikipedia.org/wiki/Lis...

Which one do you think best ?
thanks

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

Quote:

what do you mean by "sequencer" somekind a software ?

Oh for goodness sake. Don't they have google or wikipedia in your part of the world? When I type "midi sequencer" into Google the top hit is:

http://en.wikipedia.org/wiki/Lis...

As you can see in my edit above I also found online MIDI editors/sequencers and also tools to convert to RTTTL. RTTTL is the format that the original mobile phones used for monophonoic ringtones. It almost describes the tune in English. It is explained (again via Google) here:

http://en.wikipedia.org/wiki/Rin...