Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

[PIC] Need expert advice for PIC project...

Status
Not open for further replies.

biswaIITH

Full Member level 4
Full Member level 4
Joined
Aug 23, 2014
Messages
205
Helped
27
Reputation
54
Reaction score
28
Trophy points
1,308
Location
Hyderabad
Activity points
2,923
hello friends ..i am using pic 16F876A for controlling the output voltage of a buck converter with a 11.0592 MHz crystal oscillator. Below is the code i am using for it


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*unsigned int adc;*/
int T=227;
int err_val=0,I_err=0;
int current_duty_2=10;
int Emax=6810,Emin=-6810;
int Kp=22,Ki=4;
int P_term=0,I_term=0;
int Sum_err=0;
unsigned int ADCRead(unsigned char channel)
{
 unsigned char l_byte, h_byte;
 unsigned ADR;
 ADCON0 = 0x81 | (channel << 3);
 delay_us(40);
 ADCON0.F2 = 1;
  while(ADCON0.F2);
   l_byte = ADRESL;
   h_byte = ADRESH;
   ADR = ((h_byte <<8)|l_byte);
   return (ADR);
}
 
void main(void)
{
  unsigned int Ch0,Ch1;
  TRISA = 0xFF;
  ADCON0 = 0x81;
  ADCON1 = 0xC0;
  TRISC.F1=0;
  PWM2_Init(20000);
  PWM2_Start();
  PWM2_Set_Duty(current_duty_2);
 
  while(1)
  {
    Ch0= ADCRead(0);
    Ch1= ADCRead(1);
    err_val=Ch1-Ch0;
    P_term=(Kp*err_val)/T^2;
    I_err=I_err+err_val;
  if(I_err>Emax)
    I_err=Emax;
  else if(I_err<Emin)
    I_err=Emin;
    I_term=(Ki*I_err)/T^2;
  if(I_term>255)
    I_term=255;
  else if(I_term<-255)
    I_term=-255;
    Sum_err=(P_term+I_term);
  if(Sum_err>255)
    Sum_err=255;
  else if(Sum_err<0)
    Sum_err=0;
    current_duty_2=Sum_err;
    PWM2_Set_Duty(current_duty_2);
}
}

The input of the buck converter is 17 v .I have given reference load voltage as 12 v. I am feeding 4 v (which i got after using a voltage divider)through channel 1 and feed-backing the load voltage through channel 0 of pic as explained in the code.But i am not getting the result.The output voltage i am getting is 10 instead of 12(desired):-(.

is it because of inaccurate Kp and Ki values????

and one more problem
When i am varying the input voltage (in range 4-5v ),i am getting an around .7-1 v variations in the output load voltage.

Plzz someone answer
 
Last edited by a moderator:

The first thing that leaps at me in your code is the line:

P_term=(Kp*err_val)/T^2;

You've initialised T with a very large value (227) that when squared yields 51529 - which is outside the range of values representable in the (I presume) 16-bit signed integers used in your program. You'll need to make T smaller...

The integer division performed on the same line is also computationally expensive - and unnecessary - since you're simply scaling (Kp*err_val) by a design-time constant. You can replace it with a single multiplication, or absorb the constant into the value of Kp.

Kp and Ki represent the proportional and integral (respectively) gain values of the PI voltage control system. Their values will need to be adjusted depending upon your sampling rate and system dynamics/parameters such as switching frequency, output filter capacitor size etc. Once you've got your control loop functional, you'll probably want to optimise the values for best load regulation and step response. While this certainly isn't impossible in the fixed point architecture you've adopted [indeed, a fixed point implementation is a good final goal] - it can be markedly more difficult to prototype in fixed point arithmetic due to precision/overflow considerations. If your CPU has sufficient speed/idle time, it might be worthwhile getting it all to run initially with a floating point implementation, and converting the design back to fixed point at the end.

Good luck!
 
Thanks for your reply, sir!!!!

As you had suggested, i made some adjustments
below is d code


Code C - [expand]
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
/*unsigned int adc;*/
int T=56;
int err_val=0,I_err=0;
int current_duty_2=10;
int Emax=255,Emin=-255;
int Kp=5,Ki=45;
int P_term=0,I_term=0;
int Sum_err=0;
unsigned int ADCRead(unsigned char channel)
{
 unsigned char l_byte, h_byte;
 unsigned ADR;
 ADCON0 = 0x81 | (channel << 3);
 delay_us(40);
 ADCON0.F2 = 1;
  while(ADCON0.F2);
   l_byte = ADRESL;
   h_byte = ADRESH;
   ADR = h_byte;                    ( I am using only upper 8bits of the ADC result and the result is left justified)
   return (ADR);
}
 
void main(void)
{
  unsigned int Ch0,Ch1;
  TRISA = 0xFF;
  ADCON0 = 0x81;
  ADCON1 = 0x40;
  TRISC.F1=0;
  PWM2_Init(20000);
  PWM2_Start();
  PWM2_Set_Duty(current_duty_2);
 
  while(1)
  {
    Ch0= ADCRead(0);
    Ch1= ADCRead(1);
    err_val=Ch1-Ch0;
    P_term=(Kp*err_val)/T;
    I_err=I_err+err_val;
  if(I_err>Emax)
    I_err=Emax;
  else if(I_err<Emin)
    I_err=Emin;
    I_term=(Ki*I_err)/T;
  if(I_term>255)
    I_term=255;
  else if(I_term<-255)
    I_term=-255;
    Sum_err=(P_term+I_term);
  if(Sum_err>255)
    Sum_err=255;
  else if(Sum_err<0)
    Sum_err=0;
    current_duty_2=Sum_err;
    PWM2_Set_Duty(current_duty_2);
}
}



For the used values of Kp and Ki i am getting arnd 12 as desired. But when i am varying the input dc voltage(manually) the output is also varying in somewhat lesser proportions.

Now the implication is i am going to used the above code for controlling output voltage of a PFC rectifier(AC-DC rectifier followed by a dc-dc converter). I am going to control the output voltage of the second stage dc-dc converter and the input to the dc-dc converter is not constant anymore in this case.It is rather rectified ac.
 
Last edited by a moderator:

The mcu that you are using is fixed point type , so you should use Q15 format for scaling, it will give better results ,
coming to the hardware section , what is the load that you have connected at the output during observations?
 
I have connected 300 ohm as load during my observation.

Plz explain something about Q15 format ...i am not aware of it..and how scaling affect the performance???
 

Let me explain you how scaling effect the performance .assume that you have to control the speed of the dc motor and value of duty cycle register vary from say 0 to 255 . 0 corresponds to 0% duty and 255 corresponds to 100% duty cycle. Now your processor is fixed point so you can only control the motor by 256 levels but if i say multiply the duty cycle by a large no. Say 100 , now the duty cycle range is from 0 to 25500 .now you can see that controling resolution has incresed ..so this was the funda behind scaling ..although in real case the duty cycle register will hold the unscaled value.however the same concept is implented in the intermediate stage of the pid control...
N search q15 in google u'll get loads of results...
 

ok i will search in the net about this.But tell me one more thing what is the maximum switching frequency should we go for while doing closed loop using pic16f876a...i am planning to operate the pic at 50 KHz .But will it affect the performance of micro.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top