Hello, I hope you're all having a fantastic holiday.
I am digging a little project out of the storage shed and am shining some new light on it... It's basically a fancy thermostat.
Basically, what I had all working nicely before is:
-1 Seeeduino v1.0 (like the arduino Duemilanove)
-1 Serial LCD (2x16)
-1 Thermocouple and TC amp, wired into the microcontroller.
This along with some PID and liquid crystal code worked very nicely.... Ohh I also have two pushbutton switches to change the SETPOINT in steps of 10 degrees. One to increase and one to decrease.
Now what I have is the "MLX90614 IR Thermometer" and I want to switch the info the PID code gets about the temperature.
I want to switch that from the ANALOG information it was receiving from the TC amplifier over to the DIGITAL temperature reading I will be able to get with this new sensor.
Here's what my old code looked like that worked at one point:
#include <EEPROM.h>
#include <LiquidCrystal.h>
#include <PIDv1.h>
double Setpoint, Input, Output;
double aggKp=0.5, aggKi=15, aggKd=0.01 , LoLIM=50, HiLIM=255;
double consKp=.25, consKi=30, consKd=0;
double SampleTime=120;
LiquidCrystal lcd(12, 11, 8, 4, 3, 2);
const int onPin = 5; //pin to trigger heater
const int upPin = 6; // pin to increase temp
const int downPin = 7; //pin to decrease temp
int buttonState = 0; // variable for reading the pin status
int DownPushed = 0;
int UpPushed = 0;
int OnPushed = 0;
int PID_ON = 0;
int UpdScr = 0;
int inpt;
int gap;
int S_gap;
int count;
int EEPROM_ADDR;
void UpdateEEPROM() {
int val, wr;
val = (int) Setpoint;
wr = val>>8;
EEPROM.write(EEPROM_ADDR, wr);
wr = val & 0XFF;
EEPROM.write(EEPROM_ADDR+1, wr);
};
void LoadEEPROM() {
int val;
val = EEPROM.read(EEPROM_ADDR);
val = val <<8;
val +=EEPROM.read(EEPROM_ADDR+1);
Setpoint = val;
};
unsigned long lastTime, lShowTime;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint, aggKp, aggKi, aggKd, DIRECT);
void setup()
{
Serial.begin( 19200 );
//initialize the variables we're linked to
Input = analogRead(0);
LoadEEPROM();
if( (Setpoint +1.) < 0.001)
Setpoint = 570;
// Setpoint = xxx;
// Declare inputs
pinMode(onPin, INPUT); // declare pushbutton as input
pinMode(upPin, INPUT); // declare pushbutton as input
pinMode(downPin, INPUT); // declare pushbutton as input
//turn the PID on STANDBY, but start the output at its max and let the PID adjust it from there
myPID.SetOutputLimits(LoLIM, HiLIM);
myPID.SetMode(AUTOMATIC);
myPID.SetSampleTime(SampleTime);
myPID.SetTunings(aggKp, aggKi, aggKd);
lShowTime = lastTime = millis();
// set up the LCD's number of columns and rows:
lcd.begin(16,2);
count = 0;
EEPROM_ADDR = 30;
//lcd.print ("HEat");
//delay(1000);
// lcd.clear();
//lcd.print(" on ");
//delay(1000);
//lcd.clear();
//lcd.print("its way :D");
// delay(1000);
//lcd.clear();
lcd.print("hot");
lcd.setCursor( 0,1);
lcd.print(aggKp);
lcd.print("-");
lcd.print((int)(aggKi) );
lcd.print("-");
lcd.print(aggKd);
delay(2000);
lcd.clear();
lcd.print("S_Rate = ");
lcd.print((int)(SampleTime));
lcd.print(" ms");
delay(1000);
lcd.clear();
lcd.print("Limits ");
lcd.print((int)(LoLIM));
lcd.print(",");
lcd.print((int)(HiLIM));
delay(1000);
lcd.clear();
}
void loop()
{
Input = analogRead(0);
buttonState = digitalRead(onPin);
if (buttonState == HIGH) {
myPID.SetMode(AUTOMATIC);
PID_ON =1;
}
else {
myPID.SetMode(MANUAL);
Output = 0;
PID_ON =0;
}
myPID.Compute();
analogWrite(10,Output);
// I would not change these lines, because you are expecting 250 ms for a "push"
// that is if you hold button for more then 1/4 second,
if(digitalRead(upPin)==HIGH) {
if (millis()-lastTime >= 250) {
Setpoint+=10;
UpdateEEPROM();
lastTime=millis();
UpdScr = 1;
}
}
if(digitalRead(downPin)==HIGH) {
if (millis()-lastTime >= 250) {
Setpoint-=10;
UpdateEEPROM();
lastTime=millis();
UpdScr = 1;
}
}
//and output to LCD
if( (millis() - lShowTime > 100 ) || UpdScr ) {
UpdScr = 0;
lcd.setCursor(0,0);
//if heater is on - show *
//if not - empty
if( PID_ON ==1 ) {
lcd.print("*");
}
else {
lcd.print(" ");
}
lcd.print("SET.TEMP-> ");
lcd.print((int)(Setpoint) );
lcd.setCursor( 0,1);
lcd.print(" AIR.TEMP-> ");
inpt = (inpt *5 + Input)/6;
count = (count +1)%6;
if(count == 0) {
if( inpt < 100) lcd.print( " ");
lcd.print( inpt );
}
lShowTime = millis();
}
}
according to the guys on this site http://bildr.org/2011/02/mlx90614-arduino/ the sensor is pretty easy to hook up. My main question is what is the first thing i need to do to make the PID code take those digital readings?
P.S. Here's what the PID control code looks like:
#ifndef PID_v1_h
#define PID_v1_h
#define LIBRARY_VERSION 1.0.0
class PID
{
public:
//Constants used in some of the functions below
#define AUTOMATIC 1
#define MANUAL 0
#define DIRECT 0
#define REVERSE 1
//commonly used functions **************************************************************************
PID(double*, double*, double*, // * constructor. links the PID to the Input, Output, and
double, double, double, int); // Setpoint. Initial tuning parameters are also set here
void SetMode(int Mode); // * sets PID to either Manual (0) or Auto (non-0)
void Compute(); // * performs the PID calculation. it should be
// called every time loop() cycles. ON/OFF and
// calculation frequency can be set using SetMode
// SetSampleTime respectively
void SetOutputLimits(double, double); //clamps the output to a specific range. 0-255 by default, but
//it's likely the user will want to change this depending on
//the application
//available but not commonly used functions ********************************************************
void SetTunings(double, double, // * While most users will set the tunings once in the
double); // constructor, this function gives the user the option
// of changing tunings during runtime for Adaptive control
void SetControllerDirection(int); // * Sets the Direction, or "Action" of the controller. DIRECT
// means the output will increase when error is positive. REVERSE
// means the opposite. it's very unlikely that this will be needed
// once it is set in the constructor.
void SetSampleTime(int); // * sets the frequency, in Milliseconds, with which
// the PID calculation is performed. default is 100
//Display functions ****************************************************************
double GetKp(); // These functions query the pid for interal values.
double GetKi(); // they were created mainly for the pid front-end,
double GetKd(); // where it's important to know what is actually
int GetMode(); // inside the PID.
int GetDirection(); //
private:
void Initialize();
double dispKp; // * we'll hold on to the tuning parameters in user-entered
double dispKi; // format for display purposes
double dispKd; //
double kp; // * (P)roportional Tuning Parameter
double ki; // * (I)ntegral Tuning Parameter
double kd; // * (D)erivative Tuning Parameter
int controllerDirection;
double *myInput; // * Pointers to the Input, Output, and Setpoint variables
double *myOutput; // This creates a hard link between the variables and the
double *mySetpoint; // PID, freeing the user from having to constantly tell us
// what these values are. with pointers we'll just know.
unsigned long lastTime;
double ITerm, lastInput;
int SampleTime;
double outMin, outMax;
bool inAuto;
};
#endif