3 PWM for 3 phase inventer

Why not ?

raschemmel:
Why not ?

oki can you explain me ?

Example[edit]
To illustrate these concepts, consider a 230 V AC mains supply used in many countries around the world. It is so called because its root mean square value is 230 V. This means that the time-averaged power delivered is equivalent to the power delivered by a DC voltage of 230 V. To determine the peak voltage (amplitude), we can rearrange the above equation to:

Vpeak=sqrt{2} x Vrms

For 230 V AC, the peak voltage (Vpeak) is therefore 230 V x sqrt{2}, which is about 325 V.

The peak-to-peak value (V P-P of the 230 V AC is double that, at about 650 V.

Are you planning to build this or are just trying to write a program ?
You know if you don't have to use an arduino you can buy a single phase 220vac to 3-phase converter.

i'm trying to write a program

MY problem is i can't varing the frequence with pot(A0)
plz help to fix the code

// disable interrupts to avoid timing distortion
cbi (TIMSK0, TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
dfreq = 1000.0; // initial output frequency = 1000.0 Hz
tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
}
//******************************************************************
void loop()
{
if (c4ms > 250) // timer / wait for a full second
{
c4ms = 0;
dfreq = analogRead(POTEN_IN); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz
cbi (TIMSK2, TOIE2); // disble Timer2 Interrupt
tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
Serial.print(dfreq);
Serial.print(" ");
Serial.println(tword_m);
}
}

can't anyone help me ?

i have a projet and i don't have much time

Well perhaps you could give us the basic facts - the datasheet for the motor and
IGBT 3-phase bridge, the range of frequencies you want, the frequency
resolution, what PWM frequency(s).

As I said if you want a programmable frequency generator then DDS is probably
the way to go - use a timer interrupt to update the DDS and the output phase as
the main control loop. At its heart DDS is just

volatile long phase = 0L ;
volatile long frequency = 0L ;

ISR (TIMER2_OVF_vect)
{
  phase += frequency ;
  int top_phase = phase >> 24 ;   // truncate to 8 bits
  int phase_u = sinetab [0xFF & top_phase] ;
  int phase_v= sinetab [0xFF & (top_phase+85)] ;
  int phase_w = sinetab [0xFF & (top_phase+171)] ;
  ...
}

for the motor ( 220v/380v // f=50hz // rpm = 1430 )

the range of frequencies is 0 to 2KHZ

can you help to fix it and can i add the potentiomètre to varing the frequence??

#include "avr/pgmspace.h"
#include "avr/io.h"

// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM  prog_uchar sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};
  
  
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

int phase_u  = 10;
int phase_v =  11;
int phase_w =  12 ;

volatile long phase = 0L ;
volatile long frequency = 0L;


void setup()
{ 
Serial.begin(115200);
pinMode(phase_u , OUTPUT); // PWM output / frequency output
pinMode(phase_v , OUTPUT); // PWM output / frequency output
pinMode(phase_w , OUTPUT); // PWM output / frequency output

// Setup the timers
setup_timer1();
setup_timer2();
// disable interrupts to avoid timing distortion
cbi (TIMSK0, TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
}
//******************************************************************
// timer1 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer1()
{
// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer0 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0); // clear Compare Match
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0); // clear Compare Match
sbi (TCCR1A, COM1B1);
sbi (TCCR1A, WGM10); // Mode 1 / Phase Correct PWM
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer2()
{
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
ISR (TIMER2_OVF_vect)
{
  phase += frequency ;
  top_phase = phase >> 24 ;   // truncate to 8 bits
 OCR2A = = sinetab [0xFF & top_phase] ;
 OCR1A == sinetab [0xFF & (top_phase+85)] ;
 OCR1B == sinetab [0xFF & (top_phase+171)] ;
}

i used this code

#include "avr/pgmspace.h"
#include "avr/io.h"

// Look Up table of a single sine period divied up into 256 values. Refer to PWM to sine.xls on how the values was calculated
PROGMEM  prog_uchar sine256[]  = {
  127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
  242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
  221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
  76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
  33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124};
  
  
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
int PWM_OUT_1 =11; // PWM output on pin 11
int PWM_OUT_2 =10; // PWM output on pin 10
int PWM_OUT_3 =12; // PWM output on pin 9
int LED_PIN =13; // LED status on pin 13
int TEST_PIN =7; // Scope trigger on pin 7
int POTEN_IN =A0; // Potentiometer on pin 0
int OFFSET_1 =85; // Offset for second-phase
int OFFSET_2 =170; // Offset for third-phase
float dfreq;
const double refclk = 31376.6; // measured
const uint64_t twoTo32 = pow(2, 32); // compute value at startup and use as constant
// variables used inside interrupt service declared as voilatile
volatile uint8_t icnt; // var inside interrupt
volatile uint8_t icnt1; // var inside interrupt
volatile uint8_t c4ms; // counter incremented every 4ms
volatile uint32_t phase_accum; // pahse accumulator
volatile uint32_t tword_m; // dds tuning word m
//******************************************************************
void setup()
{
pinMode(LED_PIN, OUTPUT); // sets the digital pin as output
Serial.begin(115200); // connect to the serial port
Serial.println("DDS Test");

pinMode(TEST_PIN, OUTPUT); // sets the digital pin as output
pinMode(PWM_OUT_1, OUTPUT); // PWM output / frequency output
pinMode(PWM_OUT_2, OUTPUT); // PWM output / frequency output
pinMode(PWM_OUT_3, OUTPUT); // PWM output / frequency output
// Setup the timers
setup_timer1();
setup_timer2();
// disable interrupts to avoid timing distortion
cbi (TIMSK0, TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt
dfreq = 50.0; // initial output frequency = 1000.0 Hz
tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
}
//******************************************************************
void loop()
{
if (c4ms > 250) // timer / wait for a full second
{
c4ms = 0;
dfreq = analogRead(POTEN_IN); // read Poti on analog pin 0 to adjust output frequency from 0..1023 Hz
cbi (TIMSK2, TOIE2); // disble Timer2 Interrupt
tword_m = twoTo32 * dfreq / refclk; // calulate DDS new tuning word
sbi (TIMSK2, TOIE2); // enable Timer2 Interrupt

}
}
//******************************************************************
// timer1 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer1(void)
{
// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer0 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0); // clear Compare Match
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0); // clear Compare Match
sbi (TCCR1A, COM1B1);
sbi (TCCR1A, WGM10); // Mode 1 / Phase Correct PWM
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}

//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/512 = 31.25kHz clock
void setup_timer2()
{
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
//******************************************************************
// Timer2 Interrupt Service at 31.25kHz = 32us
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect)
{
sbi(PORTD, TEST_PIN); // Test / set PORTD,TEST_PIN high to observe timing with a oscope
phase_accum += tword_m; // soft DDS, phase accu with 32 bits
icnt = phase_accum >> 24; // use upper 8 bits for phase accu as frequency information
OCR2A = pgm_read_byte_near(sine256 + icnt); // read value fron ROM sine table and send to PWM DAC
OCR1A = pgm_read_byte_near(sine256 + (uint8_t)(icnt + OFFSET_1));
OCR1B = pgm_read_byte_near(sine256 + (uint8_t)(icnt + OFFSET_2));
if (icnt1++ == 125) // increment variable c4ms every 4 milliseconds
{
c4ms++;
icnt1 = 0;
}
cbi(PORTD, TEST_PIN); // reset PORTD,TEST_PIN
}

the result in the pic the 3 phase 120 degres out of phase but the problem is when i varing the frequence with potentiomètre anything happins and it 's start automatique , so how i can varing the frequence with potentiomètre ?

Sans titre1.bmp (2.25 MB)

Is the low pass filtering on the outputs just for easy of seeing the waveforms on the 'scope?

tword_m is your frequency, so set it from the pot value?
You seem to be doing that, have you checked the phase values are sensible by outputing phase on serial?

You need to disable interrupts globally when updating variables, disabling specific interrupts might lose
them, the global mechanism queues them up correctly. (noInterrupts(), interrupts())

You seem to be doing that, have you checked the phase values are sensible by outputing phase on serial?

You need to disable interrupts globally when updating variables, disabling specific interrupts might lose
them, the global mechanism queues them up correctly. (noInterrupts(), interrupts())

[/quote]

can you explain more what is "phase values are sensible by outputing phase on serial?" and "You need to disable interrupts globally when updating variables, disabling specific interrupts might lose
them, the global mechanism queues them up correctly"

I meant test that the phase increments were happening OK, by whatever
debugging options are available.

I've had a chance to run the code now and it basically works, well for
pins 10 and 11. You define PWM3 pin as 12, but it should be 9

You only update the frequency every second, which is confusing - why
not update it continuously in loop?

Did you post a link to the motor?

3 phase motor ( 220v/380v // f=50hz // rpm = 1430 )

how i can update the frequency continuously in loop?

you can give me exemple how i can update the frequency continuously in loop ?

@MarkT : can you help me i don't have much time

i want to generate 3 PWM 120 degrees out of phase with arduino mega2560 because i want to control six pluse igbt to control 3 phase motor ( 220v/380v // f=50hz // rpm = 1430 ) and display the frequence in LCD

i used this code but the problem is i can't changing the frenquency with potentiomètre
can you help me how can i fix it ?

#include "avr/pgmspace.h"
PROGMEM prog_uchar sine256[] = {
127,130,133,136,139,143,146,149,152,155,158,161,164,167,170,173,176,178,181,184,187,190,192,195,198,200,203,205,208,210,212,215,217,219,221,223,225,227,229,231,233,234,236,238,239,240,
242,243,244,245,247,248,249,249,250,251,252,252,253,253,253,254,254,254,254,254,254,254,253,253,253,252,252,251,250,249,249,248,247,245,244,243,242,240,239,238,236,234,233,231,229,227,225,223,
221,219,217,215,212,210,208,205,203,200,198,195,192,190,187,184,181,178,176,173,170,167,164,161,158,155,152,149,146,143,139,136,133,130,127,124,121,118,115,111,108,105,102,99,96,93,90,87,84,81,78,
76,73,70,67,64,62,59,56,54,51,49,46,44,42,39,37,35,33,31,29,27,25,23,21,20,18,16,15,14,12,11,10,9,7,6,5,5,4,3,2,2,1,1,1,0,0,0,0,0,0,0,1,1,1,2,2,3,4,5,5,6,7,9,10,11,12,14,15,16,18,20,21,23,25,27,29,31,
33,35,37,39,42,44,46,49,51,54,56,59,62,64,67,70,73,76,78,81,84,87,90,93,96,99,102,105,108,111,115,118,121,124
};
#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))
#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))
byte phase1=11; //PWM output for phase 1
byte phase2=10; //PWM output for phase 2
byte phase3=9; //PWM output for phase 3
byte offset120=85; //256/3;
byte offset240=171; //256/3*2;
float dfreq;
const double refclk=31372.549; // =16MHz / 510
// variables used inside interrupt service declared as voilatile
volatile byte icnt; // var inside interrupt
volatile byte icnt1; // var inside interrupt
volatile byte c4ms; // counter incremented every 4ms
volatile unsigned long phaccu; // pahse accumulator
volatile unsigned long tword_m; // dds tuning word m


void setup() {
  // put your setup code here, to run once:
Serial.begin(9600); // connect to the serial port
//pins 11,3,9 (phase 1,2 & 3) set up as output for three phases
pinMode(phase1, OUTPUT); // pin11= PWM output phase 1
pinMode(phase2, OUTPUT); // pin3= PWM output phase 2
pinMode(phase3, OUTPUT); // pin9= PWM output phase 3
Setup_timer1();
Setup_timer2();
// disable interrupts to avoid timing distortion
cbi (TIMSK0,TOIE0); // disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); // enable Timer2 Interrupt
dfreq=0.0; // initial output frequency = 1000.o Hz
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
Serial.print("  ");
Serial.println(tword_m);
}

void loop() 
{
  // put your main code here, to run repeatedly:
while(1) {
  if (c4ms > 250) { // timer / wait for a full second
c4ms=0;
dfreq=analogRead(0); //Read voltage on analog 1 to see desired output frequency, 0V = 0Hz, 5V = 100Hz
cbi (TIMSK2,TOIE2); // disble Timer2 Interrupt
tword_m=pow(2,32)*dfreq/refclk; // calulate DDS new tuning word
sbi (TIMSK2,TOIE2);
}
}
}
//******************************************************************
// timer2 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer2() {
// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20);
cbi (TCCR2B, CS21);
cbi (TCCR2B, CS22);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR2A, COM2A0); // clear Compare Match
sbi (TCCR2A, COM2A1);
cbi (TCCR2A, COM2B0);
sbi (TCCR2A, COM2B1);
sbi (TCCR2A, WGM20); // Mode 1 / Phase Correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);
}
// timer1 setup
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer1() {
// Timer2 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);
// Timer2 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0); // clear Compare Match
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0);
sbi (TCCR1A, COM1B1);
sbi (TCCR1A, WGM10); // Mode 1 / Phase Correct PWM
cbi (TCCR1A, WGM11);
cbi (TCCR1B, WGM12);
cbi (TCCR1B, WGM13);
}
//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// FOUT = (M (REFCLK)) / (2 exp 32)
// runtime : 8 microseconds ( inclusive push and pop)
ISR(TIMER2_OVF_vect)
{
phaccu=phaccu+tword_m; // soft DDS, phase accumulator with 32 bits
icnt=phaccu >> 24; // use upper 8 bits for phase accumulator as frequency information.
// Note: >> is bit right shift operator, >>24 shifts 24 bits to right leaving upper 8 bits (32-24=8)
OCR2A=pgm_read_byte_near(sine256 + icnt); // read value fron ROM sine table and send to PWM DAC
OCR2B=(pgm_read_byte_near(sine256 + (uint8_t)(icnt + offset120)));
//OCR1A=pgm_read_byte_near(sine256 + (uint8_t)(icnt + offset240));
OCR1A=(pgm_read_byte_near(sine256 + (uint8_t)(icnt + offset240))); //Phase C scales with potentiometer position depending on switch on digital 2
if(icnt1++ == 125) { // increment variable c4ms every 4 milliseconds to provide timing as timer 0 disabled
c4ms++;
icnt1=0;
}
}

Why don't you tell us us what you observe that you don't expect, and what you don't observe that you do expect?

Maybe reformat your code to make it easier to read.

There is a kind of "ground hog day" thread here. Similar problem (control of frequency), not sure if it was really solved. You might find some information useful.