3 PWM for 3 phase inventer

dlloyd:
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.

i found it but it work with arduino due , i used arduino mega2560 that's oki .

int sine[] = { 0x7ff, 0x86a, 0x8d5, 0x93f, 0x9a9, 0xa11, 0xa78, 0xadd, 0xb40, 0xba1,
	0xbff, 0xc5a, 0xcb2, 0xd08, 0xd59, 0xda7, 0xdf1, 0xe36, 0xe77, 0xeb4,
	0xeec, 0xf1f, 0xf4d, 0xf77, 0xf9a, 0xfb9, 0xfd2, 0xfe5, 0xff3, 0xffc,
	0xfff, 0xffc, 0xff3, 0xfe5, 0xfd2, 0xfb9, 0xf9a, 0xf77, 0xf4d, 0xf1f,
	0xeec, 0xeb4, 0xe77, 0xe36, 0xdf1, 0xda7, 0xd59, 0xd08, 0xcb2, 0xc5a,
	0xbff, 0xba1, 0xb40, 0xadd, 0xa78, 0xa11, 0x9a9, 0x93f, 0x8d5, 0x86a,
	0x7ff, 0x794, 0x729, 0x6bf, 0x655, 0x5ed, 0x586, 0x521, 0x4be, 0x45d,
	0x3ff, 0x3a4, 0x34c, 0x2f6, 0x2a5, 0x257, 0x20d, 0x1c8, 0x187, 0x14a,
	0x112, 0xdf, 0xb1, 0x87, 0x64, 0x45, 0x2c, 0x19, 0xb, 0x2,
	0x0, 0x2, 0xb, 0x19, 0x2c, 0x45, 0x64, 0x87, 0xb1, 0xdf,
	0x112, 0x14a, 0x187, 0x1c8, 0x20d, 0x257, 0x2a5, 0x2f6, 0x34c, 0x3a4,
0x3ff, 0x45d, 0x4be, 0x521, 0x586, 0x5ed, 0x655, 0x6bf, 0x729, 0x794};



#include "pwm01.h"
#include <math.h>
#include <Arduino.h>
#include <stdio.h>
#include "CalculateDelayValueForSinusFrequency.h"



		// Calculate the delay value for the sine wave frequency
		
 long double CalculateDelayValueForSinusFrequency ( int p_sinewave_frequency_Hz) 
 {
	long double DelayForSinFreq_us;
	DelayForSinFreq_us=1000000/ (p_sinewave_frequency_Hz*120); // f=1/T
	return DelayForSinFreq_us;

}


/***		Programm Variablen		***/
int PhaseU= 7; 
int PhaseV= 8;
int PhaseW= 9;
int SineFrequency =50 ; // desierd sine wave frequency in Hz
int p_SinusAmplitudenTeilerFaktor = 1; //  default = 1 means 3.3volt =1 = 3.3 volt for the sine wave signal

static int k = sizeof(sine)/sizeof(int)/3; //length of the sine table =120
static int j= k*2; //for the third wave length of the sine table


void setup()
{.
	// uint32_t  pwm_duty =0.5* 65535;//2^16=65536
	uint32_t  pwm_freq2 = 15000; // Set a unique frequency to the three output signals #########################

	// Set PWM Resolution
	pwm_set_resolution(12);  // #########################

	// Setup PWM Once (Up to two unique frequencies allowed
	//-----------------------------------------------------

	pwm_setup( PhaseU, pwm_freq2, 2);  // Pin 7 freq set to "pwm_freq2" on clock B
	pwm_setup( PhaseV, pwm_freq2, 2);  // Pin 8 freq set to "pwm_freq2" on clock B
	pwm_setup( PhaseW, pwm_freq2, 2);  // Pin 9 freq set to "pwm_freq2" on clock B
	
	// Write PWM Duty Cycle Anytime After PWM Setup
	//-----------------------------------------------------
	// pwm_write_duty( 7, pwm_duty );  //


	// delay(30000);  // 30sec Delay; PWM signal will still stream
	
	// Force PWM Stop On All Pins
	//-----------------------------
	
	// pwm_stop( 7 );
	// pwm_stop( 8 );
	//pwm_stop( 9 );
	}
	
	void loop()
	{
		
		while(1){
			
			for(int i = 0; i<120;i++){ 
				pwm_write_duty( 7, sine[i]/p_SinusAmplitudenTeilerFaktor);  
				pwm_write_duty( 8, sine[(i+k)%120/p_SinusAmplitudenTeilerFaktor]); 
				pwm_write_duty( 9, sine[(i+j)%120/p_SinusAmplitudenTeilerFaktor]); 
				delayMicroseconds(CalculateDelayValueForSinusFrequency(SineFrequency));
				
			}
		}
		}
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);
}
}

my problem is i can't varing the frequency and duty cycle .

adelo14:
how i can update the frequency continuously in loop?

By not deliberately delaying?

ie

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
  }
}

is changed to:

void loop()
{
  long frequency = twoTo32 * analogRead(POTEN_IN) / refclk; // calulate DDS new tuning word
  noInterrupts () ;
  tword_m = frequency ; // copy quickly with interrupts masked
  interrupts () ;
}

MarkT:

adelo14:
how i can update the frequency continuously in loop?

By not deliberately delaying?

ie

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
 }
}



is changed to:


void loop()
{
 long frequency = twoTo32 * analogRead(POTEN_IN) / refclk; // calulate DDS new tuning word
 noInterrupts () ;
 tword_m = frequency ; // copy quickly with interrupts masked
 interrupts () ;
}

it 's oki and how i can varing duty cycle ?

The code already does that, I ran it and looked at the outputs. The main problem
is only 2 outputs are driven, since you confuse pin 9 with pin 12 in the #defines.

i simulate with isis 7 and nothing happin . can you give another logicel i can simulate with it ?

What are you simulating? I just ran the code on an Uno and looked at the outputs on a
'scope, seems the obvious approach. Without a power 3-phase bridge that's the best I
can do.

MarkT:
What are you simulating? I just ran the code on an Uno and looked at the outputs on a
'scope, seems the obvious approach. Without a power 3-phase bridge that's the best I
can do.

i use arduino mega 2560 and i simulate with isis7
plz when i start simulation the pwm start directly can i control with enable and disable ??

i change my code , thanks for "MarkT"
when i start simulation the pwm start directly can i control it with enable and disable ??
Can I chnage it in a better way ?

#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()
{
  long frequency = twoTo32 * analogRead(POTEN_IN) / refclk; // calulate DDS new tuning word
  noInterrupts () ;
  tword_m = frequency ; // copy quickly with interrupts masked
  interrupts () ;
}
//******************************************************************
// 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
}

adelo14:
i use arduino mega 2560

Ah, that explains my issue with pin numbers, I think you have the
right pins for those timer channels for the Mega.

It works now (potentiometer control of the speed)?

NOTE WELL MY SIGNATURE.....

MarkT:

adelo14:
i use arduino mega 2560

Ah, that explains my issue with pin numbers, I think you have the
right pins for those timer channels for the Mega.

It works now (potentiometer control of the speed)?

NOTE WELL MY SIGNATURE.....

i can't varing ?

when i start the program i can't varing the duty cycle
can you give me what's the problems??

this my complet schematic but the problem the circuit is not working,
I use the circuit ir230 for offset .

can you give what is the problem ?

321.bmp (190 KB)

This "frequence" that you cannot control, is it the PWM frequency or the motor speed ?

To usefully control the motor speed, you need to vary the frequency of the sine wave you are generating, and you also need to vary the effective amplitude of the sinusoidal voltage that you are presenting to the motor, which you do by changing the duty cycle of the pwm.

Have you ever checked that the calculation of the long variable "frequency" in loop( ) actually works ?

You have an unnecessarily complicated equation with a long, an int, an int64 and a float in it.

Surely it would be a lot easier to just get a speed drive with a single phase supply. That would also include things like overcurrent and earth leakage protection.
Or is this partly about the challenge of making it yourself?

michinyon:
Have you ever checked that the calculation of the long variable "frequency" in loop( ) actually works ?

You have an unnecessarily complicated equation with a long, an int, an int64 and a float in it.

this is my problem i'm new in programmation , can you give how i can make it easy ?

michinyon:
This "frequence" that you cannot control, is it the PWM frequency or the motor speed ?

first i can't control PWM frequency , i like to generate frequency 12KHZ .

but i like to know how can i do it ?

adelo14:
this my complet schematic but the problem the circuit is not working,
I use the circuit ir230 for offset .

can you give what is the problem ?

Can you give more information?

You seem to have 10k resistors on the IGBT gates, that's way way way too high. Try 10 ohm
or just omit them (the driver chip has a few dozen ohms output resistance anyway).

You have the IGBTs remote from the driver chip, but that's really not a good idea, you
should have minimum capacitive coupling between each phase and to ground.

Can't read many of the parts on that image file, BTW. In particular what are the bootstrap
diodes? They have the entire bridge voltage across them and need to be suitably high
voltage rating and ultra-fast.

For testing start with a low voltage on the bus, you can vary this independently of power
for the rest of the circuit quite happily. Low voltage low power testing, then up the
voltage and check again, finally reaching final levels once you've safely tested at lower
levels - less likely to blow up your circuit.

MarkT:

adelo14:
this my complet schematic but the problem the circuit is not working,
I use the circuit ir230 for offset .

can you give what is the problem ?

Can you give more information?

You seem to have 10k resistors on the IGBT gates, that's way way way too high. Try 10 ohm
or just omit them (the driver chip has a few dozen ohms output resistance anyway).

You have the IGBTs remote from the driver chip, but that's really not a good idea, you
should have minimum capacitive coupling between each phase and to ground.

Can't read many of the parts on that image file, BTW. In particular what are the bootstrap
diodes? They have the entire bridge voltage across them and need to be suitably high
voltage rating and ultra-fast.

For testing start with a low voltage on the bus, you can vary this independently of power
for the rest of the circuit quite happily. Low voltage low power testing, then up the
voltage and check again, finally reaching final levels once you've safely tested at lower
levels - less likely to blow up your circuit.

for the resistors on the IGBT gates i change to 10 ohms .

for the bootstrap diodes
high voltage = 600v and ultra-fast.

but i think the problem first is the code !!!