Hi Folks
I am using the brilliant PID library written by Brett Beauregard. The library is working great with the exception that I cannot get the SetOutputLimits() function to work. I am trying to limit my servo travel to 10-180degrees. I could always scale the myPID output to this range but I know the library has better functionality within ( to prevent PID wind up) if I can get the SetOutputLimits() function to work.
Can anybody see in my code what the problem may be??
PS....hope this is the correct part of the forum to post this message!!??
/ *
/*-----( Import needed libraries )-----*/
#include <Wire.h> // Comes with Arduino IDE
#include <LiquidCrystal_I2C.h> /// https://bitbucket.org/fmalpartida/new-liquidcrystal/downloads Move any other LCD libraries to another folder or delete them
#include <AnalogSmooth.h>
#include "ThingSpeak.h" // added for thinkgspeak connectivity
#include <Ethernet.h> *// added for thinkgspeak connectivity
#include <SPI.h> // added for thinkgspeak connectivity to ethernet sheild
#include <Servo.h> // added for the servos! https://www.arduino.cc/en/Reference/Servo
#include <PID_v1.h>
EthernetClient client;
/*-----( Declare Constants )-----*/
//Connect Vcc and Ground, SDA to A4, SCL to A5 on Arduino
int O2FlueTempAnaloguePin = 2;
int O2AnaloguePin = 3;
int Led1Pin = 3;
int Led2Pin = 2;
int LambdaController = 7;
int myServoPin = 9;
int FlueThreshold = 15;
int HeatMeter = 4;
const float VOLTAGE_MAX = 5.0;
const float VOLTAGE_MAXCOUNTS = 1023.0;
const float HEATMETERPOWERHIGH_KW = 20; //4.5VISH
const float HEATMETERPOWERLOW_KW = 0;
const float HEATMETERPOWERHIGH_BIT = 959;
const float HEATMETERPOWERLOW_BIT = 185;
double PID_SetPoint = 19;
double P_PARAM = 10; //Needs to be a double to pass to PID library
double I_PARAM = 5; //Needs to be a double to pass to PID library
double D_PARAM = 1; //Needs to be a double to pass to PID library
double SERVO_MAX = 180; //Needs to be a double to pass to PID library
double SERVO_MIN = 10; //Needs to be a double to pass to PID library
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED}; // added for thinkgspeak connectivity
unsigned long myChannelNumber = xxxxxx; // added for thinkgspeak connectivity
const char * myWriteAPIKey = "xxxxxx"; // added for thinkgspeak connectivity
/*-----( Declare Variables )-----*/
float O2;
float FlueTemperature;
unsigned long timer;
int ServoPos = 0;
float HeatMeterPower;
double PID_Input,PID_Output;
/*-----( Declare objects )-----*/
// set the LCD address to 0x27 for a 20 chars 4 line display
// Set the pins on the I2C chip used for LCD connections:
// addr, en,rw,rs,d4,d5,d6,d7,bl,blpol
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
AnalogSmooth as_O2 = AnalogSmooth(20);
AnalogSmooth as_Flue = AnalogSmooth(20);
Servo myservo; // create servo object to control a servo
PID myPID(&PID_Input, &PID_Output, &PID_SetPoint,P_PARAM ,I_PARAM ,D_PARAM , DIRECT );
void setup()
{
Serial.println("Setup Start");
pinMode(Led1Pin, OUTPUT);
pinMode(Led2Pin, OUTPUT);
pinMode(LambdaController, OUTPUT);
digitalWrite(LambdaController,HIGH);
digitalWrite(Led1Pin,LOW);
digitalWrite(Led2Pin,LOW);
myservo.attach(myServoPin); // attaches servo
Serial.begin(9600);
lcd.begin(20,4);
lcd.setCursor(3,0); //Start at character 4 on line 0
lcd.print(F("O2 Sensor!"));
delay(1000);
lcd.setCursor(0,1); //Start at character 4 on line 0
lcd.print(F("Begin EthernetClient"));
Ethernet.begin(mac); // added for thinkgspeak connectivity
if (Ethernet.begin(mac) == 1) {
lcd.setCursor(0,2);
lcd.print(F("Ethernet OK "));
delay(1000);
lcd.setCursor(0,2);
lcd.print(F("IP Address.........."));
lcd.setCursor(0,3);
for (byte thisByte = 0; thisByte < 4; thisByte++) {
// print the value of each byte of the IP address:
lcd.print(Ethernet.localIP()[thisByte], DEC);
lcd.print(F("."));} // Print IP Address
}
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("Thingspeak Begin "));
ThingSpeak.begin(client); // added for thinkgspeak connectivity
lcd.setCursor(0,2);
lcd.print(F("OK"));
delay(1000);
lcd.clear();
lcd.setCursor(0,0);
lcd.print(F("ServoSweep"));
// SERVO SWEEP
for (ServoPos = 10; ServoPos <= 180; ServoPos += 1) { // goes from 0 degrees to 180 degrees
// in steps of 1 degree
myservo.write(ServoPos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
for (ServoPos = 180; ServoPos >= 10; ServoPos -= 1) { // goes from 180 degrees to 0 degrees
myservo.write(ServoPos); // tell servo to go to position in variable 'pos'
delay(15); // waits 15ms for the servo to reach the position
}
// SERVO SWEEP
lcd.setCursor(0,1);
lcd.print(F("Complete"));
delay(1000);
lcd.clear();
timer = millis(); //sets timer for thingspeak
Serial.println("Setup Complete");
}/*--(end setup )---*/
void loop()
{
// Read Sensors //
//Flue
int raw = as_Flue.analogReadSmooth(O2FlueTempAnaloguePin); //Smoothed raw flue signal
float Vout = raw * (VOLTAGE_MAX / VOLTAGE_MAXCOUNTS);
FlueTemperature = (Vout-1.25)/0.005;
Serial.print(F("Flue Temperature = "));
Serial.print(FlueTemperature);
Serial.println(F("degC"));
//O2
if(FlueTemperature>FlueThreshold)
{
O2 = as_O2.analogReadSmooth(O2AnaloguePin)*20/VOLTAGE_MAXCOUNTS; // smoothed O2 read
PID_Input = O2;
myPID.SetMode(AUTOMATIC);
myPID.SetOutputLimits(180, 10);
myPID.Compute();
ServoPos = PID_Output;
myservo.write(ServoPos);
}
else
{
O2 = 0;
myPID.SetMode(MANUAL);
ServoPos = SERVO_MAX;
myservo.write(ServoPos); // open damper when boiler off
}
Serial.print(F("O2 = "));
Serial.print(O2);
Serial.println(F("%"));
Serial.print(F("Servo Position = "));
Serial.print(ServoPos);
Serial.println(F("deg"));
//HeatMeter
int Raw = analogRead(HeatMeter);
HeatMeterPower = (Raw - HEATMETERPOWERLOW_BIT) * (HEATMETERPOWERHIGH_KW - HEATMETERPOWERLOW_KW)/ (HEATMETERPOWERHIGH_BIT - HEATMETERPOWERLOW_BIT);
Serial.print(F("Heat Meter = "));
Serial.print(HeatMeterPower,2);
Serial.println(F("kW"));
Serial.println(F(""));
delay(500);
if (millis()-timer >15000)
{
lcd.setCursor(19,3);
lcd.print(F("@"));
digitalWrite(Led2Pin,HIGH);
ThingSpeak.setField(1,O2);
ThingSpeak.setField(2,FlueTemperature);
ThingSpeak.setField(3,HeatMeterPower);
ThingSpeak.setField(4,ServoPos);
Serial.println(F("Thgspkupdate"));
ThingSpeak.writeFields(myChannelNumber, myWriteAPIKey);
Serial.println(F("ThgSpkUpdated"));
timer = millis(); //resets timer for thingspeak
lcd.setCursor(19,3);
lcd.print(F(" "));
digitalWrite(Led2Pin,LOW);
}
else if(millis()-timer <0)
{
timer = 0;
}
}/* --(end main loop )-- */
/* ( THE END ) */