Термостат с LCD на 5 датчиков

aleksey19ru
Offline
Зарегистрирован: 23.06.2016

Всем привет!

Взял готовый код, все работает отлично. Но появилась необходимость изменить работу.

Экран с кнопками и цифровые датчики, каждый датчик привязан к своему выходу, пробую привязать к одному датчику пару выходов, но не выходит(  как не извращался не хочет садится на один датчик несколько выходов.

 

#include
#include
#include
#include

OneWire oneWire(15); // A1 вход датчиков 18b20
DallasTemperature ds(&oneWire);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

const byte OUT[5] = {2, 3, 11, 12, 13}; // номера выходов

byte pos;
byte tempOUTon[5]; // массив с температурой включения выхода
float tempSensor[5]; // массив куда читается температура

byte qty; // количество градусников на шине.

// адреса градусников.
DeviceAddress sensor1 = {0x28, 0xEE, 0x28, 0x3D, 0x1E, 0x16, 0x01, 0x91};
DeviceAddress sensor2 = {0x28, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x8B};
DeviceAddress sensor3 = {0x00, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x8B};
DeviceAddress sensor4 = {0x00, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x8B};
DeviceAddress sensor5 = {0x00, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x8B};

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[i] < tempOUTon[i]) digitalWrite(OUT[i], HIGH);
else digitalWrite(OUT[i], LOW);
}

/////// вывод инфы на экран
lcd.setCursor(0, 0);
lcd.print(pos+1);
lcd.print(". ");
lcd.print(tempSensor[pos], 1); // показываем температуру с датчика
lcd.write(1);
lcd.print("C ");
lcd.setCursor(2, 1);
lcd.print(tempOUTon[pos]); // показываем установленную температуру
lcd.write(1);
lcd.print("C ");

lcd.setCursor(11, 0); // рисуем статус выхода
for (int i = 0; i < qty; i++){
if (digitalRead(OUT[i])) lcd.write(2);
else lcd.print(" ");
}
lcd.setCursor(11, 1); // рисуем номера выходов
for (int i = 0; i < qty; i++) lcd.print(i+1);

// delay(500); // необязательная задержка
}

bwn
Offline
Зарегистрирован: 25.08.2014

В 127-130 строках измените способ обработки данных.

aleksey19ru
Offline
Зарегистрирован: 23.06.2016

пробовал забивать один адрес на 2 сенсора и менял в киайском коде . не видит подмены почему то

DeviceAddress sensor1 = {0x28, 0xEE, 0x28, 0x3D, 0x1E, 0x16, 0x01, 0x91}; 
DeviceAddress sensor2 = {0x28, 0xEE, 0x28, 0x3D, 0x1E, 0x16, 0x01, 0x91}; 
DeviceAddress sensor3 = {0x00, 0xEE, 0x41, 0x3E, 0x16, 0x16, 0x01, 0xDE};
DeviceAddress sensor4 = {0x00, 0xEE, 0x44, 0x77, 0x16, 0x16, 0x01, 0x7F};
DeviceAddress sensor5 = {0x00, 0xEE, 0x44, 0x77, 0x16, 0x16, 0x01, 0x7F};

 и так пробовал
  tempSensor[0] = ds.getTempC(sensor1);             // немного китайского кода
   tempSensor[1] = ds.getTempC(sensor1); 
   tempSensor[2] = ds.getTempC(sensor3);
   tempSensor[3] = ds.getTempC(sensor4);
   tempSensor[4] = ds.getTempC(sensor5);

 

bwn
Offline
Зарегистрирован: 25.08.2014

For который отвечает за  обработку данных переделайте на if-ы.
И пять датчиков теперь обязательно нужны?

aleksey19ru
Offline
Зарегистрирован: 23.06.2016

переписать это , а нужно 2 датчика  и 4 пина управлять.

//// сверяем температуру и управляем выходами
for (int i = 0; i < qty; i++) {
if (tempSensor[i] < tempOUTon[i]) digitalWrite(OUT[i], HIGH);
else digitalWrite(OUT[i], LOW);
} 

так? да?
if tempSensor[0] < tempOUT[2] {
    digitalWrite(OUT[2], HIGH);
else digitalWrite(OUT[2], LOW);

if tempSensor[0] < tempOUT[3] {
    digitalWrite(OUT[3], HIGH);
else digitalWrite(OUT[3], LOW);


 

bwn
Offline
Зарегистрирован: 25.08.2014

Примерно так

dwk26111974
Offline
Зарегистрирован: 11.07.2016

Уважаемый автор aleksey19ru проекта, просьба поподробнее расказать о своем проекте и откуда брали исходный код. Проект заинтересовал. Заранее благодарен.

bwn
Offline
Зарегистрирован: 25.08.2014

dwk26111974 пишет:

Уважаемый автор aleksey19ru проекта, просьба поподробнее расказать о своем проекте и откуда брали исходный код. Проект заинтересовал. Заранее благодарен.

Для этого нужен чей то код? Читаете датчики, присваиваете значения переменным, проверяете if-ами, выполняте или не выполняете действия.  Все.

Если датчиков много, чтобы лишние строки не плодить, чтение удобнее в for обернуть, ну а проверку смотря по обстоятельствам.

aleksey19ru
Offline
Зарегистрирован: 23.06.2016

Чей то код взял потому как он  под экран с кнопками, с этим пока туго только вникаю, без экрана написал тоже скетч

переписал маленько код и все работает, не стал пока убирать массивы.

вопрос далее в коде прописал где условие на if-ах строки ниже 160, хочу сделать управление нагревателем с тремя ТЕНами, с рандомом голову ломал, но не получается того что хочу

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>
 
OneWire  oneWire(55); // A1 вход датчиков 18b20
DallasTemperature ds(&oneWire);
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
const int out1 =48;
const int out2 =50;
const int out3 =52;

const byte OUT[5] = {2, 3, 11, 12, 13}; // номера выходов 
 
byte pos;
byte tempOUTon[5];  // массив с температурой включения выхода
float tempSensor[5]; // массив куда читается температура

byte qty; // количество градусников на шине.

// адреса градусников.
DeviceAddress sensor1 = {0x28, 0xEE, 0x41, 0x3E, 0x16, 0x16, 0x01, 0xDE};
DeviceAddress sensor2 = {0x28, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x8B};
DeviceAddress sensor3 = {0x28, 0xEE, 0xBF, 0x75, 0x1E, 0x16, 0x01, 0x00};
DeviceAddress sensor4 = {0x28, 0xEE, 0x44, 0x77, 0x16, 0x16, 0x01, 0x00};
DeviceAddress sensor5 = {0x00, 0xEE, 0x44, 0x77, 0x16, 0x16, 0x00, 0x7F};

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() {
pinMode(out1, OUTPUT);
pinMode(out2, OUTPUT);
pinMode(out3, OUTPUT);

 //  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] < (tempOUTon[0] - 4)) { // тут считываем температуру и если она меньше заданой на 4 град то включаем 3 пина
     digitalWrite(out1, HIGH);                
     digitalWrite(out2, HIGH);
     digitalWrite(out3, HIGH); 
    }
    if (((tempOUTon[0] - 4) < tempSensor[0]) && (tempSensor[0] < (tempOUTon[0] - 2)))  {
    digitalWrite(out1, HIGH);                // тут считываем температуру и если она меньше заданой  на 4 град и меньше на 2 град, то включаем 2 пина и вот тут хотелось бы сделать чтобы случайным образом выбирались два из трех пинов, для того чтобы был меньше износ нагрузки
    digitalWrite(out2, HIGH);                
    digitalWrite(out3, LOW);                
    }                                        
    if (((tempOUTon[0] - 2) < tempSensor[0]) && (tempSensor[0] < tempOUTon[0])) {
    digitalWrite(out1, LOW);                 // тут считываем температуру и если она меньше заданой на 2 град и меньше заданой, то включаем 1 пина и вот тут хотелось бы сделать чтобы случайным образом выбирался один из трех пинов, цель та же....
    digitalWrite(out2, LOW);                 
    digitalWrite(out3, HIGH);                
    }                                        
    if (tempSensor[0] > tempOUTon[0]) {
     digitalWrite(out1, LOW);                // тут считываем температуру и если она больше заданой то все выключаем
     digitalWrite(out2, LOW);                
     digitalWrite(out3, LOW);
    }
    
  /////// вывод инфы на экран
  lcd.setCursor(0, 0); 
  lcd.print(pos+1); 
  lcd.print(". ");
  lcd.print(tempSensor[pos], 1);  // показываем температуру с датчика
  lcd.write(1);
  lcd.print("C  ");
  lcd.setCursor(2, 1);
  lcd.print(tempOUTon[pos]); // показываем установленную температуру
  lcd.write(1);
  lcd.print("C  ");    
  
  lcd.setCursor(11, 0);  // рисуем статус выхода  
    for (int i = 0; i < qty; i++){ 
      if (digitalRead(OUT[i])) lcd.write(2);
      else lcd.print(" ");
    }
  lcd.setCursor(11, 1); // рисуем номера выходов   
    for (int i = 0; i < qty; i++) lcd.print(i+1); 

// delay(500); // необязательная задержка
}

 

bwn
Offline
Зарегистрирован: 25.08.2014

aleksey19ru, а рандом то зачем? Для снижения максимума тока на холодном лучше диммер прикрутить, чтобы плавно выводил, а дальше уже и мощностью рулить сможете.

aleksey19ru
Offline
Зарегистрирован: 23.06.2016

Вы не поняли. Будет подключаться 3 тены, и чтобы количество часов работы всех тен уровнять между собой хоть немного... для этого и рандом включения на режимах где одна или две тены всего работают.

 

bwn
Offline
Зарегистрирован: 25.08.2014

Понял изначально, только снижение подаваемой мощности увеличивает ресурс в геометрической прогрессии.
Дело конечно Ваше. Можете стандартную функцию использовать или к миллис привязаться и прописать зависимость, либо в епром записывать время работы каждого (условно по 10 минут.) При круглосуточной работе одной ячейки хватит на 2 года (по даташиту), а скорее лет на 20-30.