Could anyone help me with my first go at PID control code? I'm not certain of what I'm doing

// Just wanting to see any massive errors in my math or logic that anyone can point out (there are //likely many as it does not balance itself amazingly right now.)
//Project consists of a motor and IMU on a seesaw with a potentiometer on a base to control the //setpoint. Motor max thrust = 2000. Motor off = 1000.
// apologies for how this is formatted as this is my firs time posting here
// Thanks for any help you can give :)

#include <Arduino_LSM9DS1.h> // IMU library
#include <Servo.h>

#define IMU_MIDPOINT 0 
#define IMU_MIN -0.86  
#define IMU_MAX 0.79   

#define DT 0.001  // delta t in seconds

#define Kp 3000   // Proportional coefficient 100
#define Ki 0    // Integral coefficient  40
#define Kd 0    // Derivative coefficient 5

#define fmap(value, oldmin, oldmax, newmin, newmax) (((value) - (oldmin)) * ((newmax) - (newmin)) / ((oldmax) - (oldmin)) + (newmin)) // allows for mapping of decimals

Servo esc;

float previous_error = 0;
float integral = 0;

void setup() 

{
                                                            
  esc.attach(8); //Specify the esc signal pin, D8   
  
  esc.writeMicroseconds(1000);  //                      Arms ESC
  delay(3000);
  


  Serial.begin(9600); 
  
  if (!IMU.begin()) {                                                                                                                  
    Serial.println("Failed to initialize IMU!");

  }


//  Serial.println("X");
//  Serial.println("setpoint");      
//  Serial.println("final_output");

}

void loop()                                                                                          

{ 

  unsigned long my_time = millis(); 
  float x, y, z;
  float setpoint = analogRead(A0); 
  float setpointDecimal = fmap(analogRead(A0), 0, 1023, -0.86f, 0.79f);  


  if (IMU.accelerationAvailable()) {
    IMU.readAcceleration(x, y, z);      

  }

  //PID BIT

  constrain(x, -0.86, 0.79); 

  float error = setpointDecimal - x;
  integral = integral + error*DT;
  float derivative = (error - previous_error)/DT;
  float output = (Kp*error + Ki*integral + Kd*derivative);           
  previous_error = error;

  float final_output = 0;

//  if (x > 0){
//    final_output = abs(output);       
//  }

  if (x < IMU_MIN){
    esc.writeMicroseconds(1000);
  }
  if (x > IMU_MAX){
    esc.writeMicroseconds(1000);
  }


  final_output = abs(output);
  Serial.println(final_output);
  esc.writeMicroseconds(final_output);





  Serial.print(setpointDecimal); 
  Serial.print(",");                        
  Serial.print(x);
  Serial.print(",");
  Serial.println(final_output/1000);
//  Serial.println(output);


// notes for limits of IMU angle 
// IMU HIGH = 0.79
// IMU LOW = -0.86

// Difference = -1.65


}

Hi @anon47459339 ,

welcome to the arduino-forum.
Well done posting code as a code-section.

You should unload work from the shoulders of your potential helpers. I mean that part of the work that you can do easily or even exclusivle yyou yourself.

This is: a detailed description of your project. It will become much miuch easier for your potential helpers if you explain your project. Otherwise your potential helpers have to solve multiple riddles from reading your code.

additionally google is always worth a 5 minute search.

https://www.google.de/search?q=arduino+strategy+for+adjusting+P+I+D+values+of+a+PID-controller

best regards Stefan

EDIT 12.11.22 21:41
@anon47459339

deleting posts is against "good habits" of the Arduino-Forum. It makes the following-up posts look "strange"
So for the convenience of other users
your initial post was restored and the thread locked

[/quote]

My problem is in the maths annd logic may not be correct, not adjusting the PID values as the post says, so a google would not do much for me here.

explicitly post your best attempt to do the math.
Write it down on a sheet of paper take a picture of it and post the pciture

For posting multiple postings in a short time and for posting pictures , the new member has to get to Discourse trust level one on the forum, which is a pretty trivial matter:

Get to trust level 1 by…

  • reading at least 5 topics
  • Reading at least 30 posts
  • Spend a total of 10 minutes reading posts

and/or add specific questions about the calculation.
Without a project-description you are asking for

"can anybody write-down a 5 pages tutorial about PID-controlling after analysing my code what I want to control?"

Don't you think this is wayyy too demanding?

So please describe
what are you trying to control?
what is the exact thing you have trouble with calculating it?

best regards Stefan

Often I post to reddit and it seems it's not too much for them. I'll go there. Thanks for the tips.

my expectattion is if you post on reddit the answer wil be similar to this one

What are good strategies for tuning PID loops?

1

A question targeted at a more specific question would be more useful. Otherwise, you should just look at the PID article, with a section on tuning

ronalchn

Oct 26, 2012 at 21:07

  • 2

I've always found tuning PIDs to be very dependent on the characteristics of the system, which is why I've never found auto-tune systems to be terribly useful. They are fine for a first pass, low performance set of parameters, but they are far from optimal, and you will have the same problem with any general strategy which is not optimised for the mechanical, electrical and control aspects of a given system.

best regards Stefan

I've already posted and it's yielded more constructive comments (every little helps)

Again tuning the PID is not the issue here (I think)

No bad feelings :slight_smile:

would you mind sharing it and post the link?
I'm very interested about the answers that you find constructive.
Maybe I can learn from it how to answer in a different way
best regards Stefan

I would but I like to keep my accounts separate to each other to prevent mean spirited people following me to other places.

If you sort the arduino subreddits by new you might see it (if you do pls just PM me, rather than linking back 2 here because of what I said above, thanks!

  • They're just general improvements in my code (I did also source some places where I have taken chunks of code from others there, so you're missing that bit of info)

  • Issue of using G's as a measurement then constraining it instead of working out angle properly

  • Noise

  • Friction

  • Filtering on both the pot and the sensor

  • Maybe some flawed mapping logic as past the setpoint the number would be wrong for motor power

When I've tested them I'll post them here if you want :smiley:

You set DT to 0.001.
But there is no timer to get a reading every 0.001 seconds...
Loop time will determine your delta t now.
Loop may be too slow due to all Serial prints...

Thanks! How would I go about fixing this?

  while(millis() - my_time < DT*1000);
}

Right at the bottom of the code?

:slight_smile:

I guess you would need micros(). But I cannot know the unit of DT...
And you need to set my_time to micros() after waiting...

your style of writing code is incompatible to my style so I'm out

Thanks for letting me know. I'll delete the post.

Deletions by OP reverted and topic locked.