Помогите с кодом чайнику (millis)

sshmel
Offline
Зарегистрирован: 08.02.2017

Программа управляет 3х фазным котлом отопления и циркуляционным насосом. Не могу добиться чтобы насос выключался через 5минут после остановки ТЭНов.

 

// Управление котлом 3фазы
// v5.0
// Arduino Mega 2560

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

// #include <LiquidCrystal_I2C.h>
// LiquidCrystal_I2C lcd(0x3F,16,2);  // Устанавливаем дисплей

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

#define KEY A0
const byte OUT[] = {32, 34, 36}; // номера выходов

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

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

// адреса градусников.
DeviceAddress sensor1 = {0x28, 0xFF, 0xAB, 0xCA, 0x94, 0x16, 0x04, 0xB8};
DeviceAddress sensor2 = {0x28, 0xFF, 0x40, 0xAA, 0x8C, 0x16, 0x03, 0x6E};
DeviceAddress sensor3 = {0x28, 0xFF, 0x6B, 0x95, 0x94, 0x16, 0x04, 0xD8};


byte gradus[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
byte on[8] = {
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b01110,
  0b00000
};


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() { //// для кнопок LCD
  int val = analogRead(0);
  if (val < 20) return 5;
  else if (val < 150) return 3;
  else if (val < 320) return 4;
  else if (val < 490) return 2;
  else if (val < 740) 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]); // сохраняем в EEPROM
    }
    else if (KEY == 5) {
      tempOUTon[pos]++;
      if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
      EEPROM.write(pos, tempOUTon[pos]);
    }
    else if (KEY == 3) {  //Выходим из меню
      lcd.clear();
      break;
    }

    delay(200);
  }/////
}//

void getTemp() { // читаем температуру и заполняем массив
  ds.requestTemperatures();
  tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода
  tempSensor[1] = ds.getTempC(sensor2);
  tempSensor[2] = ds.getTempC(sensor3);
}

void sensorTest() { // ищим датчики на шине, если количество изменилось, останавливаем работу
  ds.begin();
  if (ds.getDeviceCount() != qty) erorr();
}

void heat33() {              // Мощность 33%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  digitalWrite(30, HIGH);
}

void heat66() {               // Мощность 66%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], LOW);
  digitalWrite(30, HIGH);
}

void heat100() {               // Мощность 100%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], HIGH);
  digitalWrite(30, HIGH);
}

void heatoff() {                // Отключаем нагрев
  digitalWrite(OUT[0], LOW);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  pumpoff();


}

void pumpoff() {                // Отключаем насос через 5 минут
//  currentTime = millis();
  if (currentTime >= (previousMillis + 300000)) // сравниваем текущий таймер с переменной previousMillis + 5 мин.
  {
    digitalWrite(30, LOW);
    previousMillis = currentTime;
  }
}




void setup() {
  //  Serial.begin(9600);
  pinMode(30, OUTPUT);
  currentTime = millis();
  previousMillis = currentTime;


  ds.begin();
  ds.setResolution(sensor1, 10);
  ds.setResolution(sensor2, 10);
  ds.setResolution(sensor3, 10);
  qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников,

  pinMode(KEY, INPUT);
  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() {

  previousMillis = currentTime;
  if (key() == 1) setMenu(pos); // если нажата селект, уходим в настройки

  else if (key() == 5 && pos < qty - 1) pos++; // крутим позицию
  else if (key() == 2 && pos != 0) pos--;
  else if (key() == 4) analogWrite(10, 10); // если вниз, глушим подсветку
  else if (key() == 3) digitalWrite(10, HIGH);

  sensorTest(); // тест наличия градусников на шине
  getTemp(); // читаем температуру с датчиков

  //// сверяем температуру и управляем выходами
  if (tempSensor[1] >= tempOUTon[1]) heatoff(); //Если на подаче 85гр отключаем нагрев полностью
  else
    for (int i = 0; i < qty; i++) {
      if (tempSensor[0] < tempOUTon[0] - 4) heat100();       // В зависимости от температуры на обратке отключаем часть тэнов
      else if (tempSensor[0] < tempOUTon[0] - 3) heat66();
      else if (tempSensor[0] < tempOUTon[0] - 1) heat33();
      else if (tempSensor[0] >= tempOUTon[0] + 1);
    }


  // Вывод информации на экран
  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(13, 0);  // рисуем статус выхода
  for (int i = 0; i < qty; i++) {
    if (digitalRead(OUT[i])) lcd.write(2);
    else lcd.print("O");
  }
  lcd.setCursor(13, 1); // рисуем номера выходов
  for (int i = 0; i < qty; i++) lcd.print(i + 1);

}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

строка 175 должно быть

previousMillis = previousMillis + 300000;

 

и в логике принятия решения - косяк - строка 209,что делает, УГУ

 

sshmel
Offline
Зарегистрирован: 08.02.2017
void pumpoff() {                // Отключаем насос через 5 минут
  currentTime = millis();
  if (currentTime >= (previousMillis + 300000)) // сравниваем текущий таймер с переменной previousMillis + 5 мин.
  {
    digitalWrite(30, LOW);
    previousMillis = previousMillis + 300000;
  }
}

 

Так чтоли? Не догоняю чтото..

sshmel
Offline
Зарегистрирован: 08.02.2017

209 закомментил

sshmel
Offline
Зарегистрирован: 08.02.2017

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

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sshmel пишет:

void pumpoff() {                // Отключаем насос через 5 минут
  currentTime = millis();
  if (currentTime >= (previousMillis + 300000)) // сравниваем текущий таймер с переменной previousMillis + 5 мин.
  {
    digitalWrite(30, LOW);
    previousMillis = previousMillis + 300000;
  }
}

 

Так чтоли? Не догоняю чтото..

Эта функция из лупа будет вызываться циклически через функцию отключения тэнов, значит при первом вхождение  в функцию отключения тэнов (код в loop) надо выставлять флаг, и устанавливать переменной previousMillis текущее значение, но это делать только если не выставлен флаг, если выставлен, то пропускаем этот код
Кривоватенько, конечно, но работать обязано
Вырисовывается еще одна вложенная конструкция if в строке 221

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sshmel пишет:

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

существует 99 способов, 100, профессор, 100...

первый - лёжа, ...тогда 101 )))

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

sshmel, тебе щас насоветуют.... Никогда не прибавляй к millis, конечно если не стоит цель написать кривой, не работающий код.

if (currentTime >= (previousMillis + 300000)) //Не правильно

if (currentTime - previousMillis >= 300000) //Правильно

 

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

Andy пишет:

Никогда не прибавляй к millis...

аха - и, не вычитай.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Andy пишет:

sshmel, тебе щас насоветуют.... Никогда не прибавляй к millis, конечно если не стоит цель написать кривой, не работающий код.

if (currentTime >= (previousMillis + 300000)) //Не правильно

if (currentTime - previousMillis >= 300000) //Правильно

Это да! Онож изменит premillis, сам бы так не написал потому видимый косяк пропустил, мне простительно, изучаю недавно
Там много косяков, проще всё переписать, к примеру зачем всё время зубами (релюхами) щёлкать, оно может и не щёлкнет, но ведь совершенно незачем заходить и выполнять код выключения тэнов и насоса на каждом проходе лупа при условии превышения температуры воды свыше 85 градусов

Так правильней?

void pumpoff() {                // Отключаем насос через 5 минут
   currentTime = millis();
  if (currentTime - previousMillis  >= 300000) // сравниваем текущий таймер с переменной previousMillis + 5 мин.
  {
    digitalWrite(30, LOW);
    previousMillis = previousMillis+300000;
  }
}

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Клапауций 823 пишет:

Andy пишет:

Никогда не прибавляй к millis...

аха - и, не вычитай.

А я прибавляю, прибавлял и, буду прибавлять!!!
 

PS Лапауций, а ты откуда так хорошо русский язык знаешь, запятые по знакам пунктуации расставляешь прям

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017
void pumpoff() {
currentTime = millis();
if (currentTime - previousMillis  >= 300000) {previousMillis = currentTime;
digitalWrite(30, LOW);
}
}

 

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ua6em пишет:

PS Лапауций, а ты откуда так хорошо русский язык знаешь, запятые по знакам пунктуации расставляешь прям

ЗЫ. пленных бурят допрашивал.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Это с какого такого перепугу?
А потом у Вас часы на миллис зделать низзя
 

previousMillis = currentTime;

 

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Клапауций 823 пишет:

ua6em пишет:

PS Лапауций, а ты откуда так хорошо русский язык знаешь, запятые по знакам пунктуации расставляешь прям

ЗЫ. пленных бурят допрашивал.

Я думал ты главный по ардуинам

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ua6em пишет:

Это с какого такого перепугу?
А потом у Вас часы на миллис зделать низзя
 

previousMillis = currentTime;

у кого это у ВАС?

ну, сделай 

void pumpon() {previousMillis = currentTime; digitalWrite(30, HIGH);}

void pumpoff() {
currentTime = millis();
if (currentTime - previousMillis  >= 300000) {digitalWrite(30, LOW);}
}

 

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ua6em пишет:

Я думал ты главный по ардуинам

дуины - это хобби.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Клапауций 823 пишет:

ua6em пишет:

Это с какого такого перепугу?
А потом у Вас часы на миллис зделать низзя
 

previousMillis = currentTime;

у кого это у ВАС?

ну, сделай 

void pumpon() {previousMillis = currentTime;}

void pumpoff() {
currentTime = millis();
if (currentTime - previousMillis  >= 300000) {digitalWrite(30, LOW);}
}

по условию задачи после того, как температура на выходе станет 85 градусов надо:

1. выключить тэны
2. через пять минут выключить насос, до этого он качает

То-есть, в переменную previousMillis заносим значение, когда температура стала 85 градусов, так???

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ua6em пишет:

по условию задачи после того, как температура на выходе станет 85 градусов надо:

1. выключить тэны
2. через пять минут выключить насос, до этого он качает

То-есть, в переменную previousMillis заносим значение, когда температура стала 85 градусов, так???

фикс:

void pumpon() {previousMillis = currentTime; digitalWrite(30, HIGH);}

void pumpoff() {
currentTime = millis();
if (currentTime - previousMillis  >= 300000) {digitalWrite(30, LOW);}
}

1. какие тены, бурят?

2. какой насос, бурят?

*я тебе дал пример кода когда что-то после включения выключается через определённый промежуток времени.

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Диалог глухого со слепым, я уже выше сказал, код надо переписать, он мне не нравится, просто не нравится, то что ты написал понятно, но ТС это не надо, у меня получается надо вводить два флага и луп переписать, но я не программер, можно же сделать красиво

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ua6em пишет:

я не программер, можно же сделать красиво

я не программер - я делаю красиво

*я исправил твой код #9 - насрать на ТС

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

Клапауций 823 пишет:

ua6em пишет:

я не программер, можно же сделать красиво

я не программер - я делаю красиво

*я исправил твой код #9 - насрать на ТС

А! Всё равно работать оно не будет, там логику править надо...
Дождёмся, что ТС скажет

sshmel
Offline
Зарегистрирован: 08.02.2017

Спасибо за ответы всем. Извините что нет возможности своевременно отвечать. Работаю над проектом в свободное от работы время. Попробую, обязательно отпишусь.

sshmel
Offline
Зарегистрирован: 08.02.2017
void pumpon() {previousMillis = currentTime; digitalWrite(30, HIGH);}

void pumpoff() {
currentTime = millis();
if (currentTime - previousMillis  >= 300000) {digitalWrite(30, LOW);}
}

В таком виде работать тоже не захотела

Но я  её победил :)

// Управление котлом 3фазы
// v5.0
// Arduino Mega 2560

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

// #include <LiquidCrystal_I2C.h>
// LiquidCrystal_I2C lcd(0x3F,16,2);  // Устанавливаем дисплей

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

#define KEY A0
const byte OUT[] = {32, 34, 36}; // номера выходов

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

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

// адреса градусников.
DeviceAddress sensor1 = {0x28, 0xFF, 0xAB, 0xCA, 0x94, 0x16, 0x04, 0xB8};
DeviceAddress sensor2 = {0x28, 0xFF, 0x40, 0xAA, 0x8C, 0x16, 0x03, 0x6E};
DeviceAddress sensor3 = {0x28, 0xFF, 0x6B, 0x95, 0x94, 0x16, 0x04, 0xD8};


byte gradus[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
byte on[8] = {
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b01110,
  0b00000
};


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() { //// для кнопок LCD
  int val = analogRead(0);
  if (val < 20) return 5;
  else if (val < 150) return 3;
  else if (val < 320) return 4;
  else if (val < 490) return 2;
  else if (val < 740) 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]); // сохраняем в EEPROM
    }
    else if (KEY == 5) {
      tempOUTon[pos]++;
      if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
      EEPROM.write(pos, tempOUTon[pos]);
    }
    else if (KEY == 3) {  //Выходим из меню
      lcd.clear();
      break;
    }

    delay(200);
  }/////
}//

void getTemp() { // читаем температуру и заполняем массив
  ds.requestTemperatures();
  tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода
  tempSensor[1] = ds.getTempC(sensor2);
  tempSensor[2] = ds.getTempC(sensor3);
}

void sensorTest() { // ищим датчики на шине, если количество изменилось, останавливаем работу
  ds.begin();
  if (ds.getDeviceCount() != qty) erorr();
}

void heat33() {              // Мощность 33%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  pumpon();
}

void heat66() {               // Мощность 66%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], LOW);
  pumpon();
}

void heat100() {               // Мощность 100%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], HIGH);
  pumpon();
}

void heatoff() {                // Отключаем нагрев
  digitalWrite(OUT[0], LOW);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  pumpoff();
}

void pumpon()
{
  previousMillis = currentTime;
  digitalWrite(30, HIGH);
}

// Отключаем насос через 5 минут
void pumpoff() {
  currentTime = millis();
  if (currentTime >= (previousMillis + 30000)) {
    digitalWrite(30, LOW);
    previousMillis = currentTime;
  }
}

void setup() {
  //  Serial.begin(9600);
  pinMode(30, OUTPUT);
  currentTime = millis();
  previousMillis = currentTime;


  ds.begin();
  ds.setResolution(sensor1, 10);
  ds.setResolution(sensor2, 10);
  ds.setResolution(sensor3, 10);
  qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников,

  pinMode(KEY, INPUT);
  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() == 5 && pos < qty - 1) pos++; // крутим позицию
  else if (key() == 2 && pos != 0) pos--;
  else if (key() == 4) analogWrite(10, 10); // если вниз, глушим подсветку
  else if (key() == 3) digitalWrite(10, HIGH);

  sensorTest(); // тест наличия градусников на шине
  getTemp(); // читаем температуру с датчиков

  currentTime = millis();
  
  // сверяем температуру и управляем выходами
  if (tempSensor[1] >= tempOUTon[1]) {
    heatoff(); //Если на подаче 85гр отключаем нагрев полностью
  }
  else
    for (int i = 0; i < qty; i++) {
      if (tempSensor[0] < tempOUTon[0] - 4) heat100();       // В зависимости от температуры на обратке отключаем часть тэнов
      else if (tempSensor[0] < tempOUTon[0] - 3) heat66();
      else if (tempSensor[0] < tempOUTon[0] - 1) heat33();
      else if (tempSensor[0] >= tempOUTon[0] + 1)heatoff();
    }


  // Вывод информации на экран
  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(13, 0);  // рисуем статус выхода
  for (int i = 0; i < qty; i++) {
    if (digitalRead(OUT[i])) lcd.write(2);
    else lcd.print("O");
  }
  lcd.setCursor(13, 1); // рисуем номера выходов
  for (int i = 0; i < qty; i++) lcd.print(i + 1);

}

 

 

 

 

sshmel
Offline
Зарегистрирован: 08.02.2017

Немного переработал код

Датчик 1 - температура воздуха в помещении. От него зависит греет система или нет.

Датчик 2 стоит на обратке. От его температуры зависит сколько ТЭНов включено (для экономии электроэнергии).

Датчик 3 как аварийный, стоит на подаче. Если t превышает заданную то нагрев выключается.

При отключении нагрева насос отрабатывает заданное в скетче время потом отключается

// Управление котлом 3фазы
// v6.0
// Arduino Mega 2560

#include <EEPROM.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <LiquidCrystal.h>

// #include <LiquidCrystal_I2C.h>
// LiquidCrystal_I2C lcd(0x3F,16,2);  // Устанавливаем дисплей

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

#define KEY A0
const byte OUT[] = {32, 34, 36}; // номера выходов

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

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

// адреса градусников.
DeviceAddress sensor1 = {0x28, 0xFF, 0xAB, 0xCA, 0x94, 0x16, 0x04, 0xB8};
DeviceAddress sensor2 = {0x28, 0xFF, 0x40, 0xAA, 0x8C, 0x16, 0x03, 0x6E};
DeviceAddress sensor3 = {0x28, 0xFF, 0x6B, 0x95, 0x94, 0x16, 0x04, 0xD8};


byte gradus[8] = {
  0b00110,
  0b01001,
  0b01001,
  0b00110,
  0b00000,
  0b00000,
  0b00000,
  0b00000
};
byte on[8] = {
  0b01110,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b11111,
  0b01110,
  0b00000
};


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(); // выключаем выходы
  pumpoff();
  lcd.clear();
  lcd.print("sensor error");
  while (1) { // крутим бесконечный цикл
    analogWrite(10, 100);
    delay(500);
    analogWrite(10, 255);
    delay(500);
  }
}
////

byte key() { //// для кнопок LCD
  int val = analogRead(0);
  if (val < 20) return 5;
  else if (val < 150) return 3;
  else if (val < 320) return 4;
  else if (val < 490) return 2;
  else if (val < 740) 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]); // сохраняем в EEPROM
    }
    else if (KEY == 5) {
      tempOUTon[pos]++;
      if (tempOUTon[pos] > 125) tempOUTon[pos] = 0;
      EEPROM.write(pos, tempOUTon[pos]);
    }
    else if (KEY == 3) {  //Выходим из меню
      lcd.clear();
      break;
    }

    delay(200);
  }/////
}//

void getTemp() { // читаем температуру и заполняем массив
  ds.requestTemperatures();
  tempSensor[0] = ds.getTempC(sensor1); // немного китайского кода
  tempSensor[1] = ds.getTempC(sensor2);
  tempSensor[2] = ds.getTempC(sensor3);
}

void sensorTest() { // ищим датчики на шине, если количество изменилось, останавливаем работу
  ds.begin();
  if (ds.getDeviceCount() != qty) erorr();
}

void heaton(){
for (int i = 0; i < qty; i++) {
      if (tempSensor[1] < tempOUTon[1] - 4) heat100();       // В зависимости от температуры на обратке отключаем часть тэнов
      else if (tempSensor[1] < tempOUTon[1] - 3) heat66();
      else if (tempSensor[1] < tempOUTon[1] - 1) heat33();
      else if (tempSensor[1] >= tempOUTon[1])heatoff();
    }
}


void heat33() {              // Мощность 33%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  pumpon();
}

void heat66() {               // Мощность 66%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], LOW);
  pumpon();
}

void heat100() {               // Мощность 100%
  digitalWrite(OUT[0], HIGH);
  digitalWrite(OUT[1], HIGH);
  digitalWrite(OUT[2], HIGH);
  pumpon();
}

void heatoff() {                // Отключаем нагрев
  digitalWrite(OUT[0], LOW);
  digitalWrite(OUT[1], LOW);
  digitalWrite(OUT[2], LOW);
  pumpoff();
}

void pumpon()
{
  previousMillis = currentTime;
  digitalWrite(30, HIGH);
}

// Отключаем насос через 5 минут
void pumpoff() {
  currentTime = millis();
  if (currentTime >= (previousMillis + 10000)) {
    digitalWrite(30, LOW);
    previousMillis = currentTime;
  }
}

void setup() {
  //  Serial.begin(9600);
  pinMode(30, OUTPUT);
  currentTime = millis();
  previousMillis = currentTime;


  ds.begin();
  ds.setResolution(sensor1, 10);
  ds.setResolution(sensor2, 10);
  ds.setResolution(sensor3, 10);
  qty = ds.getDeviceCount(); // при включении, сохраняем количество градусников,

  pinMode(KEY, INPUT);
  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() == 5 && pos < qty - 1) pos++; // крутим позицию
  else if (key() == 2 && pos != 0) pos--;
  else if (key() == 4) analogWrite(10, 10); // если вниз, глушим подсветку
  else if (key() == 3) digitalWrite(10, HIGH);

  sensorTest(); // тест наличия градусников на шине
  getTemp(); // читаем температуру с датчиков

  currentTime = millis();
  
  // сверяем температуру и управляем выходами
     if (tempSensor[2] >= tempOUTon[2]) {
    heatoff(); //Если на подаче 85гр отключаем нагрев полностью
  }
    else
  if (tempSensor[0] <= tempOUTon[0]) {
    heaton();
  }
  else heatoff();
 

    
  

  // Вывод информации на экран
  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(13, 0);  // рисуем статус выхода
  for (int i = 0; i < qty; i++) {
    if (digitalRead(OUT[i])) lcd.write(2);
    else lcd.print("O");
  }
  lcd.setCursor(13, 1); // рисуем номера выходов
  for (int i = 0; i < qty; i++) lcd.print(i + 1);

}

 

Проект будет развиваться дальше.

В планах запись данных на SD карту чтобы при желании посмотреть сколько котел проработал на 1/3, 2/3 или на полную мощность, сколько соответственно потребил электроэнергии.

Удаленное управление и мониторинг+охрана:

Отдельно будет стоять ардуино мега, к ней прицепим GSM модуль и датчики пожара, охраны, может ещё чего. По запросу она будет передавать данные на телефон или на сервер, так-же по запросу управлять ардуиной котла отопления (Собрался в гараж, за час-два послал смс чтобы поднял температуру)

Andy
Andy аватар
Offline
Зарегистрирован: 01.01.2016

Говнокод, будет глючить. Ты так и не понял, почему к millis нельзя прибавлять...

ardu
Offline
Зарегистрирован: 11.02.2017

sshmel пишет:

Проект будет развиваться дальше.

В таком случае стоит переделать sensorTest() так чтобы система не отключалась банально изза того что датчик глючит или плохой контакт. В случае ошибки сделайте повторную проверку через пару секунд.

 

sshmel
Offline
Зарегистрирован: 08.02.2017

Конечно я не такой сильный гуру как вы или многие другие с этого форума но тем не  менее учусь, например с вашей помощью. Месяц назад я не мог понять почему у меня лсдшник не загорался.

По поводу глюков погонял программу с час гдето, повышал и понижал температуру на всех датчиках, пока работает как надо.

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

ну, сказано же было не делать так: if (currentTime >= (previousMillis + 10000)) {

sshmel
Offline
Зарегистрирован: 08.02.2017

Можете объяснить почему?

sshmel
Offline
Зарегистрирован: 08.02.2017

Сделал так, работает

 

void pumpoff() {
  currentTime = millis();
  if ((currentTime - previousMillis)  >= 6000) {
    digitalWrite(30, LOW);
    previousMillis = currentTime;
  }
}

 

И всё же

Я же не прибавляю к millis, я прибавляю к переменной которая равняется millis, разве не так?

Если обозвать её как то по другому суть не изменится

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017

sshmel пишет:

Можете объяснить почему?

потому, что у тебя на руках и ногах по 10-ть пальцев, а не по 10+ещё.

xDriver
xDriver аватар
Offline
Зарегистрирован: 14.08.2015

Клапауций 823 пишет:

sshmel пишет:

Можете объяснить почему?

потому, что у тебя на руках и ногах по 10-ть пальцев, а не по 10+ещё.

Он еще один посчитал :)

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

sshmel пишет:

Сделал так, работает

 

void pumpoff() {
  currentTime = millis();
  if ((currentTime - previousMillis)  >= 6000) {
    digitalWrite(30, LOW);
    previousMillis = currentTime;
  }
}

 

И всё же

Я же не прибавляю к millis, я прибавляю к переменной которая равняется millis, разве не так?

Если обозвать её как то по другому суть не изменится

 Именно это вы и делаете - прибавляете к переменной хранящей предыдущее значение времени некую константу, поэтому вам все и говорят. не делайте так
Да, эта переменная должна принимать текущее значение а момент достижения макс.температуры

Второе, алгоритм отключения двигателя через 5 минут после достижения максимальной температуры так и не реализован, а вы говорите, что всё пучком...это мантра такая???

 

Клапауций 823
Клапауций 823 аватар
Offline
Зарегистрирован: 13.01.2017