Hello everyone
I was playing around with the PID library examples tonight to try and better understand them. I want to regulate a mechanical relay depending on the temperature that is read by my AD597 thermocouple interface IC. The IC feeds a analog signal into my Arduino Uno. Which I then read and display on a GLCD. The relay will regulate the temperature to stay at a fixed value by means of switching the electrical heating elements on and off.
So according to the library PID RelayOutput Example, it should be able to do this. I've modified the code a bit to display some variables on a GLCD for me. The code can be seen below.
The thing that is not happening is that whenever the PID output pin is high it doesn't switch my relay on. Relay stays constantly off. I have a LED from the output pin as well and I can see that the LED is switching on and off, but the LED is very dim. I then removed my shield and loaded the default example sketch and connected an LED from the output to ground. I then measured the voltage out at the output pin and it is only 108 mV? I changed the pin then and tried a different output, same story. I then loaded a blink example and it switches on the led fully as well as the relay when using the same output pins?
* PID RelayOutput Example
* Same as basic example, except that this time, the output
* is going to a digital pin which (we presume) is controlling
* a relay. the pid is designed to Output an analog value,
* but the relay can only be On/Off.
*
* to connect them together we use "time proportioning
* control" it's essentially a really slow version of PWM.
* first we decide on a window size (5000mS say.) we then
* set the pid to adjust its output between 0 and that window
* size. lastly, we add some logic that translates the PID
* output into "Relay On Time" with the remainder of the
* window being "Relay Off Time"
********************************************************/
// include the library header
#include <glcd.h>
#include <PID_v1.h>
// include the Fonts
#include <fonts/allFonts.h>
#define RelayPin 2
//*************************************************************
//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);
int WindowSize = 5000;
unsigned long windowStartTime;
//*************************************************************
int sensorPin = A5; // select the input pin for the potentiometer
int Temp;
const int numReadings = 10;
int readings[numReadings]; // the readings from the analog input
int index = 0; // the index of the current reading
int total = 0; // the running total
int Raw_Value_Avg = 0; // the average
int Raw_Value = 0;
void setup()
{
// initialize all the readings to 0:
for (int thisReading = 0; thisReading < numReadings; thisReading++)
readings[thisReading] = 0;
//*************************************************************
// Initialize the GLCD
GLCD.Init();
// Select the font for the default text area
GLCD.SelectFont(System5x7);
//*************************************************************
windowStartTime = millis();
//tell the PID to range between 0 and the full window size
myPID.SetOutputLimits(0, WindowSize);
//turn the PID on
myPID.SetMode(AUTOMATIC);
//*************************************************************
}
void loop()
{
//initialize the variables we're linked to
Setpoint = 100;
Raw_Value = analogRead(sensorPin);
Averaging_RAW_Value();
Temp = Raw_Value_Avg / 2.04;
//*************************************************************
Input = Temp;
myPID.Compute();
/************************************************
* turn the output pin on/off based on pid output
************************************************/
if(millis() - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output < millis() - windowStartTime)
{
digitalWrite(RelayPin, HIGH);
/*
GLCD.CursorToXY(15, 25);
GLCD.print("HIGH");
delay(500);
GLCD.ClearScreen();
delay(500);
*/
}
else
{
digitalWrite(RelayPin,LOW);
/*
GLCD.CursorToXY(15, 35);
GLCD.print("LOW");
delay(500);
GLCD.ClearScreen();
delay(500);
*/
}
//*************************************************************
GLCD.CursorToXY(15, 15);
GLCD.print(Temp);
GLCD.DrawCircle(40,16, 1); // X, Y, Radius; Draws a little circle to be the Degree symbol
GLCD.CursorToXY(44,15); // Print unit of measurent
GLCD.print("C");
}
void Averaging_RAW_Value()
{
// subtract the last reading:
total= total - readings[index];
//void Read_Raw_Value();
Raw_Value = analogRead(sensorPin);
readings[index] = Raw_Value;
// add the reading to the total:
total= total + readings[index];
// advance to the next position in the array:
index = index + 1;
// if we're at the end of the array...
if (index >= numReadings)
// ...wrap around to the beginning:
index = 0;
// calculate the average:
Raw_Value_Avg = total / numReadings;
// send it to the computer as ASCII digits
}
I don't understand the PID controller library very well, but what I think I know is that the window period is the evaluation period to evaluate whether the temperature is below or above the set point to either turn the relay on or off.
The set point is the point you want to reach and it is just a numerical value that you can relate to another valiable (i.e. not a percentage value or something similar)?
So my big question is how I can get the output to switch on fully to get the mechanical relay to switch? Thank you everyone.
Dirk
