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

Discussion in 'Embedded Systems and Microcontrollers' started by jean120, Apr 19, 2016.

  1. jean120

    Thread Starter Member

    Jan 24, 2016
    75
    1
    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
    Code (C):
    1.  
    2. #define NUMBER_OF_TABLE_ENTRIES_FOR_180_DEGREES 64
    3. #define FACTOR_TO_GET_360_DEGREES
    4.  
    5. char i = 0;
    6. double value_adc;
    7.  
    8. unsigned int sin_table[64] = {125,137,149,161,173,184,194,204,
    9.                               213,222,229,235,240,245,248,249,
    10.                               250,249,248,245,240,235,229,222,
    11.                               213,204,194,184,173,161,149,137,
    12.                               125,113,101,89,77,66,56,46,
    13.                               37,28,21,15,10,5,2,1,
    14.                               0,1,2,5,10,15,21,28,
    15.                               37,46,56,66,77,89,101,113
    16.                              };
    17.  
    18. unsigned int TBL_POINTER_NEW[3], TBL_POINTER_OLD[3], TBL_POINTER_SHIFT[3], SET_FREQ = 0;
    19. unsigned int ADC_VAL = 0, PREV_ADC_VAL = 0;
    20. char DUTY_CYCLE[3];
    21. //Timer2
    22. //Prescaler 1:1; Postscaler 1:2; TMR2 Preload = 249; Actual Interrupt Time : 100 us
    23. //Place/Copy this part in declaration section
    24. void InitTimer2() {
    25.     T2CON = 0x0C;
    26.     PR2 = 249;
    27.     TMR2IE_bit = 1;
    28.     INTCON = 0xC0;
    29. }
    30.  
    31. void interrupt()
    32.                 {
    33.     if(TMR2IF_bit==1) {
    34.  
    35.         TBL_POINTER_NEW[0] = TBL_POINTER_OLD[0] + SET_FREQ;
    36.         if (TBL_POINTER_NEW[0] < TBL_POINTER_OLD[0]) {
    37.            CCP1CON.P1M1 = ~CCP1CON.P1M1;
    38.         }
    39.         TBL_POINTER_SHIFT[0] = TBL_POINTER_NEW[0] >> 10;
    40.         DUTY_CYCLE[0] = TBL_POINTER_SHIFT[0]*value_adc;  //check this for multiplicity of value with read data from potentiometet
    41.         CCPR1L = sin_table[DUTY_CYCLE[0]];
    42.         TBL_POINTER_OLD[0] = TBL_POINTER_NEW[0];
    43.      
    44.        // Phase2
    45.         TBL_POINTER_NEW[1] = TBL_POINTER_OLD[1] + SET_FREQ;
    46.         if (TBL_POINTER_NEW[1] < TBL_POINTER_OLD[1]){
    47.            CCP2CON.P2M1 = ~CCP2CON.P2M1;
    48.         }
    49.         TBL_POINTER_SHIFT[1] = TBL_POINTER_NEW[1] >> 10;
    50.         DUTY_CYCLE[1] = TBL_POINTER_SHIFT[1]*value_adc;
    51.         if((DUTY_CYCLE[1] + 42) < 64)DUTY_CYCLE[1] += 42;
    52.         else DUTY_CYCLE[1] -= 22;
    53.         CCPR2L = sin_table[DUTY_CYCLE[1]];
    54.         TBL_POINTER_OLD[1] = TBL_POINTER_NEW[1];
    55.         //Phase 3
    56.          TBL_POINTER_NEW[2] = TBL_POINTER_OLD[2] + SET_FREQ;
    57.         if (TBL_POINTER_NEW[2] < TBL_POINTER_OLD[2]) {
    58.            CCP3CON.P3M1 = ~CCP3CON.P3M1;
    59.         }
    60.         TBL_POINTER_SHIFT[2] = TBL_POINTER_NEW[2] >> 10;
    61.         DUTY_CYCLE[2] = TBL_POINTER_SHIFT[2]*value_adc;
    62.         if((DUTY_CYCLE[2] + 21) < 64)DUTY_CYCLE[2] += 21;
    63.         else DUTY_CYCLE[2] -= 43;
    64.         CCPR3L = sin_table[DUTY_CYCLE[2]];
    65.         TBL_POINTER_OLD[2] = TBL_POINTER_NEW[2];
    66.         TMR2IF_bit = 0;
    67.     }
    68. }
    69.      //Interrupt for ADC Value recording  ,reading the
    70.      void interrupt_ADC()
    71.           {
    72.    
    73.       if(ADIF_bit==1)
    74.       {
    75.       value_adc=ADRESH;
    76.       //value_adc=ADRESL;
    77.       ADIF_bit=0;
    78.       }
    79.            }
    80.  
    81. void main() {
    82.  
    83.     Delay_ms(2);
    84.      APFCON = 0x00;
    85.      ADCON1 = 0X20;
    86.      ADCON0=0X19;
    87.      delay_ms(2);
    88.      ADCON0.GO=1;
    89.      FVRCON = 0x00;
    90.      ANSELA =0X3F;
    91.      LATA=0X00;
    92.      CM1CON0 = 0x00;
    93.      CM2CON0 = 0x00;
    94.      TRISA = 0x01;
    95.      TRISB = 0xDF;
    96.      TRISC = 0xF9;
    97.      PORTB = 0x00;
    98.      PORTC = 0x00;
    99.      LATA = 0x00;
    100.     //Initiailization ADC reading modules
    101.      ADIF_bit=0;
    102.      while(ADIF==0)
    103.      ADIF_bit=0;
    104.      ADIE_bIT=1;
    105.      GIE_bit=1;
    106.      PEIE_bit=1;
    107.      ADC_Init();
    108.      //loop for cycles repeating
    109.      for(i = 0; i < 3; i++)
    110.             {
    111.          TBL_POINTER_SHIFT[I] = 0;
    112.          TBL_POINTER_NEW[I] = 0;
    113.          TBL_POINTER_OLD[I] = 0;
    114.          DUTY_CYCLE[I] = 0;
    115.              }
    116.      PWM1_Init(10000);
    117.      PWM2_Init(10000);
    118.      PWM3_Init(10000);
    119.  
    120.      PWM1_Set_Duty(0);
    121.      PWM2_Set_Duty(0);
    122.      PWM3_Set_Duty(0);
    123.  
    124.      PWM1_Start();
    125.      PWM2_Start();
    126.      PWM3_Start();
    127.      InitTimer2();
    128.      while(1)
    129.               {
    130.    
    131.               ADC_VAL=value_adc;
    132.               SET_FREQ=171;
    133.  
    134.           }
    135.      }
    136.  

    Thanks

    Moderators note: please use code tags for pices of code
     
    Last edited by a moderator: Apr 19, 2016
  2. dannyf

    Well-Known Member

    Sep 13, 2015
    1,768
    357
    you have made it very difficult for others to help you.

    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.
     
  3. jean120

    Thread Starter Member

    Jan 24, 2016
    75
    1
    Hello,
    1)I can generate a fixed frequency three phase signal
    2)I can make an A/D reading reliably of an analog input 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.

    Please help.

    Thanks
     
  4. dannyf

    Well-Known Member

    Sep 13, 2015
    1,768
    357
    OK. show us concurrently 3 waveforms generated by your code at 116.1Hz.
     
  5. jean120

    Thread Starter Member

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

    Please help.
     
  6. jean120

    Thread Starter Member

    Jan 24, 2016
    75
    1
    Hello,find the link here showing the waveform of that three phase signal with PIC on which I want the potentiomter to act upon.
    Find the linkhttp://www.edaboard.com/thread353448.html#post1511962
     
  7. dannyf

    Well-Known Member

    Sep 13, 2015
    1,768
    357
    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.

    Fix that and we can talk about your adc.
     
  8. dannyf

    Well-Known Member

    Sep 13, 2015
    1,768
    357
    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 (Text):
    1.  
    2.     if (TMR2IF) {
    3.         TMR2IF = 0;                            //clear the flag
    4.         //IO_FLP(LED_PORT, LED);                //flip the led - debugging only
    5.         _dds_phase+=_dds_step;                //increment the dds phase accumulator
    6.         _dds_index=_dds_phase >> 10;        //index is top 6 bits (2^6=64)
    7.         CCPR1L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm1
    8.         CCPR2L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm2
    9.         CCPR3L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm3
    10.         CCPR4L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm4
    11.         CCPR5L = dc_table[(_dds_index+=PWM_STEP*1/5) & 0b00111111];        //update pwm5
    12.     }
    13.  
    14.  
    The right shift can be simplified too.
     
  9. jean120

    Thread Starter Member

    Jan 24, 2016
    75
    1
    Dear dannyf,could you please upload the complete codes?I think it could be better if you make the codes for giving 3 half wave sine signals each 0-180degres,because I have a MOSFET Driver IR21362 which need 3 signals and internally it inverse each for getting a complete signal of 0-360 degrees.And also with the above posted codes no A/D with potentiometer which seems to be very difficult for me.

    With the DDS algorithm how will the stepping be changed?

    Thank you very much.
     
Loading...