PID RPM Control

So much to sift through here, Was hoping some one can point me in the correct direction.
I have a motor that I am controlling with a controller/driver by sending I2C command with speed setting. I also have an encoder/halleffect that I am reading with my Arduino to get pulses/period or RPM. I need to hold the RPM at a specific point. I have written some code that is NOT pid and can sometimes work well and sometimes get unruly.

currently what I am doing is this an know it can be much better with PID

if (rpm < (target - 6)) {
        targetsetpoint = (targetsetpoint + 5);
        jrk.setTarget(targetsetpoint);
        }
     else if (rpm < (target - 1 )) {
        targetsetpoint = (targetsetpoint + 1);
        jrk.setTarget(targetsetpoint);
        }        
     else if (rpm > target + 6) {
        targetsetpoint = (targetsetpoint - 5);
        jrk.setTarget(targetsetpoint);

        }   

      else if (rpm > target - 1) {
        targetsetpoint = (targetsetpoint - 1);
        jrk.setTarget(targetsetpoint);

        }

I have attached a graph of the current state without the PID.

What I don't know or understand is how to set up the PID
The input would be the RPM
the Setpoint would be the target
the Output would be the targetsetpoint (the output to the controller?)

Not even sure I have that right,
Any help would be greatly appreciated.

NoPid.PNG

Sounds right - you have to decide how often to update the PID and set the output (hint too slow and stability will be a big problem). Setting the P I and D terms is then trial and error, start with just P and dial it up until oscillation, back-off a bit. Then you can add I (usually only a little), adjusting P down to regain stability, until the steady state error is eliminated. D can be used to increase response rate to changes, but if the RPM reading isn't high quality you might just add noise.

I would like to state that the reason for needing the PID is not that the load on the motor will be changing but the voltage to the motor may be different each time it is used. For example. I am spinning something with the motor that is constant. it will not change. When I connect 12V to the motor, I can find the happy value to send to the controller that will spin the motor at the desired (never to change) RPM. But when I connect 24V to the motor, the speed is no longer correct. there fore I must adjust the value sent to the controller. This is the case with the AC-DC power supplies that I am currently using. so then in the event of battery use and drain, I need to maintain RPM right up to the end of the battery life. Hope I am explaining this well

Frictional losses are seldom constant, so you load may vary somewhat anyhow, and the friction inside a motor itself tends to vary (reduce) as it warms up.

This is the PIDBasic example file (is there a better PID lib to use?)

#include <PID_v1.h>

#define PIN_INPUT 0
#define PIN_OUTPUT 3

//Define Variables we'll be connecting to
double Setpoint, Input, Output;

//Specify the links and initial tuning parameters
double Kp=2, Ki=5, Kd=1;
PID myPID(&Input, &Output, &Setpoint, Kp, Ki, Kd, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Input = analogRead(PIN_INPUT);
  Setpoint = 100;

  //turn the PID on
  myPID.SetMode(AUTOMATIC);
}

void loop()
{
  Input = analogRead(PIN_INPUT);
  myPID.Compute();
  analogWrite(PIN_OUTPUT, Output);
}

In this example they are reading an analog pin.. PID'ing it and outputting on another pin.

Will this work for my situation?
Input is the RPM
Output is the targetsetoint?

Where do you set the period for the PID? Its vital that that is constant and a suitable rate for the system.

MarkT:
Where do you set the period for the PID? Its vital that that is constant and a suitable rate for the system.

The OP isn’t setting the update interval so it is the default 100ms used in the default constructor.

To change it, call the available member function:

    void SetSampleTime(int);              // * sets the frequency, in Milliseconds, with which 
                                          //   the PID calculation is performed.  default is 100

100ms is way to large, 1ms is a good starting point for motor control.