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

I have problem with the PI or PID code.

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



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

I have problem with the PI or PID code.
PostPosted: Wed Dec 02, 2015 1:02 pm     Reply with quote

I have problem with the PI or PID code.

Facts:
250W DC engine controlled at the moment with a PWM controller without loop/feedback. Now I have installed an encoder. All is running without the loop! I can measure the RMP and control the engine with the PWM from 500-4500 RPM. So the hardware and software is prepared to the next step, the PI or PID code.

Problem:
Implement of the PI or PID code.
The RPM is from 500-4500. Let say the PWM steering value is between (int16 )200 to 475.
I have looked and read but can’t understand how to make the implementation?
There are a SetValue and a measured EncoderValue when they are equal all is nice.

Hints
newguy



Joined: 24 Jun 2004
Posts: 1909

View user's profile Send private message

PostPosted: Wed Dec 02, 2015 2:53 pm     Reply with quote

I'd suggest you read "PID Without A PhD" by Tim Wescott: http://www.embedded.com/design/prototyping-and-development/4211211/PID-without-a-PhD.
hmmpic



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

PostPosted: Wed Dec 02, 2015 3:54 pm     Reply with quote

OK I think i solved my confusing, it was understanding of the scaling values for the PID so it return a matching value for my PWM output.
hmmpic



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 11:21 am     Reply with quote

NOPE, i cant find the logic in the scaling.

My return signal is measured from the encoder end it return about 6000us and 53000us for the engine. That will say, fast rpm short signal return. It was the most simple way just to read the signal return time...

My PWM accept a value from 1 (150 is the motor lowest running duty) to 475 (99% duty).

Now I have to scale it but I can't, I'm confused. I don't know the relationship between the Duty and the RPM on the engine. The engine is _not_ linear to the PWM....

Maybe it's me there confusing it because I miss something in my brain, or think too much in the wrong direction?

I need some help on this.
temtronic



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

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 11:36 am     Reply with quote

One way is to run the PWM from 150 to 475 in say increments of 5 and record what the RPM of the motor is. Be sure to run for 5 to 10 seconds at each PWM level to get a solid RPM reading.
From those readings (about 66 of them) you should be able to analyze the algorithm of PWM vs RPM. These days you can just dump them into eXcel or MATLAB and have that program 'reverse engineer' the algorithm.



Jay
hmmpic



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 12:38 pm     Reply with quote

yes, but is it important on a PI (D) system? It is all these considerations and thoughts I have and therefore I stalled?
Mike Walne



Joined: 19 Feb 2004
Posts: 1785
Location: Boston Spa UK

View user's profile Send private message

PostPosted: Thu Dec 03, 2015 3:40 pm     Reply with quote

OK. You've been given several pointers.

What tests have you actually performed on your real hardware?
What were the results of those tests?
Or are you spending all your time just thinking about it?

Mike
Ttelmah



Joined: 11 Mar 2010
Posts: 19552

View user's profile Send private message

PostPosted: Fri Dec 04, 2015 4:07 am     Reply with quote

You need also to understand the three parts of PID.

'P'. Proportional. Basically it sets the ratio between the requested 'output', and what is delivered to generate this. Getting this close to right helps reduce the need for the other terms. A simple 'trigger' controller on a drill or something, will only have a 'P' term. It'll slow down if loaded, but does mean that f you pull the trigger half way, the motor spins at close to half it's full speed rate.

'I'. Integral. This integrates _errors_ between what is requested, and what is actually being generated. If the motor runs slower than expected, it is this that applies the extra boost to bring the speed back. Allows the system to cope with extra power needed for extra load, and improves the ability to change speed as load changes, but at the risk that with sudden changes things can overshoot.

'D'. Differential (or derivative). This looks at the rates of change. If the output is _already moving in the requires direction_, this 'backs off' the adjustment being applied. It is this that tries to 'trap' the overshoot that sudden changes can produce. The faster the device is moving towards the desired target, the more this is applied.

Tuning a PID should be done in multiple stages. You generate a P term, by working out what rate is needed typically for the minimum load, for a given required power, and calculate the factor for this. Then you apply load, and generate an I term, that can apply the extra power needed to compensate for this. Then you try changing position quickly and see how much overshoot results, and calculate a D term for this. If the D is too high, everything will work well, but responses will be a little slow. Too small, and there will tend to be overshoot when the requested position is changed quickly. I term too small, and the motor will tend not to compensate as load increases. Too large, and it'll tend to 'hunt', overcorrecting each way.
hmmpic



Joined: 09 Mar 2010
Posts: 314
Location: Denmark

View user's profile Send private message

PostPosted: Sat Dec 05, 2015 11:23 am     Reply with quote

Thanks the help on this.

It is now running well, therefore I post my solution for other there maybe can use it, or this discussion on it.

The project is to implement a PID system on a DC motor. I use a “Hall sw” to detect the speed. It return 4 impulses/rpm. Not much but the system is running well. It is feed to ex_int_0. The measurement is done with a free running timer there are read in the interrupt on every L-H pulses.
The setpoint is made with a potentiometer connected to one AD converter and scaled for min/max pulses matching the return signal.
The control system use PWM in my case 16,7kzh with a duty cycle from >0 – 99.
In my main loop there are a time scheduler to control the read of the setpoint every 100ms, and check for stalling motor every 500ms.
The measurement task is called in the main loop, but is under control or in sync with the return impulses. On every new impulse it set a bit there mean, we have new samples and can now do the PID, and there after update the PWM. Updating of the PWM is done in sync with the already running PWN.
I post here some of the code for other. If my code or my logic is wrong, I hope someone will post correction.

Read feedback puls:
Code:

#int_ext
void EXT0_isr(){
//int on encoder. timer1 count every 4us.
 static int16 t1old=0;
 int16 t1;

 output_high(P_LED1);
 
 t1=get_timer1();
 PID.WorkPoint=t1-t1old;
 t1old=t1;
 PID.WorkPointIsNew=1;
 PID.StallBit=1;
 output_low(P_LED1);
}


Code for scaling the setpoint:
Code:

void CalcSetSpeed(){
 const int8 MaxAD=250;//must be float! Max value from AD
 int16 Speed;
 
 PID.ADBit=read_adc()&~0x01;
 
 if (PID.ADBit>MaxAD){PID.ADBit=MaxAD;}
 Speed=PID.MinRPMuS-(PID.ADBit*((float)(PID.MinRPMuS-PID.MaxRPMuS)/MaxAD));
 
 if (PID.SetPoint!=Speed){
  PID.SetIsNew=1;
  PID.SetPoint=Speed;
 }
}   


PID code:
Code:

signed int16 PIDDo(int16 SetPoint, int16 ActualPoint){
 const int8 kp=8;
 const int8 ki=100;
 const int8 kd=25;
 
 static signed int32 iState=0;
 static signed int16 dState=0;
 
 signed int16 error;
 signed int16 pTerm,iTerm,dTerm;
 
 error = (signed int16)ActualPoint-SetPoint;
 
 pTerm = error / kp;
 
 iState = error + iState;
 if (iState > 50000) {iState = 50000;} else if (iState < -50000) {iState = -50000;}
 iTerm = iState / ki;
 
 dTerm = (ActualPoint - dState) / kd;
 dState = ActualPoint;
 
 return (pTerm + iTerm - dTerm);
}



PWM update:
Code:

void UpdatePWM(signed int16 PWM){
 output_high(P_LED3);
 
 if (PWM>PID.DutyMax) PWM=PID.DutyMax; else
 if (PWM<PID.DutyMin) PWM=PID.DutyMin;
 
 clear_interrupt(INT_TIMER2);//clear and wait for a new start pwm puls some us..
 while (!interrupt_active(INT_TIMER2)){;}//wait
 
 set_pwm1_duty(PWM);
 
 output_low(P_LED3);
}


Main regulation code:
Code:

void DoReg(){
 int16 setp,workp;
 signed int16 PWM;
 
 if (!Control.RegON) {return;}
 if (!PID.WorkPointIsNew) {return;}//only when there are new input
 PID.WorkPointIsNew=0;
 output_high(P_LED2);

 Disable_interrupts(Int_EXT);//encoder
 
 setp=PID.SetPoint;
 workp=PID.WorkPoint;
 
 enable_interrupts(Int_EXT);
 
 PWM=PIDDo(setp,workp);
 
 UpdatePWM(PWM);
 
 output_low(P_LED2);
}


Some of the main code:
Code:

while (1){
   
  DoReg();
 
  if (!timer.ms100){
   CalcSetSpeed();
   timer.ms100=tReload.ms100;
  }
 
  if (!timer.ms500){
   ChkStall();
   timer.ms500=tReload.ms500;
 }


Picture of the PID timing:
http://s000.tinyupload.com/?file_id=54358656248910856983

***

CCS forum link:
http://www.ccsinfo.com/forum/viewtopic.php?p=151009
http://www.ccsinfo.com/forum/viewtopic.php?t=53610&highlight=pid
http://www.ccsinfo.com/forum/viewtopic.php?t=47389&highlight=pid

PID theory:
http://www.embedded.com/electronics-blogs/spectra/4402378/The-Control-Loop
http://www.embedded.com/design/prototyping-and-development/4211211/PID-without-a-PhD
http://stackoverflow.com/questions/14614124/how-do-i-use-a-pid-controller

Microchip has some real good application notes:
AN964A: http://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en021807
AN718A: http://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en011730
AN937A: http://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en020434

Some nice person has already posted detail explanation on the PID system and link to theory on it.
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