PID Error not going to 0?!?!?

Can someone please tell me why my code is not allowing error to reach 0?

The precision is really good the loop works just error never goes to 0 even when I enable PWM if Error is not equal to 0

#include <stdio.h>

#define DIR 12;
#define PWM 3;
#define Error_MAX 30
#define Error_MIN -30

int Error, PreviousError, ActualPosition, SetPoint;
float Input, Output, Proportional, Integral, Derivative, Control;

float Kp = 1.2;
float Ki = 0.14;
float Kd = 0.00008;

void setup()
{
  Serial.begin(9600);
  pinMode(A5, INPUT);
  pinMode(A4, INPUT);
  pinMode(12, OUTPUT); 
  pinMode(3, OUTPUT);
}

void loop()
{
  SetPoint = analogRead(A4);
  ActualPosition = analogRead(A5);
  
  ActualPosition = map(ActualPosition, 84, 947, 0, 1023);

  Error = SetPoint - ActualPosition;
  Serial.print(Error);
  Serial.print("    ");
  
  Proportional = (float)Error*Kp;
  Integral = (Integral + (float)Error)*Ki;
  Derivative = ((float)Error - (float)PreviousError)*Kd;
  Control = (Proportional + Integral + Derivative);
 
  if(Control < 0)
  {
    Control *= -1;
  }

  if((Error > Error_MIN) && (Error < Error_MAX))
  {
    Control = 0;
  }

  if(Error > 0)
  {
    digitalWrite(12, HIGH); 
    analogWrite(3, Control);  
  }
  else
  {
    digitalWrite(12, LOW); 
    analogWrite(3, Control);
  }

  if(ActualPosition != SetPoint)
  {
    analogWrite(3, (Control*=5));
  }

  Error = PreviousError;
  
}

You are using ("reading") PreviousError twice in your code, but never set it's value. Are you sure, that is what you want to do?

At the end of the loop, you set Error to PreviousError, which was never initialised. So it could very possibly contain a random value.

lg, couka

Hi thanks for the reply, at the end of the loop I did this because I thought it was the right way to work out derivative, am I not initialising it in the derivative term?

Sedgell95:
am I not initialising it in the derivative term?

No, you are just using it to calculate a difference. Again, you never set the value of PreviousError.

lg, couka

I thought at the end of the loop if I set PreviousError to the value of Error it would remember the last error as variable PreviousError so when it goes into the loop again it stores that data and works out the new error adding to the PreviousError so it can know not to repeat the error. How can I do this? I feel like I am having a really dumb moment right now and I'm not seeing the obvious way of fixing this.

Regards,
Sam

You are not setting PreviousError to the value of Error.
You are setting Error to the value of PreviousError :wink:

lg, couka

thank you very much it works now haha! you have made my day thanks again

I'm happy to hear that :smiley:

Have fun!

lg, couka