August 28, 2010 by lcruz007 How can I output a sine wave at a high frequency with an atmega328? Thanks in advance. If it's a pure sine wave you're looking for, the micro-controller doesn't do that. You can 'fake' a sine wave by using fast PWM and running it through some external filters to smooth it into a sine wave. I haven't done it, but here is a LINK to a resource document at Atmel describing this. I'm not sure exactly how high a frequency you can achieve with this method though. Other than that, you may need to use external components to create a sine wave from the square wave output by the microcontroller such as was done HERE. Good luck, Rick A sine wave is a linear function. It can be approximated like audio on a CD but even CD players have active filtering and signal conditioning to clean up the digital signal so it can resemble the analog signal. the biggest problem with sine wave generation is harmonics. If you get a clean sine wave at one frequency, chances are that it degrades rapidly as the frequency changes. That is because the filtering circuit it more or less tuned to the target frequency and loses effectiveness as change grows. You could also purchase a frequency to voltage converter, and using frequency as your output, assuming a linear f/v conversion: v(out) = af; so if f = sin(t), v(out) = asin(t). You could then use a voltage divider to reduce v(out) to sin(f). The down side is you'd also have to purchase a F/V converter. If terrific accuracy is not an issue i have a tested design for a slightly non-linear f-v converter which requires only an isolation transformer (available at radio shack), optocoupler or a photo-resistor and cds cell (as far as special components, the rest are capacitors and diodes), if you are interested. However it is not the best option in terms of accuracy. Hey lcruz007, What's the frequency (or frequency range)? What's the intended purpose of this signal (so we can get an idea of how "clean" a signal you need)? Mike Hi, Thanks all for your answers :) Mike, I want to send remote information using FM radio waves. For example, send some characters to an LCD remotely from the computer! I heard that a sine wave is the best signal I can use for radio waves. Thanks for your support! For FM transmission of digital signals you may want to just built an analog transmitter/receiver and pair of sinusoidal oscillators tuned to particular frequencies, and a digitally controlled switch between each oscillator and the transmitter, so that you only transmit one frequency at a time. Another alternative would be to acquire a voltage controlled oscillator and feed your data from a DAC into the control line, and then the VCO's output into a transmitter. I created this program for producing 500 hertz, but i don't know whether it is working since i have a problem with my computer. if i am wrong, please correct me. Program: ``````void pwm_init (){ TCCR0A = (1<0;o--){ OCR0A = o; } } int main(){ pwm_init(); int freq = 500; while(freq){ sine_digi(); } return 0; } `````` thanks in advance! I see what you're getting at---create an upward ramp, wait for a bit, then a downward ramp, wait for a bit, repeat. Not really a sine wave but an approximation, but clearly you know that. It will hang, though: ``````uint8_t i; for (i=0;i<256;i++) `````` Variable "i" is uint8_t so it can only take on values from 0 to 255, therefore it will always be less than 256 and the for loop will never exit. You're not waiting again after you get to the bottom, and you can't control the slope of the ramp. This code will generate a very steep slope, so mostly you'll get +5V with 0V spikes every once in a while. Examine the interrupt routine in the code in this article: http://interface.khm.de/index.php/lab/experiments/arduino-dds-sinewave-generator/. Ignore all the other stuff in the code--just understand how the ISR part of the code works. That gives you a good general technique for generating sine waves at a wide range of frequencies. I am a thirteen year old, so, a bit hard for me to understand but i get that through a low pass filter, they are getting rid of 32kh samples so the signal could be more accurate, but, i came across this : http://www.youtube.com/watch?v=b-vUg7h0lpE But my concern is that i will have to use a whole register to do this. But, is my program good enough to produce tones on the peizo buzzer? (after i changed the integer types) i am trying to make a synth by doing freq/1, freq/2 and so on up to 10 like on a 4017 counter decoder IC. but, i wanted it to be achieved by the mcu. My corrected program: ``````void pwm_init (){ TCCR0A = (1<0;o--){ OCR0A = o; } delay(time) } int main(){ pwm_init(); int freq = 500; while(freq){ sine_digi(); } return 0; } `````` and thanks ! i modified my code, i thought creating an interval every step of the OCR0A, so i changed my code. ``````#define F_CPU 14745600 #include #include #include #include "../libnerdkits/delay.h" #include "../libnerdkits/lcd.h" #define freq 500 void pwm_init (){ TCCR0A = (1<0;o--){ OCR0A = o; delay_ms(time); } } int main(){ pwm_init(); while (freq) { sine_digi(); delay_ms(1000); } } `````` but i got this error: In function 'sine_digi': `````` 'for' loop initial declaration outside C99 mode `````` it would be great if u can help me, thanks! The definition of the "C" language has changed over the years. C99 refers to the version of C where they decided to allow you to declare the iteration variable inside the "for" statement. By default the avr-gcc compiler doesn't let you do that. You have to say ``````int o; for (o=255; o>0; o--) `````` instead of ``````for (int o=255; o>0; o--) `````` But instead of doing either of those I would just re-used the "i" variable that you already declared and used for the previous loop. ``````int time=1/freq/255; `````` is also a problem. This will always be zero. You might try 1000000/freq/255 and then use delay_us instead of delay_ms. And this will produce a triangle wave. thanks bretm! but in order to use variable 'i'for both for loops, should i declare it as volatile integer? No, you're not using interrupts for anything. You only need volatile for variables that you're sharing between an interrupt and the mainline code, or two different interrupts. By using this code, I do get a tone but it is very faint. Should it be more audible or will I need to amplify it? What would be the preferred method of amplification?