Вот плод моих ночных бдений в свободное от работы и семьи время.
Сразу скажу, чтоб потом помидорами не закидали, что язык я специально не изучал, а с программированием до этого сталкивался еще в школе. Так что может быть скетч написан не идеально и м.б. косячки. Работу скетча проверял только на макетке. В бою не тестировал.
vlad219i написал отличный скетч, но бывает так (как у меня), что система отопления состоит не только из одного котла. Например, у меня есть котел, к которому через гидрострелку подключены радиаторы, теплый пол, бойлер косвенного нагрева. Есть 3 насоса+насос рециркуляции ГВС. И всем этим хозяйством нужно управлять. Вот я и решил немного допилить скетч vlad219i.
Изменения:
-изменение температуры термостатирования перенесено в меню
-вращение энкодера до входа в меню теперь переключает каналы термостатирования
-реле основное вкл/выкл котел, замыкает и размыкает контакты термостата котла на плате.
-3 свободных аналоговых входа использованы для подключения сдвигового регистра 74HC595. Т.о. имеем 8 цифровых выходов, к которым подключены реле для управления 8 каналами. По каждому из каналов скетч работает как у vlad219i-задается температура и поддерживается, сохранено время миниманальной паузы между включениями/выключениями. Таймеры сохранены.
Когда по каждому из 8 каналов нет запроса на тепло, то выключается основное реле и котел гаснет.
Таким образом можно регулировать температуру в 8-ми комнатах отдельно, да ещё и по расписанию. Если конечно есть исполнительные устройсва в этих комнатах.
Я планирую управлять температурой в комнатах (один датчик на все комнаты) с помощью вкл/выкл насоса радиаторов. Аналогично для теплого пола и бойлера косвенного нагрева.
Цель-экономия газа. Скетч позволит мне снижать температуру в комнатах в ночное время или во время пребывания на работе, отключать теплый пол теплый пол на ночь, не греть бойлер когда это не нужно и разогревать его максимально в пиковые часы.
Будет ли экономия существенной я узнаю только следующей зимой. А пока это только мечты...
Очень интересный проект, только не компелируется пишит
sketch_may10a:88: error: function definition does not declare parameters
sketch_may10a.ino: In function 'void getTemp()':
sketch_may10a:774: error: 'sensor' was not declared in this scope
Нет там ошибок. Ради интереса проверил. Все там компилируется. "Скетч использует 20 668 байт (64%) памяти устройства. Всего доступно 32 256 байт. Глобальные переменные используют 1 283 байт (62%) динамической памяти, оставляя 765 байт для локальных переменных. Максимум: 2 048 байт."
Спасибо что откликнулись !!! Я не спорю что в коде нет ошибок , я спрашиваю почему у меня не проходит компиляция ?
Код (термостат )автора темы у меня работает Отлично За что ему отдельное спасибо ,стоит на водогрейке Но хотелось несколько каналов А тут печалька получается
Сам себе отвечу,нет не значит,просто подсветка в каких то конф файлах включена.У меня вопрос к Slaiterx и другим кто подключает дисплей по i2c на A4 A5 висят часы а дисплей тогда куда вешать ? Или подскажите где почитать про это,никак не могу найти
Сам себе отвечу,нет не значит,просто подсветка в каких то конф файлах включена.У меня вопрос к Slaiterx и другим кто подключает дисплей по i2c на A4 A5 висят часы а дисплей тогда куда вешать ? Или подскажите где почитать про это,никак не могу найти
I2C является адресной шиной и позволяет подключать до 127 (тут не уверен, возможно больше) различных устройств. Каждое устройство имеет уникальный адрес, по которому и происходит обращение. Вот подключить двое часов или барометрических датчиков так просто не выйдет, у них он не меняется. Для часов - 0х68.
Вешаете свои устройства, запускаете i2C сканер (погуглите), находите адрес своего дисплея и указываете его в строке инициализации (в примерах обычно стоит 0х27). Если количество адресов меньше, чем подключено устройств, значит где то косяк в подключении.
Может подскажет кто как этот прект с выносным датчиком сделать,чтобы одна ардуинка с релюхой в котле сидела а вторая с датчиком и экраном в нужной комнате находилась,или можент готовые проекты есть поделитесь ссылками пожалуйста.Все это без проводов.
Может подскажет кто как этот прект с выносным датчиком сделать,чтобы одна ардуинка с релюхой в котле сидела а вторая с датчиком и экраном в нужной комнате находилась,или можент готовые проекты есть поделитесь ссылками пожалуйста.Все это без проводов.
Вот уже 2 года бесперебойно трудится такой термостат! Хочу выразить ещё раз огромную благодарность автору! Сэкономлено несколько кубов газа и, соответственно, денег. :)
Читал, что кто-то собирался разделить датчик и управляющую часть и соединить их с помощью NRF24. Очень прошу поделиться информацией! Заранее благодарен!
Ранее опубликованая мной многоканальная версия термостата доработана.
Использован LCD 2004 по I2C
Как и ранее для сбережения выходов ардуины использован сдвиговый регистр 74HC595.
К каждому из 8 выходов сдвигового регистра подключаем реле, которые управляют исполнительными устройствами (насосами, тенами, вентилями и т.д) поддерживая заданную температуру.
Есть главное реле (замыкает/размыкает контакты для комнатного термостата на плате котла, т.е. вкл/выкл котел), подключенное к отдельному пину ардуино. Если все 8 каналов, подключенных к сдвиговому регистру, выключены, то выключается и главное реле.
Адреса датчиков температуры прописывам в скетче. Все 8 датчиков подключать не обязательно!!!
/*
Суточный термостат для газового котла многоканальный
>Encoder control
>DS18B20 thermal sensor
>LCD1602 parallel
>DS1307 RTC
*/
#include <Wire.h> // i2c (для RTC)
#include <RealTimeClockDS1307.h> // RTC
#include <EEPROMex.h> // EE
#include <LiquidCrystal_I2C.h> // LCD 20*4
#include <TimerOne.h> // прерывания по таймеру1
#include <OneWire.h> // 1wire для DS18B20
#include <DallasTemperature.h> // DS18B20
#define ONE_WIRE_BUS A1 //номер пина с подключенным датчиком температуры
OneWire oneWire(ONE_WIRE_BUS); // Создаем объект OneWire
DallasTemperature DS18B20(&oneWire); // Создаем объект DallasTemperature для работы с сенсорами, передавая ему ссылку на объект для работы с 1-Wire.
DeviceAddress DS18B20Address; // Специальный объект для хранения адреса устройства
#define encoderA 2 // энкодер - поворот вправо (об землю)
#define encoderB 3 // энкодер - поворот влево (об землю)
#define encoderK 13 // энкодер - кнопка (об землю)
#define BeepPin 12 // пищалка
#define BeepToneNo 2000 // тон звука "No", герц
#define BeepToneYes 4000 // тон звука "Yes", герц
#define BeepToneNoDuration 200 // длительность звука "No", мс
#define BeepToneYesDuration 200 // длительность звука "Yes", мс
#define RelayMain 11 // нога, к которой подключено реле, которое вык/вкл котел
#define RelayOn LOW // полярность сигнала включения реле (HIGH/LOW)
#define qtyChannal 8 //количество каналов/датчиков
int channalOn=0; //количество включенных реле (каналов, температура которых ниже заданной).
LiquidCrystal_I2C lcd(0x3f, 20, 4);
//для регистра 74HС595
#define clock 16
#define data 17
#define latch 14
boolean Relay[8];
byte block3[8] = {
0b00110,0b01111,0b11111,0b11111,0b11111,0b11111,0b11110,0b01100}; //значок пламени (индикация работы котла
byte block1[8] = {
0x06,0x09,0x09,0x06,0x00,0x04,0x0E,0x1F }; // значок градуса с пламенем снизу
byte block2[8] = {
0x06,0x09,0x09,0x06,0x00,0x00,0x00,0x00 }; // значок градуса
//#define serialenabled // раскомментировать для выдачи в порт отладочной инфы
#define TstatTimerMax 180 //минимальная пауза между включениями горелки, сек
unsigned int TstatTimer[qtyChannal] ; //таймер паузы между включениями/выключениями, начальная установка 20 сек для устаканивания системы после сброса
float DS18B20Temperature[qtyChannal] ; //времянка
float Temperature[qtyChannal] ; //вычисленная температура с коррекцией
float DS18B20TempTmp[qtyChannal]; //сырая температура от датчиков
byte DS18B20iteration = 0; //счётчик измерений температуры для усреднения
float TstatTemp[qtyChannal] ; //температура термостатирования, может изменяться настройками
float TstatTempOld[qtyChannal];
float TemperatureCorr[qtyChannal]; //коррекция температуры, может изменяться настройками
float Hysteresis[qtyChannal] ; // гистерезис термостата, может изменяться настройками
float HysteresisOld[qtyChannal];
float AlarmTemp[qtyChannal] ; // температура для замерзательного орала
int Hours = 0; // времянка часов RTC для отображения и установки
int Minutes = 0; // времянка минут RTC для отображения и установки
int Seconds;
boolean PrintYesNo = false; // показывать ли после времени Yes/No (косвенно - указание на режим установка/отображение)
boolean SetH = false; // выделение часов при отображении
boolean SetM = false; // выделение минут при отображении
boolean SetYesNo = false; // выделение Yes/No при установке часов
boolean blink500ms = false; // мигающий бит, инвертируется каждые 500мс
boolean plus1sec = false; // ежесекундно взводится
boolean BeepEnabled = true;
int channel=0; //номер канала
byte MenuTimeoutTimer;
// адреса градусников.
DeviceAddress sensor []{
{0x28, 0xFF, 0x08, 0x26, 0x34, 0x16, 0x04, 0x68}, //
{0x28, 0xFF, 0x01, 0x4D, 0x34, 0x16, 0x04, 0x9F},
{0x28, 0xFF, 0x75, 0x2D, 0x34, 0x16, 0x03, 0xFE},
{0x28, 0xFF, 0x84, 0x4D, 0x34, 0x16, 0x04, 0x86},
{0x28, 0xFF, 0x4D, 0x28, 0x34, 0x16, 0x03, 0xC5},
{0x28, 0xFF, 0xF7, 0x4D, 0x34, 0x16, 0x04, 0xA5},
{0x28, 0xFF, 0x8C, 0x30, 0x34, 0x16, 0x04, 0x8D},
{0x28, 0xFF, 0xFC, 0x49, 0x34, 0x16, 0x04, 0xDB},
{0x28, 0xFF, 0xAB, 0x30, 0x34, 0x16, 0x03, 0xA7},
{0x28, 0xFF, 0x67, 0x40, 0x34, 0x16, 0x04, 0x8F},
};
// структура для суточных таймеров (8 байт)
struct buffer_template {
byte Hours;
byte Minutes;
float Temperature;
boolean Enabled;
boolean Activated;
};
buffer_template Timer[4][qtyChannal] = {0, 0, 23.0, false, false}; //объявление 4-х суточных таймеров для каждого из каналов и их начальные значения
// encoder vars
static boolean rotating=false; // debounce management
boolean A_set = false;
boolean B_set = false;
boolean encoderR = false;
boolean encoderL = false;
// EEPROM
EEMEM float TstatTempEE[qtyChannal]; //EE температура термостатирования
EEMEM float TemperatureCorrEE[qtyChannal]; // EE коррекция температуры
EEMEM float HysteresisEE[qtyChannal]; // EE гистерезис
EEMEM boolean BeepEnabledEE; // EE признак разрешения звука
EEMEM float AlarmTempEE[qtyChannal]; // EE значение недопустимого снижения температуры
EEMEM buffer_template TimerEE[4][qtyChannal]; // EE структуры для 4 суточных таймеров
// ===== SETUP ========================================================================
void setup() {
#ifdef serialenabled
Serial.begin(9600);
#endif
// задаем начальные значения
for (int j=0; j<qtyChannal; j++){
TstatTimer[j]=20 ; //таймер паузы между включениями/выключениями, начальная установка 20 сек для устаканивания системы после сброса
DS18B20Temperature[j]=0 ; //времянка
Temperature[j]=0 ; //вычисленная температура с коррекцией
}
pinMode(RelayMain, OUTPUT);
digitalWrite(RelayMain, HIGH);
lcd.begin();
lcd.createChar(1, block1);
lcd.createChar(2, block2);
lcd.createChar(3, block3);
pinMode(encoderA, INPUT);
digitalWrite(encoderA, HIGH);
pinMode(encoderB, INPUT);
digitalWrite(encoderB, HIGH);
pinMode(encoderK, INPUT);
digitalWrite(encoderK, HIGH);
attachInterrupt(0, doEncoderA, CHANGE); // encoder pin on interrupt 0 (pin 2)
attachInterrupt(1, doEncoderB, CHANGE); // encoder pin on interrupt 1 (pin 3)
Timer1.initialize(500000); // Timer0 interrupt - set a timer of length 500000 microseconds
Timer1.attachInterrupt( timerIsr ); // attach the service routine here
EEPROM.setMaxAllowedWrites(32767);
//для сдвигового регистра
pinMode(clock, OUTPUT);
pinMode(data, OUTPUT);
pinMode(latch, OUTPUT);
digitalWrite(latch, HIGH);
cleanreg();
//холодный старт
if ((digitalRead(encoderK)) == 0){ // если первая запись однокристалки (зажата кнопка при включении питания)- записать начальные значения в EE
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("Cold start..."));
for (int j=0; j<qtyChannal; j++){
for (int i=0; i<4; i++)
{
Timer[i][j].Hours = Timer[i][j].Minutes = 0;
Timer[i][j].Temperature = 23.0;
Timer[i][j].Enabled = Timer[i][j].Activated = false;
EEPROM.updateBlock(int(&TimerEE[i][j]), Timer[i][j]);
}
//присвоение начальных значений
TstatTemp[j]=25 ; //температура термостатирования, может изменяться настройками
TemperatureCorr[j]=0; //коррекция температуры, может изменяться настройками
Hysteresis[j]=0.5 ; // гистерезис термостата, может изменяться настройками
AlarmTemp[j]=20 ; // температура для замерзательного орала
//запись начальных значений в еепром
EEPROM.updateFloat(int(&TstatTempEE[j]), TstatTemp[j]);
EEPROM.updateByte(int(&BeepEnabledEE), BeepEnabled);
EEPROM.updateFloat(int(&TemperatureCorrEE[j]), TemperatureCorr[j]);
EEPROM.updateFloat(int(&HysteresisEE[j]), Hysteresis[j]);
EEPROM.updateFloat(int(&AlarmTempEE[j]), AlarmTemp[j]);
}
tone(BeepPin,2000,50);
delay(50);
tone(BeepPin,3000,50);
delay(50);
tone(BeepPin,4000,50);
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("Read settings..."));
//чтение еепром
BeepEnabled = EEPROM.readByte(int(&BeepEnabledEE));
for (int j=0; j<qtyChannal; j++)
{
TstatTemp[j] = EEPROM.readFloat(int(&TstatTempEE[j]));
TemperatureCorr[j] = EEPROM.readFloat(int(&TemperatureCorrEE[j]));
Hysteresis[j] = EEPROM.readFloat(int(&HysteresisEE[j]));
AlarmTemp[j] = EEPROM.readFloat(int(&AlarmTempEE[j]));
for (int i=0; i<4; i++)
{
EEPROM.readBlock(int(&TimerEE[i][j]), Timer[i][j]);
}
}
DS18B20.begin();
DS18B20.setResolution(DS18B20Address, 12); //устанавливаем разрешения датчика 12 бит
DS18B20.setWaitForConversion(false);
DS18B20.requestTemperatures(); //запрос на измерение температуры
tone(BeepPin,4000,50);
delay(100);
tone(BeepPin,4000,50);
delay(1000);
lcd.clear();
RTC.start();
}
// ===== MAIN CYCLE ===================================================================
void loop() {
//инфо на LCD 1 строка
lcd.setCursor(6, 0);
lcd.print(F("channel "));
lcd.print(channel+1); //чтобы не было нулевого
if (Temperature[channel]!=-127) { //если есть датчик температуры
lcd.setCursor(17, 0);
if (TstatTimer[channel] < 10) //чтобы надпись не скакала вправо/влево при переходе значения температуры с двух значного на однозначное
lcd.print(F(" "));
if (TstatTimer[channel] > 10&TstatTimer[channel] < 10) //чтобы надпись не скакала вправо/влево при переходе значения температуры с двух значного на однозначное
lcd.print(F(" "));
if (TstatTimer[channel] !=0) { //выводим остаток времени, по истечению которого возможно изменение статуса выхода
lcd.print(TstatTimer[channel]);
}
else {
lcd.print(F(" "));
}
//инфо на LCD 2 строка
lcd.setCursor(0, 1);
lcd.print(F(" "));
if (Temperature[channel] < 10) { //чтобы надпись не скакала вправо/влево при переходе значения температуры с двух значного на однозначное
lcd.print(F(" "));
}
lcd.print(Temperature[channel],1); //текущая температура
lcd.write(0x02); // значок градуса
lcd.print(F("-->"));
lcd.print(TstatTemp[channel],1); //температура термостатирования
if ( Relay[channel] == RelayOn ) { //если реле канала включено
lcd.write(0x01); // значок градуса с пламенем
}
else lcd.write(0x02); // значок градуса
lcd.print(F(" "));
if ((Temperature[channel] < AlarmTemp[channel])&(blink500ms)) { //выводим предупреждение о холоде
lcd.print(F("*"));
}
else {
lcd.print(F(" "));
}
if (digitalRead(RelayMain) == RelayOn) //если котел включен, то выводим на lcd
lcd.write(0x03); //значок работы котла
else lcd.print(F(" "));
//инфо на LCD 3 строка
lcd.setCursor(0, 2);
lcd.print(F(" "));
for (int i=0;i<4;i++){
if ((Timer[i][channel].Enabled)&!((Timer[i][channel].Activated)&(blink500ms))) { // если таймер включен - надпись светится, если сработал - мигает, обрабатываем все 4 таймера
lcd.print(F("T"));
lcd.print(i+1);
lcd.print(F(" "));
}
else {lcd.print(F(" ")); //стираем таймеры с экрана
}
}
//инфо на LCD 4 строка
lcd.setCursor(0, 3);
for (int i=0;i<4;i++){
if ((Timer[i][channel].Enabled)&!((Timer[i][channel].Activated)&(blink500ms))) { //выводим на экран температуры таймеров
lcd.print(Timer[i][channel].Temperature,1);
lcd.print(F(" "));
}
else {
lcd.print(F(" "));
}
}
}
//если нет сенсора, то не стираем с экрана все ненужное
else {
lcd.setCursor(16, 0);
lcd.print(F(" "));
lcd.setCursor(0, 1);
lcd.print(F("No sensor "));
lcd.setCursor(0, 2);
lcd.print(F(" ")); //стираем таймеры с экрана
lcd.setCursor(0, 3);
lcd.print(F(" ")); //стираем температуры таймеров с экрана
}
// печатаем текущее время
PrintYesNo = false;
PrintRTC(0,0);
Termostat();// термостатирование каждого канала в отдельности, т.е включение/выключение исполнительного устройства отвечающего за температуру по каждому из каналов
RelayMainON (); //включение/выключение котла, т.е замыкание /размыкание контактов реле, подключенных к колодки комнатного термостата (плата котла)
// если прошла 1 секунда - делаем ежесекундные дела
if (plus1sec) {
plus1sec = false; // сбрасываем до следующей секунды
RTC.readClock(); // обновляем часы
Hours=RTC.getHours();
Minutes=RTC.getMinutes();
Seconds=RTC.getSeconds();
getTemp(); // читаем температуру с датчиков
// проверка таймеров и изменение температуры термостатирования при совпадении (активации таймера)
for (int j=0; j<qtyChannal; j++){
if (Temperature[j]!=-127){ //если нет сенсора, то и не включаем таймеры
for (int i=0;i<4;i++){
if ((Hours == Timer[i][j].Hours)&(Minutes == Timer[i][j].Minutes)&(Timer[i][j].Enabled)&(Seconds == 0)) { // время T совпадает с RTC
Timer[0][j].Activated = Timer[1][j].Activated = Timer[2][j].Activated = Timer[3][j].Activated = false;
Timer[i][j].Activated = true;
TstatTemp[j] = Timer[i][j].Temperature;
EEPROM.updateFloat(int(&TstatTempEE[j]), TstatTemp[j]);
if (BeepEnabled) {
tone(BeepPin,4000,5);
}
break; // это чтобы статус Activated остался взведённым
}
}
}
}
// дебаг-инфо - в терминал если раскомментировано выше
#ifdef serialenabled
Serial.print(F("iteration ="));
Serial.print (DS18B20iteration);
Serial.print(F(" channalOn="));
Serial.print (channalOn);
if (digitalRead(RelayMain) == RelayOn) Serial.println(F(" MAIN Relay ON "));
else Serial.println(F(" MAIN Relay Of "));
for (int j=0; j<qtyChannal; j++){
Serial.print(F("sensor"));
Serial.print(j,1);
Serial.print(F(" Temp="));
Serial.print(Temperature[j], 1);
Serial.print(F(" TstatTemp="));
Serial.print(TstatTemp[j], 1);
Serial.print(F(" Hyster="));
Serial.print(Hysteresis[j], 1);
Serial.print(F(" ("));
Serial.print(DS18B20Temperature[j], 1);
Serial.print(F(" "));
Serial.print(DS18B20TempTmp[j], 1);
Serial.print(F(",corr "));
Serial.print(TemperatureCorr[j], 1);
Serial.print(F("),Timer="));
Serial.print(TstatTimer[j]);
if (Relay[j]==RelayOn) Serial.println(F(" ON "));
else Serial.println(F(" OF "));
}
Serial.println(F(" "));
#endif
//сообщение о недопустимом снижении температуры
for (int j=0; j<qtyChannal; j++){
if ((Temperature[j] < AlarmTemp[j])&(Temperature[j]!=-127))
tone(BeepPin,4000,5);
}
} //конец ежесекундных дел
// обработка поворота энкодера на изменение канала))
rotating = true; // reset the debouncer
if ((encoderR)|(encoderL)) {
if (encoderR) {
channel += 1;
}
else
{
channel -= 1;
}
if ( channel > qtyChannal-1) { // количество каналов, т.к считаем с нуля
channel = 0;
}
if ( channel < 0 ) {
channel = qtyChannal-1;
}
encoderR = false;
encoderL = false;
}
// ================ по нажатию кнопки энкодера - меню настроек ====================
if(digitalRead(encoderK) == 0) {
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("< SETUP > Channel "));
lcd.print(channel);
if (BeepEnabled) {
tone(BeepPin,4000,50);
}
delay(200);
int menuitem = 0;
do { //обработка пунктов меню (по выбранному каналу)
rotating = true; // reset the debouncer
if ((encoderR)|(encoderL)) {
MenuTimeoutTimer = 10; //таймер таймаута, секунд
if (encoderR) {
menuitem += 1;
}
else {
menuitem -= 1;
}
if ( menuitem > 10 ) {
menuitem = 0;
} // границы пунктов меню
if ( menuitem < 0 ) {
menuitem = 10;
}
encoderR = false;
encoderL = false;
}
// индикация пункта меню (номер пункта - в menuitem)
lcd.setCursor(0, 1); //инфо на LCD
switch(menuitem)
{
case 0:
lcd.print(F("0.T-ON Relay "));
break;
case 1:
lcd.print(F("1.TIMER1 SET "));
break;
case 2:
lcd.print(F("2.TIMER2 SET "));
break;
case 3:
lcd.print(F("3.TIMER3 SET "));
break;
case 4:
lcd.print(F("4.TIMER4 SET "));
break;
case 5:
lcd.print(F("5.CLOCK SET "));
break;
case 6:
lcd.print(F("6.HYSTERESIS SET"));
break;
case 7:
lcd.print(F("7.T-CORRECT SET "));
break;
case 8:
lcd.print(F("8.SOUND SET "));
break;
case 9:
lcd.print(F("9.T-ALARM SET "));
break;
case 10:
lcd.print(F("10.BACK "));
break;
}
if (MenuTimeoutTimer == 0) {
menuitem = 10;
}
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0)); // если нажата кнопка энкодера или таймаут - обработка пункта меню (номер пункта - в menuitem)
if (BeepEnabled) {
tone(BeepPin,4000,50);
}
switch(menuitem)
{
// ====== пункт 0 - выход
case 10:
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration);
} //звук "NO"
break; // case 0 out
// ====== пункт 1 - установка Timer1
case 1:
TimerXSetup(0);
break; // case 1 out
// ====== пункт 2 - установка Timer2
case 2:
TimerXSetup(1);
break; // case 2 out
// ====== пункт 3 - установка Timer3
case 3:
TimerXSetup(2);
break; // case 3 out
// ====== пункт 4 - установка Timer4
case 4:
TimerXSetup(3);
break; // case 4 out
// ====== пункт 5 - установка RTC
case 5:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SETUP CLOCK"));
delay(200);
RTC.readClock();
Hours=RTC.getHours();
Minutes=RTC.getMinutes();
SetYesNo = false;
PrintYesNo = true;
SetTime(0,1); // в позиции 0,1 - запрос ввода времени
if (MenuTimeoutTimer != 0) {
if (SetYesNo)
{
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
RTC.setHours(Hours);
RTC.setMinutes(Minutes);
RTC.setSeconds(0);
RTC.setClock();
RTC.start();
}
else
{
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
}
else {
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
break; // case 5 out
// ====== пункт 6 - установка гистерезиса
case 6:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
HysteresisOld[channel] = Hysteresis[channel];
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SETUP HYSTERESIS"));
delay(200);
do {
lcd.setCursor(0,1);
if (blink500ms) {
lcd.print(" ");
}
else {
lcd.print(Hysteresis[channel], 1);
lcd.write(0x02); // значок градуса
}
rotating = true; // reset the debouncer
if (encoderR) {
Hysteresis[channel] += 0.1;
encoderR = false;
}
if (encoderL) {
Hysteresis[channel] -= 0.1;
encoderL = false;
}
Hysteresis[channel] = constrain(Hysteresis[channel], 0.1, 20); // крайние значения
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) {
EEPROM.updateFloat(int(&HysteresisEE[channel]), Hysteresis[channel]); // запись в ЕЕПРОМ
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
else {
Hysteresis[channel] = HysteresisOld[channel];
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
break; // case 6 out
// ====== пункт 7 - установка коррекции температуры
case 7:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SETUP T-CORRECT "));
delay(200);
do {
lcd.setCursor(0,1);
if (blink500ms) {
lcd.print(F(" "));
}
else {
if (TemperatureCorr[channel] >= 0) {
lcd.print(F("+"));
}
lcd.print(TemperatureCorr[channel], 1);
lcd.write(0x02); // значок градуса
}
rotating = true; // reset the debouncer
if (encoderR) {
TemperatureCorr[channel] += 0.1;
encoderR = false;
}
if (encoderL) {
TemperatureCorr[channel] -= 0.1;
encoderL = false;
}
TemperatureCorr[channel] = constrain(TemperatureCorr[channel], -8, 8); // крайние значения
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) {
EEPROM.updateFloat(int(&TemperatureCorrEE[channel]), TemperatureCorr[channel]); // запись в ЕЕПРОМ
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
else {
TemperatureCorr[channel] = EEPROM.readFloat(int(&TemperatureCorrEE[channel]));
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
break; // case 7 out
// ====== пункт 8 - вкл/выкл звука
case 8:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SOUND SET "));
delay(200);
do {
lcd.setCursor(0,1);
if (BeepEnabled) {
lcd.print(F("BEEP ON "));
}
else {
lcd.print(F("BEEP OFF "));
}
rotating = true; // reset the debouncer
if ((encoderR)|(encoderL)) {
BeepEnabled = !BeepEnabled;
encoderR = false;
encoderL = false;
}
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) {
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
EEPROM.updateByte(int(&BeepEnabledEE), BeepEnabled);
}
if (MenuTimeoutTimer == 0) {
BeepEnabled = EEPROM.readByte(int(&BeepEnabledEE));
}
break; // case 8 out
// ====== пункт 9 - установка предупреждалки о холоде
case 9:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("ALARM-TEMP SET "));
delay(200);
do {
lcd.setCursor(0,1);
if (blink500ms) {
lcd.print(F(" "));
}
else {
if (AlarmTemp[channel] >= 0) {
lcd.print(F("+"));
}
lcd.print(AlarmTemp[channel], 0);
lcd.write(0x02); // значок градуса
}
rotating = true; // reset the debouncer
if (encoderR) {
AlarmTemp[channel] += 1;
encoderR = false;
}
if (encoderL) {
AlarmTemp[channel] -= 1;
encoderL = false;
}
AlarmTemp[channel] = constrain(AlarmTemp[channel], 5, 40); // крайние значения
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) {
EEPROM.updateFloat(int(&AlarmTempEE[channel]), AlarmTemp[channel]); // запись в ЕЕПРОМ
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
else {
AlarmTemp[channel] = EEPROM.readFloat(int(&AlarmTempEE[channel]));
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
break; // case 9 out
// ====== пункт 10 - установка температуры термостатирования
case 0:
MenuTimeoutTimer = 10; //таймер таймаута, секунд
TstatTempOld[channel]=TstatTemp[channel];
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SETUP T-ON Raley"));
delay(200);
do {
lcd.setCursor(0,1);
if (blink500ms) {
lcd.print(" ");
}
else {
lcd.print(TstatTemp[channel], 1);
lcd.write(0x02); // значок градуса
}
rotating = true; // reset the debouncer
if (encoderR) {
TstatTemp[channel] += 0.1;
encoderR = false;
}
if (encoderL) {
TstatTemp[channel] -= 0.1;
encoderL = false;
}
TstatTemp[channel] = constrain(TstatTemp[channel], 1, 80); // крайние значения
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) {
for (int i=0;i<4;i++){
Timer[i][channel].Activated=false;
}
EEPROM.updateFloat(int(&TstatTempEE[channel]), TstatTemp[channel]); // запись в ЕЕПРОМ и если питание пропадет, то будет
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
else {
TstatTemp[channel] = TstatTempOld[channel];
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
break; // case 10 out
}
delay(200);
lcd.clear();
}
}
// ===== SUBROUTINES ==================================================================
//функция очистки сдвигового регистра
void cleanreg(){
for(int i=0; i<8; i++)
Relay[i]=!RelayOn;
digitalWrite(latch, LOW);
shiftOut(data, clock, LSBFIRST, 0);
digitalWrite(latch, HIGH);
}
// ========================================
//функция управления сдвиговым регистром
void sendpin(int pin, boolean state){
Relay[pin]=state;
byte value = 0;
byte add = 1;
for(int i=0; i<8; i++){
if(Relay[i]==HIGH) value+=add;
add*=2;
}
digitalWrite(latch, LOW);
shiftOut(data, clock, MSBFIRST, value);
digitalWrite(latch, HIGH);
}
// ========================================
// измеряем температуру на всех датчиках
void getTemp(){
DS18B20.requestTemperatures(); //запускаем новое измерение
for (int j=0; j<qtyChannal; j++){
DS18B20TempTmp[j] = DS18B20.getTempC(sensor[j]); //получаем температуру с каждого датчика
//иногда температура не измеряется, и проскакивают значения -127, среднее значение резко падает и канал меняет состоянее. Нижние 2 строчки помогают. Ничего другого не придумал
if (DS18B20TempTmp[j]==-127&Temperature[j]!=-127&Temperature[j]!=0) //если проскочит значение -127, а ранее фиксировали не -127 и не первое измерение
DS18B20TempTmp[j]=Temperature[j]; //проигнорируем его и заменим на среднюю измеренную ранее, а затем просуммирум
DS18B20Temperature[j] += DS18B20TempTmp[j]; // суммируем для усреднения
}
DS18B20iteration ++;
if (DS18B20iteration == 10){
DS18B20iteration = 0;
for (int j=0; j<qtyChannal; j++){
Temperature[j] = (DS18B20Temperature[j] / 10) + TemperatureCorr[j]; //усреднённая + коррекци
DS18B20Temperature[j] = 0;
}
}
}
// ========================================
void Termostat() {//термостатирование
for (int j=0; j<8; j++){
if(Temperature[j]==-127) //если нет датчика, выключаем реле
{
if ( Relay[j]!=RelayOn) // если реле включено
{
sendpin(j, !RelayOn); // выключить реле;
}
}
else {
if ( TstatTimer[j] == 0 ) //если пауза между вкл/выкл реле превысила TstatTimerMax;
{
if ( Temperature[j] > ( TstatTemp[j] + Hysteresis[j] ) ) // если температра канала > температура заданная+гистерезис
{
if ( Relay[j]==RelayOn ) // если реле включено -
{
sendpin(j, !RelayOn); // выключить реле;
TstatTimer[j] = TstatTimerMax; // реле держать выключённым не менее заданного в TstatTimerMax времени
}
}
if (Temperature[j] < TstatTemp[j]) //если температура канала меньше заданной
{
if ( Relay[j]==!RelayOn ) // если реле выключено
{
sendpin(j, RelayOn); // включить реле
TstatTimer[j] = TstatTimerMax; // реле держать включённым не менее заданного в TstatTimerMax времени
}
}
}
}
}}
// ========================================
void RelayMainON () {//вкл и выключение котла
channalOn=qtyChannal; //количество вкл каналов=количеству каналов
for (int j=0; j<qtyChannal; j++){
if (Relay[j]==!RelayOn) //если канал выключен
channalOn-=1; //считаем количество включенных каналов
}
if (channalOn==0) { //если нет включенных реле (нет запроса на тепло ни по одному из каналов)
if ( digitalRead(RelayMain) == RelayOn) //если котел включен
digitalWrite(RelayMain, !RelayOn); //выключить котел
}
if (channalOn>0) { //если есть включенные реле (есть запрос на тепло хотя бы по одному из каналов)
if ( digitalRead(RelayMain) == !RelayOn) //если котел выключен
digitalWrite(RelayMain, RelayOn); //включить котел
}
}
// ========================================
void SetTime(char x, char y)
{
// ========= set hours
SetH = true;
do {
PrintRTC(x,y);
rotating = true; // reset the debouncer
if (encoderR) {
Hours += 1;
if(Hours > 23) {
Hours = 0;
};
encoderR = false;
}
if (encoderL) {
Hours -= 1;
if(Hours < 0) {
Hours = 23;
};
encoderL = false;
}
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (BeepEnabled) {
tone(BeepPin,4000,50); //звук "YES"
}
SetH = false;
delay(200);
// ========= set minutes
SetM = true;
do {
PrintRTC(0,1);
rotating = true; // reset the debouncer
if (encoderR) {
Minutes += 1;
if(Minutes > 59) {
Minutes = 0;
};
encoderR = false;
}
if (encoderL) {
Minutes -= 1;
if(Minutes < 0) {
Minutes = 59;
};
encoderL = false;
}
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (BeepEnabled) {
tone(BeepPin,4000,50); //звук "YES"
}
if (PrintYesNo) {
SetM = false;
delay(200);
// ========= set yes-no
SetYesNo = false;
do {
PrintRTC(0,1);
rotating = true; // reset the debouncer
if ((encoderR)||(encoderL)) {
SetYesNo = !SetYesNo;
encoderR = false;
encoderL = false;
}
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
delay(200);
}
}
// ========================================
void PrintRTC(char x, char y)
{
lcd.setCursor(x,y);
if (SetH&&blink500ms) {
lcd.print(F(" "));
}
else {
if (Hours < 10) {
lcd.print(F("0"));
}
lcd.print(Hours);
}
// мигающее двоеточие, если не в режиме установки времени
if (!(SetH||SetM||PrintYesNo||blink500ms))
{
lcd.print(F(" "));
}
else {
lcd.print(F(":"));
}
if (SetM&&blink500ms) {
lcd.print(F(" "));
}
else {
if (Minutes < 10) {
lcd.print(F("0"));
}
lcd.print(Minutes);
}
lcd.print(F(" "));
if (PrintYesNo) {
lcd.print(F("["));
if (!(SetH||SetM||blink500ms))
{
lcd.print(F(" "));
}
else {
if (SetYesNo)
{
lcd.print(F("YES"));
}
else {
lcd.print(F("NO "));
}
}
lcd.print(F("]"));
}
}
// ============================ Encoder interrupts =============================
// Interrupt on A changing state
void doEncoderA(){
if ( rotating ) {
delay (1) ; // wait a little until the bouncing is done
}
// Test transition, did things really change?
if( digitalRead(encoderA) != A_set ) { // debounce once more
A_set = !A_set;
// adjust counter + if A leads B
if ( A_set && !B_set )
{
MenuTimeoutTimer = 10; //таймер таймаута, секунд
if (BeepEnabled) {
tone(BeepPin,4000,5);
}
encoderR = true;
rotating = false; // no more debouncing until loop() hits again
}
}
}
// Interrupt on B changing state, same as A above
void doEncoderB(){
if ( rotating ) {
delay (1);
}
if( digitalRead(encoderB) != B_set ) {
B_set = !B_set;
// adjust counter - 1 if B leads A
if( B_set && !A_set ) {
MenuTimeoutTimer = 10; //таймер таймаута, секунд
if (BeepEnabled) {
tone(BeepPin,4000,5);
}
encoderL = true;
rotating = false;
}
}
}
// ============================ Timer0 interrupt =============================
// run every 500ms
void timerIsr()
{
blink500ms = !blink500ms; // инверсия мерцающего бита
if(blink500ms) {
plus1sec = true; // ежесекундно взводится
for (int j=0; j<qtyChannal; j++) {
if (TstatTimer[j] != 0) {
TstatTimer[j] --; // ежесекундный декремент этого таймера
}
}
if (MenuTimeoutTimer != 0) {
MenuTimeoutTimer --; // ежесекундный декремент этого таймера
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
void TimerXSetup(int X) {
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("SETUP TIMER"));
lcd.print(X+1); // выводим номер таймера на LCD
delay(200);
Hours=Timer[X][channel].Hours;
Minutes=Timer[X][channel].Minutes;
SetYesNo = false;
PrintYesNo = true;
SetTime(0,1); // в позиции 0,1 - запрос ввода времени
if (MenuTimeoutTimer != 0) {
if (SetYesNo) // если при установке времени выбрано "Yes"
{
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
Timer[X][channel].Hours = Hours;
Timer[X][channel].Minutes = Minutes;
Timer[X][channel].Enabled = true;
EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
MenuTimeoutTimer = 10; //таймер таймаута, секунд
lcd.clear();
lcd.setCursor(0, 0); //инфо на LCD
lcd.print(F("Timer"));
lcd.print(X+1);
lcd.print(F(" Temp. Set"));
delay(200);
do {
lcd.setCursor(0,1);
if (blink500ms) {
lcd.print(F(" "));
}
else {
lcd.print(Timer[X][channel].Temperature, 1);
lcd.write(0x02); // значок градуса
}
rotating = true; // reset the debouncer
if (encoderR) {
Timer[X][channel].Temperature += 0.1;
encoderR = false;
}
if (encoderL) {
Timer[X][channel].Temperature -= 0.1;
encoderL = false;
}
Timer[X][channel].Temperature = constrain(Timer[X][channel].Temperature, 5, 80); // крайние значения
}
while ((digitalRead(encoderK)==1)|(MenuTimeoutTimer==0));
if (MenuTimeoutTimer != 0) { // если после выбора температуры нажата кнопка энкодера
EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
else { // если не нажата - используем старую температуру
EEPROM.readBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
if (BeepEnabled) {
tone(BeepPin,BeepToneYes,BeepToneYesDuration); //звук "YES"
}
}
}
else // если при установке времени выбрано "No"
{
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
EEPROM.readBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
Timer[X][channel].Enabled = false;
EEPROM.updateBlock(int(&TimerEE[X][channel]), Timer[X][channel]);
}
}
else {
if (BeepEnabled) {
tone(BeepPin,BeepToneNo,BeepToneNoDuration); //звук "NO"
}
}
}
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~````
Народ, кто нибуть может дать список библиотек использованных в авторском скетче. Что-то я понакачал стандартных библиотек с Arduino.cc у них имена другие, переименовывал, переименовывал и все равно ошибки вылазят при подключении библиотек. Может не все нашел ? Нахрена их надо было переименовывать в проекте ?
Народ, кто нибуть может дать список библиотек использованных в авторском скетче. Что-то я понакачал стандартных библиотек с Arduino.cc у них имена другие, переименовывал, переименовывал и все равно ошибки вылазят при подключении библиотек. Может не все нашел ? Нахрена их надо было переименовывать в проекте ?
C:\skech\skech.ino:13:40: fatal error: RealTimeClockDS1307.h: No such file or directory
#include <RealTimeClockDS1307.h> // RTC
^
compilation terminated.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
Пишет вот это, я понимаю что нет библиотеки в указанной папке.
Запихал в librares RealTimeClockDS1307, теперь не может найти другую -
...
C:\skech\skech.ino:14:28: fatal error: EEPROMex.h: No such file or directory
#include <EEPROMex.h> // EE
^
compilation terminated.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307 (legacy)
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307 (legacy)
Используем библиотеку EEPROMEx версии 1.0.0 из папки: C:\Electronics\Arduino\libraries\EEPROMEx
Используем библиотеку LiquidCrystal версии 1.0.7 из папки: C:\Electronics\Arduino\libraries\LiquidCrystal
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
P.S. Все пользователские библиотеки вставляй сюда - Мои документы\Arduino\libraries\ . Не надо лезть в папку, где находятся стандартные библиотеки Arduino IDE.
P.S. Все пользователские библиотеки вставляй сюда - Мои документы\Arduino\libraries\ . Не надо лезть в папку, где находятся стандартные библиотеки Arduino IDE.
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307
Используем библиотеку EEPROMEx версии 1.0.0 из папки: C:\Electronics\Arduino\libraries\EEPROMEx
вот и я почти доделал с небольшими изменениями у меня дисплей 2004 и датчик уличный будет для мониторинга температуры и влажности на улице
i2c дисплей 2004 и дополнительный датчик для измерения температуры и влажности на улице пока dht11 в дальнейшем dht22
по I2C часы и LCD работают.
добавил 4-й таймер. типа: утро, день, вечер, ночь.
Если нетрудно, добавте пожалуйста в меню, включение и отключение подсветки дисплея и регулировку яркости.
[quote=olezhan36]
Вот плод моих ночных бдений в свободное от работы и семьи время.
Сразу скажу, чтоб потом помидорами не закидали, что язык я специально не изучал, а с программированием до этого сталкивался еще в школе. Так что может быть скетч написан не идеально и м.б. косячки. Работу скетча проверял только на макетке. В бою не тестировал.
За основу были взяты 3 скетча:
1. скетч автора этой темы
2.https://www.youtube.com/watch?v=mFtgO3kWA4g
3.http://cxem.net/arduino/arduino166.php для работы со сдвиговым регистром.
vlad219i написал отличный скетч, но бывает так (как у меня), что система отопления состоит не только из одного котла. Например, у меня есть котел, к которому через гидрострелку подключены радиаторы, теплый пол, бойлер косвенного нагрева. Есть 3 насоса+насос рециркуляции ГВС. И всем этим хозяйством нужно управлять. Вот я и решил немного допилить скетч vlad219i.
Изменения:
-изменение температуры термостатирования перенесено в меню
-вращение энкодера до входа в меню теперь переключает каналы термостатирования
-реле основное вкл/выкл котел, замыкает и размыкает контакты термостата котла на плате.
-3 свободных аналоговых входа использованы для подключения сдвигового регистра 74HC595. Т.о. имеем 8 цифровых выходов, к которым подключены реле для управления 8 каналами. По каждому из каналов скетч работает как у vlad219i-задается температура и поддерживается, сохранено время миниманальной паузы между включениями/выключениями. Таймеры сохранены.
Когда по каждому из 8 каналов нет запроса на тепло, то выключается основное реле и котел гаснет.
Таким образом можно регулировать температуру в 8-ми комнатах отдельно, да ещё и по расписанию. Если конечно есть исполнительные устройсва в этих комнатах.
Я планирую управлять температурой в комнатах (один датчик на все комнаты) с помощью вкл/выкл насоса радиаторов. Аналогично для теплого пола и бойлера косвенного нагрева.
Цель-экономия газа. Скетч позволит мне снижать температуру в комнатах в ночное время или во время пребывания на работе, отключать теплый пол теплый пол на ночь, не греть бойлер когда это не нужно и разогревать его максимально в пиковые часы.
Будет ли экономия существенной я узнаю только следующей зимой. А пока это только мечты...
Очень интересный проект, только не компелируется пишит
Подскажите пожалуста почему ошибки при компилирование скетча с 5 страницы
Нет там ошибок. Ради интереса проверил. Все там компилируется. "Скетч использует 20 668 байт (64%) памяти устройства. Всего доступно 32 256 байт. Глобальные переменные используют 1 283 байт (62%) динамической памяти, оставляя 765 байт для локальных переменных. Максимум: 2 048 байт."
Ищите ошибку у себя
Спасибо что откликнулись !!! Я не спорю что в коде нет ошибок , я спрашиваю почему у меня не проходит компиляция ?
Код (термостат )автора темы у меня работает Отлично За что ему отдельное спасибо ,стоит на водогрейке Но хотелось несколько каналов А тут печалька получается
Значит скопировали не верно... Телепатов тут нет.
Нет не в копирование дела , не один раз копиравал А по поводу Телепатов ,плохо что нет
Нет не в копирование дела , не один раз копиравал А по поводу Телепатов ,плохо что нет
В какой версии Arduino IDE компилируете?
1.0.6
А у автора какая IDE?
У меня не компилится в виду отсустствия библиотек.
У вас какая версия IDE ? Ошибок как у меня я понял у вас нет
У меня IDE 1.8.2
Из ошибок
Но это из за того что библиотек нет. Может если скачать и установить библиотеки будут еще ошибки, а может и нет. Но вроде выше писали что все ок.
Нада значит IDE 1.8.2 поставить и еще не могу понять в коде ,куда цыплять 74HC595.
Кто-нибудь прикрутил к термостату NRF24L01?
Подскажите как правильн скетч с поста скопировать,сначала в редактор потом сохранить в ино ?Просто циферки строк смущают )
наводим курсор на код, справа сверху появляется окошечко, выбираем левый пункт, появляется окно с кодом для копирования в иде
Спасибо,если красным посвечивает это занчит библиотек не хватает ?
Сам себе отвечу,нет не значит,просто подсветка в каких то конф файлах включена.У меня вопрос к Slaiterx и другим кто подключает дисплей по i2c на A4 A5 висят часы а дисплей тогда куда вешать ? Или подскажите где почитать про это,никак не могу найти
Сам себе отвечу,нет не значит,просто подсветка в каких то конф файлах включена.У меня вопрос к Slaiterx и другим кто подключает дисплей по i2c на A4 A5 висят часы а дисплей тогда куда вешать ? Или подскажите где почитать про это,никак не могу найти
I2C является адресной шиной и позволяет подключать до 127 (тут не уверен, возможно больше) различных устройств. Каждое устройство имеет уникальный адрес, по которому и происходит обращение. Вот подключить двое часов или барометрических датчиков так просто не выйдет, у них он не меняется. Для часов - 0х68.
Вешаете свои устройства, запускаете i2C сканер (погуглите), находите адрес своего дисплея и указываете его в строке инициализации (в примерах обычно стоит 0х27). Если количество адресов меньше, чем подключено устройств, значит где то косяк в подключении.
Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.
Интересно! Где смотреть?
Если нетрудно, добавте пожалуйста в меню, включение и отключение подсветки дисплея и регулировку яркости.
пора наверное на OLED перейти.
LCD реально как ночник работает.
Может подскажет кто как этот прект с выносным датчиком сделать,чтобы одна ардуинка с релюхой в котле сидела а вторая с датчиком и экраном в нужной комнате находилась,или можент готовые проекты есть поделитесь ссылками пожалуйста.Все это без проводов.
Добрый день! Сделал термостат разработанный vlad219i. Но при включении рядом стоящего холодильника бывает зависает. Посоветуйте как бороться.
LC фильтр по питанию поставить или просто дросселек один,возможно поможет
Может подскажет кто как этот прект с выносным датчиком сделать,чтобы одна ардуинка с релюхой в котле сидела а вторая с датчиком и экраном в нужной комнате находилась,или можент готовые проекты есть поделитесь ссылками пожалуйста.Все это без проводов.
Вот тут есть интересный проект http://arduino.ru/forum/proekty/moi-termostat-dlya-kotla-baxi
сам хочу что-то подобное сделать.
Коллеги, недельный таймер, аналогичный этому, никто не делал?
По идее недельный даже не нужен, достаточно пнд-чтв, птн, сбт-вск или будни/выходные.
Подскажите, AT24C32A для EEPROM достаточно?
Подскажите, AT24C32A для EEPROM достаточно?
Если речь идёт про этот проект, то здесь используется EEPROM, встроенный в микроконтроллер.
А если нет - то ДА, конечно, достаточно. :-)
Ну это все в принципе меняет :), а я собрался AT24C32A прикручивать
Отличный термостатик получился. Автору премного благодарностей! Если кому интересно есть код на два модуля с радиосвязью по RF24.
Плохо что здесь в личку писать нельзя, как общаться, не понимаю!?
Если можно demonik-13 киньте пожалуйста свой код и схему желательно, если есть.
lkostyan@mail.ru
Вот уже 2 года бесперебойно трудится такой термостат! Хочу выразить ещё раз огромную благодарность автору! Сэкономлено несколько кубов газа и, соответственно, денег. :)
Читал, что кто-то собирался разделить датчик и управляющую часть и соединить их с помощью NRF24. Очень прошу поделиться информацией! Заранее благодарен!
Всем привет. Я снова в деле:-))
Ранее опубликованая мной многоканальная версия термостата доработана.
Использован LCD 2004 по I2C
Как и ранее для сбережения выходов ардуины использован сдвиговый регистр 74HC595.
К каждому из 8 выходов сдвигового регистра подключаем реле, которые управляют исполнительными устройствами (насосами, тенами, вентилями и т.д) поддерживая заданную температуру.
Есть главное реле (замыкает/размыкает контакты для комнатного термостата на плате котла, т.е. вкл/выкл котел), подключенное к отдельному пину ардуино. Если все 8 каналов, подключенных к сдвиговому регистру, выключены, то выключается и главное реле.
Адреса датчиков температуры прописывам в скетче. Все 8 датчиков подключать не обязательно!!!
Огромное спасибо за вашь труд!!!)) Суточный термостат это очень полезная в быту вещь, я его потключил к обогревателю для экономии электроэнегрии.
Я слегка изменил ваш скечь т.к. небыло ds1307 и DS18B20 пришлось поставить ds1302 и DHT 11.
Вот скечь если кому интересно
И схема подключения в догонку:
DHC11 OUT - A0
lcd 1602 i2c SDA-A4, SCL-A5
RTC DS1302 RST-D9, DAT-D10, CLK-D11
Encoder(Keyes) CLK-D2, DT-D3, SW-D4
Твердотельное реле D12+, GND-
Народ, кто нибуть может дать список библиотек использованных в авторском скетче. Что-то я понакачал стандартных библиотек с Arduino.cc у них имена другие, переименовывал, переименовывал и все равно ошибки вылазят при подключении библиотек. Может не все нашел ? Нахрена их надо было переименовывать в проекте ?
Народ, кто нибуть может дать список библиотек использованных в авторском скетче. Что-то я понакачал стандартных библиотек с Arduino.cc у них имена другие, переименовывал, переименовывал и все равно ошибки вылазят при подключении библиотек. Может не все нашел ? Нахрена их надо было переименовывать в проекте ?
Список библиотек - в первых строках проекта:
Список библиотек - в первых строках проекта:
Что библиотеки должны подключаться в первых строках командой #includ я в курсе.
Но что то не получается.
...
C:\skech\skech.ino:13:40: fatal error: RealTimeClockDS1307.h: No such file or directory
#include <RealTimeClockDS1307.h> // RTC
^
compilation terminated.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
Пишет вот это, я понимаю что нет библиотеки в указанной папке.
У тебя не установлена библиотека RealTimeClockDS1307
Запихал в librares RealTimeClockDS1307, теперь не может найти другую -
...
C:\skech\skech.ino:14:28: fatal error: EEPROMex.h: No such file or directory
#include <EEPROMex.h> // EE
^
compilation terminated.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307 (legacy)
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
Запихал EEPROMex теперь другая -
...
C:\skech\skech.ino:16:67: fatal error: TimerOne.h: No such file or directory
#include <TimerOne.h> // прерывания по таймеру1
^
compilation terminated.
Используем библиотеку Wire версии 1.0 из папки: C:\Electronics\Arduino\hardware\arduino\avr\libraries\Wire
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307 (legacy)
Используем библиотеку EEPROMEx версии 1.0.0 из папки: C:\Electronics\Arduino\libraries\EEPROMEx
Используем библиотеку LiquidCrystal версии 1.0.7 из папки: C:\Electronics\Arduino\libraries\LiquidCrystal
exit status 1
Ошибка компиляции для платы Arduino Pro or Pro Mini.
В дистрибутиве вообще никаких библиотек нет чтоли ? Их все нужно добавлять ?
Ну так найди и установи её...
P.S. Все пользователские библиотеки вставляй сюда - Мои документы\Arduino\libraries\ . Не надо лезть в папку, где находятся стандартные библиотеки Arduino IDE.
Ну так найди и установи её...
P.S. Все пользователские библиотеки вставляй сюда - Мои документы\Arduino\libraries\ . Не надо лезть в папку, где находятся стандартные библиотеки Arduino IDE.
Я их туда и пихаю.
В дистрибутиве вообще никаких библиотек нет чтоли ? Их все нужно добавлять ?
В дистрибутиве есть библиотеки, но в том скетче используется много сторонних библиотек.
Из стандартных там используется всего две: Wire и LiquidCrystal, остальные все сторонние.
TimerOne нашел аж 4 штуки-
TimerOne
TimerOne v9
TimerOne r11
TimerOne-master
Все с сайта Arduino.cc
Какой пихать то ?
Я их туда и пихаю.
Нет, не туда:
Используем библиотеку RealTimeClockDS1307 в папке: C:\Electronics\Arduino\libraries\RealTimeClockDS1307
Используем библиотеку EEPROMEx версии 1.0.0 из папки: C:\Electronics\Arduino\libraries\EEPROMEx
Надо сюда: Мои документы\Arduino\libraries\