How to Build a Pure Sine Wave Inverter using Arduino SPWM

 It's early morning, 4:30 AM, and I just completed Arduino based pure sine wave inverter design. This inverter design is actually an improvement over the previous Arduino SPWM inverter design. The previous build Arduino inverter used simple transistor that has direct connection between the MOSFETs and Arduino PWM controller. It worked but the problem is the slow switching of the push pull MOSFETs. Slower switching of MOSFETs leads to heat generation because the energy gets trapped in the gate capacitance of the MOSFET. That is the reason why most diy inverter fails.

This version includes symmetrical totem pole driver using BC547/BC557 for the MOSFETs. By adding totem pole driver to drive the MOSFETs, the MOSFET gate capacitance gets discharged quicker resulting in faster operating, less heat generation and the MOSFETs operates in linear region. Most DIY inverters fail because of this. Furthermore, improvement has also been made in the software that generates the SPWM signal. The previous Arduino inverter code used Fast PWM whereas this improved version use Phase Correct PWM. Thus, the improvements are in both hardware and software. 

Circuit Diagram

Below is the circuit diagram of the improved SPWM Arduino sine wave inverter.

arduino spwm inverter circuit diagram

This circuit diagam shows the revised Pure Sine Wave Inverter that uses SPWM (Sinusoidal Pulse Width Modulation) to convert 12V DC into AC power. It operates on a Push-Pull topology.

Here is the step-by-step breakdown of how it works:

1. The Control Brain (Arduino Nano)

The Arduino generates high frequency 20kHz SPWM signals from pins D9 and D10.

  • Instead of a simple square wave, the width of these pulses varies according to a sine lookup table.

  • D9 handles the positive half-cycle of the AC wave.

  • D10 handles the negative half-cycle.

2. The Gate Driver (Totem-Pole)

Arduino pins cannot provide enough current to rapidly charge and discharge the large internal capacitance of power MOSFETs.

  • Q1/Q5 and Q3/Q4 form Totem-Pole drivers.

  • The NPN transistor (top) quickly "pushes" current into the MOSFET gate to turn it ON.

  • The PNP transistor (bottom) quickly "pulls" current out to ground to turn it OFF.

  • The 10kOhm resistors (R5/R6) ensure the gates stay at 0V during startup to prevent accidental shorts.

3. The Switching Stage (MOSFETs)

The MOSFETs (Q2 and Q6) act as high-speed electronic switches. They alternate at 50Hz, but while they are "ON," they are actually pulsing at the high carrier frequency 10kHz. This "chops" the 12V DC into a high-frequency SPWM signal.

4. The Transformer (Push-Pull)

The transformer has a Center-Tapped Primary.

  • When Q2 is active, current flows through the top half of the primary.

  • When Q6 is active, current flows through the bottom half in the opposite direction.

  • This alternating current (AC) in the primary induces a high-voltage AC signal in the secondary (e.g. 220V).

5. The Output Filter (LC Filter)

The output from the transformer is still a "chopped" high-frequency signal.

  • The Inductor (L1) \(2mH\) and Capacitor (C1) $2.2 \mu H$

  • form a low-pass filter.

  • They block the high-frequency switching noise and smooth out the pulses.

  • The result is a clean 50Hz Pure Sine Wave that powers the bulb (B1) just like a standard wall outlet.

Program Code

The Arduino program code for the above SPWM inverter is below.


/*
 * Pure Sine Wave SPWM Generator
 * Carrier Frequency: 20kHz (Silent Operation)
 * Output Frequency: 50Hz
 * Board: Arduino Nano / Uno (ATmega328P)
 */

#include <avr/pgmspace.h>

// 200-sample Sine Look-Up Table (Half-wave)
// Values scaled to 400 to match the ICR1 TOP value
const uint16_t sineTable[] PROGMEM = {
  0, 6, 12, 18, 25, 31, 37, 43, 50, 56, 62, 68, 74, 80, 86, 92, 98, 104, 110, 116, 
  122, 128, 134, 140, 146, 151, 157, 163, 168, 174, 179, 185, 190, 195, 200, 205, 210, 215, 220, 225, 
  229, 234, 238, 243, 247, 251, 255, 259, 263, 267, 271, 275, 278, 282, 285, 288, 292, 295, 298, 301, 
  304, 307, 309, 312, 315, 317, 320, 322, 324, 327, 329, 331, 333, 335, 337, 338, 340, 342, 343, 345, 
  346, 347, 349, 350, 351, 352, 353, 354, 354, 355, 356, 356, 357, 357, 358, 358, 358, 359, 359, 359, 
  359, 359, 359, 359, 358, 358, 358, 357, 357, 356, 356, 355, 354, 354, 353, 352, 351, 350, 349, 347, 
  346, 345, 343, 342, 340, 338, 337, 335, 333, 331, 329, 327, 324, 322, 320, 317, 315, 312, 309, 307, 
  304, 301, 298, 295, 292, 288, 285, 282, 278, 275, 271, 267, 263, 259, 255, 251, 247, 243, 238, 234, 
  229, 225, 220, 215, 210, 205, 200, 195, 190, 185, 179, 174, 168, 163, 157, 151, 146, 140, 134, 128, 
  122, 116, 110, 104, 98, 92, 86, 80, 74, 68, 62, 56, 50, 43, 37, 31, 25, 18, 12, 6
};

volatile uint16_t sampleIndex = 0;
volatile bool phase = 0; // 0 = Positive Half, 1 = Negative Half

void setup() {
  pinMode(9, OUTPUT);  // High Side MOSFET Drive
  pinMode(10, OUTPUT); // Low Side MOSFET Drive
  noInterrupts();

  // Mode 10: Phase Correct PWM, TOP = ICR1
  TCCR1A = _BV(WGM11);
  TCCR1B = _BV(WGM13) | _BV(CS10); // Prescaler = 1
  
  // ICR1 = 400 sets carrier frequency to 20kHz
  // Formula: 16MHz / (2 * 1 * 400) = 20,000 Hz
  ICR1 = 400; 

  TIMSK1 = _BV(TOIE1); // Enable Overflow Interrupt
  interrupts();
}

ISR(TIMER1_OVF_vect) {
  uint16_t dutyCycle = pgm_read_word(&sineTable[sampleIndex]);

  if (phase == 0) {
    // Positive half-cycle: D9 pulses, D10 stays OFF
    OCR1A = dutyCycle; 
    OCR1B = 0;
    TCCR1A |= _BV(COM1A1);  // Enable PWM on D9
    TCCR1A &= ~_BV(COM1B1); // Disable PWM on D10
  } else {
    // Negative half-cycle: D10 pulses, D9 stays OFF
    OCR1A = 0; 
    OCR1B = dutyCycle;
    TCCR1A &= ~_BV(COM1A1); // Disable PWM on D9
    TCCR1A |= _BV(COM1B1);  // Enable PWM on D10
  }

  sampleIndex++;

  // 200 samples at 20kHz = 10ms (one half-cycle)
  if (sampleIndex >= 200) { 
    sampleIndex = 0;
    phase = !phase; // Swap sides to create AC direction change
  }
}

void loop() {
  // Main loop remains empty; all timing is handled by Timer 1
}

This code is a high-speed SPWM generator that uses the Arduino's internal hardware timer to create a precise 50Hz sine wave.

Here is the breakdown of the logic:

1. The Sine Look-Up Table (The Map)

  • The sineTable contains 200 pre-calculated values representing a half-circle (sine wave).

  • The values range from 0 to 359. These tell the Arduino how long to keep the MOSFET "ON" at any given microsecond to mimic a sine wave's shape.

2. Timer 1 Configuration (The Engine)

  • Mode 10 (Phase Correct PWM): This is the most stable mode for power electronics. The timer counts up to a "TOP" value and then back down to zero.

  • ICR1 = 400: This sets the "TOP" limit. At a 16MHz clock speed, counting up and down to 400 creates exactly a 20kHz carrier frequency.

  • No Prescaler: This runs the timer at the full speed of the Arduino 16MHz for maximum precision.


3. The Interrupt Service Routine (The Brain)

The ISR(TIMER1_OVF_vect) is a special function that runs 20,000 times per second. Each time it runs, it performs three tasks:

  • Duty Cycle Update: It grabs the next value from the sine Table and loads it into the Pulse Width registers (OCR1A or OCR1B).

  • Phase Switching: It manages the Push-Pull logic.

    • Phase 0: It sends the pulses to Pin 9 and keeps Pin 10 at 0V.

    • Phase 1: It sends the pulses to Pin 10 and keeps Pin 9 at 0V.

  • Timing Control: It counts the samples. After 200 samples, it knows that 10ms has passed (half of a 50Hz, so it flips the phase to the other MOSFET.

4. Why This Works for an Inverter

By rapidly switching the MOSFETs on and off at 20kHz with varying "ON" times (the SPWM), the transformer "sees" an average voltage that looks like a sine wave.

Video Demonstraion

The following video demonstrates how this Arduino based SPWM Inverter circuit works. It shows charging and discharging of the MOSFET gate capacitance that reduces loss due to high frequency operation of the MOSFET by the totem pole driver.



Related

Post a Comment

Previous Post Next Post