user14515: I am making a system of regulation of the temperature using PID.
I want to keep my temperature in 37 celsius.
in order to understand the stability of my system easily, I want to see the fuction of temperature in terms of time. 
I found a function pulseIn() who Read a pulse (either HIGH or LOW) on a pin. 
But I don't know how to do it into my program. 
this is the program of my PID system: 
#include <PID_v1.h>
#include "math.h" 
int c=0;
int  i=0, output2 = 0, output3 = 0; 
double val=0.0;
double val2 = 0.0;
//Define Variables we'll be connecting to
double Setpoint, Input, Input2, Output=0;
double tOnMax = 50.0;

//Specify the links and initial tuning parameters
PID myPID( &Input, &Output, &Setpoint,10,20,20, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Setpoint = 37; //temperature a reguler 

  //turn the PID on
  pinMode(9, OUTPUT);
  myPID.SetOutputLimits(-100, 100);
  myPID.SetMode(AUTOMATIC);
  Serial.begin(19200);
  while (!Serial); 
}

void loop()
{
  // phase haute
  digitalWrite(9,HIGH);
  delay(output2);
  // phase basse
  digitalWrite(9,LOW);

  for (i = 0; i < 64;i++)
      val += analogRead(0);
  val /= 64.;

 for (i = 0; i < 64;i++)
      val2 += analogRead(1);
  val2 /=64.;

  float mv = round (( val/1024.0)*5000);
  float mv2 = round (( val2/1024.0)*5000);
  Input = mv/10;
  Input2 = mv2/10;
//  Serial.println(Input);
  myPID.Compute();
  output2 = map(Output, -100, 100, 0, tOnMax);
  output3 = map(Output, -100, 100, 0, tOnMax);
//  Serial.print("output is :");
//  Serial.println(output2); 
//  Serial.print("Input: ");
for (c=0; c < 500; c++) {}
Serial.println(Input);

}

thnak you in advance

user313: 
I want to see the evolution of the function tempertaure (t), in other words, i want to see in my screen for exemple: 24.1C -> 20ms ; 25C-> 200ms; 26 -> 500ms

Quite apart from managing the heater, it sounds as if you need to sample the temperature at a constant rate, compare its value to any of several temperature-intervals, and, when it moves out of one interval into another, report the time it spent within the previous one. This will require saving which interval the temperature was last observed in, and the time it entered that interval, re-saving both when it moves into a new one. You may need to apply some smoothing to the temperature data to if there is any noise in the temperature data to prevent it appearing to jitter back and forth between intervals during interval edge crossings.

user6628: OK, with such a slow heater as compared to the calculation time of the arduino, you likely want to use a much longer sampling time. One could disconnect the PWM time and the sampling time from the loop() time by replacing the delay() with millis() as in Using Arduino for simultaneous lighting effects and below, and with a sampling time of 1s, 10s or 60s, the parameters of the PID and the integral and derivative terms could start making sense. i.e. the D term would conform to watts/(degreeError/minute), the I term to Watts/(degreeError*minutes) and P to watts/degreeError.  
One nice way to think of a PID controller is that it converts process errors into a control variable.  If you want to convert "degrees below setpoint" into "milliseconds of heat per tOnMax second cycle", set that directly:
// Tuned for full power (1000ms/sec) up to 35C: P=1000/2 
PID myPID( &Degrees, &millisecondsOn, &Setpoint,500,0,0, DIRECT);
myPID.SetOutputLimits(0, tOnMax);
...

Or "duty cycle of heater"
// Tuned for full power (100%) up to 35C: P=1.0/2 
PID myPID( &Degrees, &millisecondsOn, &Setpoint,0.5,0,0, DIRECT);
myPID.SetOutputLimits(0, 1.0);
...

I didn't want to edit your code too much, but went for a 1s PWM frequency, 10s sampling or PID cycle time.   The 1sec PWM/cycle time is the minimum most commercial PID controllers work with (typically 1s-999s to handle a range from solid-state-relay controlled resistive heating elements to relay controlled mechanical systems like pilot light heaters or fan/pump systems) and should be plenty fast enough for your system.  Slower PWM times are better for mechanical systems, and faster times are better for thermal cycling of resistive elements.
The 10s cycle time is ~200x slower than your initial code looks like it is sampling, but the 10s time might be more in keeping with the physical changes in your system as compared to your resolution.  I can't tell the temperature resolution of your sensor for your code, but assuming it is 0.1C, taken with a (37C-20C)/30m=0.0094C/s rate of change, it would take about 10s to make 1 bit of  detectable change.  If you sample faster than that, all you will be getting is noise or no change.  Sampling significantly faster than the physical process changes can serve to confuse a PID in the integral and derivative terms--Derivative because the derivative of error is mostly zeros or noise, and Integral because the integral accumulator can wind up before the system even begins to move.  Looking at the Arduino PID library code at https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.cpp#L57 with a I=20, output limits of (-100,100), a t0=20C, a setpoint of 37, sampling time of 50ms, and a temperature rate of change of 0.0094C/s, the Iterm accumulator would be wound up to 100 in just 0.300 seconds.  The wound-up integral would guarantee an overshoot until the integral accumulator erodes afterwards (For example: 37.5C for 10s? 37.1C for 100s? ???)    
With a 1000ms PWM and 10s sampling time base, you would need to reconsider your PID settings.   In particular, the I and D terms strongly sensitive to the sampling time and the output range.  As a start, PID myPID( &Input, &Output, &Setpoint,500,0,0, DIRECT); would start to proportionally turn the heater off at 37-1000/500)=35C, which might be good enough for your needs.  If that isn't close enough, you could increase P more to tighten the proportional band.  ("Proportional band" is error band where the P*error term of the PID doesn't saturate the output limits, i.e., PropBand = +/-(tOnMax/P) )   Alternately, you could fiddle with the I term to completely eliminate the droop.
#include <PID_v1.h>
#include "math.h" 
int c=0;
int  i=0, output2 = 0, output3 = 0; 
double val=0.0;
double val2 = 0.0;
//Define Variables we'll be connecting to
double Setpoint, Input, Input2, Output=0;
double tOnMax = 1000.0; // 1 second PWM controlling 10w heater
unsigned long sampleTime, heaterTime;

//Specify the links and initial tuning parameters
// Process takes 30m to come to 37C from 17C at 10W
// Proportional: Full power to setpoint-2C, then proportional taper: P= tOnMax/2
// Integral: 30m = 300 samples, so area under curve = 20*300/2=3000
// so for integral to roll up to 50% power (1/2 tOnMax) in 30m:
// I = tOnMax/2/3000 = 1000/2/3000 = 0.15
// Derivative: Max slew rate of 20C/30m = 20C/300 10sSamples = 0.067C/sample
// Ignore the derivative for now to avoid potential noise problems, 
// but D=tOnMax/0.067=15000 would anticipate and counteract the maximum slewing rate
PID myPID( &Input, &Output, &Setpoint,tOnMax/2,0.15,0, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Setpoint = 37; //temperature a reguler 

  //turn the PID on
  pinMode(9, OUTPUT);
  myPID.SetOutputLimits(0, tOnMax);
  myPID.SetMode(AUTOMATIC);
  Serial.begin(19200);
  while (!Serial); 
  heaterTime=sampletime=millis();
}

void loop()
{
  unsigned long now = millis();
  if(heaterTime < now){
     if(digitalRead(9)) {// phase haute -> basse
        heaterTime += tOnMax-output2; // schedule on 
        digitalWrite(9,LOW);}
     } else {  // phase basse -> haute
       heaterTime += output2);  // schedule off
       digitalWrite(9,HIGH);
     }
  if (sampleTime < now ) {
      sampleTime = sampleTime + 10000;  // every 10 seconds
      val=0=val2=0;
      for (i = 0; i < 64;i++)
          val += analogRead(0);
      val /= 64.;

      float mv = round (( val/1024.0)*5000); // convert to degrees*10?
      Input = mv/10;        // degrees
      myPID.Compute();
      output2 = Output;
      Serial.print(Input);
      Serial.print("C -> ");
      Serial.print(output2); 
      Serial.print("ms / "); 
      Serial.println(tOnMax); 
   } // end sample
}


14515: <p>I am making a system of regulation of the temperature using PID.
I want to keep my temperature in 37 celsius.
in order to understand the stability of my system easily, I want to see the fuction of temperature in terms of time. 
I found a function pulseIn() who Read a pulse (either HIGH or LOW) on a pin. 
But I don't know how to do it into my program. 
this is the program of my PID system: </p>

<pre class="lang-c prettyprint-override"><code>#include &lt;PID_v1.h&gt;
#include "math.h" 
int c=0;
int  i=0, output2 = 0, output3 = 0; 
double val=0.0;
double val2 = 0.0;
//Define Variables we'll be connecting to
double Setpoint, Input, Input2, Output=0;
double tOnMax = 50.0;

//Specify the links and initial tuning parameters
PID myPID( &amp;Input, &amp;Output, &amp;Setpoint,10,20,20, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Setpoint = 37; //temperature a reguler 

  //turn the PID on
  pinMode(9, OUTPUT);
  myPID.SetOutputLimits(-100, 100);
  myPID.SetMode(AUTOMATIC);
  Serial.begin(19200);
  while (!Serial); 
}

void loop()
{
  // phase haute
  digitalWrite(9,HIGH);
  delay(output2);
  // phase basse
  digitalWrite(9,LOW);

  for (i = 0; i &lt; 64;i++)
      val += analogRead(0);
  val /= 64.;

 for (i = 0; i &lt; 64;i++)
      val2 += analogRead(1);
  val2 /=64.;

  float mv = round (( val/1024.0)*5000);
  float mv2 = round (( val2/1024.0)*5000);
  Input = mv/10;
  Input2 = mv2/10;
//  Serial.println(Input);
  myPID.Compute();
  output2 = map(Output, -100, 100, 0, tOnMax);
  output3 = map(Output, -100, 100, 0, tOnMax);
//  Serial.print("output is :");
//  Serial.println(output2); 
//  Serial.print("Input: ");
for (c=0; c &lt; 500; c++) {}
Serial.println(Input);

}
</code></pre>

<p>thnak you in advance</p>
 313: <blockquote>
  <p>I want to see the evolution of the function tempertaure (t), in other words, i want to see in my screen for exemple: 24.1C -> 20ms ; 25C-> 200ms; 26 -> 500ms</p>
</blockquote>

<p>Quite apart from managing the heater, it sounds as if you need to sample the temperature at a constant rate, compare its value to any of several temperature-intervals, and, when it moves out of one interval into another, report the time it spent within the previous one. This will require saving which interval the temperature was last observed in, and the time it entered that interval, re-saving both when it moves into a new one. You may need to apply some smoothing to the temperature data to if there is any noise in the temperature data to prevent it appearing to jitter back and forth between intervals during interval edge crossings.</p>
 6628: <p>OK, with such a slow heater as compared to the calculation time of the arduino, you likely want to use a much longer sampling time. One could disconnect the PWM time and the sampling time from the loop() time by replacing the delay() with millis() as in <a href="https://arduino.stackexchange.com/questions/17918/using-arduino-for-simultaneous-lighting-effects/17929#17929">Using Arduino for simultaneous lighting effects</a> and below, and with a sampling time of 1s, 10s or 60s, the parameters of the PID and the integral and derivative terms could start making sense. i.e. the D term would conform to watts/(degreeError/minute), the I term to Watts/(degreeError*minutes) and P to watts/degreeError.  </p>

<p>One nice way to think of a PID controller is that it converts process errors into a control variable.  If you want to convert "degrees below setpoint" into "milliseconds of heat per tOnMax second cycle", set that directly:</p>

<pre><code>// Tuned for full power (1000ms/sec) up to 35C: P=1000/2 
PID myPID( &amp;Degrees, &amp;millisecondsOn, &amp;Setpoint,500,0,0, DIRECT);
myPID.SetOutputLimits(0, tOnMax);
...
</code></pre>

<p>Or "duty cycle of heater"</p>

<pre><code>// Tuned for full power (100%) up to 35C: P=1.0/2 
PID myPID( &amp;Degrees, &amp;millisecondsOn, &amp;Setpoint,0.5,0,0, DIRECT);
myPID.SetOutputLimits(0, 1.0);
...
</code></pre>

<p>I didn't want to edit your code too much, but went for a 1s PWM frequency, 10s sampling or PID cycle time.   The 1sec PWM/cycle time is the minimum most commercial PID controllers work with (typically 1s-999s to handle a range from solid-state-relay controlled resistive heating elements to relay controlled mechanical systems like pilot light heaters or fan/pump systems) and should be plenty fast enough for your system.  Slower PWM times are better for mechanical systems, and faster times are better for thermal cycling of resistive elements.</p>

<p>The 10s cycle time is ~200x slower than your initial code looks like it is sampling, but the 10s time might be more in keeping with the physical changes in your system as compared to your resolution.  I can't tell the temperature resolution of your sensor for your code, but assuming it is 0.1C, taken with a (37C-20C)/30m=0.0094C/s rate of change, it would take about 10s to make 1 bit of  detectable change.  If you sample faster than that, all you will be getting is noise or no change.  Sampling significantly faster than the physical process changes can serve to confuse a PID in the integral and derivative terms--Derivative because the derivative of error is mostly zeros or noise, and Integral because the integral accumulator can wind up before the system even begins to move.  Looking at the Arduino PID library code at <a href="https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.cpp#L57" rel="nofollow noreferrer">https://github.com/br3ttb/Arduino-PID-Library/blob/master/PID_v1.cpp#L57</a> with a I=20, output limits of (-100,100), a t0=20C, a setpoint of 37, sampling time of 50ms, and a temperature rate of change of 0.0094C/s, the Iterm accumulator would be wound up to 100 in just 0.300 seconds.  The wound-up integral would guarantee an overshoot until the integral accumulator erodes afterwards (For example: 37.5C for 10s? 37.1C for 100s? ???)    </p>

<p>With a 1000ms PWM and 10s sampling time base, you would need to reconsider your PID settings.   In particular, the I and D terms strongly sensitive to the sampling time and the output range.  As a start, PID myPID( &amp;Input, &amp;Output, &amp;Setpoint,500,0,0, DIRECT); would start to proportionally turn the heater off at 37-1000/500)=35C, which might be good enough for your needs.  If that isn't close enough, you could increase P more to tighten the proportional band.  ("Proportional band" is error band where the P*error term of the PID doesn't saturate the output limits, i.e., PropBand = +/-(tOnMax/P) )   Alternately, you could fiddle with the I term to completely eliminate the droop.</p>

<pre class="lang-c prettyprint-override"><code>#include &lt;PID_v1.h&gt;
#include "math.h" 
int c=0;
int  i=0, output2 = 0, output3 = 0; 
double val=0.0;
double val2 = 0.0;
//Define Variables we'll be connecting to
double Setpoint, Input, Input2, Output=0;
double tOnMax = 1000.0; // 1 second PWM controlling 10w heater
unsigned long sampleTime, heaterTime;

//Specify the links and initial tuning parameters
// Process takes 30m to come to 37C from 17C at 10W
// Proportional: Full power to setpoint-2C, then proportional taper: P= tOnMax/2
// Integral: 30m = 300 samples, so area under curve = 20*300/2=3000
// so for integral to roll up to 50% power (1/2 tOnMax) in 30m:
// I = tOnMax/2/3000 = 1000/2/3000 = 0.15
// Derivative: Max slew rate of 20C/30m = 20C/300 10sSamples = 0.067C/sample
// Ignore the derivative for now to avoid potential noise problems, 
// but D=tOnMax/0.067=15000 would anticipate and counteract the maximum slewing rate
PID myPID( &amp;Input, &amp;Output, &amp;Setpoint,tOnMax/2,0.15,0, DIRECT);

void setup()
{
  //initialize the variables we're linked to
  Setpoint = 37; //temperature a reguler 

  //turn the PID on
  pinMode(9, OUTPUT);
  myPID.SetOutputLimits(0, tOnMax);
  myPID.SetMode(AUTOMATIC);
  Serial.begin(19200);
  while (!Serial); 
  heaterTime=sampletime=millis();
}

void loop()
{
  unsigned long now = millis();
  if(heaterTime &lt; now){
     if(digitalRead(9)) {// phase haute -&gt; basse
        heaterTime += tOnMax-output2; // schedule on 
        digitalWrite(9,LOW);}
     } else {  // phase basse -&gt; haute
       heaterTime += output2);  // schedule off
       digitalWrite(9,HIGH);
     }
  if (sampleTime &lt; now ) {
      sampleTime = sampleTime + 10000;  // every 10 seconds
      val=0=val2=0;
      for (i = 0; i &lt; 64;i++)
          val += analogRead(0);
      val /= 64.;

      float mv = round (( val/1024.0)*5000); // convert to degrees*10?
      Input = mv/10;        // degrees
      myPID.Compute();
      output2 = Output;
      Serial.print(Input);
      Serial.print("C -&gt; ");
      Serial.print(output2); 
      Serial.print("ms / "); 
      Serial.println(tOnMax); 
   } // end sample
}
</code></pre>
