dee
Научный сотрудник
Минск
7K 1.8K
skonik, норм контроллер, заводские детальки всегда быстрее собрать и надежнее, я про контроллеры влажности не подумал .. а бытовой увлажнитель рассчитан на помещение в 10-20 квадратов т.е 25-30 кубов а холодильник 0,1-0,2 куба, я поэтому и брал почти игрушечный usb-увлажнитель, маломощный. на ардуино получается значительно дешевле: ардуино 3, шилд 3, реле и датчик по 1 доллару итого 10, пусть с коробкой и блоком 15 баксов зато функционал неограничен.
Скетч для ардуино
// для ЖК дисплея
#include <LiquidCrystal.h>;
#include <Wire.h>;
#include <EEPROM.h>
LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); //стандартный дисплей ардуино 10 й пин отогнут
//для датчика температуры и влажности
#include "DHT.h"
#define DHTPIN 2 // только INT0 или INT1 т.е 2 и 3 ПИН
// Uncomment whatever type you're using!
//#define DHTTYPE DHT11 // DHT 11
#define DHTTYPE DHT22 // DHT 22 (AM2302)
//#define DHTTYPE DHT21 // DHT 21 (AM2301)
// Connect pin 1 (on the left) of the sensor to +5V
// Connect pin 2 of the sensor to whatever your DHTPIN is
// Connect pin 4 (on the right) of the sensor to GROUND
// Connect a 10K resistor from pin 2 (data) to pin 1 (power) of the sensor
DHT dht(DHTPIN, DHTTYPE);
// состояние (режим работы) контроллера
int state;
//для календаря, пока нету
byte minyt; // прошло минут с начала процесса
byte chas; // прошло часов с начала процесса
byte day; // прошло дней с начала процесса
byte month; // прошло месяцев с начала процесса
byte year; // прошло лет с начала процесса
//для регулятора мощности ТЭНа, пока нету
byte ten_procent; //установка мощности ТЭНа
unsigned long time_now;
unsigned long time_ten_on; //время следующего включения нагревателя, в милисекундах
unsigned long time_ten_off;
//для статистики времени работы компрессора
unsigned long time_kompressor_on; //время включения компрессора, в милисекундах
unsigned long time_kompressor_off;
unsigned long time_kompressor_work; //время работы компрессора, в милисекундах
unsigned int time_s_kompressor_on; //последнее время работы компрессора, в секундах
unsigned int time_s_kompressor_off;
unsigned int n_kompressor_on; //число включений компрессора
//для регулировки температуры и влажности
byte temperatura_set; //установка температуры
int temperatura_now; //показания температуры
byte temperatura_dt; //дельта температуры для включения компрессора
byte humidity_set; //установка влажности
byte humidity_now; //показания влажности
byte humidity_dt; //дельта влажности
//бит включение компрессора
byte kompressor_set;
//для регистрации крайних значений температуры и влажности
int temperatura_min; //минимальное значение температуры
int temperatura_max;
int humidity_min; //влажность
int humidity_max; //
//массив символов для ЖК
char lcd_text1[16];
//для кновпок LCD привызывает к названиям кнопок цифры
int button;
const int BUTTON_NONE = 0;
const int BUTTON_RIGHT = 1;
const int BUTTON_UP = 2;
const int BUTTON_DOWN = 3;
const int BUTTON_LEFT = 4;
const int BUTTON_SELECT = 5;
void ChangeState(int state_next) //процедура очищает экран вносит задержку 0,2с в переклюениии между режимами для избежания дребезга контактов
{
delay(200);
lcd.clear();
state = state_next;
}
void clrTHstat() //очистить статистику по мин макс температуре и влажности
{
temperatura_min = 255; //крайние значения температуры и влажности
temperatura_max = 0; //
humidity_min = 99; //влажность
humidity_max = 0; //влажность
}
//процедура определения нажатой кнопки ЖК дисплея
int getPressedButton()
{
int buttonValue = analogRead(0); // считываем значения с аналогового входа(A0)
if (buttonValue < 100) {
return BUTTON_RIGHT;
}
else if (buttonValue < 200) {
return BUTTON_UP;
}
else if (buttonValue < 400){
return BUTTON_DOWN;
}
else if (buttonValue < 600){
return BUTTON_LEFT;
}
else if (buttonValue < 800){
return BUTTON_SELECT;
}
return BUTTON_NONE;
}
/* не реализовано
void vremia() //процедура выводит время работы контроллера
{
tik = millis()/10; //присваиваем счетчику число минут с начал работы контроллера
day = tik/1440;
chas = (tik-day*1440)/60;
minyt = (tik-day*1440-chas*60);
sprintf(lcd_text1,"%02ud%02uh%02u",day,chas,minyt); //выравниввает значения по левому краю, добавляет нули и еще что-то
lcd.print(lcd_text1);
}
*/
/* не реализовано
//регулятор мощности ТЭНа:
void ten_shim_set (int ten_procent) //расчет времени включения и выключения одного такта шим ТЭНа
{
time_now = millis();
if (time_now > time_ten_on && time_now < time_ten_off) {
digitalWrite(13, HIGH);
}
else {
digitalWrite(13, LOW);
} //шим для ТЭНа, проверяет необходимость включить ТЭН
if (time_now > time_ten_off) {
time_ten_on = time_now + 255 - ten_procent; //устанавливает время вклчюение ТЭна исходя из мощности, ступенька регулирования 1/255 = 0,4%
time_ten_off = time_now + 255; //устанавилвает время выключения ТЭНа - 1 сек = 1000 мс
} //запускает расчет времени включения и выключения следующего такта шим ТЭНа
}
ISR (TIMER2_COMPA_vect) // процедура которая вызывается при переполнении таймера 2
{
ten_shim_set (ten_procent);
}
*/
void setup()
{
//чтение настроек из памяти
temperatura_set = EEPROM.read(0);
temperatura_dt = EEPROM.read(1);
humidity_set = EEPROM.read(2);
humidity_dt = EEPROM.read(3);
clrTHstat(); //сбросить мин макс значения температуры и влажности
pinMode(13, OUTPUT); //пин с компрессором холодильника, для наглядности
pinMode(12, OUTPUT); //увлажнитель, пока нет
pinMode(11, OUTPUT); //НИМ, продувка морозилки для удаления влажности , пока нет
pinMode(10, OUTPUT); //ШИМ, продувка холодильника внешним воздухом, пока нет
state = 0; //первое состояние контроллера
//инициализация дисплея
lcd.begin(16, 2); //запуск ЖК экрана
//запуск датчика температуры и влажности
dht.begin();
/* // для медленного ШИМ регулятора мощности ТЭНа
//найстройка таймера для вызыва примерно 60 раз в секунду
//------ Timer2 ----------
TCCR2A = (1<<WGM21); // Режим CTC (сброс по совпадению)
TCCR2B = (1<<CS20); // Тактирование от CLK.
// Если нужен предделитель :
// TCCR2B = (1<<CS21); // CLK/8
// TCCR2B = (1<<CS20)|(1<<CS21); // CLK/32
// TCCR2B = (1<<CS22); // CLK/64
// TCCR2B = (1<<CS20)|(1<<CS22); // CLK/128
// TCCR2B = (1<<CS21)|(1<<CS22); // CLK/256
TCCR2B = (1<<CS20)|(1<<CS21)|(1<<CS22); // CLK/1024
OCR2A = 30; // Верхняя граница счета. Диапазон от 0 до 255.
// Частота прерываний будет = Fclk/(N*(1+OCR2A))
// где N - коэф. предделителя (1, 8, 32, 64, 128, 256 или 1024)
TIMSK2 = (1<<OCIE2A); // Разрешить прерывание по совпадению
sei (); // Глобально разрешить прерывания
*/
}
void loop()
{
// вывести в нижнюю строку время работы контроллера
//vremia();
// обработка нажатых конопок
button = getPressedButton();
//чтение температуры и влажности из датчика
humidity_now = dht.readHumidity();
temperatura_now = 10 * dht.readTemperature();
switch (state)
{
case 0: // основной экран
//определение минимальной и максимальной температуры
if (temperatura_now > temperatura_max) temperatura_max = temperatura_now;
if (temperatura_now < temperatura_min) temperatura_min = temperatura_now;
if (humidity_now < humidity_min) humidity_min = humidity_now;
if (humidity_now > humidity_max) humidity_max = humidity_now;
//снижение температуры включением холодильника + расчет времени работы холодильника и числа включений
if (temperatura_now > (temperatura_set + temperatura_dt))
{
if (kompressor_set == 0)
{
time_kompressor_on = millis();
time_kompressor_work = time_kompressor_on - time_kompressor_off;
time_s_kompressor_off = time_kompressor_work / 1000 ;
n_kompressor_on++;
}
kompressor_set = 1;
}
if (temperatura_now < (temperatura_set - temperatura_dt))
{
if (kompressor_set == 1)
{
time_kompressor_off = millis();
time_kompressor_work = time_kompressor_off - time_kompressor_on;
time_s_kompressor_on = time_kompressor_work / 1000 ;
}
kompressor_set = 0;
}
digitalWrite(13, kompressor_set); //включение/выключение компрессора холодильника на 13 пине арудины
//заготовка на продувку чистым воздухом 10 и 11 пин ШИМ, 11 пин на осушение морозильник/холодильник
// if (kompressor_set == 1) analogWrite(10, 255); else analogWrite(10, 0);
//вывод текста на экран, 1я строка
lcd.setCursor(0, 0);
sprintf(lcd_text1,"%03dT%03u %02uH%02u",temperatura_now, temperatura_set, humidity_now, humidity_set); // информация о температуре и влажности
lcd.print(lcd_text1);
lcd.setCursor(0, 1); //вторая строка
sprintf(lcd_text1,"%04u %04u %04u", time_s_kompressor_on, time_s_kompressor_off, n_kompressor_on); // информация о времени работы компрессора
lcd.print(lcd_text1);
//lcd.print("=16y01m20d16h20m");
switch (button)
{
case BUTTON_RIGHT:
break;
case BUTTON_LEFT:
break;
case BUTTON_UP:
break;
case BUTTON_DOWN:
break;
case BUTTON_SELECT:
ChangeState(1);
break;
}
break;
case 1: // уставка температуры
lcd.setCursor(0, 0);
lcd.print("TEMPERAURA");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"NOW:%03u SET:%03u",temperatura_now, temperatura_set); // информация о температуре
lcd.setCursor(0, 1);
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(2);
break;
case BUTTON_LEFT:
ChangeState(8);
break;
case BUTTON_UP:
if (temperatura_set < 255) temperatura_set++;
ChangeState(1);
break;
case BUTTON_DOWN:
if (temperatura_set > 0) temperatura_set--;
ChangeState(1);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 2: // установка дельты температуры
lcd.setCursor(0, 0);
lcd.print("TEMPERAURA DELTA");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"NOW:%02u",temperatura_dt); // информация о температуре
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(3);
break;
case BUTTON_LEFT:
ChangeState(1);
break;
case BUTTON_UP:
if (temperatura_dt < 15) temperatura_dt++;
ChangeState(2);
break;
case BUTTON_DOWN:
if (temperatura_dt > 1) temperatura_dt--;
ChangeState(2);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 3: // установка влажности
lcd.setCursor(0, 0);
lcd.print("HUMIDITY ");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"NOW:%02u, SET:%02u", humidity_now, humidity_set); // информация о температуре
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(4);
break;
case BUTTON_LEFT:
ChangeState(2);
break;
case BUTTON_UP:
if (humidity_set < 99) humidity_set++;
ChangeState(3);
break;
case BUTTON_DOWN:
if (humidity_set > 1) humidity_set--;
ChangeState(3);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 4: // установка дельты влажности
lcd.setCursor(0, 0);
lcd.print("HUMIDITY DELTA");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"NOW:%02u",humidity_dt); // информация дельте влажности
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(5);
break;
case BUTTON_LEFT:
ChangeState(3);
break;
case BUTTON_UP:
if (humidity_dt < 10) humidity_dt++;
ChangeState(4);
break;
case BUTTON_DOWN:
if (humidity_dt > 0) humidity_dt--;
ChangeState(4);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 5: // минимальная и максимальная температура и влажность
lcd.setCursor(0, 0);
lcd.print("TEMP HUM MIN MAX");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"%03dT%03d %03dH%03d",temperatura_min, temperatura_max, humidity_min, humidity_max); //минимальная и максимальная температура и влажность
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(6);
break;
case BUTTON_LEFT:
ChangeState(4);
break;
case BUTTON_UP:
clrTHstat();
ChangeState(5);
break;
case BUTTON_DOWN:
clrTHstat();
ChangeState(5);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 6: // сохранить изменения
lcd.setCursor(0, 0);
lcd.print("SAVE SETTINGS ?");
lcd.setCursor(0, 1);
lcd.print("UP-YES , DOWN-NO");
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(8);
break;
case BUTTON_LEFT:
ChangeState(5);
break;
case BUTTON_UP:
clrTHstat();
ChangeState(7);
break;
case BUTTON_DOWN:
clrTHstat();
ChangeState(0);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
case 7: // запись в епром
EEPROM.write(0, temperatura_set);
EEPROM.write(1, temperatura_dt);
EEPROM.write(2, humidity_set);
EEPROM.write(3, humidity_dt);
ChangeState(0);
break;
case 8: // статитика работы компрессора, крайние значения времени работы
lcd.setCursor(0, 0);
lcd.print("REF STAT ON OFF N");
lcd.setCursor(0, 1);
sprintf(lcd_text1,"%04d %04d %04d", time_s_kompressor_on, time_s_kompressor_off, n_kompressor_on); // информация о времени работы компрессора
lcd.print(lcd_text1);
switch (button)
{
case BUTTON_RIGHT:
ChangeState(1);
break;
case BUTTON_LEFT:
ChangeState(6);
break;
case BUTTON_UP:
time_s_kompressor_on = 0;
time_s_kompressor_off = 0;
n_kompressor_on = 0;
ChangeState(8);
break;
case BUTTON_DOWN:
time_s_kompressor_on = 0;
time_s_kompressor_off = 0;
n_kompressor_on = 0;
ChangeState(8);
break;
case BUTTON_SELECT:
ChangeState(0);
break;
}
break;
} //конец switch (state)
} //конец void loop()
[/hr]