Управление солнечным обогревом. Нужна помощь!

plymba
Offline
Зарегистрирован: 20.04.2016

Приветствую всех! Есть задача перекачивать горячий воздух с чердака в пространство под полом с целью увеличить температуру полов и комнатную температуру ночью за счёт аккумуляции тепла в подполе. В летнее время.  

За основу взял скетч для термостата с управлением 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(" ");
    }
  

}

 

 

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

plymba пишет:
При нынешнем коде не могу понять какой пин будет включаться при выполнении заданного условия.

Будут включаться все 5 выходов одновременно, потому как идет 5 раз сравнение одной и той же температуры:

  for (int i = 0; i < qty; i++) { 
   if (tempSensor[0] > tempSensor[1]) digitalWrite(OUT[i], HIGH);
    else digitalWrite(OUT[i], LOW);
  } 

Если нужно тупо один выход включать, то вместо всего цикла for напиши:

digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW); 

 

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

plymba пишет:

Нужно определить работу только одного определённого пина для управления нагрузкой. Условия включения нагрузки:  Т (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]

Mr.Privet
Mr.Privet аватар
Offline
Зарегистрирован: 17.11.2015

Tomasina пишет:

digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW); 

принципиално отличается от

if(tempSensor[0]>tempSensor[1])digitalWrite(OUT[0],HIGH);else digitalWrite(OUT[0],LOW);

или это одно и тоже с точки зрения компилятора?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Tomasina пишет:

Если нужно тупо один выход включать, то вместо всего цикла for напиши:

digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW); 

Или ещё короче:

digitalWrite(OUT[0], tempSensor[0] > tempSensor[1]);

 

plymba
Offline
Зарегистрирован: 20.04.2016

Mr.Privet пишет:

Tomasina пишет:

digitalWrite(OUT[0], (tempSensor[0] > tempSensor[1]) ? HIGH : LOW); 

принципиално отличается от

if(tempSensor[0]>tempSensor[1])digitalWrite(OUT[0],HIGH);else digitalWrite(OUT[0],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

plymba
Offline
Зарегистрирован: 20.04.2016

Убрал всё лишнее, получилось вот так:
 

// Термостат, до пяти датчиков 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В

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

у тебя только 3-й пин определен как выходной:

pinMode(3, OUTPUT); // Выход на реле

На нем либо 0, либо +5.

Второй пин не определен, поэтому на нем может быть что угодно.

plymba
Offline
Зарегистрирован: 20.04.2016

Tomasina пишет:

у тебя только 3-й пин определен как выходной:

pinMode(3, OUTPUT); // Выход на реле

На нем либо 0, либо +5.

Второй пин не определен, поэтому на нем может быть что угодно.

 

Так третий пин вообще всегда 0 выдаёт

 

plymba
Offline
Зарегистрирован: 20.04.2016

Разобрался! всем спасибо! Проблема была не только в коде. 

Но у меня теперь такой вопрос. Имеетсе вот такое реле (только на 5V). Когда с цифрового пина на реле подаётся сигнал, там около 4,8В. Лампочки на реле горят, но сама релюха не щёлкает. Пробовал подклучать реле от обычного зарядника 5В - релюха щёлкает.

Как можно решить этот вопрос? ну кроме установки повышающеко преобразователя перед реле

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

это не реле, а таймер - блок реле включается через N сек после подачи питания (настраивается крутилкой). Либо аналогично выключается, зависит от схемотехники.

Повышающий преобразователь тут не поможе.

plymba
Offline
Зарегистрирован: 20.04.2016

Tomasina пишет:

это не реле, а таймер - блок реле включается через N сек после подачи питания (настраивается крутилкой). Либо аналогично выключается, зависит от схемотехники.

Повышающий преобразователь тут не поможе.

 

Это реле с таймером. Сама релюха от ардуинки щёлкает, а если подключать через вход, как положено(т.е. через таймер), то не щёлкает. 

yul-i-an
yul-i-an аватар
Offline
Зарегистрирован: 10.12.2012

Напрямую к транзистору подпаяться и все.

Я бы так выкрутился

Тут посмотрите по периферии

plymba
Offline
Зарегистрирован: 20.04.2016

yul-i-an пишет:

Напрямую к транзистору подпаяться и все.

Я бы так выкрутился

Тут посмотрите по периферии

 

тогда нужная мне задержка времени не будет работать

Tomasina
Tomasina аватар
Offline
Зарегистрирован: 09.03.2013

у тебя же контроллер есть, пусть рулит.

plymba
Offline
Зарегистрирован: 20.04.2016

Tomasina пишет:

у тебя же контроллер есть, пусть рулит.

мало чё понимаю, разбираюсь на ходу, поэтому и хочу решить вопрос аппаратно.

Так то вопрос решил. Сделал на макетке плату задержки включения и выключения на таймере 555, конденсаторах и транзисторе. Осталось только диодов докупить и спаять