Go Down

Topic: 3 PWM for 3 phase inventer (Read 30894 times) previous topic - next topic

MarkT

#30
May 09, 2014, 01:46 pm Last Edit: May 09, 2014, 01:50 pm by MarkT Reason: 1
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())
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

adelo14


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"

MarkT

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?
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

adelo14

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

adelo14

how i can update the frequency continuously in loop?

adelo14

#35
May 10, 2014, 05:52 pm Last Edit: May 10, 2014, 05:58 pm by adelo14 Reason: 1
you can give me exemple  how i can update the frequency continuously in loop ?

adelo14

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

ghost123

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 ?
Code: [Select]

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

AWOL

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.
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

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.

adelo14


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 .

Code: [Select]
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));

}
}
}




adelo14

#41
May 11, 2014, 11:28 pm Last Edit: May 11, 2014, 11:30 pm by adelo14 Reason: 1
Code: [Select]
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 .

MarkT


how i can update the frequency continuously in loop?


By not deliberately delaying?

ie
Code: [Select]
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:
Code: [Select]
void loop()
{
 long frequency = twoTo32 * analogRead(POTEN_IN) / refclk; // calulate DDS new tuning word
 noInterrupts () ;
 tword_m = frequency ; // copy quickly with interrupts masked
 interrupts () ;
}
[ I will NOT respond to personal messages, I WILL delete them, use the forum please ]

adelo14



how i can update the frequency continuously in loop?


By not deliberately delaying?

ie
Code: [Select]
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:
Code: [Select]
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 ?

MarkT

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 will NOT respond to personal messages, I WILL delete them, use the forum please ]

Go Up