NerdKits - electronics education for a digital generation

You are not logged in. [log in]

NEW: Learning electronics? Ask your questions on the new Electronics Questions & Answers site hosted by CircuitLab.

Microcontroller Programming » Frequency

March 27, 2011
by hariharan
hariharan's Avatar

Hey, i was wondering, how can i output a specific frequency?

March 28, 2011
by Ralphxyz
Ralphxyz's Avatar

Probable the closesest you will get to frequency output is using PWM.

Ralph

March 28, 2011
by Hexorg
Hexorg's Avatar

If you have an op-amp I can post here a few circuits to generate square, sine, and triangular waves at variable frequencies. But Ralph is right, with only microcontroller you can output a square wave using PWM or timer.

March 29, 2011
by Ralphxyz
Ralphxyz's Avatar

Yeah Hexorg, having some signal generating circuits would be good to have.

I was thinking of making a signal generator to learn how to use my oscilloscope.

I figured if I had a known signal, where I knew all of the parameters then I could learn how to identify them using the oscilloscope.

So I for one will use your circuits.

Ralph

March 29, 2011
by 6ofhalfdozen
6ofhalfdozen's Avatar

Ralph,

If you don't need exacting frequencies but rather want something decent to test your o-scope with, don't forget a 555 with a potentiometer can give you a pretty wide range of freq's and duty cycles. I recently built a pulse counter to hook up to a flow meter at work(post soon to appear elsewhere), but I used a 555 with a trimpot to test and do quick cals on it.

March 29, 2011
by hariharan
hariharan's Avatar

I don't know exactly how to make a frequency output andor program a PWM. what is a PWM?

March 29, 2011
by Ralphxyz
Ralphxyz's Avatar

hariharan, you need to read the specsheet. Of course I know one can diligently read the specsheet and not come away knowing what PWM is, as it is rather boring reading cover to cover, until you want to find something specific (like PWM). So search the specsheet for PWM and then search the Nerdkits forum.

A very simplified example of using PWM is to brighten and dim a led. Ever thought of doing that or how you would do that short of wiring in a potentiometer? Well PWM will do that for you and a lot else.

Ralph

March 29, 2011
by bretm
bretm's Avatar

I don't think PWM is relevant to the original question. PWM is Pulse Width Modulation. It's about changing the duty cycle (pulse width) of a fixed-frequency signal.

The original question was "how can I output a specific frequency". PWM may be completely unnecessary for this, depending on what he's doing.

On the Atmega168 there are two main ways to output a specific frequency. One is to do it manually by toggling a pin periodically, with the period calculated to produce the desired frequency, and the other is to set up a timer and let the timer toggle the pin for you.

The "best" method depends on what the frequency (or range of frequencies) is, whether the frequency changes over time or in response to some external influence, and to some extent why you want to output a specific frequency.

So let's start with : What frequency do you want to generate?

March 29, 2011
by Hexorg
Hexorg's Avatar

I've posted the oscillation circuits here unfortunately, I wasn't able to come up with some formials. :\

March 30, 2011
by hariharan
hariharan's Avatar

i want to generate 516 hz for 1 sec. how do you do it?

April 01, 2011
by Ralphxyz
Ralphxyz's Avatar

hariharan, I had hoped that bretm would finish answering your question on frequency.

I'll try to enlighten you further with my limited knowledge.

Ok here we go, those more knowledgable than I please jump right in:

The mcu is a "digital" device "frequency" is normally considered a "analog" system of measure.

So you could turn a pin on and off with a "frequency" (repetition) but the wave (square) would only go from 0 to 5 volts.

You cannot get a sine (frequency) wave from a digital device.

Using PWM you can can a variable timing of your square wave but it still will not be a sine wave (frequency).

So what exactly are you tying to do? Maybe "we" can help you once we know the details beyond trying to produce a frequency.

Ralph

April 01, 2011
by hariharan
hariharan's Avatar

What i am trying to do is making a music with the MCU but with the PWM.

April 02, 2011
by hariharan
hariharan's Avatar

I did some research and thought why not change the OCR1a with a delay. So i calculated frequency to millisec and converted that to the value of OCR1A. But it does not work. Why?

//By Hariharan
//Pwm music box

#define F_CPU 14745600

#include <avr/io.h>
#include <inttypes.h>
#include <stdlib.h>
#include "../libnerdkits/delay.h"

int main(){
//instead of definig freq
//calculated time for each freq
// in http://www.sengpielaudio.com/calculator-period.htm
//and calculated OCR1A
// that is 1843.2 X millisec
//note  FREQUENCY     MS           OCR1a
//D5    851      1.175088132    2165.922445
//E5    758      1.319261214    2431.66227
//Fsh5  675      1.481481481    2730.666666
//G5    637      1.569858713    2893.56358
//A5    568      1.76056338     3245.070422
//B5    506      1.976284585    3642.687747
//C6    477      2.096436059    3864.150944
//D6    425      2.352941176    4336.941176

unint16_t D5= 2165.922445 ;
unint16_t E5= 2431.66227;
unint16_t Fsh = 2730.666666;
unint16_t  G5= 2893.56358;
unint16_t A5= 3245.070422;
unint16_t B5= 3642.687747;
unint16_t C6= 3864.150944;
unint16_t D6= 4336.941176;

}
void pwm_init() {

    //Fast PWM
  pwm_set(PWM_START);
  TCCR1A = (1<<COM1B1) | (1<<WGM11) | (1<<WGM10);
  TCCR1B = (1<<WGM13) | (1<<WGM12) | (1<<CS11);
  }

void int main(){
while (1){
// give ocr1a it's note
OCR1A = D5;
//then it's delay
delay_ms(500);
OCR1A= E5;
delay_ms(500);
OCR1A= D5;
delay_ms(500);
OCR1A= G5;
delay_ms(500);
OCR1A= Fsh;
delay_ms(1000);

OCR1A = D5;
delay_ms(500);
OCR1A= E5;
delay_ms(500);
OCR1A= D5;
delay_ms(500);
OCR1A= A5;
delay_ms(500);
OCR1A= G5;
delay_ms(1000);

OCR1A = D5;
delay_ms(500);
OCR1A = D6;
delay_ms(500);
OCR1A = B5;
delay_ms(500);
OCR1A =G5;
delay_ms(500);
OCR1A =Fsh;
delay_ms(500);
OCR1A= E5;
delay_ms(500);

OCR1A= C6;
delay_ms(500);
OCR1A = B5;
delay_ms(500);
OCR1A= G5;
delay_ms(500);
OCR1A= A5;
delay_ms(500);
OCR1A= G5;
delay_ms(1000);
}
}
April 02, 2011
by 6ofhalfdozen
6ofhalfdozen's Avatar

Hello Hariharan,

When you say "it does not work", what exactly do you mean? This might help us help you. Do you mean the NK sits there quietly doing nothing, or is there some compiler issue, or does the NK make this horrible racket instead of music? If the NK sits there quietly, check the wires, check the wires, check the wires, then check your code. If the NK has code/compiler issues, well I don't see anything blatently wrong with your code so a local guru will need to help with that.

If the NK is making a horrible racket instead of vaguely recognizable music, I have two guesses. My first thought is that if you are using the buzzer, they don't quite make the same kind of sound as a true speaker so the sound might be off due to that. Though usually, with the buzzer the music is a little elevatory but usually interpretable. If it is making true racket unlike any music, my guess is that there is something off in how you set up your timing. While I am not audio engineer, I spent a decent bit of my time back a few years ago working on MOD/S3M and midi music files and I learned the hard way that the "silences" are almost as important as the musical notes. After all, in true sine waves the positive portion is only half the wave and if the spacing is off you can set up wierd overtones, harmonics and such. Those are the wierd things that your ears can hear as something wrong but untrained ears, like mine, can't really sort out what is wrong and it gets very frustrating. I see that you have your code changing ocra1 for the "high" time but staying as fixed 500/1000ms for the low time. I would suggest that you match your "low" time to the preceding high time to balance it out. This should close up the spacing on the notes and make it "flow" a little better. For example, your lines 46 to 58 might look like this.

while (1){ // give ocr1a it's note 
OCR1A = D5; //then it's delay 
delay_ms(D5/1843);  //divide by 1843 to get back to ms
OCR1A= E5;
delay_ms(E5/1843);
OCR1A= D5; 
delay_ms(D5/1843);
OCR1A= G5;
delay_ms(G5/1843);
OCR1A= Fsh; 
delay_ms(Fsh/1843);

Anyhow, that is my quick suggestion. Hopefully it helps or sparks something that leads to helpfull posts.

April 02, 2011
by hariharan
hariharan's Avatar

i meant that the code is not compiling. it says that the notes are not declared.

April 02, 2011
by 6ofhalfdozen
6ofhalfdozen's Avatar

Hiya Hariharan,

I dunno how I missed this last time through your code, but you have to "main"'s. One on line 11-36 which has your notes, and one on lines 45-95 which has the "playing portion." I am guessing that the compiler is eating the first one with your notes and erroring out on the second one because there are no notes left.

April 02, 2011
by bretm
bretm's Avatar

There are a number of problems with the program. The biggest one is that PWM isn't the appropriate timer mode for making music--you need to use the CTC mode of the timer, not the PWM mode. There is a Nerdkits tutorial that shows how to make music with the MCU.

When you manipulate OCR1A in PWM mode you're changing the duty cycle, not the frequency.

April 02, 2011
by bretm
bretm's Avatar

Ok, I take part of that back. It looks like that particular PWM mode might let you adjust frequency with OCR1A, but it's still not what you want. And even though it's called a fast PWM mode it doesn't look like it behaves like PWM. I would still use one of the CTC modes.

April 02, 2011
by hariharan
hariharan's Avatar

i did not under stand how they created frequencies with the mcu in the music with mcu code. they just define some frequencies and then output it?

April 02, 2011
by hariharan
hariharan's Avatar

I am not sure if this is the right way to do it. if not, please correct me.

//By Hariharan
    //Pwm music box

    #define F_CPU 14745600

    #include <avr/io.h>
    #include <inttypes.h>
    #include <stdlib.h>
    #include "../libnerdkits/delay.h"

    int main(){
    //instead of definig freq
    //calculated time for each freq
    // in http://www.sengpielaudio.com/calculator-period.htm
    //and calculated OCR1A
    // that is 1843.2 X millisec
    //note  FREQUENCY     MS           OCR1a
    //D5    851      1.175088132    2165.922445
    //E5    758      1.319261214    2431.66227
    //Fsh5  675      1.481481481    2730.666666
    //G5    637      1.569858713    2893.56358
    //A5    568      1.76056338     3245.070422
    //B5    506      1.976284585    3642.687747
    //C6    477      2.096436059    3864.150944
    //D6    425      2.352941176    4336.941176

    unint16_t D5= 2165.922445 ;
    unint16_t E5= 2431.66227;
    unint16_t Fsh = 2730.666666;
    unint16_t  G5= 2893.56358;
    unint16_t A5= 3245.070422;
    unint16_t B5= 3642.687747;
    unint16_t C6= 3864.150944;
    unint16_t D6= 4336.941176;

    }
    void pwm_init() {

        //Fast PWM
      pwm_set(PWM_START);
      TCCR1A = (1<<COM1B1) ;
      TCCR1B =  (1<<WGM12) | (1<<CS11);
      }

    void int main(){
    while (1){
    // give ocr1a it's note
    OCR1A = D5;
    //then it's delay
    delay_ms(500);
    OCR1A= E5;
    delay_ms(500);
    OCR1A= D5;
    delay_ms(500);
    OCR1A= G5;
    delay_ms(500);
    OCR1A= Fsh;
    delay_ms(1000);

    OCR1A = D5;
    delay_ms(500);
    OCR1A= E5;
    delay_ms(500);
    OCR1A= D5;
    delay_ms(500);
    OCR1A= A5;
    delay_ms(500);
    OCR1A= G5;
    delay_ms(1000);

    OCR1A = D5;
    delay_ms(500);
    OCR1A = D6;
    delay_ms(500);
    OCR1A = B5;
    delay_ms(500);
    OCR1A =G5;
    delay_ms(500);
    OCR1A =Fsh;
    delay_ms(500);
    OCR1A= E5;
    delay_ms(500);

    OCR1A= C6;
    delay_ms(500);
    OCR1A = B5;
    delay_ms(500);
    OCR1A= G5;
    delay_ms(500);
    OCR1A= A5;
    delay_ms(500);
    OCR1A= G5;
    delay_ms(1000);
    }
    }

Post a Reply

Please log in to post a reply.

Did you know that you can connect to certain car computers via the OBD-II port with a microcontroller? Learn more...