Please let us in the comment zone any suggestions that you think will improve the article!
If you like the article click the follow button to stay in touch with us!
In an older post i have explained how to generate a sine wave with arduino or atmega 328 and now let’s try to generate a two phase signals.
From an arduino uno with this method we can obtain only two sine signals. Ok now you can say that this device has 6 pwm pins and why can obtain only two signals, but one timer which controls 2 pins(more exactly timer 1 pin 9 and 10) is used to manage interrupts.
So for sine waves we have pins 5 and 6 and pins 11 and 3(timer 0 and timer 2).
Let’s say that we want those two signals to have an 120 degrees phase shift like in the three phase AC energetical systems.
But how we know where are those 120 degrees because we use an lookup table.
The lookup table used in the previous post with only one signal is for an half dutycycle(one positive and one negative) and it has 314 elements.
In the image below you see what i want to say:
If for 180 degrees we have 314 elements for 120 degrees we have 209 pulses, so the second signal must start when the first is at 209 pulse.
In time, the second signal must start after 6.66 miliseconds after the first signal.
To mantain the program as simple as we can we use only one lookup table and two variables (i and j) one for a signal and one for the other.
In the interrupt the first signal start and when “i” reach position 209 in the lookup table we must start the second wave.
We have four PWM pins 3, 5, 6 and 11.
To generate the signals correct we must work in pairs with these pins, for example OCR0A in pair with OCR2A and OCR0B with OCR2B, OCR0A and OCR2A(OCR0A=pin 6, OCR2A=pin 11) for positive half duty cycle and OCR0B(OCR0B=5, OCR2B=3) and OCR2B for negative half duty cycle.
If we do not respect these associations the signals will not be as we want, because after the positive half duty cycle of the first signal must start the positive duty cycle of the second signal.
Now, below is the program for this project and some images:
int i=0;
int j=0;
int x=0;
int y=0;
int OK=0;
int OK1=0;
int OK2=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(5, OUTPUT);
pinMode(6,OUTPUT);
pinMode(3,OUTPUT);
pinMode(11,OUTPUT);
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
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 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 6
i=0;// go to first value of vector
OK=1;//enable pin 5
}
if(i>313 && OK==1){// final value from vector for pin 5
i=0;//go to first value of vector
OK=0;//enable pin 6
}
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 5 0
OCR0A=x;//enable pin 6 to corresponding duty cycle
}
if(OK==1){
OCR0A=0;//make pin 6 0
OCR0B=x;//enable pin 5 to corresponding duty cycle
}
if ((i==209) || OK1==1){// the first signal has reached to position 209
//in the lookup table
OK1=1;// to maintain if function valid
if(j>313 && OK2==0){// final value from vector for pin 11
j=0;// go to first value of vector
OK2=1;//enable pin 3
}
if(j>313 && OK2==1){// final value from vector for pin 3
j=0;//go to first value of vector
OK2=0;//enable pin 11
}
y=sinPWM[j];// x 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 3 0
OCR2A=y;//enable pin 11 to corresponding duty cycle
}
if(OK2==1){
OCR2A=0;//make pin 11 0
OCR2B=y;//enable pin 3 to corresponding duty cycle
}
}
}
void loop() {
}
After you read the code i must say that as you can see the if function when the i==209 , when the second signal must start is executed only once because i==209, after that OK1 became 1 and the program run almost as the if function it doesn’t exist.
So not every time when the first signal reach the position 209 in the lookup table the second signal is controlled from that if when i==209, just only once.
Next let’s see some picture from the scope, but first in the image bellow is how i connect some resistors and some polyester capacitors to obtain a low pass filter, but only for the positive half duty cycle(the low pass filter is between pin and gnd).
Now on the scope as i say before it will appear only positive half duty cycle:
Those vertical white lines is the time interval between signal 1 and signal 2, and it is 6.640 ms and that is a good result.
Now if i measure signal from pin 3 and i will invert it the result is:
In this case the time interval is 16.64ms exact as it should because we have more 10 ms from the positive half duty cycle.