EasyC and PID

Is it possible to do PID control using EasyC?

Yes
(10 char)

Jpearman:
I am trying to get my more advanced team to learn PID and what it is about. There are a few guides out there, but I did not see much on PID with EasyC. i am having to learn it myself.
Any suggestions?
Thanks

The only difference between implementing PID control with EasyC and RobotC/PROS/ConVEX is that EasyC does not support multitasking with threads. This makes running a PID loop while running a driver control/autonomous routine a little bit trickier.

It is easily possible to create a user function that takes an input (encoder/pot value), runs the PID loop, and outputs a new motor value. The only difficult thing to do is to keep it running at regular intervals while not interrupting other code. This is where multitasking comes in with other programming environments. The easiest way to do this in EasyC is with timers. All you have to do is create a timer and check its value with an if statement in your while loop. If the timer is above a certain value (20ms is generally good), call your PID function and assign its output to your motors. Reset the timer and in 20ms it will run the loop again.

If you want to run the PID loop in autonomous, things get a little bit more difficult. Typically, EasyC autonomous routines are executed as a series of motor commands with delays. The delays completely halt the processor. For a PID loop to execute, you need to move the autonomous code into a while loop. Instead of stopping the processor when delaying, use a timer to check the amount of time elapsed since the previous autonomous action. When that amount of time has passed, execute the next action. You can use another timer to continuously run the PID loop at constant intervals.

Thanks 4256. That makes sense. We wanted to do an antonymous routine. It is a lot to consider for sure.

PID as a concept is not hard, there are plenty of guides as you said and you can always start with a P controller and then add in the additional terms when you have that working. The difference between a P controller and a PID controller is not very much, two more multiplies and an addition to the equation that calculates the motor drive value.

There are several ways to implement PID in EasyC.

  1. Use the built in functions if you have an IME, take a look at the function block “PID Control”, you define the PID constants and then start PID control of a particular motor.

  2. Call the PID calculation in your main while loop. As 4256 explained in the previous post you can use a timer (see Timer block under program flow) to run the calculation at a more or less constant rate.

  3. Use what’s known as a repeating timer. This is some easyc functionality that’s not well know of, a repeating timer can be used to run a small amount of code at a constant rate in the background. This is a little like being able to use multi tasking but you have to be very careful what type of code you run in this way, for example, never use Wait or printtoscreen.

The easiest way to use a repeating timer is to also create a new source file into which you can type your own code. It is possible to do this with block programming, but it a good opportunity to start typing in real C code. Here is a small example of how to do this (which I have not tested) for a P controller.

// PidControl.c : implementation file
#include "Main.h"

// Variable to hold target
static  int targetPosition = 0;

// The P controller constant
#define Kp  0.33

void PidInitController()
{
    // get the current value of the pot
    targetPosition = GetAnalogInput ( 1 );

    // Start the controller
    RegisterRepeatingTimer( 20, PidController );

}

// Set the target position
void PidSetTarget( int value )
{
    targetPosition = value;
}

// A repeating timer function that is called every 20mS
void PidController()
{
    int potValue;
    int error;
    int drive;

    // Get the potentiometer value
    potValue = GetAnalogInput ( 1 ) ; 

    // Calculate error as difference between a target position
    // and the actual position
    error = targetPosition - potValue;

    // P controller, calculate motor drive
    drive = Kp * error;

    // Clip to legal values
    if( drive >  127 ) drive =  127;
    if( drive < -127 ) drive = -127;

    // Finally, send to the motor
    SetMotor ( 1 , drive ) ; 
}

I created a new source file (right click on Source files in the program explorer) and entered the code above. Then you need to add what are know as prototypes to the file UserInclude.h. A prototype explains to the compiler how a function should be called. So add these to that file.


// UserInclude.h : header file
#ifndef USERINCLUDE_H_
#define USERINCLUDE_H_

void PidInitController( void );
void PidSetTarget( int value );
void PidController( void );

#endif // USERINCLUDE_H_

Then in Autonomous you can call “PidInitController” to set the initial target position and start the repeating timer.

#include "Main.h"

void Autonomous ( unsigned long ulTime )
{
    PidInitController();
    PidSetTarget( 1000 );
    // Do something else, drive, whatever 
}

You can use “C Code” blocks to enter those calls.

So I hope this helps. It seems there are questions about PID almost everyday at the moment so I think I will have to create and post an example project sometime in the next few days.

I was not aware this feature existed in EasyC. It will definitely be MUCH easier to use than what I was talking about, especially for autonomous.