user51466: I've been trying to simulate a PID using Brett Beauregard's PID library in order to understand it better. Here is my code.
#include <PID_v1.h>

const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
void setup()

{
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  Serial.begin(115200);
  Setpoint = 300;
  myPID.SetOutputLimits(-2,2);
  myPID.SetSampleTime(100);
  Input = random(292, 302) ;
}

void loop()
{
  if (i % 2 == 0) {
  Input += random(-2,3);
  }
  angle += 1 % 360;
  Input += sin(angle*355/(113*180));
  myPID.Compute();
  Input += Output;
    analogVals[i] = Input;
    i++;
    if (i>= numReadings)
    {
      for (int j = 0; j < i; j++) {
      Serial.println(analogVals[j]);
      } 

      i = 0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }
}

Even if I restrict the output of the PID to a very small value, I get huge nonsense results of this code. It oscillates like -1000 to 1000. I've read this https://robotics.stackexchange.com/questions/167/what-are-good-strategies-for-tuning-pid-loops 
and tried to adjust my parameters, but they're just shots in the dark really, I can't even damp these massive oscillations. How would I tune a PID to cancel out a sin error ? 
Thanks in advance

user54511: I do not have your PID_v1.h, but I made a simple experiment trying to control your example with a simple P-Controller instead of the PID lib. I made the following changes to your code:
...
double K_P = 1;
... 
//myPID.Compute();
  Output = K_P*(Setpoint - Input);
  Input += Output;

This is working for very small amounts of K_P, but as soon as K_P gets higher than 2.0 it gets instable very fast. I guess this is what you are observing. The reason for me is, that you have implemented a ideal control path. In real control tasks you will always have some transfer behavior
Therefore I added a simple PT1 element (first-order lag element) to your code, now your system is much more stable and you can experiment with the K, I and D factors. Here it works with K_P even higher than 400:
// #include <PID_v1.h>

const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
double Input_PT1;
double K_P = 20;
//Specify the links and initial tuning parameters
//PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
void setup()

{
  //turn the PID on
  // myPID.SetMode(AUTOMATIC);
  Serial.begin(115200);
  Setpoint = 300;
  // myPID.SetOutputLimits(-2,2);
  //myPID.SetSampleTime(100);
  Input = random(292, 302) ;
}

void loop()
{
  if (i % 2 == 0) {
    Input += random(-2, 3);
  }
  angle += 1 % 360;
  Input += sin(angle * 355 / (113 * 180));
  //myPID.Compute();
  Output = K_P * (Setpoint - Input_PT1);
  Input += Output;
  // start PT1
  Input_PT1 -= Input_PT1 / 25;
  Input_PT1 += Input / 25;
  // end PT1
  analogVals[i] = Input_PT1;
  i++;
  if (i >= numReadings)
  {
    for (int j = 0; j < i; j++) {
      Serial.println(analogVals[j]);
    }

    i = 0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
}

Some hint: 

The sketch above does not initialize Input_PT1, so it takes some secondes until you reach a steady value of 300, if you do not want to wait, just initialize Input_PT1 with 300. But this is exactly where you can start increasing first I, then D factors to try to increase speed for reaching a steady value of 300 and experiencing what influence I and D part will have.
Input_PT1 is not a good naming, since this is the output of the PT1 element, but since you are using it as the PID Input, I did not change.

Here a drawing of what I implemented in contrast to your sketch (at least I hope so ;-))


51466: <p>I've been trying to simulate a PID using <a href="https://github.com/br3ttb/Arduino-PID-Library/" rel="nofollow noreferrer">Brett Beauregard's PID library</a> in order to understand it better. Here is my code.</p>

<pre class="lang-cpp prettyprint-override"><code>#include &lt;PID_v1.h&gt;

const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&amp;Input, &amp;Output, &amp;Setpoint,2,5,1, DIRECT);
void setup()

{
  //turn the PID on
  myPID.SetMode(AUTOMATIC);
  Serial.begin(115200);
  Setpoint = 300;
  myPID.SetOutputLimits(-2,2);
  myPID.SetSampleTime(100);
  Input = random(292, 302) ;
}

void loop()
{
  if (i % 2 == 0) {
  Input += random(-2,3);
  }
  angle += 1 % 360;
  Input += sin(angle*355/(113*180));
  myPID.Compute();
  Input += Output;
    analogVals[i] = Input;
    i++;
    if (i&gt;= numReadings)
    {
      for (int j = 0; j &lt; i; j++) {
      Serial.println(analogVals[j]);
      } 

      i = 0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
    }
}
</code></pre>

<p>Even if I restrict the output of the PID to a very small value, I get huge nonsense results of this code. It oscillates like -1000 to 1000. I've read this <a href="https://robotics.stackexchange.com/questions/167/what-are-good-strategies-for-tuning-pid-loops">https://robotics.stackexchange.com/questions/167/what-are-good-strategies-for-tuning-pid-loops</a> 
and tried to adjust my parameters, but they're just shots in the dark really, I can't even damp these massive oscillations. How would I tune a PID to cancel out a sin error ? </p>

<p>Thanks in advance</p>
 54511: <p>I do not have your PID_v1.h, but I made a simple experiment trying to control your example with a simple P-Controller instead of the PID lib. I made the following changes to your code:</p>

<pre><code>...
double K_P = 1;
... 
//myPID.Compute();
  Output = K_P*(Setpoint - Input);
  Input += Output;
</code></pre>

<p>This is working for very small amounts of <code>K_P</code>, but as soon as <code>K_P</code> gets higher than 2.0 it gets instable very fast. I guess this is what you are observing. The reason for me is, that you have implemented a ideal control path. In real control tasks you will always have some transfer behavior</p>

<p>Therefore I added a simple PT1 element (first-order lag element) to your code, now your system is much more stable and you can experiment with the K, I and D factors. Here it works with K_P even higher than 400:</p>

<pre><code>// #include &lt;PID_v1.h&gt;

const unsigned int numReadings = 500;
double analogVals[numReadings];
unsigned int i = 0;
int angle = 0;
//Define Variables we'll be connecting to
double Setpoint, Input, Output;
double Input_PT1;
double K_P = 20;
//Specify the links and initial tuning parameters
//PID myPID(&amp;Input, &amp;Output, &amp;Setpoint,2,5,1, DIRECT);
void setup()

{
  //turn the PID on
  // myPID.SetMode(AUTOMATIC);
  Serial.begin(115200);
  Setpoint = 300;
  // myPID.SetOutputLimits(-2,2);
  //myPID.SetSampleTime(100);
  Input = random(292, 302) ;
}

void loop()
{
  if (i % 2 == 0) {
    Input += random(-2, 3);
  }
  angle += 1 % 360;
  Input += sin(angle * 355 / (113 * 180));
  //myPID.Compute();
  Output = K_P * (Setpoint - Input_PT1);
  Input += Output;
  // start PT1
  Input_PT1 -= Input_PT1 / 25;
  Input_PT1 += Input / 25;
  // end PT1
  analogVals[i] = Input_PT1;
  i++;
  if (i &gt;= numReadings)
  {
    for (int j = 0; j &lt; i; j++) {
      Serial.println(analogVals[j]);
    }

    i = 0; //reset to beginning of array, so you don't try to save readings outside of the bounds of the array
  }
}
</code></pre>

<p>Some hint: </p>

<ul>
<li>The sketch above does not initialize <code>Input_PT1</code>, so it takes some secondes until you reach a steady value of 300, if you do not want to wait, just initialize <code>Input_PT1</code> with 300. But this is exactly where you can start increasing first I, then D factors to try to increase speed for reaching a steady value of 300 and experiencing what influence I and D part will have.</li>
<li><code>Input_PT1</code> is not a good naming, since this is the output of the PT1 element, but since you are using it as the PID Input, I did not change.</li>
</ul>

<p>Here a drawing of what I implemented in contrast to your sketch (at least I hope so ;-))</p>

<p><a href="https://i.stack.imgur.com/3Mbhv.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/3Mbhv.png" alt="enter image description here"></a></p>
