Afternoon,
I'm making a PID controller for meat curing which will control temperature and humidity with a heater, cooler, humidifier and dehumidifier in a sealed and insulated container. The quirk being that the set point for the RH and temp will change every few hours which may be above or below ambient (hence needing all four output devices).
To provide timing for these changes i'm using the TimeAlarm library, however some of the time periods these set points will be held at for will exceed 24 hours. I'm unsure if its possible for the "timerOnce" command to accept values above 23?
I've been programming without an Arduino in front of me, and it's far from finished code, when i do get a chance to test it, the thought of doing so over 30 or so hours is not something i look forward too. So to save me some time and hopefully get it right first time, could this excellent community browse over my code. I expect there to be many errors! but it does compile.
This is the part that i think i'll probably have a problem with:
Alarm.timerOnce(hour() + prgHour,0,0, prg);
The aim is to reset the alarm that calls the function that this line is within, whilst updating it be called again x amount of hours on top of the current time. The problem being, if the current time was 11pm, and the next phase needed to run for 30 hours, would 23+30 = 2 days and 5 hours later or just a confused Arduino?
Full code:
#include <PID_v1.h>
#include <Time.h>
#include <TimeAlarms.h>
#include <DS1307RTC.h>
#include <LiquidCrystal.h>
#include <Bounce.h>
#include <Encoder.h>
#include <Wire.h>
int RH, Temp, programme, prgStep, prgHour;
// Programme One - Snack Salami
int prgOne[] = {2, 36, 6, 6, 6, 6, 36, 144}; // Hours
int prgOneRH[] = {85, 92, 88, 85, 82, 80, 80, 80}; // Relative Humidity
int prgOneTemp[] = {22, 25, 22, 20, 17, 14, 12, 10}; // Temperature
// Programme Two - Saucison Sec
int prgTwo[] = {2, 48, 6, 6, 6, 12, 72, 144}; // Hours
int prgTwoRH[] = {85, 92, 88, 85, 82, 80, 80, 80}; // Relative Humidity
int prgTwoTemp[] = {22, 25, 22, 20, 17, 14, 12, 10}; // Temperature
// Programme three - Bacon
int prgThree[] = {2, 12, 3, 3, 3, 3, 3, 9}; // Hours
int prgThreeRH[] = {85, 92, 88, 85, 82, 80, 80, 80}; // Relative Humidity
int prgThreeTemp[] = {22, 25, 22, 20, 17, 14, 12, 10}; // Temperature
// Programme Four - Large Meat
int prgFour[] = {2, 60, 12, 12, 12, 12, 48, 132}; // Hours
int prgFourRH[] = {85, 92, 88, 85, 82, 80, 80, 80}; // Relative Humidity
int prgFourTemp[] = {22, 25, 22, 20, 17, 14, 12, 10}; // Temperature
//heater
double heInput, heOutput, heSetpoint;
double heKp = 1, heKi = 0.05, heKd = 0.25;
int windowSize = 5000;
unsigned long windowStartTime;
//cooler
double coInput, coOutput, coSetpoint;
double coKp = 1, coKi = 0.05, coKd = 0.25;
//humidifier
double huInput, huOutput, huSetpoint;
double huKp = 1, huKi = 0.05, huKd = 0.25;
//dehumidifier
double deInput, deOutput, deSetpoint;
double deKp = 1, deKi = 0.05, deKd = 0.25;
PID heater(&heInput, &heOutput, &heSetpoint, heKp, heKi, heKd, DIRECT);
PID cooler(&coInput, &coOutput, &coSetpoint, coKp, coKi, coKd, REVERSE);
PID humidifier(&huInput, &huOutput, &huSetpoint, huKp, huKi, huKd, DIRECT);
PID dehumidifier(&deInput, &deOutput, &deSetpoint, deKp, deKi, deKd, REVERSE);
void setup()
{
Serial.begin(9600);
setTime(0,0,0,1,1,13); // set time to Saturday 0:00:00am Jan 1 2013
// setTime to be synced to RTC
// Select program, map to 1,2,3 or 4
programme = 1; // call function to get user input
prgStep = 0;
//Alarm.timerOnce(now() + prgHour,0,0, prg);
prg;
heInput = analogRead(0); // needs changing to input pin
coInput = heInput;
huInput = analogRead(0); // needs changing to input pin
deInput = huInput;
heSetpoint = Temp;
coSetpoint = Temp;
huSetpoint = RH;
deSetpoint = RH;
windowStartTime = millis();
heater.SetOutputLimits(0, windowSize);
heater.SetMode(AUTOMATIC);
cooler.SetMode(AUTOMATIC);
humidifier.SetMode(AUTOMATIC);
dehumidifier.SetMode(AUTOMATIC);
//output RH and Temp values to PID and initilise
}
void loop(){
Alarm.delay(0); // wait one second between clock display
heInput = analogRead(0); // needs changing to input pin
coInput = heInput;
huInput = analogRead(0); // needs changing to input pin
deInput = huInput;
heater.Compute();
cooler.Compute();
humidifier.Compute();
dehumidifier.Compute();
unsigned long now = millis();
if(now - windowStartTime>windowSize){ //time to shift the Relay Window
windowStartTime += windowSize;
}
if(heOutput > now - windowStartTime){
digitalWrite(1,HIGH); // Needs changing to output pin
}
else{
digitalWrite(1,LOW); // Needs changing to output pin
}
analogWrite(1, coOutput); // Needs changing to output pin
analogWrite(1, huOutput); // Needs changing to output pin
analogWrite(1, deOutput); // Needs changing to output pin
//write statistics to the screen and monitor buttons for exit (with conformation)
//feedback current step, current temp, target temp, current RH, target RH, time left total, time to next step
}
void restart(){
RH = 80;
Temp = 10;
programme = 2;// call function to get user input
//setTime(0,0,0,1,1,13);
prgStep = 0;
}
void prg(){
if(prgStep == 8){
restart;
return;
}
else {
switch (programme) {
case 1:{ // Programme One - Snack Salami
prgHour = prgOne[prgStep];
RH = prgOneRH[prgStep];
Temp = prgOneTemp[prgStep];
break;
}
case 2:{ // Programme Two - Saucison Sec
prgHour = prgTwo[prgStep];
RH = prgTwoRH[prgStep];
Temp = prgTwoTemp[prgStep];
break;
}
case 3:{ // Programme three - Bacon
prgHour = prgThree[prgStep];
RH = prgThreeRH[prgStep];
Temp = prgThreeTemp[prgStep];
break;
}
case 4:{ // Programme Four - Large Meat
prgHour = prgFour[prgStep];
RH = prgFourRH[prgStep];
Temp = prgFourTemp[prgStep];
break;
}
}
Alarm.timerOnce(hour() + prgHour,0,0, prg);
prgStep = prgStep + 1;
Serial.println("Program ");
Serial.print(programme);
Serial.print(". Step ");
Serial.print(prgStep -1);
Serial.print(" of 8.");
}
}