Please help me make 3ph inverter PWM

// Pin definitions
#define HIN_A 8
#define LIN_A 9
#define HIN_B 10
#define LIN_B 11
#define HIN_C 12
#define LIN_C 13

// State variables
bool stateA = false;
bool stateB = false;
bool stateC = false;
uint8_t phase = 0; // 0-119 (divided into 120 steps)

// Timer configuration
void setupTimer1() {
  noInterrupts();
  // 10kHz PWM (16MHz / (1(prescaler) * (1599+1))) = 10kHz
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 1599; // Set compare value (10kHz)
  TCCR1B |= (1 << WGM12); // CTC mode
  TCCR1B |= (1 << CS10); // Prescaler 1
  TIMSK1 |= (1 << OCIE1A); // Enable timer compare interrupt
  interrupts();
}

void setup() {
  // Set pin mode
  pinMode(HIN_A, OUTPUT);
  pinMode(LIN_A, OUTPUT);
  pinMode(HIN_B, OUTPUT);
  pinMode(LIN_B, OUTPUT);
  pinMode(HIN_C, OUTPUT);
  pinMode(LIN_C, OUTPUT);

  // Initialize all outputs to LOW
  digitalWrite(HIN_A, LOW);
  digitalWrite(LIN_A, LOW);
  digitalWrite(HIN_B, LOW);
  digitalWrite(LIN_B, LOW);
  digitalWrite(HIN_C, LOW);
  digitalWrite(LIN_C, LOW);

  // Configure timer
  setupTimer1();
}

ISR(TIMER1_COMPA_vect) {
  phase = (phase + 1) % 120; // 120 steps (each step = 3 degrees)

  // Phase A (0° reference)
  handlePhase(HIN_A, LIN_A, phase, &stateA);

  // Phase B (120° delay)
  handlePhase(HIN_B, LIN_B, (phase + 40) % 120, &stateB);

  // Phase C (240° delay)
  handlePhase(HIN_C, LIN_C, (phase + 80) % 120, &stateC);
}

void handlePhase(uint8_t hin, uint8_t lin, uint8_t currentPhase, bool *state) {
  if (currentPhase < 60) { // First half cycle (0–59) - HIN ON
    if (!*state) {
      // Apply dead time (4 µs)
      digitalWrite(lin, LOW);
      delayMicroseconds(4);
      digitalWrite(hin, HIGH);
      *state = true;
    }
  } else { // Second half cycle (60–119) - LIN ON
    if (*state) {
      // Apply dead time (4 µs)
      digitalWrite(hin, LOW);
      delayMicroseconds(4);
      digitalWrite(lin, HIGH);
      *state = false;
    }
  }
}

void loop() {
  // Main operation handled in timer interrupt
}

I am trying to generate 3 PWM signals for a three-phase inverter. Each PWM consists of one HIN and one LIN, so a total of 6 output pins (3 HINs and 3 LINs) are used. Phase 1 PWM, Phase 2 PWM (120 degrees out of phase from phase 1), and Phase 3 PWM (240 degrees out of phase from phase 2).
The frequency of all waveforms must be 10kHz, meaning each cycle must be 100 µs, and a dead time of approximately 4 µs is required between HIN and LIN. When executing the code below, the PWM phase difference was correctly implemented, but the PWM period came out to be 12 ms. Please tell me how to fix this.
And if the overall concept itself to make 3ph PWM is wrong, let me know what kind of code I should use to generate the PWM signals I want. I'm completely new to Arduino. I'd be grateful if you guys help me out. thx

You have a 120 phase steps 100us each.
120 * 100 uS = 12mS

Variation on your program,

basis idea is that 3 phases at 120 ° will give a repeating pattern every 6 steps.
In every step there is only one output that changes.

The interrupt timing need to be adjusted to get 3 outputs of 10 kHz pulses.
Think they are now at 3333 Hz.

//  Pin definitions
#define HIN_A 8
#define LIN_A 9
#define HIN_B 10
#define LIN_B 11
#define HIN_C 12
#define LIN_C 13


//  3 phases repeat after 6 steps.
int step = 0;


// Timer configuration
void setupTimer1() 
{
  noInterrupts();
  //  10 kHz PWM (16MHz / (1(prescaler) * (1599+1))) = 10 kHz
  TCCR1A = 0;
  TCCR1B = 0;
  TCNT1 = 0;
  OCR1A = 1599;            //  Set compare value (10 kHz)
  TCCR1B |= (1 << WGM12);  //  CTC mode
  TCCR1B |= (1 << CS10);   //  Prescaler 1
  TIMSK1 |= (1 << OCIE1A); //  Enable timer compare interrupt
  interrupts();
}


void setup()
{
  // Set pin mode
  pinMode(HIN_A, OUTPUT);
  pinMode(LIN_A, OUTPUT);
  pinMode(HIN_B, OUTPUT);
  pinMode(LIN_B, OUTPUT);
  pinMode(HIN_C, OUTPUT);
  pinMode(LIN_C, OUTPUT);

  // Initialize all outputs to LOW
  digitalWrite(HIN_A, LOW);
  digitalWrite(LIN_A, LOW);
  digitalWrite(HIN_B, LOW);
  digitalWrite(LIN_B, LOW);
  digitalWrite(HIN_C, LOW);
  digitalWrite(LIN_C, LOW);

  // Configure timer
  setupTimer1();
}


ISR(TIMER1_COMPA_vect)
{
  step = step + 1;
  if (step >= 6) step = 0;

  switch(step)
  {
    case '0':
      digitalWrite(LINA, LOW);
      delayMicroseconds(4);
      digitalWrite(HINA, HIGH);
      break;
    case '1':
      digitalWrite(LINB, LOW);
      delayMicroseconds(4);
      digitalWrite(HINB, HIGH);
      break;
    case '2':
      digitalWrite(LINC, LOW);
      delayMicroseconds(4);
      digitalWrite(HINC, HIGH);
      break;
    case '3':
      digitalWrite(LINA, HIGH);
      delayMicroseconds(4);
      digitalWrite(HINA, LOW);
      break;
    case '4':
      digitalWrite(LINB, HIGH);
      delayMicroseconds(4);
      digitalWrite(HINB, LOW);
      break;
    case '5':
      digitalWrite(LINC, HIGH);
      delayMicroseconds(4);
      digitalWrite(HINC, LOW);
      break;
  }
}


void loop() {
  // Main operation handled in timer interrupt
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.