# Three phase AC with frequency adjustment via a potentiometer in ADC Mode with PIC16F1937

#### jean120

Joined Jan 24, 2016
75
Hello everybody,I would like to control the frequency of my Three Phase DC-AC Inverter with the variable frequency so that the VFD can be implemented using PIC16F1937,I have the codes here in attachment I tried to implement the adc reading capability with interrupts but I am not coming at the stage where the frequency can be variable,I want it to be adjustable with the voltage at the output of the three phase DC-AC Inverter.Please could you help?so that the frequency and amplitude changes proportionally with my PIC here,I am using the IR21362 so that I need the output at P1A,P2A and P3A of the PIC which through the driver IR21362 gives the complete cycle (360degrees for each phase).

Codes
C:
#define NUMBER_OF_TABLE_ENTRIES_FOR_180_DEGREES 64
#define FACTOR_TO_GET_360_DEGREES

char i = 0;

unsigned int sin_table[64] = {125,137,149,161,173,184,194,204,
213,222,229,235,240,245,248,249,
250,249,248,245,240,235,229,222,
213,204,194,184,173,161,149,137,
125,113,101,89,77,66,56,46,
37,28,21,15,10,5,2,1,
0,1,2,5,10,15,21,28,
37,46,56,66,77,89,101,113
};

unsigned int TBL_POINTER_NEW[3], TBL_POINTER_OLD[3], TBL_POINTER_SHIFT[3], SET_FREQ = 0;
char DUTY_CYCLE[3];
//Timer2
//Prescaler 1:1; Postscaler 1:2; TMR2 Preload = 249; Actual Interrupt Time : 100 us
//Place/Copy this part in declaration section
void InitTimer2() {
T2CON = 0x0C;
PR2 = 249;
TMR2IE_bit = 1;
INTCON = 0xC0;
}

void interrupt()
{
if(TMR2IF_bit==1) {

TBL_POINTER_NEW[0] = TBL_POINTER_OLD[0] + SET_FREQ;
if (TBL_POINTER_NEW[0] < TBL_POINTER_OLD[0]) {
CCP1CON.P1M1 = ~CCP1CON.P1M1;
}
TBL_POINTER_SHIFT[0] = TBL_POINTER_NEW[0] >> 10;
DUTY_CYCLE[0] = TBL_POINTER_SHIFT[0]*value_adc;  //check this for multiplicity of value with read data from potentiometet
CCPR1L = sin_table[DUTY_CYCLE[0]];
TBL_POINTER_OLD[0] = TBL_POINTER_NEW[0];

// Phase2
TBL_POINTER_NEW[1] = TBL_POINTER_OLD[1] + SET_FREQ;
if (TBL_POINTER_NEW[1] < TBL_POINTER_OLD[1]){
CCP2CON.P2M1 = ~CCP2CON.P2M1;
}
TBL_POINTER_SHIFT[1] = TBL_POINTER_NEW[1] >> 10;
if((DUTY_CYCLE[1] + 42) < 64)DUTY_CYCLE[1] += 42;
else DUTY_CYCLE[1] -= 22;
CCPR2L = sin_table[DUTY_CYCLE[1]];
TBL_POINTER_OLD[1] = TBL_POINTER_NEW[1];
//Phase 3
TBL_POINTER_NEW[2] = TBL_POINTER_OLD[2] + SET_FREQ;
if (TBL_POINTER_NEW[2] < TBL_POINTER_OLD[2]) {
CCP3CON.P3M1 = ~CCP3CON.P3M1;
}
TBL_POINTER_SHIFT[2] = TBL_POINTER_NEW[2] >> 10;
if((DUTY_CYCLE[2] + 21) < 64)DUTY_CYCLE[2] += 21;
else DUTY_CYCLE[2] -= 43;
CCPR3L = sin_table[DUTY_CYCLE[2]];
TBL_POINTER_OLD[2] = TBL_POINTER_NEW[2];
TMR2IF_bit = 0;
}
}
{

{
}
}

void main() {

Delay_ms(2);
APFCON = 0x00;
delay_ms(2);
FVRCON = 0x00;
ANSELA =0X3F;
LATA=0X00;
CM1CON0 = 0x00;
CM2CON0 = 0x00;
TRISA = 0x01;
TRISB = 0xDF;
TRISC = 0xF9;
PORTB = 0x00;
PORTC = 0x00;
LATA = 0x00;
GIE_bit=1;
PEIE_bit=1;
//loop for cycles repeating
for(i = 0; i < 3; i++)
{
TBL_POINTER_SHIFT[I] = 0;
TBL_POINTER_NEW[I] = 0;
TBL_POINTER_OLD[I] = 0;
DUTY_CYCLE[I] = 0;
}
PWM1_Init(10000);
PWM2_Init(10000);
PWM3_Init(10000);

PWM1_Set_Duty(0);
PWM2_Set_Duty(0);
PWM3_Set_Duty(0);

PWM1_Start();
PWM2_Start();
PWM3_Start();
InitTimer2();
while(1)
{

SET_FREQ=171;

}
}

Thanks

Moderators note: please use code tags for pices of code

Last edited by a moderator:

#### dannyf

Joined Sep 13, 2015
2,197

For example, your code is poorly documented so that it is hard for others, as well as you, to follow....

There are a lot of things that you can do to help you identify where it is.

I would suggest the following:

1) can you generate a fixed frequency 3-phase signal?
2) can you adc a pot reliably?
3) can you combine the two together?

Forget about the fancy things you are trying to do for a moment. Learn to crawl before attempting to run.

#### jean120

Joined Jan 24, 2016
75
Hello,
1)I can generate a fixed frequency three phase signal
3)The problem comes on the combination of the two because here the values is read from the look up table and then multiplied with the ADC Value read from the potentiometer (variable resistor) and then the result is sent to the port for PWM parameters like duty cycle,etc.

Thanks

#### dannyf

Joined Sep 13, 2015
2,197
1)I can generate a fixed frequency three phase signal
OK. show us concurrently 3 waveforms generated by your code at 116.1Hz.

#### jean120

Joined Jan 24, 2016
75
Hello,see the image of what I got,with this simulated file the pic used was PIC16F1936.

#### jean120

Joined Jan 24, 2016
75

#### dannyf

Joined Sep 13, 2015
2,197
Maybe you can help others help you by posting the pictures here as well?

You will need to understand how the code works. It is a DDS algorithm. To change the output frequency, you will need to change its stepping, which the code is attempting to do in a convoluted way.

#### dannyf

Joined Sep 13, 2015
2,197
This may help get you going in the right direction.

5-ch pwm output implemented over a 16f1936, with variable frequency output, perfectly aligned. The code utilizes your sine table, as well.

The isr is as follows, in its entirety:

Code:
    if (TMR2IF) {
TMR2IF = 0;                            //clear the flag
//IO_FLP(LED_PORT, LED);                //flip the led - debugging only
_dds_phase+=_dds_step;                //increment the dds phase accumulator
_dds_index=_dds_phase >> 10;        //index is top 6 bits (2^6=64)
CCPR1L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm1
CCPR2L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm2
CCPR3L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm3
CCPR4L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm4
CCPR5L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm5
}
The right shift can be simplified too.

#### Attachments

• 63.7 KB Views: 3