PID Controlled Heating System suffering random overshoots in Output

Dear comrades,

The Arduino Due is being used in project as PID controller “raughly speaking”. The Due reads-in the analog input through a thermoouple amplifier (voltage in mV, Gain X8), then injects to PID control algotithm, with fixed setpoint it pumps out the suitable output log, and writes in on DAC pins. The DAC pins are used to control the voltage which leads to temperatures control. After system starts in serial monitor everything looks fine, but some seconds later, one can see that it start kicking analogWrite(255), which show on sensor value of 1445.10… and it proceeds like that analogWrite(0), then analogWrite(255) again analogWrite(0), analogWrite(255). Please have a looks at snapshot from serial. Any ideas what might be the reason for this phenomena=?..

Any help is HIGHLY appreciated many many times!

Image from Original Post so we don’t have to download it. See this Image Guide

9405211726f0a4a823f0e3a90f863e870528922f.jpg

…R

As you can see your image is unreadable. Please don’t post pictures of text… Just copy and paste the text and use the code button <>

so it looks like this

Also post your program.

Is the program running long enough to demonstrate that it works properly some of the time?

Is it possible that something is corrupting your code (such as writing beyond the bounds of an array) and causing the Arduino to reset?

…R

Arduino does not reset, otherwise would have see break in serial data. On multimeter, which is connected to DAC output pin, i can see that DAC outputs just 0.0 - to 3.3 Volts, and nothing else. That said if PID is working it should output proper compensation, and it should be lets say small amount of voltage if the Error(t) is not too big. By the way when i turn off or unplug the DAC outputs the glitch goes away. Which makes me think that they are directly related to each other.

Serial data

<MAX-31856 Starting up…

Running PID Control Algorithm…

analog channel stream (mV) = 0.3828 Calculating output data = 5.99 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 13.5000 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.5391 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6562 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6328 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6250 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6641 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6875 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.6406 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.7109 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)=
analog channel stream (mV) = 1441.6328 Calculating output data = 0.00 Setpoint = 2.80 runtime
analog channel stream (mV) = 2.7109 Calculating output data = 255.00 Setpoint = 2.80 runtime (ms)>

The Code running on Arduino Due…

<#include <PID_v1.h>
#include <Adafruit_MAX31856.h>

double Set_point, Input_log, Output_log; unsigned long tetta; const int Potti_analog_channel_port=A0;
double Potti_analog_channel_stats=0.0;

Adafruit_MAX31856 max = Adafruit_MAX31856( 9, 10, 11, 12);

//P_ON_M specifies that Proportional on Measurement be used
//P_ON_E (Proportional on Error) is the default behavior
PID myPID(&Input_log, &Output_log, &Set_point,P_ON_E,5,5,1, DIRECT);

void setup()
{
Serial.begin(115200);
max.begin(); // Starting MAX-31856 hardware registers
max.setThermocoupleType(MAX31856_VMODE_G8); // Setting-up MAX-31856 for voltage data measurements with Gain-X8 amplification mode
Serial.print("------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
Serial.print("\n\n");
Serial.print(“MAX-31856 Starting up…”);
Serial.print("\n\n");
Serial.print(“Running PID Control Algorithm…”);
Serial.print("\n\n");
delay(1000);
analogReadResolution(12);
//initialize the variables we’re linked to
Input_log = abs(max.readThermocoupleTemperature()); // capturing MAX-31856 data transmission
Set_point = 2.80;
myPID.SetMode(AUTOMATIC); // turn the PID Controller On
}

void loop()
{
myPID.Compute();
Potti_analog_channel_stats=analogRead(Potti_analog_channel_port)*5.0/4095.0 *1000;
myPID.SetOutputLimits(0, 255);
Set_point=2.80;
Input_log =abs(max.readThermocoupleTemperature());
tetta=millis();
myPID.Compute(); // Computing Data…
analogWrite(DAC0, Output_log);
analogWrite(DAC1, Output_log);
Serial.print(“analog channel stream (mV) = “);
Serial.print(Input_log, 4);
Serial.print(”\t\t”);
Serial.print(“Calculating output data = “);
Serial.print(Output_log);
Serial.print(”\t\t”);
Serial.print(“Setpoint = “);
Serial.print(Set_point);
Serial.print(”\t\t”);
myPID.Compute();
myPID.Compute();
// Serial.print(“Potti_input(mV)= “);
// Serial.print(Potti_analog_channel_stats, 4);
Serial.print(”\t\t”);
Serial.print(“runtime (ms)= “);
Serial.print(tetta);
Serial.print(”\n”);
myPID.Compute();
}>

Hi,

Please read the first post in any forum entitled how to use this forum.
http://forum.arduino.cc/index.php/topic,148850.0.html then look down to item #7 about how to post your code.
It will be formatted in a scrolling window that makes it easier to read.

Why does your analog input jump around, shouldn't it be more constant than going from 0.26 to 1441 from one sample to the next.

Have you got code that just reads the thermocouple and prints it to Serial, with NO PID content.
I hope you developed this in stages and one of the first things you did was establish consistent and accurate temperature readings.

How have you got your project wired, I hope the thermocouple circuitry is well away from the output circuitry.

Can you please post a copy of your circuit, in CAD or a picture of a hand drawn circuit in jpg, png?

Thanks.. Tom... :slight_smile:

finally figured out how to post code in right way :slight_smile: , thanks.

I have tried the sensor and setup without any PID and DAC output. Just getting stable readings from thermocouple and printing them on screen. It looks quite resonable.

MAX-31856 Starting up.........

analog channel stream (mV) = 0.1875		1252
analog channel stream (mV) = 0.1094		1502
analog channel stream (mV) = 0.1094		1752
analog channel stream (mV) = 0.1484		2002
analog channel stream (mV) = 0.1094		2252
analog channel stream (mV) = 0.1016		2502
analog channel stream (mV) = 0.0937		2752
analog channel stream (mV) = 0.1016		3002
analog channel stream (mV) = 0.0781		3252
analog channel stream (mV) = 0.0781		3502
analog channel stream (mV) = 0.0625		3752
analog channel stream (mV) = 0.0859		4002
analog channel stream (mV) = 0.0937		4252
analog channel stream (mV) = 0.0859		4502
analog channel stream (mV) = 0.0703		4752
analog channel stream (mV) = 0.0859		5002
analog channel stream (mV) = 0.0547		5252
analog channel stream (mV) = 0.1016		5502
analog channel stream (mV) = 0.0625		5752
analog channel stream (mV) = 0.1016		6002
analog channel stream (mV) = 0.0781		6252
analog channel stream (mV) = 0.1016		6502
analog channel stream (mV) = 0.0703		6752
analog channel stream (mV) = 0.1172		7002
analog channel stream (mV) = 0.0625		7252
analog channel stream (mV) = 0.1172		7502
analog channel stream (mV) = 0.0625		7752
analog channel stream (mV) = 0.1172		8002
analog channel stream (mV) = 0.0625		8252
analog channel stream (mV) = 0.1094		8502
analog channel stream (mV) = 0.0469		8752
analog channel stream (mV) = 0.1172		9002
analog channel stream (mV) = 0.0469		9252
analog channel stream (mV) = 0.1094		9502
analog channel stream (mV) = 0.0156		9752
analog channel stream (mV) = 0.1484		10002
analog channel stream (mV) = 0.0547		10252
analog channel stream (mV) = 0.1406		10502
analog channel stream (mV) = 0.0000		10752
analog channel stream (mV) = 0.1328		11002
analog channel stream (mV) = 0.0625		11252
analog channel stream (mV) = 0.1172		11502
analog channel stream (mV) = 0.0469		11752
analog channel stream (mV) = 0.1250		12002
analog channel stream (mV) = 0.0469		12252
analog channel stream (mV) = 0.1250		12502
analog channel stream (mV) = 0.0469		12752
analog channel stream (mV) = 0.1172		13002
analog channel stream (mV) = 0.0547		13252
analog channel stream (mV) = 0.1172		13502
analog channel stream (mV) = 0.0

The setup drawing is attached.

Hi,
OPs pic.

Tom.. :slight_smile:

David_ZI:
finally figured out how to post code in right way :slight_smile: , thanks.

But you did not actually post the code :slight_smile:

...R

Hi,
What are your DAC outputs doing, how do they control the amount of heat output?
How big is your heating system, that is how big heating element .

A bigger circuit diagram showing power supplies and heating elements will be good.

Thanks.. Tom... :slight_smile:

That is not stable. It is alternating between 0.1172 and 0.0625.

Why are you printing mV when you say you have a MAX31865? That gives temperature directly.

I have found that chip to be very sentitive to RF interference. Any high power electronics nearby may be screwing up your measurements.

There is something wrong with your measurements as the DUE DAC pins can't produce 0V or 3.3V.

Max-31856 is setup to send voltage readings with X8 gain, because the sensor is so small, it is better to have pure voltage without any Max internal calculations. Later we can do in in code. I added some amplifing circuitry to Due DACS so that they can produce voltage in range of ~0.0 - 3.3 volts, removed the offset of the DACs output. The heaters of the sensor are tiny, they are dopped on the membrane. So small amount of milivolts can heat up the system very fast. DAC1, and DAC0 are connected to PID output to output suitable voltage to heat up the sensor.

 #include <PID_v1.h>
  #include <Adafruit_MAX31856.h>

  //double Set_point, Input_log,  Output_log;  unsigned long tetta;  const int Potti_analog_channel_port=A0;       
                                                                     double Potti_analog_channel_stats=0.0;  
  
  
  Adafruit_MAX31856 max = Adafruit_MAX31856( 9, 10, 11, 12);

//P_ON_M specifies that Proportional on Measurement be used
//P_ON_E (Proportional on Error) is the default behavior  
  PID myPID(&Input_log, &Output_log, &Set_point,P_ON_E,5,5,1, DIRECT);
  
    void setup()
     {
       pinMode(DAC0, OUTPUT); pinMode(DAC1, OUTPUT);
       Serial.begin(115200); 
       max.begin(); // Starting MAX-31856 hardware registers
       max.setThermocoupleType(MAX31856_VMODE_G8); // Setting-up MAX-31856 for voltage data measurements with Gain-X8 amplification mode
       Serial.print("------------>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
       Serial.print("\n\n"); 
       Serial.print("MAX-31856 Starting up.........");
       Serial.print("\n\n"); 
       Serial.print("Running PID Control Algorithm......");
       Serial.print("\n\n");
       delay(1000);
       analogReadResolution(12);
     //initialize the variables we're linked to
       Input_log = abs(max.readThermocoupleTemperature()); // capturing MAX-31856 data transmission 
       Set_point = 2.80;
       myPID.SetMode(AUTOMATIC);  // turn the PID Controller On   
       }
     
     void loop()
      {
        myPID.Compute();
        Potti_analog_channel_stats=analogRead(Potti_analog_channel_port)*5.0/4095.0 *1000;
        myPID.SetOutputLimits(0, 255);
        Set_point=2.80;
        Input_log =abs(max.readThermocoupleTemperature());
        tetta=millis();   
        myPID.Compute(); // Computing Data...
        analogWrite(DAC0, Output_log);
        analogWrite(DAC1, Output_log);
        Serial.print("analog channel stream (mV) = ");
        Serial.print(Input_log, 4);
        Serial.print("\t\t");
        Serial.print("Calculating output data = ");
        Serial.print(Output_log);
        Serial.print("\t\t");
        Serial.print("Setpoint = ");
        Serial.print(Set_point);
        Serial.print("\t\t");
        myPID.Compute();
        myPID.Compute();
        Serial.print("Potti_input(mV)= ");
        Serial.print(Potti_analog_channel_stats, 4);
        Serial.print("\t\t");
        Serial.print("runtime (ms)= ");
        Serial.print(tetta);
        Serial.print("\n");
        myPID.Compute();
      }

Hi,
OPs pics


So we are looking at a micro system?
Where are the "sensors" heaters located with respect to the thermocouple?
What sort of temperatures are you aiming for?

Tom... :slight_smile:

PID is not sutiable for temperature control.
PI can help, in some cases
P will offer stability by itself.
do not make your P too tight.

this is where I comes in.

P gets you close, I walks you closer after upsets.
after upsets.

so, your main control is P to get you withing a window of near instability.
the tighter you make it, the more prone to self inflicted upsets.
so the P window is wide enough to be acceptable, but close enough to make you feel like you are in control.

think of your hysteresys. P gets you between the points where control is needed, the P window.

once you are in there I starts it's thing and slooooooowly pushes you towards the center.

I cannot be too fast.

temperature control is like having an automatic bird bath filler.
that is 100 meters long, you pour in a cup on one end, it filters through the gravel, then the sand, then comes out the other end a few minuts later. in almost every case, you put in too little or too much. and by the way, the birdbath leaks.

unlike sound or movement that are very dynamic and can be controlled at the speed of sound, temperature is controlled at a speed slow enough to allow paint to dry.

datalog, put in your P responses, your I responses and your feedback.
once you understand the process, you can better control it.

heating is power.
heat is inputted as energy, and the thing heated is releasing energy in 3 ways
radiation, conduction and convection.

if you know the amount of those, you can control the power in as your baseline.
then your actual control is more or less than that.

if your process consumes 1 watt all the time, but the variation is from 0.001 to 0.1 watt. your choices are to try to have a control of 1.001 to 1.1
or have a constant 1.000 and your control becomes 0.1 to 0.001, almost 1,000 times more precise.

guys, the strong jump of the analog value is related to DAC’s 0/1! I can explain why.

When the system runs by default (including PID) and the both DACs are disconnected ( which represent sensor heaters ), the reading of the analog input (PID input) are acceptable, that said (some minor 0.09mv) I relate to room temperature drift (heating, room conditioning on/off). Also one can see that the PID calculated Output value is changing with respect to input. If i put setpont similar as input, one can see that output becomes zero. What we expect. But as soon as i connect back DACs e.g. heaters to sensor, this 1445.00 something comes in and PID Outputs analogWrite(0) then analogWrite(255) max heating.

!(http://C:\Users\Zebrovski\Pictures\PID Controller development for Fast-Scanning Calorimetry\Sensor_2.jpg)

Hi,
Have you got some 0.1uF capacitors, to place across the heater terminals, to filter any noise that my be from the DAC?

How long are the leads from the Arduino to the Oven?

How much current does the heater assembly consume?
Where are you getting the power for them?

Tom.. :slight_smile:

David_ZI:
Max-31856 is setup to send voltage readings with X8 gain, because the sensor is so small, it is better to have pure voltage without any Max internal calculations. Later we can do in in code. I added some amplifing circuitry to Due DACS so that they can produce voltage in range of ~0.0 - 3.3 volts, removed the offset of the DACs output. The heaters of the sensor are tiny, they are dopped on the membrane. So small amount of milivolts can heat up the system very fast. DAC1, and DAC0 are connected to PID output to output suitable voltage to heat up the sensor.

All of that would have been good to know in the beginning. We're focussed on the wrong things if you don't tell us that.

And you really take a very good temperature chip and throw away all its temperature calculations? That's like buying a Ferrari and leaving it in Neutral.

I don't think I can diagnose a system of this complexity over the internet without the proper information.

I've decided to remove the MAX-31856 completely. It slows down the loop execution too strong. It looks like all that internal calculations and approximations are killing the system speed. I think MAX-31856 is not useful if superfast measurements are needed. I have removed the MAX31856 library and function call, my loop and measument became several orders of magnitue faster. Any ideas what one could build as thermocouple amplifier which Arduino Due can read with its own ADC?

David_ZI:
I've decided to remove the MAX-31856 completely. It slows down the loop execution too strong.

I thought you are trying to control the temperature of a room?

How could any time delays due to a sensor have any impact? I suspect it would be unnecessary to update the PID (or whatever) calculations more often than once a minute.

Any ideas what one could build as thermocouple amplifier which Arduino Due can read with its own ADC?

I don't know about a Due but a Mega has an internal amplifier.

...R

the only post you had if data shows that the P part of the loop is not tuned.

if you limit the current to be at the maximum safe current value for your heater, then being on maximum would not danger the process.
if you monitor current being applied, you would also have an eye into the process.

then, open your P until the heater stops bouncing.
add the variable for runtime
reduce how many words in your output text so you get more columns on the screen

if you want faster analog, then get into an industrial op-amp for the gain and use a micro that has a built in ADC that has the resolution that you like.\

you can even make an analog control. it will be much faster than your digital control.

look at the Teensy chips.
maybe the the ESP32 ?