PIC18f4431 PWM Generation

Discussion in 'Embedded Systems and Microcontrollers' started by bilal sheikh, Apr 4, 2015.

  1. bilal sheikh

    Thread Starter New Member

    Jan 21, 2015
    22
    0
    hello all, recently i am working on a project that is variable frequency drive. i have to control the speed of a single phase AC induction motor. inverter design which i am following in a full H-bridge circuit containing power mosfets. now i have to generate variable frequency PWM signles using MCU, for that purpose i am using pic18f4431. here is the result of simulation which i am also getting on hardware.
    Screenshot (46).png

    now, have a look at the 10ms delay, during which both the channels are off (which i cant bear when actually driving a motor). the 10ms delay is due to the fact that i am checking adc value every now and than to varry the frequency, if the user wants.
    any solutions ? so that i am unable to check the adc value as well as both the pwm channels operate without delay (continuesly) . comments are appreciated :)
     
  2. Papabravo

    Expert

    Feb 24, 2006
    10,163
    1,796
    Why did you code it that way?
    You should be able to write the code in such a way that the operation of the PWM signals is overlapped with the A2D conversion. It would help if you could post your code, and remember to use the code tags.
     
    bilal sheikh likes this.
  3. atferrari

    AAC Fanatic!

    Jan 6, 2004
    2,648
    764
    In that particular micro you have two peripherics that can generate PWM signals without compromising the micro in charge of more generic tasks.

    One is the same as in most micros of the 18F family and the other is oriented to power control. Maybe you could need this last. There is a vast list of options.

    Read the datasheet with that in mind.
     
    bilal sheikh likes this.
  4. Papabravo

    Expert

    Feb 24, 2006
    10,163
    1,796
    Please tell me that you did not write your code to "START CONVERSION" and then wait for the "END OF CONVERSION" flag in a tight loop with interrupts disabled.

    The proper way to do it is to START CONVERSION, then use an END of CONVERSION interrupt or periodically check the END OF CONVERSION flag, whil maintaining the PWM.
     
    Last edited: Apr 4, 2015
    bilal sheikh likes this.
  5. bilal sheikh

    Thread Starter New Member

    Jan 21, 2015
    22
    0
    sir, i am trying to obtain sine pwm using sine look up table. for each and every frequency, sine look up table is generated during runtime. my code is given. i have checked it on hardware, its not continuously running.

    Code (Text):
    1.  
    2. #include<p18f4431.h>
    3. #include <math.h>
    4. #pragma config LVP =OFF
    5. #pragma config WDTEN = OFF
    6. #pragma config OSC=HS
    7. #include <math.h>
    8. unsigned char p=0;
    9. unsigned char q=0;
    10. unsigned char r=0;
    11. unsigned char x=0;
    12. float f1=96.66;
    13. unsigned char sinee [64];
    14. float factor;
    15. float frequency,val,pr2;
    16. unsigned char sine [64]={0, 4, 8, 13, 17, 21, 25, 29, 33, 37, 41, 44, 48, 51, 55, 58, 61, 64, 66, 69, 72, 74, 76, 78, 79, 81, 82, 83, 84, 85, 86, 86, 86, 86, 86, 85, 84, 83, 82, 81, 79, 78, 76, 74, 72, 69, 66, 64, 61, 58, 55, 51, 48, 44, 41, 37, 33, 29, 25, 21, 17, 13, 8, 4};
    17. float factor;
    18. void deadtime (unsigned char d)               // function for dead time
    19. {
    20. unsigned char t=0;
    21. while(t<d)
    22.     {
    23.         t=t+1;
    24.     }
    25. }
    26. void pwm (void)
    27. {
    28. for( p=0; p<64; p=p+1)                        //loop for implementing look-up table, writing duty cycle value to CCPR1L register which is copied in CCPR1H on each interupt
    29.                                             //i.e when a match between TMR2 & PR2 occura
    30.         {
    31.             CCPR1L=sinee[p];
    32.             PIR1bits.TMR2IF=0;
    33.             while(PIR1bits.TMR2IF==0);                    //when interupt occurs TMR2IF bit sets to 1, showing that inerupt has occured
    34.         }
    35.         //CCPR1L=0;                           //after the above loop executed 64 times i.e for 10ms, square waves are inverted
    36.         //deadtime(50);                                  // insertion of dead time between two PWM channels
    37.  
    38.         for( q=0; q<64; q=q+1)                       //loop for implementing look-up table, writing duty cycle value to CCPR1L register which is copied in CCPR1H on each interupt
    39.         {                                     //i.e when a match between TMR2 & PR2 occur
    40.             CCPR2L=sinee[q];
    41.             PIR1bits.TMR2IF=0;
    42.             while(    PIR1bits.TMR2IF==0);
    43.     }
    44.  
    45. }
    46. void setup(void)                                //function for adc setup
    47. {
    48.  
    49.     //ADCON0bits.ACONV=1;               // contineous mode
    50.     ADCON0bits.ACONV=0;             // single shoot mode
    51.     ADCON0bits.ACSCH=0;      
    52.     ADCON0bits.ACMOD0=0;             //sequential mode
    53.     ADCON0bits.ACMOD1=0;
    54.     //ADCON0bits.ACMOD0=0;             //contineous mode single channel mode
    55.     //ADCON0bits.ACMOD1=0;
    56.     ADCON1bits.VCFG0=0;
    57.     ADCON1bits.VCFG1=0;
    58.     ADCON2bits.ADFM=0;             // left justified
    59.     ADCON2bits.ACQT0=1;               // aquction time=2*tad
    60.     ADCON2bits.ACQT1=0;
    61.     ADCON2bits.ACQT2=0;
    62.     ADCON2bits.ACQT3=0;
    63.     ADCON2bits.ADCS0=0;              // tad=32tosc
    64.     ADCON2bits.ADCS1=1;
    65.     ADCON2bits.ADCS2=0;
    66.     ADCHSbits.GASEL0=0;
    67.     ADCHSbits.GASEL1=0;
    68.     ANSEL0=1;
    69.  
    70.     TRISC=0x00;            //pwm setup
    71.     CCP1CON=0x00;                                    
    72.     CCP2CON=0x00;  
    73.     CCPR1L=0;
    74.     //    CCPR2L=0;                                  /                                
    75.     CCP1CON=0xC;
    76.     CCP2CON=0xC;  
    77.     T2CON=6;  
    78. }
    79. int ADCRead(unsigned char ch)
    80. {
    81.  
    82.     ADCON0bits.ADON=1;                 //switch on the adc module
    83.     ADCON0bits.GO=1;                 //Start conversion
    84.     while(ADCON0bits.GO);                 //wait for the conversion to finish
    85.     ADCON0bits.ADON=0;                 //switch off adc
    86.     frequency=0.1953125*ADRESH;             //0-5Volts of adc ----> 0---->50Hz output, using 8 MSB's of adc
    87.  
    88. pr2  =( 2456 *(pow(frequency,-1.002)))-0.888;         // period register calculation formula
    89.                                                          
    90.     factor=pr2/f1;                                  //contant factor that should be multiplied with basic sine lookup table to get the table for desired frequency
    91.     PR2=pr2;
    92.     for (r=0;r<64;r=r+1)
    93.       {
    94.           sinee[r]=factor*sine[r];
    95.  
    96.       }
    97. return PR2;
    98. }
    99.  
    100. void main()
    101. {
    102.     setup();  
    103.     ADCRead(0);
    104.     pwm();
    105.     deadtime(50000000);
    106.  
    107.  
    108. }
    109.  
    kindly help if u can.

    Moderators note : Please use code tags for pieces of code
     
    Last edited by a moderator: Apr 5, 2015
  6. Papabravo

    Expert

    Feb 24, 2006
    10,163
    1,796
    It is as I feared. Each of your processes has what is called "busy waiting" in it.
    1. while(ADCON0bits.GO); //wait for the conversion to finish
    2. t=t+1;
    3. while( PIR1bits.TMR2IF==0);
    You need to stop doing things this way.

    Also, Why are you calling setup each time around the main() loop?

    The smart way to do things is to start the various processes and do them all in parallel. Do the high priority tasks first and the low priority tasks last. Your deadtime routine is ridiculous, you don't know for certain how long it takes except by empirical measurement and that is no way to to do things.

    Code (Text):
    1.  
    2. main()
    3. {
    4.   setup()
    5.   while(1)
    6.   {
    7.     if(ADCON0bits.GO == 0) processConversion() ;
    8.     if(deadTime) processDeadtimeIncrement() ;
    9.     else nextSineWaveSection() ;
    10.   }
    11. }
    12.  
    Of course you will need to work out the details. The main principle is:
    Never create an infinite loop with a single exit condition.
     
    bilal sheikh likes this.
Loading...