/*********************************************************************
Работа с газовыми сенсорами для управления открытием и закрытием окна
в зависимости от загрязнения атмосферы
**********************************************************************/
#include <Wire.h> //библиотека для дисплея
#include <LiquidCrystal_I2C.h> //библиотека для дисплея
#include <dht11.h>//библиотека для датчика температуры и влажности
//-------------------
String inputString = ""; // строка для приема данных от компьютера
int invar1; // данные с компьютера
int invar2; // данные с компьютера
char bufstr[10]; // массив для передачи данных в компьютер
//-------------------
#if defined(ARDUINO) && ARDUINO >= 100
#define printByte(args) write(args);
#else
#define printByte(args) print(args,BYTE);
#endif
//----массивы символов для дисплея------------
uint8_t heart[8] = {0x0, 0xa, 0x1f, 0x1f, 0xe, 0x4, 0x0}; //сердечко
uint8_t celc[8] = {0xc, 0x12, 0x12, 0xc, 0x0, 0x0, 0x0}; //цельсия
//--------------------------------------------
LiquidCrystal_I2C lcd(0x27, 16, 2); // установить адрес для дисплея 0x27 (16 символов и 2 строки
dht11 DHT11;
#define DHT11PIN 2 //pin 2 для снятия отсчета с датчика
String instring = "";
int sensorValue0 = A0;
int sensorValue1 = A1;
int sensorTermo = A3;
int Value0 = 0;
int Value1 = 0;
int Val_cikl = 0;
//******изменяемые параметры**************
int Value0_max = 40; //красная зона
int Value0_min = 30; //желтая зона
int Value1_max = 90; //красная зона
int Value1_min = 75; //желтая зона
int time_open = 5; //время открытия окна сек.
int period = 300; //частота отсчетов
//****************************************
boolean window_open = true;
int open_level = 20;
int ledState = LOW;
int count_opencom = 16; //время полного открытия окна
//****************************************************
int buf_int; //временный буфер
//****************
void setup() {
Serial.begin(9600);
pinMode(DHT11PIN, INPUT); //установить 2 ножку на ввод
DDRD = B01100000; //установить 5 и 6 ноги на вывод //pinMode(window_on, OUTPUT);
lcd.init(); // initialize the lcd
lcd.backlight();
lcd.createChar(3, heart); //записать матрицу символа сердечко
lcd.createChar(4, celc); //записать матрицу символа градус
lcd.home(); //Перемещает курсор в левый верхний угол экрана.
lcd.print("This programm by");
lcd.setCursor(0, 1); //перевести курсор на вторую строку
lcd.print("Ruben Lachinov ");
lcd.printByte(3); //сердечко
//---передача настроек в компьютер---
save_info();
}
void loop() {
if (ledState == LOW) { //частота преобразований 13
ledState = HIGH;
PORTB = PORTB | B00100000;
} else {
ledState = LOW;
PORTB = PORTB & B11011111;
}
//=============================
int chk = DHT11.read(DHT11PIN); //снять информацию с сенсора DHT11
//=============================
Value0 = Value0 + analogRead(A0);
delay(10);
Value1 = Value1 + analogRead(A1);
delay(10);
Val_cikl = Val_cikl + 1;
if (Val_cikl == 8)
{
Val_cikl = 0;
// lcd.clear();
Value0 = Value0 / 8;
Value1 = Value1 / 8;
//получили усредненное значение после 8ми измерений
if (window_open == true and Value0 >= Value0_max)
{ //закрыть окно
win_open(-1, 16, 0); //count_opencom);
}
else if (window_open == false and Value0 <= Value0_min)
{ //открыть окно
win_open(1, time_open, 0); //count_opencom);
} else if (Value1 >= Value1_max and Value0 <= Value0_min and count_opencom < 16)
{ //приоткрыть окно
win_open(1, 1, 0);
}
instring = "@f";
instring += Value0, DEC;
Serial.println(instring);
delay(1);
instring = "@s";
instring += Value1, DEC;
Serial.println(instring);
//****************** LCD ****************
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("C=");
lcd.print((float)DHT11.temperature, 0);
lcd.printByte(4); //цельсия
lcd.print(" H=");
lcd.print((float)DHT11.humidity, 0);
lcd.print("%");
lcd.setCursor(0, 1);
lcd.print(" "); lcd.print(Value0, DEC); lcd.print(" // ");
lcd.print(Value1, DEC);
instring = "@t";
instring += (float)DHT11.temperature;
Serial.println(instring);
instring = "@h";
instring += (float)DHT11.humidity;
Serial.println(instring);
Value0 = 0;
Value1 = 0;
}
delay(period); // delay in between reads for stability
}

void serialEvent() {
while (Serial.available()) {
char inChar = (char)Serial.read(); // принять новый байт:
inputString += inChar; // добавить в inputString:
if (inChar == ';') { // признак конца сообщения
decoder(); // расшифровать послание
inputString = ""; //очистить строку
break; //выйти из цикла
}
}
inputString = "";
}

void decoder() {
int vvv = firstkey(inputString);
//==============================
switch (vvv) {
case 1: //канал A0 - установка границ
Value0_max = invar1; //красная зона
Value0_min = invar2; //желтая зона
break;
case 2: //канал A1 - установка границ
Value1_max = invar1; //красная зона
Value1_min = invar2; //желтая зона
break;
case 3: //открыть/закрыть окно
win_open(invar1, invar2, 1);
break;
case 4: //время открытия
time_open = invar1;
break;
case 5: //период
period = invar1;
break;
case 6: //передать установки в компьютер
save_info(); break;
case 7: break;//резерв
default: invar2 = 2;
}
}

int firstkey(String buf_str) {
int result;
String str1 = buf_str;
int lenstr = str1.length();
str1.remove(2, lenstr - 2); //оставили первые два сивола
if (str1 == "%a") result = 1; else //канал A0 - 2 параметра
if (str1 == "%b") result = 2; else //канал A1 - 2 параметра
if (str1 == "%w") result = 3; else //открыть/закрыть окно
if (str1 == "%t") result = 4; else //время открытия
if (str1 == "%p") result = 5; else //период опроса датчиков
if (str1 == "%i") result = 6; else //передать установки в компьютер
if (str1 == "%r") result = 7; else //резерв
result = 0;
//===
if (result != 0) { //есть данные - выделение параметров.
buf_str.remove(0, 2); //удалили первые два символа
str1 = buf_str;
int buf_int = str1.indexOf(",");
int lenstr = str1.length();
str1.remove(buf_int, lenstr);
invar1 = str1.toInt();
str1 = buf_str; //принятая строка без первых 2х символов
buf_int = str1.indexOf(",");
str1.remove(0, buf_int + 1); //удалить все до запятой
buf_int = str1.indexOf(";");
lenstr = str1.length();
str1.remove(buf_int, lenstr);
invar2 = str1.toInt();
}
return result;
}
void win_open(int win_com, int win_time, int key_in) {
switch (win_com) {
case 0: //снять напряжение
PORTD = PORTD & B10011111; //сброс 5 и 6 ножки
break;
case 1: //открыть окно
PORTD = PORTD & B10011111; //сброс 5 и 6 ножки
PORTD = PORTD | B00100000; //сигнал на 5 ногу - открыть окно
if (key_in == 0) window_open = true; //иначе без изменения флага открытого окна
count_opencom = count_opencom + win_time;
if (count_opencom > 16 ) count_opencom = 16;
break;
case -1: //закрыть окно
PORTD = PORTD & B10011111; //сброс 5 и 6 ножки
PORTD = PORTD | B01000000; //сигнал на 6 ногу - закрыть окно
if (key_in == 0) window_open = false;
count_opencom = count_opencom - win_time;
if (count_opencom < 0 ) count_opencom = 0;
break;
}
delay(win_time * 1000);
PORTD = PORTD & B10011111; //сброс 5 и 6 ножки
open_level = open_level + win_com * win_time * 10; //10 * кол-во секунд
if (open_level < 0 ) open_level = 0;
instring = "@w";
instring += String(open_level);
instring += ",";
instring += String(count_opencom);
Serial.println(instring); //установить на компьютере индикатор открытого окна
}

void save_info(void) {
save_date("@a", Value0_max, Value0_min);//формирование строки с параметрами первого канала
//"@a" - префикс первого канала, Value0_max - граница красной зоны,Value0_min - граница желтой зоны
save_date("@b", Value1_max, Value1_min);
save_date("@w", open_level, count_opencom);
save_date("@v", time_open, 0);
save_date("@p", period, 0);
}
void save_date(String prefics, int par1, int par2) {
instring = prefics; // instring = "@a"; //префикс первого канала
instring += par1, DEC; //instring += Value0_max, DEC; //граница красной зоны
if (par2 != 0) {
instring += ","; //разделитель значений
instring += par2, DEC; //instring += Value0_min, DEC; //граница желтой зоны
}
Serial.println(instring); //передать в компьютер
delay(10);
}