Pure sine wave generation using PIC microcontroller

Published by MKDas on

In this tutorial, we are going to make Pure sine wave generation using PIC microcontroller. We can use the PIC16F73 or PIC16F76 microcontroller for this purpose. We will learn how SPWM is generated and how we can get a pure sine wave from SPWM. After learning the basic concept you can implement this into your project. So be with me and read to the end of this article.

Disclaimer: Electricity is always dangerous. Skill required to work with electricity. Do work at your own risk. The author will not be responsible for any misuse or harmful act. This website contents are also copyright protected. Anything copied and directly posted on your website and claiming it as yours is prohibited and nonsensical. The author published all the articles as open source to help you to make your project and learning purpose only. Learn and make one for yourself. If need any help feel free to ask the author. The author will be helpful to you. Thanks.

Pure sine wave generation techniques:

Generating pure sine waves is one of the most interesting works in power electronics study. A pure sine wave can be generated in different ways. You can use either

  • Analog Circuits designed with Op-Amp
  • Using ICL8038 function generating IC
  • SPWM generation with Op-Amp circuits.
  • Using SPWM generated with a micro-controller.

You may find other ways to generate a sine wave. Whatever the way you select it depends on your choice. In this article, we will discuss the last technique from the list mentioned above.

What is SPWM:

SPWM means Sinusoidal Pulse Width Modulation. A PWM signal with variable duty cycle according to a sinusoidal wave. It is something like this:

SPWM signal

Here there is a triangular wave and a sine wave of low frequency than the triangular one. If we compare these two signals with the help of an Op-Amp, we will get a PWM signal. This PWM signal has a variable duty cycle, which is increasing slowly in the midpoint of our reference sine wave and decreasing in corners.

SPWM feature of micro-controller:

No, the PIC16F73/76 micro-controller does not have any special feature to generate SPWM. But it can generate PWM which is known as the CCP module of the micro-controller.

Using this CCP module we can generate a PWM signal. Now, all we need to do is changing the duty cycle of this PWM signal in a sinusoidal way so that we can get a pure sine wave after filtering this signal. Now we will do coding for SPWM. But to make a sine wave, here we are using a lookup table. This table can be self-written or you can use software to generate your sine table. I’ll use Smart Sine to generate my sine table here.

Sine table generation using Smart Sine:

This tool is very easy to use. Just put your No. of table entries, peak point, and angle. You’ll get a sine table clicking the calculate button.

Sine table generation using Smart Sine

So here

sin_table[32]=
{0, 25, 49, 73, 96, 118, 139, 159, 177, 193, 208, 220, 231, 239, 245, 249, 250,
249, 245, 239, 231, 220, 208, 193, 177, 159, 139, 118, 96, 73, 49, 25};
is our sine table of 32 entries.

MicroC Code:

/*******************************************************************************
* Pure sine wave generation technique using PIC microcontroller                *
* Program Written by_ Engr. Mithun K. Das                                      *
* MCU:PIC16F73; X-Tal: 20MHz; mikroC pro for PIC v7.6.0                        *
* Date: 13-04-2020                                                             *
*******************************************************************************/

unsigned char sin_table[32]=
{0, 25, 49, 73, 96, 118, 139, 159, 177, 193, 208, 220, 231, 239, 245, 249, 250, 
249, 245, 239, 231, 220, 208, 193, 177, 159, 139, 118, 96, 73, 49, 25};

int duty=0;

void Interrupt() iv 0x0004 ics ICS_AUTO
{
   if (TMR2IF_bit == 1)
   {
      duty++;
      if(duty>=32)
      {
        duty=0;
        CCPR1L=0;
        asm nop;// no operation for one cycle
      }
      
      CCPR1L = sin_table[duty];
      TMR2IF_bit = 0;
   }
}

void main()
{
   TRISC = 0x00;//all output
   PR2 = 249;
   CCP1CON = 0x4C;
   TMR2IF_bit = 0;
   T2CON = 0x2C;
   TMR2IF_bit = 0;
   TRISC = 0;
   TMR2IE_bit = 1;
   GIE_bit = 1;
   PEIE_bit = 1;
   while(1)
   {
       //infinity loop
   }
}//end 

Code Explanation:

You already know that we are using a sine table here named,

sin_table[32]=
{0, 25, 49, 73, 96, 118, 139, 159, 177, 193, 208, 220, 231, 239, 245, 249, 250,
249, 245, 239, 231, 220, 208, 193, 177, 159, 139, 118, 96, 73, 49, 25};

Now, there is no limit of the number of entry for you sine table. More the entry, more the pure sine wave you’ll get. Only one thing to know that more entry will consume more memory. Anyway, here we will use 32 entries.

That means, if we want to get a sine of 50Hz, we have 10ms in each half-cycle. So we have to use a timer interrupt which is called 32 times within this 10ms.

void Interrupt() iv 0x0004 ics ICS_AUTO
{
   if (TMR2IF_bit == 1)
   {
      duty++;
      if(duty>=32)
      {
        duty=0;
        CCPR1L=0;
        asm nop;// no operation for one cycle
      }
      
      CCPR1L = sin_table[duty];
      TMR2IF_bit = 0;
   }
}

Here is that interrupt where we are using Timer2. Timer2 is configured by this code here to generate interrupt 32 times within 10ms.

   PR2 = 249; //Prescaler
   CCP1CON = 0x4C; //PWM control
   TMR2IF_bit = 0;
   T2CON = 0x2C;//Timer2 control bit settings
   TMR2IF_bit = 0;
   TRISC = 0;
   TMR2IE_bit = 1;
   GIE_bit = 1;
   PEIE_bit = 1;

PR2 is Prescaler and CCP1CON is the PWM control bit. And T2CON is a timer2 control bit. You can read the datasheet to know more about this.

Test Result:

We can test the simulated result using proteus. Note that you’ll find a small spike in the sine wave because of our sine table value. If you can edit the value if required to get a 100% pure result.

Sine wave generation simulation result
SPWM

Now you can try your own to generate pure sine waves using PIC16F73. To get the result with PIC16F76, just use the same hex. It will work fine.


MKDas

I'm Mithun K. Das; B.Sc. in EEE from KUET, Bangladesh. Blog: https://labprojectsbd.com. "First, electronics was my passion, then it was my education, and finally, electronics is now my profession." I run my own electronics lab, M's Lab (https://mlabsbd.com). Where I work with the creation of new products from ideas to something in real life. Besides this is my personal blog where I write for hobbyists and newcomers in the electronics arena. I also have a YouTube channel where I publish other helpful videos, you can find the link inside the articles. I always try to keep it simple so that it becomes easy to understand. I hope these will help them to learn electronics and apply the knowledge in their real life.

11 Comments

enrique · September 12, 2020 at 3:57 pm

Hello, thank you very much for sharing your knowledge, I admire your work, I want to tell you that I am starting in this wonderful field of micro controllers, I would like to know, if someone helps me, what part of the code should I change to work at 60 Hz and 120 volts, in my country this is the standard.
Thank you very much

    Mithun K. Das · September 13, 2020 at 4:37 am

    Still have no design for 60Hz. But I’ll try to edit the code for 60Hz in future.

Hariharan K · January 17, 2021 at 2:12 am

Sir is this code is available in using Mplab XC8 Compiler?

    Mithun K. Das · January 19, 2021 at 3:43 am

    No, but maybe a little modification will fit in MPLAB

Georg · February 22, 2021 at 4:18 pm

Dear Mithun K. Das!

I got very important knowledge from the pulicized article, thank you very much! I just started learning with microcontrollers and the C programming language – I’m a beginner. I sought help for my first project. The task would be to produce a sine signal without overtones ( without distortion ). It is 50 Hz by default, but can also be switched to 67.5 Hz. This analog signal should be in a very good quality analog amplifier stage. This unit is already working perfectly. I have a PIC16F887 type microcontroller in MikroElektronika MikroC PRO and EasyPIC v7 development environment. I would like to ask if I need to change anything in the program when using the PIC16F887? How can I attach the signal directly from the microcontroller, or would it be better with a DAC device? I can’t use PROTEUS completely well yet. I design with MULTISIM software. Does step 32 generate a sufficiently “smooth” sine signal, or can the number of steps be increased?

Thanks for helping!

    Mithun K. Das · February 23, 2021 at 5:04 am

    It is not clear to me about the use of your sine wave signal. If you want to generate a pure signal, I’ll suggest using dsPIC. But it completely depends on your requirement and use of the signal. If you still want to use PIC MCUs then you must consider a little distortion will be in your signal. Although it is negligible % you must keep it in mind. If you need any help let me know.

Georg · February 25, 2021 at 7:27 am

Thanks for the reply! I am designing a custom built turntable. It is powered by 2 synchronous motor motors running simultaneously with a belt drive. I want to control these motors. Two frequency values ​​are required – for speeds 33.3 and 45 (and 78 possibly). I conduct the sine wave to an amplifier stage, which produces 220 v AC at 50 Hz and 65.5 Hz. I need to pay attention to the right torque and fine frequency tuning is also required. That’s why I want to solve it using PIC. I would like to start from the example given. Fine-tuning is absolutely necessary. I can’t do that with a Quartz oscillator. I have already built a quartz oscillator control.

    Mithun K. Das · February 25, 2021 at 8:34 am

    In this case, I strongly recommend you use a VFD. Making an inverter using PIC MCUs will not serve your purpose. Use dsPIC or PIC24 series with Motor Controller module built-in. Also, pay attention to the IGBT driver section.

    If you need professional’s help you can contact with our admin: mithun060@gmail.com

      Georg · February 25, 2021 at 5:50 pm

      Thank you very much for the advice and thank you for the email contact as well. I need to be further informed on the subject.

Solomon · June 19, 2021 at 6:30 pm

i ve pic16f877a ,i want to generate spwm sinusoidal pulse width modulation 50hz,carrier wave 16khz,50%,also if im not rude i want to understand the calculation
thx forward

    MKDas · June 20, 2021 at 5:37 am

    Generating such a signal will be a little hassle with the PIC16F series. I advise using the dsPIC series instead. But if you still want to use PIC16F series then follow this instruction:
    First, create a timer interrupt. Set this timer as sample/cycle rate. That means, if you want to keep 10 samples (say) for one cycle (for 10ms, half of 50Hz) then you should set the timer interrupt in a way so that it calls interrupt 10 times per 10ms. That means a 1ms timer interrupt. Now for inverters, 32 samples per cycle is a good one.

    Next, set the PWM signal according to the sine table(with the same sample nos of PWM values). And then change that PWM duty according to the sine table.

    I think you got the point. Now you can calculate everything.

    This is the first and basic method. Another method is using CCP or Capture Compare Module. Where a prescale is used and the CCP compares that prescale and generates a PWM signal if it is changed the CCP value according to the sine table.

Leave a Reply

Avatar placeholder

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