// SPWM code for Arduino Nano Inverter (50Hz output) // Uses Hardware Timer 1 on Pins 9 and 10 at ~31.3 kHz switching frequency const int steps = 20; // A true half-sine wave lookup table (0 to 255 to 0) const byte sineTable[20] = { 0, 40, 79, 117, 153, 185, 213, 235, 249, 255, 255, 249, 235, 213, 185, 153, 117, 79, 40, 0 }; volatile int stepIndex = 0; volatile boolean currentHalfCycle = 0; // 0 = Positive Half, 1 = Negative Half void setup() { // Set Pin 9 and 10 as outputs pinMode(9, OUTPUT); pinMode(10, OUTPUT); // Clear Timer 1 Control Registers TCCR1A = 0; TCCR1B = 0; TCNT1 = 0; // Configure Timer 1 for Phase Correct PWM, 8-bit mode (Mode 1) // This gives a PWM frequency of 16MHz / (2 * 255) = ~31.37 kHz TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM10); TCCR1B = _BV(CS10); // No prescaling // Configure Timer 2 to handle the 50Hz timing grid // 50Hz full wave = 20ms. Each half wave = 10ms. // 10ms / 20 steps = 500 microseconds per step interval. TCCR2A = 0; TCCR2B = 0; TCNT2 = 0; OCR2A = 124; // Clear Timer on Match (CTC) target TCCR2A = _BV(WGM21); // CTC Mode TCCR2B = _BV(CS21) | _BV(CS20); // Prescaler 64 -> (16MHz / 64) = 250kHz clock (4us per tick) // 125 ticks * 4us = 500us interval TIMSK2 = _BV(OCIE2A); // Enable Timer 2 Compare Match A Interrupt } // Timer 2 Interrupt service routine updates the SPWM duty cycle every 500us ISR(TIMER2_COMPA_vect) { byte pwmVal = sineTable[stepIndex]; if (currentHalfCycle == 0) { // Positive half cycle: Drive Pin 9 with SPWM, keep Pin 10 at 0 analogWrite(10, 0); analogWrite(9, pwmVal); } else { // Negative half cycle: Drive Pin 10 with SPWM, keep Pin 9 at 0 analogWrite(9, 0); analogWrite(10, pwmVal); } stepIndex++; // If we reach the end of the 20-step half-cycle, switch sides if (stepIndex >= steps) { stepIndex = 0; currentHalfCycle = !currentHalfCycle; // Toggle between positive and negative halves } } void loop() { // The entire SPWM generation runs perfectly inside the hardware interrupts. // Your loop stays free to read voltage/current protection overrides! }