3 PWM for 3 phase motor

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

i use timer 1 and 2 :
timer 1 (controls pin 12, 11)
timer 2 (controls pin 10, 9)

can you help me to fix the code for my arduino uno because the problem is the frenquence output
MY problem is i can't varing the frequence with pot(A0)

#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 =9; // 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 = 50.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
}

Normally 3-phase PWM can only be done with synchronized outputs - its easy with the Mega as it has
timers with 3 PWM pins each.

Ths synchronization is required for 3-wire motors where the phases interfere. 6-wire motors can be PWM'd
independently, but they are rare, 3 wires is common.

See threads PWM for 3-phase Inverter - Motors, Mechanics, Power and CNC - Arduino Forum, 3 PWM for 3 phase inventer - Motors, Mechanics, Power and CNC - Arduino Forum

Somewhere there I think I have some sync code for timers.

When i sumulate this programme with arduino mega i can't also varie the frequency using potentiometer
can you help me to fix it

Why are you disabling/enabling timer2 interrupts to write tword_m?
You should use noInterrupts(), interrupts() for a critical section, you only want to defer
interrupts, not lose them at random or get spurious interrupts.

I don't think that's the main problem though, you seem to be doing the right thing with
tword_m and phase_accum.

i've tried and still same problem

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

// table of 256 sine values / one sine period / stored in flash memory
const byte sine256[] PROGMEM =
{
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 test_pin=7;//scoope trigger pin
int Led_Pin=13;//Led status
int PWM1= 11;// PWM1 output, phase 1
int PWM2 = 9; //PWM2 ouput, phase 2
int PWM3 = 10; //PWM3 output, phase 3
int POTEN_IN = A0; // Potentiometer on pin A0
int OFFSET_1=85;//dephasage 120
int OFFSET_2=170;//dephasage 120
int val;
int val1;
double dfreq; //initial output freqquency
const double refclk=3921.56; // measured output frequency
const uint64_t twoTo32=pow(2,32);
// variables used inside interrupt service declared as voilatile
volatile uint32_t tword_m; // dds tuning word m, refer to DDS_calculator (from Martin Nawrath) for explination.
volatile uint8_t icnt ; // Keep track of where the current count is in sine 256 array
volatile uint8_t icnt1; //variable used to generate a 4ms delay
volatile uint8_t c4ms; // after every 4ms this variable is incremented, its used to create a delay of 1 second
volatile uint32_t phase_accum; // phase accumulator

void setup()
{
pinMode(Led_Pin,OUTPUT);
Serial.begin(115200); // connect to the serial port
Serial.println("DDS Test");

pinMode(test_pin, OUTPUT); // sets the digital pin as output
pinMode(PWM1, OUTPUT); //sets the digital pin as output
pinMode(PWM2, OUTPUT); //sets the digital pin as output
pinMode(PWM3, OUTPUT); //sets the digital pin as output

pinMode(POTEN_IN,INPUT);

Setup_timer1();
Setup_timer2();

//Disable Timer 1 interrupt to avoid any timing delays
cbi (TIMSK0,TOIE0); //disable Timer0 !!! delay() is now not available
sbi (TIMSK2,TOIE2); //enable Timer2 Interrupt

dfreq=50.0; //initial output frequency = 50.o Hz
tword_m=twoTo32*dfreq/refclk; //calulate DDS new tuning word

}

void loop()
{
val=analogRead(POTEN_IN);

long frequency = twoTo32 *val / refclk; // calulate DDS new tuning word
noInterrupts () ;
tword_m = frequency ; // copy quickly with interrupts masked
interrupts () ;

}
// timer1 setup (sets pins 9 and 10)
// set prscaler to 1, PWM mode to phase correct PWM, 16000000/510 = 31372.55 Hz clock
void Setup_timer1() {

// Timer1 Clock Prescaler to : 1
sbi (TCCR1B, CS10);
cbi (TCCR1B, CS11);
cbi (TCCR1B, CS12);

// Timer1 PWM Mode set to Phase Correct PWM
cbi (TCCR1A, COM1A0); // clear OC1A on Compare Match, PWM pin 9
sbi (TCCR1A, COM1A1);
cbi (TCCR1A, COM1B0); // clear OC1B on Compare Match, PWM pin 10
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, fast PWM
void Setup_timer2() {

// Timer2 Clock Prescaler to : 1
sbi (TCCR2B, CS20); // set
cbi (TCCR2B, CS21); // clear
cbi (TCCR2B, CS22);

// Timer2 PWM Mode
cbi (TCCR2A, COM2A0); // clear OC2A on Compare Match, PWM pin 11
sbi (TCCR2A, COM2A1);

// set to fast PWM
sbi (TCCR2A, WGM20); // Mode 1, phase correct PWM
cbi (TCCR2A, WGM21);
cbi (TCCR2B, WGM22);

sbi (TIMSK2,TOIE2); // enable overflow detect

}

//******************************************************************
// Timer2 Interrupt Service at 31372,550 KHz = 32uSec
// this is the timebase REFCLOCK for the DDS generator
// runtime : 8 microseconds ( inclusive push and pop)
// OC2A - pin 11
// OC1B - pin 10
// OC1A - pin 9
// https://www.arduino.cc/en/Tutorial/SecretsOfArduinoPWM
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
}

So what does happen? I've not got an Uno or 'scope to hand at the moment to test this...

Uploaded that to an Uno, seems to work for me. voltage on A0 definitely affects the period of the
waveform.

i simulated with isis and nothing happen the frequency isn't variable with the potentiometre

Maryem:
i simulated with isis and nothing happen the frequency isn't variable with the potentiometer

Show us a photo of your potentiometer, and show us what sort of potentiometer it is, and also show how it is connected (eg.... wiring, DC voltages etc).

Just make sure that you're getting valid readings coming through. Forget about the three-phase for the moment, and focus on confirming that the arduino is getting proper readings when you adjust the voltage on A0 (with the potentiometer).

but the problem is when i varing the frequence with potentiomètre anything happins and it 's start automatique

Well with open-loop control of the frequency you won't get solid regulation as there is no position feedback,
you have something a bit like a stepper motor in effect.

Read up on motor control

Sorry but i can't undrestand what you me

You said anything happens - in other words the motor isn't going at the frequency you expect,
but the PWM waveforms are as expected?

[ Also can you explain what the motor is, how its being driven, power supply, etc ]

Maryem:
Sorry but i can't undrestand what you me

You're going to have to put in a better effort in explaining what the issue is. Show photos etc of your system, including the waveforms that you're getting. Can't be expected to get proper answers quickly if too vague, and especially when you appear as if you don't care about what you type or convey.... for example:

"can't undrestand what you me"

Help yourself by helping others help you. For example.... show pictures.... your potentiometer connections (wiring, voltage levels etc), plus waveform photos. Providing enough details allows others to home in on the problem effectively.

You can buy 1-phase to 3-phase fixed or variable frequency invertors with price depending on power level and features from various suppliers.

The 3-phase fixed or variable frequency with an arduino isn't very difficult. A single pwm source with simple gating will give you the required power modulating signals.

The power part IS a significant problem.

I think you'll blow up a lot of semiconductors if you're not skilled in this specialist field.

3-phase IGBT opto-isolated bridges seem to be the current approach at lower power levels.

Above that big thyristors.

What power level do you require?

Allan

3-phase IGBT opto-isolated bridges seem to be the current approach at lower power levels.

Above that big thyristors.

IGBT's are the device of choice for AC inverters from the fractional to 500kw range with voltages to about 2kv with a standard 6 device bridge. Since IGBT's are relatively easy to parallel, there are low voltage (<1kv) AC VFD's well into the multi-megawatt range with different bridge paralleling arrangements as well as higher voltage series arrangements ultilizing capacitive voltage dividers with multipulse totem-pole outputs. Typical carrier frequency ranges are from 2 to 8 Khz and higher.

Thyristors are still in widespread use in LV DC drives and other utility power conversion products but they've never seen much, if any, use in AC VFD's in the last twenty years.

I stand corrected. I didn't know IGBT's were up to such power levels.

Not my field.

What do modern electric trains use? - 25kVac overhead line supply.

Allan

ME CAGO EN TU PUTA MADRE GUIRI >:( >:( >:( >:( >:( >:( >:( >:( >:(

allanhurst:
I stand corrected. I didn't know IGBT's were up to such power levels.

Not my field.

What do modern electric trains use? - 25kVac overhead line supply.

Allan

I'm an LV guy so my MV/HV drives knowledge is only what I pick up along the way...

The current 25KV traction systems employ IGBT's as well. Most of the systems are 3 to 5 level outputs in order to be more motor friendly. There are also IGCT (integrated gate-commutated thyristor) based systems as well in the usual MV ranges.

in this project i used Bridge , 3phase IGBT .
this is my first time that i use arduino so that i'd like to varing duty cycle and the frequency if it possible and display them on an LCD.
i have problem with the code
i want control the speed of motor(230V-50hz) by varing the frequency