The only electronic website that replies to every comment, and addresses all circuit related issues.

Arduino SPWM Generator Circuit

In this post we learn how to generate sine wave pulse-width-modulation or SPWM through Arduino, which can be used for making a pure sine wave inverter circuit or similar gadgets.


The Arduino code is developed by me, and it is my first Arduino code, ...and it looks pretty good :)

What is SPWM


I have already explained how to generate SPWM using opamps in one of my earlier articles, you could go through it for understanding how it can be created using discrete components and regarding its importance.

Basically, SPWM which stands for sine wave pulse width modulation, is a type of pulse modulation where the pulses are modulated to simulate a sinusoidal waveform, so that the modulation is able to attain properties of a pure sine wave.

To implement a SPWM the pulses are modulated with an initial narrower widths which gradually get broader at the center of the cycle, and finally end being narrower at the end to finish the cycle.

To be more precise, the pulses begin with narrowest widths which gradually get broader with each subsequent pulses, and gets broadest at the center pulse, after this, the sequence continues on but with an opposite modulation, that is the pulses now gradually begin getting narrower until the cycle finishes.



This constitutes one SPWM cycle, and this repeats throughout at a particular rate as determined by the application frequency (usually 50Hz or 60Hz). Typically, SPWM is used for driving power devices such as mosfets or BJTs in inverters or converters.

This special modulation pattern ensures that the frequency cycles are executed with a  gradually changing average voltage value (also called the RMS value) , instead of throwing sudden Hi/low voltage spikes as normally witnessed in flat square wave cycles.

This gradually modifying PWMs in a SPWM is purposely enforced so that it closely replicates the exponentially rising/falling pattern of a standard sinewaves or sinusoidal waveform, hence the name sinewave PWM or SPWM.


Generating SPWM with Arduino


The above explained SPWM can be easily implemented using a few discrete parts, and also using Arduino which will probably enable you to get more accuracy with the waveform periods.

The following Arduino code can be used for implementing the intended SPWM for a given application.

Gosh!! that looks awfully big, if you know how to shorten it, you may certainly feel free to do it at your end.

// By Swagatam (my first Arduino Code)
 
void setup(){
  pinMode(8, OUTPUT);
  pinMode(9, OUTPUT);
}

void loop(){

  digitalWrite(8, HIGH);
  delayMicroseconds(500);
  digitalWrite(8, LOW);
  delayMicroseconds(500);
  digitalWrite(8, HIGH);
  delayMicroseconds(750);
  digitalWrite(8, LOW);
  delayMicroseconds(500);
  digitalWrite(8, HIGH);
  delayMicroseconds(1250);  
  digitalWrite(8, LOW);
  delayMicroseconds(500); 
  digitalWrite(8, HIGH);
  delayMicroseconds(2000);
  digitalWrite(8, LOW);
  delayMicroseconds(500);
  digitalWrite(8, HIGH);
  delayMicroseconds(1250);
  digitalWrite(8, LOW);
  delayMicroseconds(500);
  digitalWrite(8, HIGH);
  delayMicroseconds(750);
  digitalWrite(8, LOW);
  delayMicroseconds(500);
  digitalWrite(8, HIGH);
  delayMicroseconds(500);
  digitalWrite(8, LOW);
  
 //...... 
    
digitalWrite(9, HIGH);
  delayMicroseconds(500);
  digitalWrite(9, LOW);
  delayMicroseconds(500);
  digitalWrite(9, HIGH);
  delayMicroseconds(750);
  digitalWrite(9, LOW);
  delayMicroseconds(500);
  digitalWrite(9, HIGH);
  delayMicroseconds(1250);  
  digitalWrite(9, LOW);
  delayMicroseconds(500); 
  digitalWrite(9, HIGH);
  delayMicroseconds(2000);
  digitalWrite(9, LOW);
  delayMicroseconds(500);
  digitalWrite(9, HIGH);
  delayMicroseconds(1250);
  digitalWrite(9, LOW);
  delayMicroseconds(500);
  digitalWrite(9, HIGH);
  delayMicroseconds(750);
  digitalWrite(9, LOW);
  delayMicroseconds(500);
  digitalWrite(9, HIGH);
  delayMicroseconds(500);
  digitalWrite(9, LOW);
  
}
//-------------------------------------//
In the next post I'll explain how to use the above Arduino based SPWM generator to make a pure sinewave inverter circuit....keep reading!


The above SPWM code was further improved by Mr Atton for enhancing its performance, as given below:

/*
This code was based on Swagatam SPWM code with changes made to remove errors. Use this code as you would use any other Swagatam’s works.
Atton Risk 2017 
*/
const int sPWMArray[] = {500,500,750,500,1250,500,2000,500,1250,500,750,500,500}; // This is the array with the SPWM values change them at will
const int sPWMArrayValues = 13; // You need this since C doesn’t give you the length of an Array 
// The pins
const int sPWMpin1 = 10;
const int sPWMpin2 = 9;
// The pin switches
bool sPWMpin1Status = true;
bool sPWMpin2Status = true;

void setup()
{
 pinMode(sPWMpin1, OUTPUT);
 pinMode(sPWMpin2, OUTPUT);
}

void loop()
{
 // Loop for pin 1
 for(int i(0); i != sPWMArrayValues; i++)
 {
  if(sPWMpin1Status)
  {
   digitalWrite(sPWMpin1, HIGH);
   delayMicroseconds(sPWMArray[i]);
   sPWMpin1Status = false;
  }
  else
  {
   digitalWrite(sPWMpin1, LOW);
   delayMicroseconds(sPWMArray[i]);
   sPWMpin1Status = true;
  }
 }
 
 // Loop for pin 2 
 for(int i(0); i != sPWMArrayValues; i++)
 {
  if(sPWMpin2Status)
  {
   digitalWrite(sPWMpin2, HIGH);
   delayMicroseconds(sPWMArray[i]);
   sPWMpin2Status = false;
  }
  else
  {
   digitalWrite(sPWMpin2, LOW);
   delayMicroseconds(sPWMArray[i]);
   sPWMpin2Status = true;
  }
 }
}




Please Share this Post:
  •  Facebook
  •  Twitter
  •  Google+
  •  Stumble



  • 12 comments:

    1. Hi sir,

      Its good to see you involving in arduino projects, I hope you will soon master in this field too :)

      I would like to point some errors in the code:

      1) we must not use pin 13 in arduino, unless we run out of pins, since it is always connected with LED, it will deviate our results. we can use other pins say 8 and 9.

      2) we cannot use delay for less than 1ms and we can't use decimal place in delay function like delay(1.25); . Instead use delayMicroseconds(); for instance delayMicroseconds(500); for 500us and delayMicroseconds(1250); for 1.25ms. You may replace all delay with this function.

      The above errors won't show up while compiling but, it affects our end result.

      Regards


      ReplyDelete
      Replies
      1. Thank you Girish,

        Although I hardly find time, I did this just to have some fun ... :)

        I will surely correct the above code as per your suggestions, as soon as possible..

        I appreciate your help very much and I am sure the readers will also get an opportunity to learn from this discussion.

        Thanks again, and keep up the good work!

        Delete
    2. Hi,

      The output 8 and 9 of the arduino represents the positive and negative cycle of the sine wave? Sorry I am quite new to arduino but how do the output pins recognize that it is negative or positive since the code looks the same? Is the delay used in this code arbitrary chosen? If I need 50Hz, should the delay change as well?

      ReplyDelete
      Replies
      1. Hi,
        as per the given code pin8/9 will alternately produce SPWM pulses at the rate of 50Hz. The total delay periods across the two pins are calculated to produce 50Hz frequency

        The SPWM waveform rate (delays) is arbitrarily set in the code, you can tweak it to create a different RMS value depending upon your transformers primary voltage rating.

        alternatively the Arduino code could be further upgraded for responding to a feedback from the transformer output and for achieving an automatic RMS adjustment

        Delete
    3. Halo sir.

      I will try your code and the driver as pure sine wave inverter.
      If I successful to make it, may I re-post this article?
      at least for arduino code only.

      Thank you.
      Yogi S.

      ReplyDelete
      Replies
      1. Hello Yoyo,
        you can submit the details to me, I'll post it in the above article with your credentials in it, but if you use it for your own website then that could be a copyright violation....

        Delete
    4. // Some changes made by Atton Risk for Swagatam
      const int sPWMArray[] = {500,500,750,500,1250,500,2000,500,1250,500,750,500,500}; // This is the array with the SPWM values change them at will
      const int sPWMArrayValues = 13; // You need this since C doesn’t give you the length of an Array
      // The pins
      const int sPWMpin1 = 8;
      const int sPWMpin2 = 9;
      // The pin switches
      bool sPWMpin1Status = true;
      bool sPWMpin2Status = true;

      void setup()
      {
      pinMode(sPWMpin1, OUTPUT);
      pinMode(sPWMpin2, OUTPUT);
      }

      void loop()
      {
      // Loop for pin 1
      for(int i(0); i != sPWMArrayValues; i++)
      {
      if(sPWMpin1Status)
      {
      digitalWrite(sPWMpin1, HIGH);
      delayMicroseconds(sPWMArray[i]);
      sPWMpin1Status = false;
      }
      else
      {
      digitalWrite(sPWMpin1, LOW);
      delayMicroseconds(sPWMArray[i]);
      sPWMpin1Status = true;
      }
      }

      // Loop for pin 2
      for(int i(0); i != sPWMArrayValues; i++)
      {
      if(sPWMpin1Status)
      {
      digitalWrite(sPWMpin1, HIGH);
      delayMicroseconds(sPWMArray[i]);
      sPWMpin1Status = false;
      }
      else
      {
      digitalWrite(sPWMpin1, LOW);
      delayMicroseconds(sPWMArray[i]);
      sPWMpin1Status = true;
      }
      }
      }

      ReplyDelete
      Replies
      1. Thank you very much Atton, I hope the readers will benefit immensely from this information! I appreciate it a lot!

        Delete
      2. No problem I hope we can work together in the future.

        Delete
    5. Made some changes and put it on paste bin to make things easy
      https://pastebin.com/1sQAi9vr

      ReplyDelete
      Replies
      1. could you please throw some light regarding how this modification would help to improve the performance of the PWM output, I am sure the readers will love to know about it.

        Delete

    Please Note: If you find any DEAD link starting with http//:homemadecircuitsandschematics.blogspot.com, please replace it with http://www.homemade-circuits.com/ for making it visible and alive again.