3 phase SPWM using arduino mega . My target fundamental frequency is 60Hz with a switching frequency of 1980Hz

I have the code below that does SPWM but problem is it has a frequency of 50Hz and I don't know how to change the frequency to the desired 60Hz . And I don't know how to incorporate my switching frequency of 4000Hz.

The code:

int i = 0;
int j = 0;
int k = 0;
int x = 0;
int y = 0;
int z = 0;
int OK = 0;
int OK1 = 0;
int OK2 = 0;
int OK3 = 0;
int OK4 = 0;
int sinPWM[] = {
    1,   2,   5,   7,   10,  12,  15,  17,  19,  22,  24,  27,  30,  32,  34,
    37,  39,  42,  44,  47,  49,  52,  54,  57,  59,  61,  64,  66,  69,  71,
    73,  76,  78,  80,  83,  85,  88,  90,  92,  94,  97,  99,  101, 103, 106,
    108, 110, 113, 115, 117, 119, 121, 124, 126, 128, 130, 132, 134, 136, 138,
    140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168,
    169, 171, 173, 175, 177, 178, 180, 182, 184, 185, 187, 188, 190, 192, 193,
    195, 196, 198, 199, 201, 202, 204, 205, 207, 208, 209, 211, 212, 213, 215,
    216, 217, 219, 220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231,
    232, 233, 234, 235, 236, 237, 237, 238, 239, 240, 240, 241, 242, 242, 243,
    243, 244, 244, 245, 245, 246, 246, 247, 247, 247, 248, 248, 248, 248, 249,
    249, 249, 249, 249, 255, 255, 255, 255, 249, 249, 249, 249, 249, 248, 248,
    248, 248, 247, 247, 247, 246, 246, 245, 245, 244, 244, 243, 243, 242, 242,
    241, 240, 240, 239, 238, 237, 237, 236, 235, 234, 233, 232, 231, 230, 229,
    228, 227, 226, 225, 224, 223, 222, 221, 220, 219, 217, 216, 215, 213, 212,
    211, 209, 208, 207, 205, 204, 202, 201, 199, 198, 196, 195, 193, 192, 190,
    188, 187, 185, 184, 182, 180, 178, 177, 175, 173, 171, 169, 168, 166, 164,
    162, 160, 158, 156, 154, 152, 150, 148, 146, 144, 142, 140, 138, 136, 134,
    132, 130, 128, 126, 124, 121, 119, 117, 115, 113, 110, 108, 106, 103, 101,
    99,  97,  94,  92,  90,  88,  85,  83,  80,  78,  76,  73,  71,  69,  66,
    64,  61,  59,  57,  54,  52,  49,  47,  44,  42,  39,  37,  34,  32,  30,
    27,  24,  22,  19,  17,  15,  12,  10,  7,   5,   2,   1};

void setup() {
  Serial.begin(9600);

  pinMode(4, OUTPUT);   // Phase A negative half cycle
  pinMode(13, OUTPUT);  // Phase A positive half cycle
  pinMode(9, OUTPUT);   // Phase B negative half cycle
  pinMode(10, OUTPUT);  // Phase B positive half cycle
  pinMode(2, OUTPUT);   // Phase C negative half cycle
  pinMode(3, OUTPUT);
  pinMode(5, OUTPUT);  // Phase C positive half cycle

  cli();       // stop interrupts
  TCCR0A = 0;  // reset the value
  TCCR0B = 0;  // reset the value
  TCNT0 = 0;   // reset the value
  // 0b allow me to write bits in binary
  TCCR0A = 0b10100001;  // phase correct pwm mode
  TCCR0B = 0b00000001;  // no prescaler

  TCCR2A = 0;  // reset the value
  TCCR2B = 0;  // reset the value
  TCNT2 = 0;   // reset the value
  // 0b allow me to write bits in binary
  TCCR2A = 0b10100001;  // phase correct pwm mode
  TCCR2B = 0b00000001;  // no prescaler

  TCCR3A = 0;  // reset the value
  TCCR3B = 0;  // reset the value
  TCNT3 = 0;   // reset the value
  // 0b allow me to write bits in binary
  TCCR3A = 0b10100001;  // phase correct pwm mode
  TCCR3B = 0b00000001;  // no prescaler
  TCCR1A = 0;           // reset the value
  TCCR1B = 0;           // reset the value
  TCNT1 = 0;            // reset the value
  OCR1A = 509;          // compare match value
  TCCR1B = 0b00001001;  // WGM12 bit is 1 for CTC mode and no prescaler

  TIMSK1 |= (1 << OCIE1A);  // enable interrupts

  sei();  // stop interrupts
}
ISR(TIMER1_COMPA_vect) {     // interrupt when timer 1 match with OCR1A value
  if (i > 313 && OK == 0) {  // final value from vector for pin 13
    i = 0;                   // go to first value of vector
    OK = 1;                  // enable pin 4
  }
  if (i > 313 && OK == 1) {  // final value from vector for pin 4
    i = 0;                   // go to firs value of vector
    OK = 0;                  // enable pin 13
  }
  x = sinPWM[i];  // x take the value from vector corresponding to position i(i
                  // is zero indexed)
  i = i + 1;      // go to the next position
  if (OK == 0) {
    OCR0B = 0;  // make pin 4 0
    OCR0A = x;  // enable pin 13 to corresponding duty cycle
  }
  if (OK == 1) {
    OCR0A = 0;  // make pin 13 0
    OCR0B = x;  // enable pin 4 to corresponding duty cycle
  }

  if ((i == 209) || OK1 == 1) {  // if i equal with 209 enable second signal
    OK1 = 1;                     // mantain if function
    if (j > 313 && OK2 == 0) {   // final value from vector for pin 10
      j = 0;                     // go to first value of vector
      OK2 = 1;                   // enable pin 9
    }
    if (j > 313 && OK2 == 1) {  // final value from vector for pin 9
      j = 0;                    // go to firs value of vector
      OK2 = 0;                  // enable pin 10
    }
    y = sinPWM[j];  // y take the value from vector corresponding to position
                    // j(j is zero indexed)
    j = j + 1;      // go to the next position
    if (OK2 == 0) {
      OCR2B = 0;  // make pin 9 0
      OCR2A = y;  // enable pin 10 to corresponding duty cycle
    }
    if (OK2 == 1) {
      OCR2A = 0;  // make pin 10 0
      OCR2B = y;  // enable pin 9 to corresponding duty cycle
    }
  }
  if ((j == 209) || OK3 == 1) {  // if j equal with 209 enable third signal
    OK3 = 1;                     // mantain if function
    if (k > 313 && OK4 == 0) {   // final value from vector for pin 5
      k = 0;                     // go to first value of vector
      OK4 = 1;                   // enable pin 2
    }
    if (k > 313 && OK4 == 1) {  // final value from vector for pin 2
      k = 0;                    // go to firs value of vector
      OK4 = 0;                  // enable pin 5
    }
    z = sinPWM[k];  // z take the value from vector corresponding to position
                    // k(k is zero indexed)
    k = k + 1;      // go to the next position
    if (OK4 == 0) {
      OCR3B = 0;  // make pin 2 0
      OCR3A = z;  // enable pin 5 to corresponding duty cycle
    }
    if (OK4 == 1) {
      OCR3A = 0;  // make pin 5 0
      OCR3B = z;  // enable pin 2 to corresponding duty cycle
    }
  }
}
void loop() {
}

You get about 60Hz if you change this line:

  OCR1A = 509;          // compare match value

to

  OCR1A = 425;          // compare match value

What do you mean by "switching frequency"? The PWM frequency in the code is a bit more the 31kHz and will be above 37kHz after above change. If you want it to be 4kHz you won't get a smooth sinus any more and it will change almost the complete sketch. Why do you think you need that?

1 Like

For SPWM isn’t I compare the triangular waveform with a switching frequency of 4kHz to sine wave with 60 Hz hence the switching frequency of 4kHz. And it won’t be a good sine wave output but I have a filter at the output to filter the harmonics so 4kHz was ideal for my situation.

On the note of the 4kHz , when you check in my code I have a lookup table for sine , isn’t that one somehow related to the switching frequency since the values in the table are varying gate pulses .

I will change my frequency to 60 Hz . Thank you

PWM for VFD.

PWM has a rectangular waveform so the answer is no. I also have no clue where the 4kHz are coming from, you can use any PWM frequency significantly higher than the sine wave frequency to get that effect given the driven component accepts PWM or a corresponding smoothening circuit is used.

If the switching frequency is the PWM frequency: yes, it is related but that code doesn't produce a 4 kHz frequency. As you can see the the sine table has 314 entries and shows one half wave, so the actual PWM frequency has to be 628 times higher than the sine wave frequency. The PWM frequencies are 31.4kHz and 37.7kHz.

Okay I understand that. So using the code above , would it be possible to change the PWM frequency to 4kHz

You may find this old paper of interest:

trans_pe_mar_2004_complete.pdf (utk.edu)

The backstory:
untitled (tinaja.com)

No. that would result in a complete rewrite. The sinus wave wouldn't be that smoothed but much more squared. Why do you think you need that?

At the output of the inverter I have an LCL filter that takes care of the square wave which is why I am using 4kHz . My project requires me to use 4kHz so that I can then filter the harmonics at the output. So I want to adjust the code above to meet the 4kHz requirements

I had a similar idea once where I'd create a tone on one pin that would drive a transistor. Another pin would drive a PWM square wave signal going to a second transistor. The output would go through the two transistors in series (not a Darlington array) so there would be a PWM signal that has a frequency each time it's signal is high. IDK if that helps or generates any ideas.

Feel free to change the PWM frequency to 4kHz and adapt the sine table. You then have to change the index values in the code too (i,j,k) to match the corresponding indices in your array.

That is what I have been trying to do . Is there a way you can be able to assist ?

I think I did that in my last post. I won't do the programming for you but I gave you enough hints so you can do it yourself. You might have to study the datasheet and learn how PWM and timers work. And you have to understand how the current code works, otherwise modifying it will probably fail.

1 Like

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