Κώδικας:
#include <Keypad.h>
#include <LiquidCrystal.h>
#include <WString.h>
#include <EEPROM.h>
#include <Wire.h>
#include <PID_v1.h>
//****************************************************************************************************
#define HotSolenoidPin 40
#define ColdSolenoidPin 41
//****************************************************************************************************
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
//****************************************************************************************************
#define RIGHT 0
#define UP 1
#define DN 2
#define LEFT 3
#define MENU 4
#define LM75_ADDRESS 0x4F
#define DS1307_I2C_ADDRESS 0x68
//****************************************************************************************************
float temp;
float setTemp;
float farenheit;
const int DEBOUNCE_DELAY = 50;
byte screenRefresh = 120;
int command = 0; // This is the command char, in ascii form, sent from the serial port
int i;
long previousMillis = 0; // will store last time Temp was updated
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
byte test;
int hourBuffer, minuteBuffer, secondBuffer, dateBuffer, monthBuffer, yearBuffer = 0;
double aggKp=8, aggKi=8, aggKd=8;
double consKp=1, consKi=0.05, consKd=0.25;
double Setpoint, Input, Output;
//Specify the links and initial tuning parameters
PID myPID(&Input, &Output, &Setpoint,aggKp,aggKi,aggKd, DIRECT);//2,5,1
int WindowSize = 750;
unsigned long windowStartTime;
// Default menu choice
byte screen = 2;
byte lastScreen = 4;
//****************************************************************************************************
//Key message
int adcKeyIn;
int NUM_KEYS = 5;
int key=-1;
int oldKey=-1;
int adcKeyVal[5] ={ 30, 150, 360, 535, 760 };
//****************************************************************************************************
byte FI[8] = {
B01110,
B10101,
B10101,
B10101,
B01110,
B00100,
B00100,
B00000
};
byte PSI[8] = {
B10101,
B10101,
B10101,
B01110,
B00100,
B00100,
B00100,
B00000
};
byte down_arrow[8] = {
B00000,
B00000,
B00000,
B00000,
B10001,
B01010,
B00100,
B00000
};
byte GAMMA[8] = {
B11111,
B10000,
B10000,
B10000,
B10000,
B10000,
B10000,
B00000
};
byte DELTA[8] = {
B00100,
B01010,
B10001,
B10001,
B10001,
B10001,
B11111,
B00000
};
byte LAMDA[8] = {
B00100,
B01010,
B10001,
B10001,
B10001,
B10001,
B10001,
B00000
};
byte KSI[8] = {
B11111,
B00000,
B00000,
B01110,
B00000,
B00000,
B11111,
B00000
};
byte PEE[8] = {
B11111,
B10001,
B10001,
B10001,
B10001,
B10001,
B10001,
B00000
};
//****************************************************************************************************
//****************************************************************************************************
void setup()
{
lcd.createChar(0, FI);
lcd.createChar(1, PSI);
lcd.createChar(2, down_arrow);
lcd.createChar(3, GAMMA);
lcd.createChar(4, DELTA);
lcd.createChar(5, LAMDA);
lcd.createChar(6, KSI);
lcd.createChar(7, PEE);
Wire.begin();
lcd.begin(16, 2);
pinMode(HotSolenoidPin, OUTPUT);
lcd.setCursor(0,0);
lcd.print(" HOT WATER MIXER");
lcd.setCursor(0,1);
lcd.print(" v1.0 ");
delay(2000);
lcd.clear();
windowStartTime = millis();
//initialize the variables we're linked to
Setpoint = 50;
setTemp = Setpoint;
myPID.SetSampleTime(500);
//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()
{
Input = temp;
myPID.Compute();
/************************************************
* turn the output pin on/off based on pid output
************************************************/
unsigned long now = millis();
if(now - windowStartTime>WindowSize)
{ //time to shift the Relay Window
windowStartTime += WindowSize;
}
if(Output > now - windowStartTime) digitalWrite(HotSolenoidPin,LOW);
else digitalWrite(HotSolenoidPin,HIGH);
screen_1();
delay(500);
showTemp();
}
//****************************************************************************************************
// Convert ADC value to key number
int getKey(unsigned int input)
{
int k;
for (k = 0; k < NUM_KEYS; k++)
{
if (input < adcKeyVal[k])
{
return k;
}
}
if (k >= NUM_KEYS)
k = -1; // No valid key pressed
return k;
}
//****************************************************************************************************
int getKeyDebounce()
{
// wait for no keypress, then return keypress held for debounce period
adcKeyIn = analogRead(0); // read the value from the sensor
key = getKey(adcKeyIn); // convert into key press
do
{
key = getKey(analogRead(0));
}
while (key != -1);
oldKey = key;
while (oldKey == -1 || key == -1 || key != oldKey)
{
oldKey = key;
delay(DEBOUNCE_DELAY);
key = getKey(analogRead(0));
}
return key;
}
//****************************************************************************************************
void getTemp()
{
Wire.beginTransmission(LM75_ADDRESS);
Wire.send(0x00);
Wire.requestFrom(LM75_ADDRESS, 1);
if (Wire.available())
{
temp = Wire.receive();
}
Wire.endTransmission();
}
//****************************************************************************************************
void showTemp()
{
getTemp(); lcd.setCursor(8,0); lcd.print(temp);
lcd.setCursor(8,1); lcd.print(setTemp);
}
//****************************************************************************************************
// Convert normal decimal numbers to binary coded decimal
byte decToBcd(byte val)
{
return ( (val/10*16) + (val%10) );
}
//****************************************************************************************************
// Convert binary coded decimal to normal decimal numbers
byte bcdToDec(byte val)
{
return ( (val/16*10) + (val%16) );
}
//****************************************************************************************************
void setDateDs1307()
{
/* second = (byte) ((Serial.read() - 48) * 10 + (Serial.read() - 48)); // Use of (byte) type casting and ascii math to achieve result.
minute = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
hour = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
dayOfWeek = (byte) (Serial.read() - 48);
dayOfMonth = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
month = (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
year= (byte) ((Serial.read() - 48) *10 + (Serial.read() - 48));
*/
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x01);
Wire.send(decToBcd(second)); // 0 to bit 7 starts the clock
Wire.send(decToBcd(minute));
Wire.send(decToBcd(hour)); // If you want 12 hour am/pm you need to set
// bit 6 (also need to change readDateDs1307)
Wire.send(decToBcd(dayOfWeek));
Wire.send(decToBcd(dayOfMonth));
Wire.send(decToBcd(month));
Wire.send(decToBcd(year));
Wire.endTransmission();
}
//****************************************************************************************************
// Gets the date and time from the ds1307 and prints result
void getDateDs1307()
{
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(0x01);
Wire.endTransmission();
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
second = bcdToDec(Wire.receive() & 0x7f);
minute = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(Wire.receive());
dayOfMonth = bcdToDec(Wire.receive());
month = bcdToDec(Wire.receive());
year = bcdToDec(Wire.receive());
}
//****************************************************************************************************
//****************************************************************************************************
void screen_1()
{
lcd.setCursor(0,0);
lcd.print("Out T"); lcd.write(223); lcd.print("= "); lcd.setCursor(13,0); lcd.print(" "); lcd.write(223); lcd.print("C");
lcd.setCursor(0,1);
lcd.print("Set T"); lcd.write(223); lcd.print("= "); lcd.setCursor(13,1); lcd.print(" "); lcd.write(223); lcd.print("C");
}
//****************************************************************************************************
void showMenu()
{
boolean inMenu = 0;
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(" Please select ");
lcd.setCursor(0, 1);
lcd.print(" mode: ");
lastScreen = 100;
delay(2000);
while (inMenu == 0)
{
if ((screen == 0)&&(lastScreen != 0))
{
lcd.clear();
lcd.print("Set Target Temp");
lastScreen = 0;
}
if ((screen == 1)&&(lastScreen != 1))
{
lcd.clear();
lcd.print("^ ");
lcd.print("Target Temp "); lcd.write(223); lcd.print("C");
lcd.setCursor(0,1); lcd.write(2); lcd.print(" ");
lcd.print("Target Temp "); lcd.write(223); lcd.print("F");
lastScreen = 1;
}
if ((screen == 2)&&(lastScreen != 2))
{
lcd.clear();
lcd.print('^');
lcd.print(" Date, time");
lcd.setCursor(0,1);
lcd.write(2);
lastScreen = 2;
}
if ((screen == 3)&&(lastScreen != 3))
{
lcd.clear();
lcd.print('^');
lcd.print(" Options");
lastScreen = 3;
}
switch (getKeyDebounce())
{
case 1:
if (screen != 0)
screen--;
break;
case 2:
if (screen != 3)
screen++;
break;
case 4:
inMenu = 1;
break;
}
}
if (screen == 2){}
// bla bla bla
if (screen == 4){}
//bla bla bla
screenRefresh = 120;
}