Управление солнечным обогревом. Нужна помощь!
- Войдите на сайт для отправки комментариев
Приветствую всех! Есть задача перекачивать горячий воздух с чердака в пространство под полом с целью увеличить температуру полов и комнатную температуру ночью за счёт аккумуляции тепла в подполе. В летнее время.
За основу взял скетч для термостата с управлением 5 нагрузками с 5 датчиков.
У меня так:
Датчик DS18B20 на чердаке (sensor0)
Датчик DS18B20 в комнате(sensor2)
Датчик DS18B20 в подполе (sensor1)
Управлять нужно только одной нагрузкой - вентилятором: просто подавать 5В с любого пина на реле.
На данный момент переделал индикацию на дисплей, осталось только сделать так, чтобы на первом экране отображалось то, что уже есть, а на втором настройки времени и интервалы работы вентилятора(это ещё не готово).
Проблема в следующем:
Нужно определить работу только одного определённого пина для управления нагрузкой. Условия включения нагрузки: Т (sensor0) > Т (sensor1).
При нынешнем коде не могу понять какой пин будет включаться при выполнении заданного условия.
Помогите привести в порядок, пожалуйста)
// Термостат, до пяти датчиков DS18B20.
//
// v 0.2.1 beta
#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
OneWire oneWire(15); // A1 вход датчиков 18b20
DallasTemperature ds(&oneWire);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const byte OUT[5] = {2, 12, 11, 13, 3}; // номера выходов
byte pos;
byte tempOUTon[5]; // массив с температурой включения выхода
float tempSensor[5]; // массив куда читается температура
byte qty; // количество градусников на шине.
// адреса градусников.
DeviceAddress sensor1 = {0x28, 0x18, 0xC0, 0xB4, 0x06, 0x00, 0x00, 0x88};
DeviceAddress sensor2 = {0x28, 0xB4, 0x61, 0x88, 0x06, 0x00, 0x00, 0x0D};
DeviceAddress sensor3 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
DeviceAddress sensor4 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
DeviceAddress sensor5 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0};
byte gradus[8] = {
0b00110,
0b01001,
0b01001,
0b00110,
0b00000,
0b00000,
0b00000,
0b00000
};
byte on[8] = {
0b00110,
0b01111,
0b11111,
0b11111,
0b11111,
0b11111,
0b11110,
0b01100
};
void readSet(){
for (byte i = 0; i < qty; i++) tempOUTon[i] = EEPROM.read(i);
}
void outOff(){ // выключает выходы
for (byte i = 0; i < qty; i++) digitalWrite(OUT[i], LOW);
}
void erorr(){ // останавливает работу программы и сигнализирует ошибку
outOff(); // выключаем выходы
lcd.clear();
lcd.print("sensor error");
while(1){ // крутим бесконечный цикл
analogWrite(10, 100);
delay(500);
analogWrite(10, 255);
delay(500);
}
}
////
byte key(){ //// для кнопок ЛСДшилда
int val = analogRead(0);
if (val < 50) return 5;
else if (val < 150) return 3;
else if (val < 350) return 4;
else if (val < 500) return 2;
else if (val < 800) return 1;
else return 0;
}
////
void setMenu(byte pos){ // установка температуры
outOff();
lcd.clear();
while(1){ // крутим бесконечный цикл
byte KEY = key(); // читаем состояние кнопок
lcd.setCursor(2, 0); // выводим на экран
lcd.print("Out:");
lcd.print(pos+1);
lcd.setCursor(9, 0);
lcd.print("Pin:");
lcd.print(OUT[pos]);
lcd.print(" ");
lcd.setCursor(0, 1);
lcd.print(" PinON: ");
lcd.print(tempOUTon[pos]);
lcd.write(1);
lcd.print("C <>");
if (KEY == 2) { // если нажата кнопка
tempOUTon[pos]--; // изменяем значение
if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
EEPROM.write(pos, tempOUTon[pos]); // сохраняем в еепром
}
else if (KEY == 5){
tempOUTon[pos]++;
if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
EEPROM.write(pos, tempOUTon[pos]);
}
delay(200);
}/////
}//
void getTemp(){ // читаем температуру и заполняем массив
ds.requestTemperatures();
tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода
tempSensor[1] = ds.getTempC(sensor2);
tempSensor[2] = ds.getTempC(sensor3);
tempSensor[3] = ds.getTempC(sensor4);
tempSensor[4] = ds.getTempC(sensor5);
}
void sensorTest(){ // ищим датчики на шине, если количество изменилось, останавливаем работу
ds.begin();
if(ds.getDeviceCount() != qty) erorr();
}
void setup() {
// Serial.begin(9600);
ds.begin();
qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников,
// можно и лучше количество указать руками.
for (int i = 0; i < qty; i++) pinMode(OUT[i], OUTPUT);
for (int i = 0; i < qty; i++) digitalWrite(OUT[i], LOW);
lcd.createChar(1, gradus);
lcd.createChar(2, on);
lcd.begin(16, 2);
lcd.clear();
readSet(); // читаем настройки из еепром
}
void loop() {
if (key() == 1) setMenu(pos); // если нажата селект, уходим в настройки
else if (key() == 4 && pos < qty-1) pos++; // крутим позицию
else if (key() == 3 && pos != 0) pos--;
sensorTest(); // тест наличия градусников на шине
getTemp(); // читаем температуру с датчиков
//// сверяем температуру и управляем выходами
for (int i = 0; i < qty; i++) {
if (tempSensor[0] > tempSensor[1]) digitalWrite(OUT[i], HIGH);
else digitalWrite(OUT[i], LOW);
}
/////// вывод инфы на экран
lcd.setCursor(0, 0);
lcd.print("1");
lcd.print(":");
lcd.print(tempSensor[0], 1); // показываем температуру с датчика 0
lcd.write(1);
lcd.print(" 2");
lcd.print(":");
lcd.print(tempSensor[1], 1); // показываем температуру с датчика 1
lcd.write(1);
lcd.setCursor(0, 1);
lcd.print("3");
lcd.print(":");
lcd.print(tempSensor[2], 1); // показываем температуру с датчика 2
lcd.write(1);
lcd.setCursor(10, 1);
lcd.print("Fan:");
lcd.setCursor(15, 1); // рисуем статус выхода
{
if (digitalRead(3)) lcd.write(2);
else lcd.print(" ");
}
}
Будут включаться все 5 выходов одновременно, потому как идет 5 раз сравнение одной и той же температуры:
for (int i = 0; i < qty; i++) { if (tempSensor[0] > tempSensor[1]) digitalWrite(OUT[i], HIGH); else digitalWrite(OUT[i], LOW); }Если нужно тупо один выход включать, то вместо всего цикла for напиши:
Нужно определить работу только одного определённого пина для управления нагрузкой. Условия включения нагрузки: Т (sensor0) > Т (sensor1).
При нынешнем коде не могу понять какой пин будет включаться при выполнении заданного условия.
for (int i = 0; i < qty; i++) { if (tempSensor[0] > tempSensor[1]) digitalWrite(OUT[i], HIGH); else digitalWrite(OUT[i], LOW); }Все.
Для чего Вы одно и то же условие "(tempSensor[0] > tempSensor[1])" проверяете qty раз, хотя поменяться оно не может, я не понимаю, но это и не моё дело. Но при выполнении этого условия включаться будут все от OUT[0] до OUT[qty-1]
digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW);
принципиално отличается от
или это одно и тоже с точки зрения компилятора?
Если нужно тупо один выход включать, то вместо всего цикла for напиши:
Или ещё короче:
digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW);
принципиално отличается от
или это одно и тоже с точки зрения компилятора?
Сделал. Теперь получилось так:
// Термостат, до пяти датчиков DS18B20. // // v 0.2.1 beta #include <EEPROM.h> #include <OneWire.h> #include <DallasTemperature.h> #include <LiquidCrystal.h> OneWire oneWire(15); // A1 вход датчиков 18b20 DallasTemperature ds(&oneWire); LiquidCrystal lcd(8, 9, 4, 5, 6, 7); const byte OUT[5] = {2}; // номера выходов byte pos; byte tempOUTon[5]; // массив с температурой включения выхода float tempSensor[5]; // массив куда читается температура byte qty; // количество градусников на шине. // адреса градусников. DeviceAddress sensor1 = {0x28, 0x18, 0xC0, 0xB4, 0x06, 0x00, 0x00, 0x88}; DeviceAddress sensor2 = {0x28, 0xB4, 0x61, 0x88, 0x06, 0x00, 0x00, 0x0D}; DeviceAddress sensor3 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; DeviceAddress sensor4 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; DeviceAddress sensor5 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; byte gradus[8] = { 0b00110, 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }; byte on[8] = { 0b00110, 0b01111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11110, 0b01100 }; void readSet(){ for (byte i = 0; i < qty; i++) tempOUTon[i] = EEPROM.read(i); } void outOff(){ // выключает выходы for (byte i = 0; i < qty; i++) digitalWrite(OUT[i], LOW); } void erorr(){ // останавливает работу программы и сигнализирует ошибку outOff(); // выключаем выходы lcd.clear(); lcd.print("sensor error"); while(1){ // крутим бесконечный цикл analogWrite(10, 100); delay(500); analogWrite(10, 255); delay(500); } } //// byte key(){ //// для кнопок ЛСДшилда int val = analogRead(0); if (val < 50) return 5; else if (val < 150) return 3; else if (val < 350) return 4; else if (val < 500) return 2; else if (val < 800) return 1; else return 0; } //// void setMenu(byte pos){ // установка температуры outOff(); lcd.clear(); while(1){ // крутим бесконечный цикл byte KEY = key(); // читаем состояние кнопок lcd.setCursor(2, 0); // выводим на экран lcd.print("Out:"); lcd.print(pos+1); lcd.setCursor(9, 0); lcd.print("Pin:"); lcd.print(OUT[pos]); lcd.print(" "); lcd.setCursor(0, 1); lcd.print(" PinON: "); lcd.print(tempOUTon[pos]); lcd.write(1); lcd.print("C <>"); if (KEY == 2) { // если нажата кнопка tempOUTon[pos]--; // изменяем значение if (tempOUTon[pos] > 125) tempOUTon[pos] = 0; EEPROM.write(pos, tempOUTon[pos]); // сохраняем в еепром } else if (KEY == 5){ tempOUTon[pos]++; if (tempOUTon[pos] > 125) tempOUTon[pos] = 0; EEPROM.write(pos, tempOUTon[pos]); } delay(200); }///// }// void getTemp(){ // читаем температуру и заполняем массив ds.requestTemperatures(); tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода tempSensor[1] = ds.getTempC(sensor2); tempSensor[2] = ds.getTempC(sensor3); tempSensor[3] = ds.getTempC(sensor4); tempSensor[4] = ds.getTempC(sensor5); } void sensorTest(){ // ищим датчики на шине, если количество изменилось, останавливаем работу ds.begin(); if(ds.getDeviceCount() != qty) erorr(); } void setup() { // Serial.begin(9600); ds.begin(); qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников, // можно и лучше количество указать руками. for (int i = 0; i < qty; i++) pinMode(OUT[i], OUTPUT); for (int i = 0; i < qty; i++) digitalWrite(OUT[i], LOW); lcd.createChar(1, gradus); lcd.createChar(2, on); lcd.begin(16, 2); lcd.clear(); readSet(); // читаем настройки из еепром } void loop() { if (key() == 1) setMenu(pos); // если нажата селект, уходим в настройки else if (key() == 4 && pos < qty-1) pos++; // крутим позицию else if (key() == 3 && pos != 0) pos--; sensorTest(); // тест наличия градусников на шине getTemp(); // читаем температуру с датчиков //// сверяем температуру и управляем выходами if(tempSensor[0]>tempSensor[1])digitalWrite(2,HIGH); else digitalWrite(2,LOW); /////// вывод инфы на экран lcd.setCursor(0, 0); lcd.print("1"); lcd.print(":"); lcd.print(tempSensor[0], 1); // показываем температуру с датчика 0 lcd.write(1); lcd.print(" 2"); lcd.print(":"); lcd.print(tempSensor[1], 1); // показываем температуру с датчика 1 lcd.write(1); lcd.setCursor(0, 1); lcd.print("3"); lcd.print(":"); lcd.print(tempSensor[2], 1); // показываем температуру с датчика 2 lcd.write(1); lcd.setCursor(10, 1); lcd.print("Fan:"); lcd.setCursor(15, 1); // рисуем статус выхода { if (digitalRead(2)) lcd.write(2); else lcd.print(" "); } }Но проблема в том, что на 2 пине постоянно 4,67В. Хотя при изменении температуры, на дисплее показывает что пин в статусе LOW
Убрал всё лишнее, получилось вот так:
// Термостат, до пяти датчиков DS18B20. // // v 0.2.1 beta #include <EEPROM.h> #include <OneWire.h> #include <DallasTemperature.h> #include <LiquidCrystal.h> OneWire oneWire(15); // A1 вход датчиков 18b20 DallasTemperature ds(&oneWire); LiquidCrystal lcd(8, 9, 4, 5, 6, 7); byte pos; float tempSensor[5]; // массив куда читается температура byte qty; // количество градусников на шине. // адреса градусников. DeviceAddress sensor1 = {0x28, 0x18, 0xC0, 0xB4, 0x06, 0x00, 0x00, 0x88}; DeviceAddress sensor2 = {0x28, 0xB4, 0x61, 0x88, 0x06, 0x00, 0x00, 0x0D}; DeviceAddress sensor3 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; DeviceAddress sensor4 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; DeviceAddress sensor5 = {0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0}; byte gradus[8] = { 0b00110, 0b01001, 0b01001, 0b00110, 0b00000, 0b00000, 0b00000, 0b00000 }; byte on[8] = { 0b00110, 0b01111, 0b11111, 0b11111, 0b11111, 0b11111, 0b11110, 0b01100 }; void erorr(){ // останавливает работу программы и сигнализирует ошибку lcd.clear(); lcd.print("sensor error"); while(1){ // крутим бесконечный цикл analogWrite(10, 100); delay(500); analogWrite(10, 255); delay(500); } } //// byte key(){ //// для кнопок ЛСДшилда int val = analogRead(0); if (val < 50) return 5; else if (val < 150) return 3; else if (val < 350) return 4; else if (val < 500) return 2; else if (val < 800) return 1; else return 0; } //// void setMenu(byte pos){ // установка температуры lcd.clear(); while(1){ // крутим бесконечный цикл byte KEY = key(); // читаем состояние кнопок } }///// void getTemp(){ // читаем температуру и заполняем массив ds.requestTemperatures(); tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода tempSensor[1] = ds.getTempC(sensor2); tempSensor[2] = ds.getTempC(sensor3); tempSensor[3] = ds.getTempC(sensor4); tempSensor[4] = ds.getTempC(sensor5); } void sensorTest(){ // ищим датчики на шине, если количество изменилось, останавливаем работу ds.begin(); if(ds.getDeviceCount() != qty) erorr(); } void setup() { // Serial.begin(9600); ds.begin(); pinMode(3, OUTPUT); // Выход на реле qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников, // можно и лучше количество указать руками. lcd.createChar(1, gradus); lcd.createChar(2, on); lcd.begin(16, 2); lcd.clear(); } void loop() { if (key() == 1) setMenu(pos); // если нажата селект, уходим в настройки else if (key() == 4 && pos < qty-1) pos++; // крутим позицию else if (key() == 3 && pos != 0) pos--; sensorTest(); // тест наличия градусников на шине getTemp(); // читаем температуру с датчиков //// сверяем температуру и управляем выходами if(tempSensor[0]>tempSensor[1])digitalWrite(3,HIGH); else digitalWrite(3,LOW); /////// вывод инфы на экран lcd.setCursor(0, 0); lcd.print("1"); lcd.print(":"); lcd.print(tempSensor[0], 1); // показываем температуру с датчика 0 lcd.write(1); lcd.print(" 2"); lcd.print(":"); lcd.print(tempSensor[1], 1); // показываем температуру с датчика 1 lcd.write(1); lcd.setCursor(0, 1); lcd.print("3"); lcd.print(":"); lcd.print(tempSensor[2], 1); // показываем температуру с датчика 2 lcd.write(1); lcd.setCursor(10, 1); lcd.print("Fan:"); lcd.setCursor(15, 1); // рисуем статус выхода { if (digitalRead(3)) lcd.write(2); else lcd.print(" "); } }И теперь всё равно ничего не поменялось. не смотря на то что теперь 3 пин управляет реле, на нём всегдо 0В, а на 2 пине 4,67В
у тебя только 3-й пин определен как выходной:
На нем либо 0, либо +5.
Второй пин не определен, поэтому на нем может быть что угодно.
у тебя только 3-й пин определен как выходной:
На нем либо 0, либо +5.
Второй пин не определен, поэтому на нем может быть что угодно.
Так третий пин вообще всегда 0 выдаёт
Разобрался! всем спасибо! Проблема была не только в коде.
Но у меня теперь такой вопрос. Имеетсе вот такое реле (только на 5V). Когда с цифрового пина на реле подаётся сигнал, там около 4,8В. Лампочки на реле горят, но сама релюха не щёлкает. Пробовал подклучать реле от обычного зарядника 5В - релюха щёлкает.
Как можно решить этот вопрос? ну кроме установки повышающеко преобразователя перед реле
это не реле, а таймер - блок реле включается через N сек после подачи питания (настраивается крутилкой). Либо аналогично выключается, зависит от схемотехники.
Повышающий преобразователь тут не поможе.
это не реле, а таймер - блок реле включается через N сек после подачи питания (настраивается крутилкой). Либо аналогично выключается, зависит от схемотехники.
Повышающий преобразователь тут не поможе.
Это реле с таймером. Сама релюха от ардуинки щёлкает, а если подключать через вход, как положено(т.е. через таймер), то не щёлкает.
Напрямую к транзистору подпаяться и все.
Я бы так выкрутился
Тут посмотрите по периферии
Напрямую к транзистору подпаяться и все.
Я бы так выкрутился
Тут посмотрите по периферии
тогда нужная мне задержка времени не будет работать
у тебя же контроллер есть, пусть рулит.
у тебя же контроллер есть, пусть рулит.
мало чё понимаю, разбираюсь на ходу, поэтому и хочу решить вопрос аппаратно.
Так то вопрос решил. Сделал на макетке плату задержки включения и выключения на таймере 555, конденсаторах и транзисторе. Осталось только диодов докупить и спаять