Generate sine wave modulated PWM with AVR microcontroller

This example will show how ease can sinewave modulated PWM modulated using AVR microcontroller and few lines of code. For this example I used Atmega8 MCU. All project is set up in VMLAB simulator.

To achieve this I saved sinewave lookup table in a Program memory (don’t forget to include interrupt.h header file):

const uint8_t sinewave[] PROGMEM= //256 values {0×80,0×83,0×86,…};

PWM is generated by using Phase and frequency correct PWM using 16 bit timer in Atmega8. Modulation is done by updating OCR1A value with one from sinewave table each time when compare matches.

Reading from flash program memory is done simply:

OCR1A=pgm_read_byte(&sinewave[i]);

The line above is placed inside the output compare interrupt for OCR1A service routine.

Resulting signal in scope simulator:

sinewave_PWM.PNG

Download project Sinewave modulated PWM source code if you want to try it by yourself.

This way you can modulate PWM with any signal shape that is stored in lookup table.

Updated AVRStudio4 project files!

19 Responses to Generate sine wave modulated PWM with AVR microcontroller

  1. Very nice article. I am quite new with using embedded systems, at the moment I am working with an AT90CAN128 microprocessor. I am trying to adapt this program to generate PWMs on that type of microprocessor, but I’m not having any luck. Does anybody have an idea of how you can generate PWMs on the AT90CAN128? Thanks, Andrei.

  2. Hei Andrei contact me by email, sallesroberto@yahoo.com.br . I have this code working to AT90CAN128 , I can send you!. Salles

  3. hi, i need a mickoC program that generates a sine wave, triangle wave and an impuls with freqv between 100khz-1Mhz and the amplitude of the wave form between 0,1V-5V and the kind of wave form can be modified by “string” or input keyboard .
    i am using a PIC16F877A…. please help….

  4. thanks a lot,very simple and explicit…
    is there another way to generate SPWM waveform?

  5. thanks for simple and explicit describe
    i cant open the source file that you told for downloading…(when open with codevision ,an error accure:bad data in project file)
    what can i do??

  6. The source code is written for WinAVR. Actualy All project is set up in VMLAB simulator which uses WinAVR GCC compiler.

  7. I begin my search on single phase inverter with true sinewave o/p i need some paper or books that explain the digital syntheses for spwm
    plz send me any help on my mail
    thank you

  8. Hello
    Gud work man.
    I want to make sine inverter and can i use this technique but i have made square wave UPS and that requires 2 pin wave generated like one cycle is generated from pin 1 and 2nd pin remains low and vice versa.So is this possiable to make sine wave Invreter if y then please guide me

  9. I wanna create a sine wave for an ATmega64 in AVR
    ucing C language
    Any hints will help >> would be awesome

  10. hi guys!can somebody help me with the code to generates PWM by using AVR ATmega169

  11. Hello,
    good program.
    Why do you designate port D pins as input? Can you send me schematic?
    thank you,
    Vlad

  12. Don’t mind PortD settings. These were left from other project template. Actually I updated project files for AVRStudio4. You’ll find them at the end of article.
    And there is no specific schematic – signal is generated directly on PinB1 (OC1A) pin. Any general Atmega8 circuit will do for testing.

  13. thank you,
    i actually thought about using the external counter source T1 on Bit5 of PortD;
    By changing frequency of external clock source we can change the frequency of output sine wave, right?
    Vlad

  14. Thats right. Never tried this but should work fine once T1 frequency is at least twice lower than main clock frequency for correct sampling.

  15. thank you for the prompt answer.
    I use stk500 board and atmega8. When clock frequency is intern 8mhz, the frequency of sinusoide is around 100hz. When i connected external crystal 16mhz to the board and changed fuses, the signal frequency changed to 220hz.
    This is is max frequency for atmega. How can i make output frequency higher?

  16. In example code there is a correct phase and frequency mode used where dual slope timer counting is used. If you need higher frequency then you should try Fast PWM mode. It uses single slope counting – this should lead to twice bigger max frequency.

  17. Yes, i understand that, thank you.
    how can i calculate the relationship between clk frequency (8 mhz in your program) and frequency of output sinusoidal signal?

  18. Ok, mode is phase correct so we can calculate pwm frequency by formula found in datasheet:
    fPWM=FCLK/(2*N*TOP)=8000000/(2*255)=15686 Hz
    one pwm coded sine period is generated at 15686/256=61 Hz

  19. Hi, I implemented your code, but a I have some issues. I used a 16mHz crystal as main clock and i used phase correct pwm as you. But in my oscyloscope i mesured 220Hz sin wave frecuency when I expected 122Hz.

    fPWM=FCLK/(2*N*TOP)=16000000/(2*255)=31372 Hz /256=122 Hz

    I fix the problem using the timer overflow interrupt (not the OC1A interrupt vector) in order to update the OCR1A but i can’t understand why. Can you Help me? Thanks. (Sorry for my english)

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

To submit your comment, click the image below where it asks you to...