#include <EEPROM.h>
#define INIT_ADDR 1023 // номер резервной ячейки
#define INIT_KEY 50 // ключ первого запуска. 0-254, на выбор
uint32_t myTimer1, myTimer2, lastTime;
#define USE_SERIAL_2004_LCD
#include "LCDBigNumbers.hpp"
#include <LiquidCrystal_I2C.h>
LiquidCrystal_I2C lcd(0x27, 20, 4);
LCDBigNumbers bigNumberLCD(&lcd, BIG_NUMBERS_FONT_3_COLUMN_2_ROWS_VARIANT_2);
// byte doorClose1[] = {
// B11111,
// B10000,
// B10000,
// B10000,
// B10001,
// B10011,
// B10111,
// B11111
// };
// byte doorClose2[] = {
// B11111,
// B00111,
// B01111,
// B11111,
// B11111,
// B11111,
// B11111,
// B11111
// };
// byte doorClose3[] = {
// B11111,
// B10111,
// B10011,
// B10001,
// B10000,
// B10000,
// B10000,
// B11111
// };
// byte doorClose4[] = {
// B11111,
// B11111,
// B11111,
// B11111,
// B11111,
// B10111,
// B10011,
// B11111
// };
// byte doorOpen1[] = {
// B11111,
// B10000,
// B10000,
// B10000,
// B10000,
// B10000,
// B10000,
// B10000
// };
// byte doorOpen2[] = {
// B11111,
// B00001,
// B00001,
// B00001,
// B00001,
// B00001,
// B00001,
// B00001
// };
// byte doorOpen3[] = {
// B10000,
// B10000,
// B11000,
// B11000,
// B11100,
// B11100,
// B11110,
// B11111
// };
// byte doorOpen4[] = {
// B10000,
// B10000,
// B10000,
// B10000,
// B10000,
// B10000,
// B10000,
// B11111
// };
// byte doorOpen5[] = {
// B00001,
// B00001,
// B00001,
// B00001,
// B00001,
// B00001,
// B00001,
// B11111
// };
// byte doorOpen6[] = {
// B11111,
// B11110,
// B11100,
// B11100,
// B11000,
// B11000,
// B10000,
// B10000
// };
#include <EncButton.h>
EncButton eb(2, 3, 4);
#include <dht.h>
#define DHTPINa 5
#define DHTPINb 6
dht DHTa;
dht DHTb;
struct Data {
uint8_t tempin = 25;
uint8_t tempout = 15;
uint32_t secInt = 5;
bool ventOn = false;
bool ventOnChk = false;
boolean releyFlag1 = HIGH;
boolean releyFlag2 = HIGH;
};
Data data;
typedef enum {
SET_VIS,
SET_HID,
SET_INT,
} Mode1;
Mode1 mode1 = SET_VIS;
typedef enum {
SET_TEMPIN,
SET_TEMPOUT,
} Mode;
Mode mode = SET_TEMPIN;
void nextMode1() {
switch (mode1) {
case SET_VIS:
mode1 = SET_HID;
break;
case SET_HID:
mode1 = SET_INT;
break;
case SET_INT:
mode1 = SET_VIS;
break;
}
}
void nextMode() {
switch (mode) {
case SET_TEMPIN:
mode = SET_TEMPOUT;
break;
case SET_TEMPOUT:
mode = SET_TEMPIN;
break;
}
}
void printDHT(const uint8_t pina, const uint8_t pinb) // uint8_t is an 8 bit unsigned integer
{
int chka = DHTa.read22(pina);
int chkb = DHTb.read22(pinb);
if (chka == DHTLIB_OK)
{
lcd.setCursor(0, 2);
lcd.print(" ");
lcd.setCursor(3, 2);
lcd.print(DHTa.temperature, 1);
} else{
switch (chka)
{
case DHTLIB_ERROR_CHECKSUM:
lcd.setCursor(3, 2);
lcd.print("CHSM");
break;
case DHTLIB_ERROR_TIMEOUT:
lcd.setCursor(3, 2);
lcd.print("TIMO");
break;
case DHTLIB_ERROR_CONNECT:
lcd.setCursor(3, 2);
lcd.print("NCNN");
break;
case DHTLIB_ERROR_ACK_L:
lcd.setCursor(3, 2);
lcd.print("ACKL");
break;
case DHTLIB_ERROR_ACK_H:
lcd.setCursor(3, 2);
lcd.print("ACKH");
break;
default:
lcd.setCursor(3, 2);
lcd.print("UNKN");
break;
}
}
if (chkb == DHTLIB_OK)
{
lcd.setCursor(13, 2);
lcd.print(DHTb.temperature, 1);
} else{
switch (chkb)
{
case DHTLIB_ERROR_CHECKSUM:
lcd.setCursor(13, 2);
lcd.print("CHSM");
break;
case DHTLIB_ERROR_TIMEOUT:
lcd.setCursor(13, 2);
lcd.print("TIMO");
break;
case DHTLIB_ERROR_CONNECT:
lcd.setCursor(13, 2);
lcd.print("NCNN");
break;
case DHTLIB_ERROR_ACK_L:
lcd.setCursor(13, 2);
lcd.print("ACKL");
break;
case DHTLIB_ERROR_ACK_H:
lcd.setCursor(13, 2);
lcd.print("ACKH");
break;
default:
lcd.setCursor(13, 2);
lcd.print("UNKN");
break;
}
}
return ;
}
void hidPrintDHT(const uint8_t pina, const uint8_t pinb) // uint8_t is an 8 bit unsigned integer
{
int chka = DHTa.read22(pina);
int chkb = DHTb.read22(pinb);
if (chka == DHTLIB_OK)
{
lcd.setCursor(0, 3);
lcd.print(" ");
// lcd.setCursor(2, 3);
// lcd.print("(");
lcd.setCursor(3, 3);
lcd.print(DHTa.temperature, 1);
// lcd.setCursor(8, 3);
// lcd.print(")");
} else{
switch (chka)
{
case DHTLIB_ERROR_CHECKSUM:
lcd.setCursor(3, 3);
lcd.print("CHSM");
break;
case DHTLIB_ERROR_TIMEOUT:
lcd.setCursor(3, 3);
lcd.print("TIMO");
break;
case DHTLIB_ERROR_CONNECT:
lcd.setCursor(3, 3);
lcd.print("NCNN");
break;
case DHTLIB_ERROR_ACK_L:
lcd.setCursor(3, 3);
lcd.print("ACKL");
break;
case DHTLIB_ERROR_ACK_H:
lcd.setCursor(3, 3);
lcd.print("ACKH");
break;
default:
lcd.setCursor(3, 3);
lcd.print("UNKN");
break;
}
}
if (chkb == DHTLIB_OK)
{
// lcd.setCursor(12, 3);
// lcd.print("(");
lcd.setCursor(13, 3);
lcd.print(DHTb.temperature, 1);
// lcd.setCursor(18, 3);
// lcd.print(")");
} else{
switch (chkb)
{
case DHTLIB_ERROR_CHECKSUM:
lcd.setCursor(13, 3);
lcd.print("CHSM");
break;
case DHTLIB_ERROR_TIMEOUT:
lcd.setCursor(13, 3);
lcd.print("TIMO");
break;
case DHTLIB_ERROR_CONNECT:
lcd.setCursor(13, 3);
lcd.print("NCNN");
break;
case DHTLIB_ERROR_ACK_L:
lcd.setCursor(13, 3);
lcd.print("ACKL");
break;
case DHTLIB_ERROR_ACK_H:
lcd.setCursor(13, 3);
lcd.print("ACKH");
break;
default:
lcd.setCursor(13, 3);
lcd.print("UNKN");
break;
}
}
return ;
}
void updateValue(int delta) {
switch (mode) {
case SET_TEMPIN:
data.tempin = constrain(data.tempin + (-delta), 0, 100);
break;
case SET_TEMPOUT:
data.tempout = constrain(data.tempout + (-delta), 0, 100);
break;
}
}
void updateValue1(int delta) {
data.secInt = constrain(data.secInt + (-delta), 0, 1000);
}
void updateDisplay() {
switch (mode1) {
case SET_VIS:
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp/in");
lcd.setCursor(3, 3);
lcd.print("(");
lcd.setCursor(4, 3);
lcd.print(data.tempin);
lcd.setCursor(6, 3);
lcd.print(")");
lcd.setCursor(12, 0);
lcd.print("Temp/out");
lcd.setCursor(13, 3);
lcd.print("(");
lcd.setCursor(14, 3);
lcd.print(data.tempout);
lcd.setCursor(16, 3);
lcd.print(")");
break;
case SET_HID:
lcd.clear();
lcd.setCursor(1, 0);
lcd.print("Temp/in");
lcd.setCursor(4, 2);
lcd.print(data.tempin);
if (mode == SET_TEMPIN) {
lcd.setCursor(3, 2);
lcd.print(">");
}
lcd.setCursor(11, 0);
lcd.print("Temp/out");
lcd.setCursor(14, 2);
lcd.print(data.tempout);
if (mode == SET_TEMPOUT) {
lcd.setCursor(13, 2);
lcd.print(">");
}
break;
case SET_INT:
lcd.clear();
lcd.setCursor(3, 0);
lcd.print("Interval reley");
bigNumberLCD.setBigNumberCursor(5, 2);
bigNumberLCD.print(data.secInt, 1);
break;
}
lcd.display();
}
void printDoorClose(){
lcd.setCursor(9, 0);
lcd.print("-");
// lcd.setCursor(10, 0);
// lcd.print(" ");
// lcd.setCursor(10, 1);
// lcd.print(" ");
// lcd.createChar(0, doorClose1);
// lcd.createChar(1, doorClose2);
// lcd.createChar(2, doorClose3);
// lcd.createChar(3, doorClose4);
// lcd.setCursor(8, 0);
// lcd.write(0);
// lcd.setCursor(9, 0);
// lcd.write(1);
// lcd.setCursor(8, 1);
// lcd.write(2);
// lcd.setCursor(9, 1);
// lcd.write(3);
}
void printDoorOpen(){
lcd.setCursor(9, 0);
lcd.print("+");
// lcd.createChar(0, doorOpen1);
// lcd.createChar(1, doorOpen2);
// lcd.createChar(2, doorOpen3);
// lcd.createChar(3, doorOpen4);
// lcd.createChar(4, doorOpen5);
// lcd.createChar(5, doorOpen6);
// lcd.setCursor(8, 0);
// lcd.write(0);
// lcd.setCursor(9, 0);
// lcd.write(1);
// lcd.setCursor(10, 0);
// lcd.write(2);
// lcd.setCursor(8, 1);
// lcd.write(3);
// lcd.setCursor(9, 1);
// lcd.write(4);
// lcd.setCursor(10, 1);
// lcd.write(5);
}
void setup() {
Serial.begin(9600);
pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
pinMode(12, OUTPUT);
digitalWrite(9, data.releyFlag2);
digitalWrite(10, data.releyFlag1);
digitalWrite(11, data.releyFlag2);
digitalWrite(12, data.releyFlag1);
if (EEPROM.read(INIT_ADDR) != INIT_KEY) { // первый запуск
EEPROM.write(INIT_ADDR, INIT_KEY); // записали ключ
EEPROM.put(0, data);
}
EEPROM.get(0, data);
eb.setBtnLevel(LOW);
eb.setClickTimeout(100);
eb.setDebTimeout(50);
eb.setHoldTimeout(600);
eb.setStepTimeout(100);
eb.setEncReverse(0);
eb.setEncType(EB_STEP4_LOW);
eb.setFastTimeout(30);
// сбросить счётчик энкодера
eb.counter = 0;
lcd.begin(20, 4);
lcd.init();
lcd.backlight();
bigNumberLCD.begin();
updateDisplay();
data.ventOnChk ? printDoorOpen() : printDoorClose();
}
void loop() {
eb.tick();
if (eb.hold()) {
EEPROM.put(0, data);
nextMode1();
updateDisplay();
}
if (mode1 == SET_VIS) {
if (millis() - lastTime >= 2000) // print every 2000 milliseconds
{
lastTime = millis();
printDHT(DHTPINa, DHTPINb);
}
if (data.releyFlag2 && !data.ventOn && data.ventOn == data.ventOnChk && DHTa.temperature > data.tempin) {
data.ventOn = !data.ventOn;
data.releyFlag1 = !data.releyFlag1;
EEPROM.put(0, data);
digitalWrite(12,data.releyFlag1); // вкл/выкл
digitalWrite(10,data.releyFlag1); // вкл/выкл
myTimer1 = millis();
Serial.print("Open "); // вкл/выкл
Serial.print(digitalRead(12)); // вкл/выкл
Serial.print(digitalRead(10)); // вкл/выкл
Serial.println(data.releyFlag1); // вкл/выкл
printDoorOpen();
}
if (!data.releyFlag1 && millis() - myTimer1 >= (data.secInt*1000)) {
data.ventOnChk = data.ventOn;
data.releyFlag1 = !data.releyFlag1;
EEPROM.put(0, data);
digitalWrite(10,data.releyFlag1); // вкл/выкл
digitalWrite(12,data.releyFlag1); // вкл/выкл
myTimer1 = millis(); // сбросить таймер
Serial.print("Off Open "); // вкл/выкл
Serial.print(digitalRead(12)); // вкл/выкл
Serial.print(digitalRead(10)); // вкл/выкл
Serial.println(data.releyFlag1); // вкл/выкл
printDoorOpen();
}
if (data.releyFlag1 && data.ventOn && data.ventOn == data.ventOnChk && DHTa.temperature < data.tempout && DHTa.read22(DHTPINa) == DHTLIB_OK) {
data.ventOn = !data.ventOn;
data.releyFlag2 = !data.releyFlag2;
EEPROM.put(0, data);
digitalWrite(11,data.releyFlag2); // вкл/выкл
digitalWrite(9,data.releyFlag2); // вкл/выкл
myTimer1 = millis();
Serial.print("Close "); // вкл/выкл
Serial.print(digitalRead(11)); // вкл/выкл
Serial.print(digitalRead(9)); // вкл/выкл
Serial.println(data.releyFlag2); // вкл/выкл
printDoorClose();
}
if (!data.releyFlag2 && millis() - myTimer1 >= (data.secInt*1000)) {
data.ventOnChk = data.ventOn;
data.releyFlag2 = !data.releyFlag2;
EEPROM.put(0, data);
digitalWrite(11,data.releyFlag2); // вкл/выкл
digitalWrite(9,data.releyFlag2); // вкл/выкл
myTimer1 = millis(); // сбросить таймер
Serial.print("Off Close "); // вкл/выкл
Serial.print(digitalRead(11)); // вкл/выкл
Serial.print(digitalRead(9)); // вкл/выкл
Serial.println(data.releyFlag2); // вкл/выкл
printDoorClose();
}
}
if (mode1 == SET_HID) {
if (millis() - lastTime >= 2000) // print every 2000 milliseconds
{
lastTime = millis();
hidPrintDHT(DHTPINa, DHTPINb);
}
}
if (eb.hasClicks() && mode1 == SET_HID) {
nextMode();
updateDisplay();
}
if (eb.turn() && mode1 == SET_HID) {
updateValue(eb.dir());
updateDisplay();
}
if (eb.turn() && mode1 == SET_INT) {
updateValue1(eb.dir());
updateDisplay();
}
}