CCS C Software and Maintenance Offers
FAQFAQ   FAQForum Help   FAQOfficial CCS Support   SearchSearch  RegisterRegister 

ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

CCS does not monitor this forum on a regular basis.

Please do not post bug reports on this forum. Send them to CCS Technical Support

pid motor

 
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion
View previous topic :: View next topic  
Author Message
nasbyc



Joined: 27 Apr 2009
Posts: 50

View user's profile Send private message AIM Address

pid motor
PostPosted: Fri Aug 19, 2011 9:20 am     Reply with quote

Hi I try to control dc motor angle with pot (single turn) as my feedback. I used l293d to control the direction of the motor. I have been testing this pid for a month, however up until now still couldn't move it to the desired angle without having high overshoot and long settling time. I post my code here, because not quite sure either its my pid or pwm setting might be wrong.
Code:

#include <16f877a.h>
#device adc = 10
#use delay(clock=20000000)
#fuses hs,noprotect,nowdt,nolvp
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, parity=N)

void MotorFish_CW(); void MotorFish_CCW(); void MotorFish_Stop ();

void main ()
{

   set_tris_b(0b11100001); //
   setup_port_a(ALL_ANALOG);
   //setup_adc(ADC_CLOCK_INTERNAL);
   setup_adc(ADC_CLOCK_DIV_32);
   setup_ccp1(CCP_PWM);
   setup_ccp2(CCP_PWM);
   setup_timer_2(T2_DIV_BY_4, 250, 1); //Frequency = 5kHz
 
   set_adc_channel(0);
   delay_us(10);
   
   int16  P_Error = 0;
   int16 Prev_Error = 0;
   int16 Acc_Error = 0;
   int16 I_Error,D_Error;

   int8 P = 160;
   int8 I = 3;
   int8 D = 7;
   int16 Desired_Angle,Theta_out;
   signed int32 U_Signal;
   int Motor_Status;
   signed int32 numeric_val;
   
   byte mystat=0;
   char mydata;
   
   Desired_Angle = 527; //approx 8 degree
   
   MotorFish_Stop();
   
   for(;;)
   {
     
      if(kbhit())
      {   mydata=getch();
          mystat=1;}
         
      if(mystat==1)
      {
         P_Error = 0;
         Acc_Error = 0;
         
         if(mydata=='a'||mydata=='A')
         {
             Desired_Angle = 512;
         }
         if(mydata=='b'||mydata=='B')
         {
             Desired_Angle = 527;
         }
         if(mydata=='c'||mydata=='C')
         {
             Desired_Angle = 487;
         }

         mystat=0;
       }
       
      Theta_out = read_adc();
      if(Theta_out>= 731)
      {
         MotorFish_Stop();
      }
      printf("Desired_Angle:%Ld and Theta_out:%Ld\n", Desired_Angle,Theta_out);
      delay_ms(33);

      //I_Error = Acc_Error + P_Error;
      P_Error = Desired_Angle - Theta_out;
     
      if (abs(P_Error) <= 3)
      {
         P_Error = 0;
         Acc_Error = 0;
      }
         
      I_Error = Acc_Error + P_Error;
      D_Error = (P_Error - Prev_Error);
     
      U_Signal = P_Error*P + I_Error*I + D_Error*D;
     
      numeric_val = U_Signal & 0x7FFF;
      if (U_Signal & 0x8000)
         U_Signal = -32768 + numeric_val;
         
     
      if(U_Signal > 0)
      {
         Motor_Status = 0;
      }
      else if(U_Signal < 0)
      {
         Motor_Status = 1;
      }
      else
         MotorFish_Stop();

      Prev_Error = P_Error;
      Acc_Error = Acc_Error + P_Error;
     
      if(U_Signal > 32767)
      {
         U_Signal = 32767;
      }

      else if(U_Signal < -32767)
      {
         U_Signal = 32767;
      }
     
      U_Signal = U_Signal*((float)1023/32767);
      U_Signal = abs(U_Signal);
     
      if(Motor_Status == 0)
      {
         MotorFish_CW();
         set_pwm2_duty(U_Signal);
      }
      else if(Motor_Status == 1)
      {
         MotorFish_CCW();
         set_pwm2_duty(U_Signal);
      }     
   }
}

void MotorFish_CW()
{
   output_low(PIN_B1);
   output_high(PIN_B2);
}

void MotorFish_CCW()
{
   output_high(PIN_B1);
   output_low(PIN_B2);
}

void MotorFish_Stop()
{
   output_low(PIN_B1);
   output_low(PIN_B2);
}
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Fri Aug 19, 2011 11:46 am     Reply with quote

PID systems have to be 'tuned' based upon 'what happens when these commands' are issued. In the good old days this meant a lot of trial and error, recording of data, testing, etc. Nowadays you could use Matlab (or other software' to get a good 'feel' for the numbers.
You might 'google' PID calculators or something like that for help.
My experience lies in PID with DC motors (servo systems) that send voltages to the motor not PWM signals. Good old school stuff with LM12CLK power op amps.
John P



Joined: 17 Sep 2003
Posts: 331

View user's profile Send private message

PostPosted: Fri Aug 19, 2011 4:03 pm     Reply with quote

I wonder if you'll get anywhere doing this in integer math, though one hates to force the processor to do floating point. But I don't think it can be done any other way. Try looking up PIC PID in Google and you might get some ideas. I think getting the derivative term (velocity) from a pot might be a big problem too.
SherpaDoug



Joined: 07 Sep 2003
Posts: 1640
Location: Cape Cod Mass USA

View user's profile Send private message

PostPosted: Fri Aug 19, 2011 7:24 pm     Reply with quote

Properly scaled 16 bit ints should be fine. If people do FFTs with ints on PICs, doing PID should be easy. Using floats may lead to lag problems from the computation time.
_________________
The search for better is endless. Instead simply find very good and get the job done.
nasbyc



Joined: 27 Apr 2009
Posts: 50

View user's profile Send private message AIM Address

PostPosted: Mon Aug 22, 2011 5:08 am     Reply with quote

I already simulate it using matlab and obtained the desired output, the problem are the values for P , I , D are in float. Whenever I tried to change the int to float, it produces an error in calculation and the duty cycle just set to the max which is 255.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 22, 2011 5:34 am     Reply with quote

You've got Usignal declared as a signed 32 integer.._+ and - values)

signed int32 U_Signal;

and the PICs PWM module only needs an 8 or 16 bit integer(uses only 10 bits though).

Somewhere 'in the math' you need to 'cast' the proper values.
I suggest doing the math by hand (or on a PC) to see what the correct numbers should be, then write a small program to have the PIC display the results. Say full right, 1/2 right, center, half 1/2 left, full left. This should show you where your original math went wrong.

Been there done that !!
nasbyc



Joined: 27 Apr 2009
Posts: 50

View user's profile Send private message AIM Address

PostPosted: Mon Aug 22, 2011 6:07 am     Reply with quote

Temtronic, what do you mean by cast the proper values?. Is it means that I have to put for example input scale factor to be multiply to my proportional, integral and derivative term.
FvM



Joined: 27 Aug 2008
Posts: 2337
Location: Germany

View user's profile Send private message

PostPosted: Mon Aug 22, 2011 6:42 am     Reply with quote

In most cases, a PID can work with 16 bit signed integer. The trick is to aplly suitable scaling. A 16*16 multiply results in a 32 bit number that has to be reduced to 16 bit appying suitable truncation with saturation.
temtronic



Joined: 01 Jul 2010
Posts: 9229
Location: Greensville,Ontario

View user's profile Send private message

PostPosted: Mon Aug 22, 2011 7:05 am     Reply with quote

Casting is C's way of converting variables from one type to another.
Variables can be bits, bytes, words, double words (1,8,16,32 bits wide).
Depending on the 'math' or other operation performed, the results of using 'mixed' sized variables can be a disaster!

That's why it's important to 'try the math' with known values BEFORE you run a servo plant ! Just have the PIC display the numbers and compare to what you KNOW they should be.

also...

Check the onscreen CCS C compiler help (press F11) and look for 'variable types' or similar wording.

You should also 'Google' for a 'C for dummies' type book or reference to better understand C. Like every high level language it has it's quirks.
Display posts from previous:   
Post new topic   Reply to topic    CCS Forum Index -> General CCS C Discussion All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2005 phpBB Group