Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

LFR with PID

Status
Not open for further replies.

koolguy

Active Member
Hi,

I am working on Line follower robot with two sensor connected with variable 20K making voltage divider. directly to ADC input ...it is working fine..
i want to add PID for gaining more speed and control...
so, this link tutorial for one sensors..
how to set offset and other const parameters?

Code:
Kp = 10                               ! Initialize our three variables
offset = 45
Tp = 50
Loop forever
   LightValue = read light sensor     ! what is the current light reading?
   error = LightValue - offset        ! calculate the error by subtracting the offset
   Turn = Kp * error                  ! the "P term", how much we want to change the motors' power
   powerA = Tp + Turn                 ! the power level for the A motor
   powerC = Tp - Turn                 ! the power level for the C motor
   MOTOR A direction=forward power=powerA ! issue the command with the new power level in a MOTOR block
   MOTOR C direction=forward power=powerC ! same for the other motor but using the other power level
end loop forever                      ! done with this loop, go back to the beginning and do it again
 
It would help a lot if you could tell how much do you know about PID control.. in general.
 
I would be fairly confident that I know the answer to that question. But I may be wrong.

Mike.

I know.. actually knowing the system would be more helpful. Ritesh, only way to design a PID controller (properly) is to know your system. If you do not have a mathematical model of your system, then you have to go for trial and error.. PID is well known and exhaustively studied control method, but in practice even most industrial controllers are poorly tuned (experimentally tuned to just barely meet the specs). Google around. There are so much material you can study.

Even if you had some good method how to tune the system, your algorithm might not be good enough to perform "tightly". There are so many ways to implement PID control.. and so many tricks to compensate for special cases.

At the end.. if the code you posted is OK. then you can get decent results just by experimenting. First increase the Proportional gain until the system is unstable.. then go back about 30% from that value. Then increase the derivative carefully.. keep the integral at small value.

http://bestune.50megs.com/typeABC.htm
http://www.youtube.com/user/ControlLectures/videos
https://www.electro-tech-online.com/custompdfs/2013/08/PID.pdf
https://www.electro-tech-online.com/custompdfs/2013/08/PID-without-a-PhD.pdf

EDIT:

Some reasons that the system is not performing well:
- PID is tuned wrong
- PID algorithm is poor (bad code)
- There is too much delay between sensor reading and PID control execution (too much lag)
- Too much noise in sensor reading (too low PID loop execution rate)
- The system is just too unlinear.. more sophisticated control is needed.
- etc. etc. etc.
 
Last edited:
here is the code...

Code:
#include <htc.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000


int ReadADC(unsigned char ch);
void main(void){
	ADCON0=0b01000001;//000 = channel 0, (RA0/AN0)
	ADCON1=0b10000000;
TRISC=0X00;
unsigned int b;


	int number;
	int number1;

	PR2 = 0b11111001 ;
	T2CON = 0b00000100 ;   
	CCP1CON = 0b00111100; 
CCP2CON = 0b00111100;                  
	PORTC = 0 ; 
	CCPR1L = 145 ;//pwm1 
	CCPR2L = 145 ; //pwm 2


__delay_ms(100);
RC4=1;//forward a
RC3=0;
RC0=0;//forward b
RC6=1;

__delay_ms(100);
RC4=0;
RC3=0;
RC0=0;
RC6=0;


while(1){
b = ReadADC(2);// compare value 
number = ReadADC(0);	 //sensor 1
number1 = ReadADC(1);// sensor 2

if(number<=b&&number1<=b){
	CCPR1L = 145 ;
	CCPR2L = 145 ; 
RC4=1;//forward a
RC3=0;
RC0=0;//forward b
RC6=1;
}
if(number>=b&&number1<=b){
	CCPR1L = 155 ;
	CCPR2L = 155 ;
RC4=0;//forward a
RC3=1;
RC0=0;//forward b
RC6=1;

}
if(number<=b&&number1>=b){
	CCPR1L = 155 ;
	CCPR2L = 155 ;
RC4=1;//forward a
RC3=0;
RC0=1;//forward b
RC6=0;

}
if(number>b&&number1>b){
	CCPR1L = 155 ;
	CCPR2L = 155 ;
RC4=0;//forward a
RC3=0;
RC0=0;//forward b
RC6=0;

}
 
}
}





int ReadADC(unsigned char ch)
	{
	int ret = 0;
	ADCON0 = 0b10000001 + (ch<<3);	// set channel to read
	__delay_ms(5);
	GO_DONE = 1;					// start conversion
   	while(GO_DONE);					// wait for conversion
   	ret =  (ADRESH & 0x3) << 8;		// get
   	ret +=	ADRESL;					// result
	return ret;

	}
 
In the above most link he is using one sensors....i.e. offset 45
light_number_line_2.gif

but i am using 2 sensors with black line on white the voltage is 0..2 to 0.5 and for black it is more than 2.8V (ranges is 0 to 5V) so, how should i calculate offset or just reading on black line?
 

Attachments

  • my.JPG
    my.JPG
    4.8 KB · Views: 185
Last edited:
so, how should i calculate offset or just reading on black line?

That is something that you just need to figure out yourself. Test, take measurements.. Nobody can tell you what your sensor reading will be from half way around the world. Buy a good test equipment and measure things! You can get an analog oscilloscope for 50 USD and then there is the PicKit (with 3-channel logic analyzer).. buy it!
 
I have written this for P controller...


Code:
#include <htc.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000


int ReadADC(unsigned char ch);
void main(void){
	ADCON0=0b01000001;//000 = channel 0, (RA0/AN0)
	ADCON1=0b10000000;
TRISC=0X00;
unsigned int b;


	int number;
	int number1;

	PR2 = 0b11111001 ;
	T2CON = 0b00000100 ;   
	CCP1CON = 0b00111100; 
CCP2CON = 0b00111100;                  
	PORTC = 0 ; 

int turnr,turnl,kp,tp,offsetr,offsetl,errorl,errorr;


while(1){
number = ReadADC(0);	//sensor 1
number1 = ReadADC(1);//sensor 2
kp = 1000;                             
offsetr = 1.67; //sensor average value on black and wwhite
offsetl = 1.57;                            
tp = 155;//random set pwm duty cycle

       
   errorr = number - offsetr;    
   errorl = number1 - offsetl;     
   turnr = kp * errorr;                     
   turnr = turnr/100 ;
   turnl = kp * errorl;                    
   turnl= turnl/100;
                       
   	CCPR1L = tp + turnr;  //pwm1 change                 
  	CCPR2L = tp - turnl;  //pwm1 change                        
   

if(number<=b&&number1<=b){
	 
RC4=1;//forward a
RC3=0;
RC0=0;//forward b
RC6=1;
}
if(number>=b&&number1<=b){

RC4=0;//forward a
RC3=1;
RC0=0;//forward b
RC6=1;

}
if(number<=b&&number1>=b){

RC4=1;//forward a
RC3=0;
RC0=1;//forward b
RC6=0;

}
if(number>b&&number1>b){
	
RC4=0;//forward a
RC3=0;
RC0=0;//forward b
RC6=0;

}
 
}
}





int ReadADC(unsigned char ch)
	{
	int ret = 0;
	ADCON0 = 0b10000001 + (ch<<3);	// set channel to read
	__delay_ms(5);
	GO_DONE = 1;					// start conversion
   	while(GO_DONE);					// wait for conversion
   	ret =  (ADRESH & 0x3) << 8;		// get
   	ret +=	ADRESL;					// result
	return ret;

	}

Code:
#include <htc.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000


int ReadADC(unsigned char ch);
void main(void){
	ADCON0=0b01000001;//000 = channel 0, (RA0/AN0)
	ADCON1=0b10000000;
TRISC=0X00;
unsigned int ch,b;


	int number;
	int number1;

	PR2 = 0b11111001 ;
	T2CON = 0b00000100 ;   
	CCP1CON = 0b00111100; 
CCP2CON = 0b00111100;                  
	PORTC = 0; 

 int turnr,turnl,kp,tp,offsetr,offsetl,errorl;
 int errorr,powerr,powerl;

RC4=1;//forward a
RC3=0;
RC0=0;//forward b
RC6=1;
__delay_ms(1000);
RC4=0;//forward a
RC3=0;
RC0=0;//forward b
RC6=0;

while(1){
number = ReadADC(0);	//sensor 1
number1 = ReadADC(1);//sensor 2
kp = 1000;                             
offsetr = 1.67; //sensor average value on black and wwhite
offsetl = 1.57;                            
tp = 105;//random set pwm duty cycle
      
   errorr = number - offsetr;    
   errorl = number1 - offsetl;     
   turnr = kp * errorr;                     
   turnr = turnr/100 ;
   turnl = kp * errorl;                    
   turnl= turnl/100;               
   powerl = tp + turnr;  //pwm1 change                 
  powerr = tp - turnl;  //pwm1 change  
CCPR2L =  powerl;  //pwm1 change                 
  	CCPR1L =powerr;  //pwm1 change                       
   if(powerl>0){
	

RC4=0;//forward a
RC3=1;
}
else{
powerl= powerl* (-1);
RC4=1;//forward a
RC3=0;
//RC0=0;//forward b
//RC6=1;}
}

   if(powerr>0){
	

RC0=0;//forward b
RC6=1;
}
else{
powerr= powerr* (-1);
RC0=1;//forward b
RC6=0;
//RC0=0;//forward b
//RC6=1;}
}
}
}
 
Last edited:
When you start reading and understanding your own code maybe I start reading your code too.. If that even is your own code.
 
Ritesh, you have posted 4 different sets of code.. which one are you actually using? And even if the code is ok, the problem might be in the hardware or the tuning of the controller.
 
Ok.. I read your code. I see that you do not fully understand how microcontrollers work. Your controller loop frequency is higher than your pwm frequency. That is a huge problem. Think about how fast the while-loop executes.. just think, once try thinking on your own.
 
Think about how fast the while-loop executes.. just think, once try thinking on your own.
AT 20Mhz 20mhz/4.....5Mhz


Code:
#include <htc.h>
__CONFIG(LVP_OFF & BOREN_OFF & PWRTE_ON & WDTE_OFF & FOSC_HS);
#define _XTAL_FREQ 20000000


int ReadADC(unsigned char ch);
void main(void){
	ADCON0=0b01000001;//000 = channel 0, (RA0/AN0)
	ADCON1=0b10000000;
TRISC=0X00;
unsigned int ch,b;


	int number;
	int number1;

	PR2 = 0b11111001 ;
	T2CON = 0b00000100 ;   
	CCP1CON = 0b00111100; 
CCP2CON = 0b00111100;                  
	PORTC = 0; 

 int turnr,turnl,kp,tp,offsetr,offsetl,errorl;
 int errorr,powerr,powerl;

RC4=1;//forward a
RC3=0;
RC0=0;//forward b
RC6=1;
__delay_ms(1000);
RC4=0;//forward a
RC3=0;
RC0=0;//forward b
RC6=0;

while(1){
number = ReadADC(0);	//sensor 1
number1 = ReadADC(1);//sensor 2
kp = 1000;                             
offsetr = 1.67; //sensor average value on black and wwhite
offsetl = 1.57;                            
tp = 105;//random set pwm duty cycle
      
   errorr = number - offsetr;    
   errorl = number1 - offsetl;     
   turnr = kp * errorr;                     
   turnr = turnr/100 ;
   turnl = kp * errorl;                    
   turnl= turnl/100;               
   powerl = tp + turnr;  //pwm1 change                 
  powerr = tp - turnl;  //pwm1 change  
CCPR2L =  powerl;  //pwm1 change                 
  	CCPR1L =powerr;  //pwm1 change                       
   if(powerl>0){
	

RC4=0;//forward a
RC3=1;
}
else{
powerl= powerl* (-1);
RC4=1;//forward a
RC3=0;
//RC0=0;//forward b
//RC6=1;}
}

   if(powerr>0){
	

RC0=0;//forward b
RC6=1;
}
else{
powerr= powerr* (-1);
RC0=1;//forward b
RC6=0;
//RC0=0;//forward b
//RC6=1;}
}
}
}
[/QUOTE]
 
AT 20Mhz 20mhz/4.....5Mhz

That is how fast single instructions are executed. How fast is your control algorithms update rate? (it is too fast)
 
It is hard to say what you should do without any measurements. Control systems engineering is all about measuring the system etc. You are working blind.
 
Status
Not open for further replies.

Latest threads

New Articles From Microcontroller Tips

Back
Top