#include <PID_v1.h>
#include <Sensirion.h>
#include <avr/wdt.h>
#include <MemoryFree.h>
const byte RELAYPIN = 6; //fog machine
const byte DATAPIN = 2; // SHTxx serial data
const byte SCLKPIN = 3; // SHTxx serial clock
const byte LCDPIN = 1;
const byte AUTOTURNPIN = 7; //switch to choose RH setpoint
const unsigned long TRHSTEP = 10000; // measure RH every 10 s
const unsigned long LCDTEMP1 = 0; //8s temp display
const unsigned long LCDTEMP2 = 8000;
const unsigned long LCDHUM1 = 16000; //8s RH display
const unsigned long LCDHUM2 = 24000; //8s RH display
const unsigned long LCDTURN = 32000; //8s
const unsigned long LCDPID = 40000; //8s pidinfo
const unsigned long LCDSTOP = 48000;
float PTERM = 2.00;
float ITERM = 0.50;
float DTERM = 1.00;
double Setpoint, Input, Output;
unsigned int rawData;
float temperature;
float humidity = 90.0;
byte measActive = false;
byte measType = TEMP;
unsigned long windowSize = 120000; //in milliseconds, pid windowsize 2 minutes, so pid output ranges from 0 s to 120 s
unsigned long windowStartTime;
unsigned long rhMillis = 0;
unsigned long curMillis=0;
unsigned long lcdMillis=0;
unsigned long timevalue=0;
Sensirion sht = Sensirion(DATAPIN, SCLKPIN);
PID mijnPID(&Input, &Output, &Setpoint,PTERM,ITERM,DTERM, DIRECT);
float humidity1Minute[6] = {
50.0,50.0,50.0,50.0,50.0,50.0};
byte hum1MinIndex = 0;
float averageHum1Min = 50.0;
byte humidity1Hour[60] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte hum1HourIndex = 0;
byte humidity24Hours[24] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte hum24HourIndex = 0;
byte temperature1Minute[6] = {
0,0,0,0,0,0};
byte temp1MinIndex = 0;
byte temperature1Hour[60] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
byte temp1HourIndex = 0;
byte lcdState = 5;
boolean fillUpArray = true;
byte averageTemp1Minute = 0;
byte maxTemp1Minute = 0;
byte minTemp1Minute = 0;
byte averageTemp1Hour = 0;
byte maxTemp1Hour = 0;
byte minTemp1Hour = 0;
byte averageHum1Hour = 0;
byte minHum1Hour = 0;
byte maxHum1Hour = 0;
byte averageHum24Hours = 0;
byte minHum24Hours = 0;
byte maxHum24Hours = 0;
void setup()
{
wdt_enable(WDTO_8S);
averageHum1Min=constrain(averageHum1Min,0.0,100.0);
Serial.begin(19200);
delay(20);
byte stat;
byte error = 0;
mijnPID.SetOutputLimits(0,windowSize); //minimum 0 seconde fog machine on
mijnPID.SetSampleTime(10000);
windowStartTime = 0;
mijnPID.SetMode(AUTOMATIC);
pinMode(RELAYPIN, OUTPUT);
digitalWrite(RELAYPIN, LOW);
pinMode(8, OUTPUT); //no autoturn yet
pinMode(9, OUTPUT);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
pinMode(13, OUTPUT);
digitalWrite(13, LOW);
wdt_reset();
showString(PSTR("?f?n"));
showString(PSTR("***tok**tok**tok****"));
delay(2000);
showString(PSTR("********************"));
showString(PSTR("Bezig met opstarten "));
showString(PSTR("********************"));
showString(PSTR("You toking to me??"));
delay(3000);
lcdMillis = millis();
}
void loop()
{
wdt_reset();
curMillis = millis(); // Get current time
if (digitalRead(AUTOTURNPIN) == HIGH) Setpoint = 600; //538 = 55%, 614 = 60%, change humidity setpoint according to switch position
else Setpoint = 700; //70% RH
pidparameterchange(); //set pid aggressiveness according to distance from setpoint
if (curMillis - rhMillis >= TRHSTEP) // Time for new measurements?
{
digitalWrite(13, HIGH); //LED lights up
measActive = true;
measType = TEMP;
sht.meas(TEMP, &rawData, NONBLOCK); // Start temp measurement
rhMillis = curMillis;
}
if (measActive && sht.measRdy())
{ // Check measurement status
if (measType == TEMP)
{ // Process temp or humi?
measType = HUMI;
temperature = sht.calcTemp(rawData); // Convert raw sensor data
temperature = temperature - 0.9;
sht.meas(HUMI, &rawData, NONBLOCK); // Start humi measurement
}
else
{
measActive = false;
humidity = sht.calcHumi(rawData, temperature); // Convert raw sensor data
digitalWrite(13, LOW); //led off
wdt_reset();
humcalc(); //calculate humidity
tempcalc(); //calculate temperature
}
wdt_reset();
Input = map(humidity,0.0,100.0,0,1023); // input pid rescaled from 0 to 1023
mijnPID.Compute(); //run PID algorithm
if(curMillis - windowStartTime>=windowSize) windowStartTime = curMillis;
if(Output > curMillis - windowStartTime) digitalWrite(RELAYPIN,HIGH); //should the fogger be on
else digitalWrite(RELAYPIN,LOW); //or off?
lcdprint(); //display one of the 6 different screens
wdt_reset();
}
}
void pidparameterchange()
{
if (Setpoint-map(humidity,0.0,100.0,0,1023)>100)
{
PTERM = 10.0;
ITERM = 1.00;
}
else
{
if (Setpoint-map(humidity,0.0,100.0,0,1023)>50)
{
PTERM = 2.0;
ITERM = 0.0;
}
else
{
PTERM = 0.10;
ITERM = 0;
}
}
}
void humcalc() //calculate humidity values
{
humidity1Minute[hum1MinIndex] = floor(humidity+0.5);
averageHum1Min = 0.0;
for (int i=0;i<=5;i++)
{
averageHum1Min += humidity1Minute[i];
}
averageHum1Min /= 6.0; //calculate average humidity in the last minute
if (hum1MinIndex==5)
{
hum1MinIndex=0; //reset index
humidity1Hour[hum1HourIndex] = floor(averageHum1Min + 0.5);
averageHum1Hour = averageValue (59, humidity1Hour);
minHum1Hour = minimumValue (59, humidity1Hour);
maxHum1Hour = maximumValue (59, humidity1Hour);
if (hum1HourIndex == 59) //fill next level
{
hum1HourIndex = 0; //reset index
humidity24Hours[hum24HourIndex] = averageHum1Hour;
averageHum24Hours = averageValue (23, humidity24Hours);
minHum24Hours = minimumValue (23, humidity24Hours);
maxHum24Hours = maximumValue (23, humidity24Hours);
if (hum24HourIndex == 23) hum24HourIndex = 0; //reset index
else hum24HourIndex++;
}
else hum1HourIndex++;
}
else hum1MinIndex++;
}