Термостат с развитием

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

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

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

Комментарии к программе я использовал наиболее ёмко, возможно даже чрезмерно. Но так мне проще будет потом.

В этом проекте использовались:

  1. Arduino nano
  2. LCD экран 16Х2 с I2C
  3. Аналоговый джойстик нонейм
  4. Датчик DS18B20 в герметичном корпусе
  5. Блок реле на 4 реле с транзисторами без опторазвязки. (Как что-то сдохнет, переключу на другое)
  6. 3,5мм гнездо 3 пина с дополнительными контактами (миниджек)
  7. Разъём DIN-5
  8. Вилка DIN-5
  9. БП 5В от самсунга
  10. Коробка распаячная под дерево 100х100
  11. Резистор 4,7к
  12. Предполагается еще - Датчик DS18B20 в неизвестном исполнении
  13. Предполагается еще - Вилка 3,5мм 3 пина
  14. Предполагается еще - Резистор 4,7к

 

Распиновка:

Разъём DIN-5

1 — плюс

2 — авто - D4

3 — горелка - D5

4 — датчик - D2

5 — минус

 по часовой стрелке

 

3,5 мм разъем

1 — общий - плюс

2 — центр дата – D6

3 — конец - минус

4 — нз на минус – D7

 

Джойстик

1 — минус

2 — плюс

3 — VRX - A0

4 — VRY – A1

5 — SW – D3

 

LCD экран

1 — минус

2 — плюс

3 — SDA – A4

4 — SCL – A5

//ver. 2.2 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 



#define NoSensor1 0
#define NoSensor2 1

#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define SensorINput 7 //Контакт подключения датчика в помещении. Подтянуть к плюсу. При отсутствии датчика - замкнут на землю
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
//#define Buzzer=10; //Порт бузера там есть ШИМ



  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20 TN(&OneWire1); //Создаем экземпляр объекта ТН
  //OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  //DS18B20 TIN(&OneWire2); //Создаем экземпляр объекта TIN






byte newButton;
byte oldButton;

DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки


unsigned long lastMillis;
byte temperatureStrobe;

byte sensorStrobe;
byte backLightStrobe;
byte Tset;
//byte plam;
byte lightStrobe;
float Ttn;
char Ttn_char[6]; //Массив под отображение т-ры теплоносителя
char Tset_char[6]; //Массив под отображение т-ры внутренней




// ***********************ПП ошибки датчиков **************************
void SensorsError(int err) {
  
    digitalWrite(Auto, HIGH); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
    switch (err) {
      case NoSensor1:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
        break; 
      case NoSensor2:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor IN");  
        break;      
    }
   // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран установленной температуры ***********************

void lcdPrintTset(byte Tt){
    lcd.setCursor(0,1);
    lcd.print("Tset=");
    lcd.print("            ");
    lcd.setCursor(5,1);
    dtostrf(Ttn, 3, 0, Tset_char);     
    lcd.print(Tset_char);
    lcd.print((char)223);     
    lcd.print("C");       
}

// ******************** Подпрограмма считывания и выдачи на экран текущей температуры теплоносителя ************************
float Ttn_print(){
   float _Ttn = TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
    
    lcd.setCursor(0,0);
    lcd.print("Ttn =");
    lcd.setCursor(4,0);
    lcd.print("            ");
    lcd.setCursor(4,0);
    dtostrf(_Ttn, 4, 1, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    return _Ttn;
}

// ******************** Сетуп ************************

void setup(void) {
  Serial.begin(9600);
    Tset=EEPROM.read(0);
    if ((Tset <20)|(Tset>80)) { // если в EEPROM не поймешь чего
      Tset=20;
      EEPROM.write(0,Tset);
    }
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Joystik, INPUT);
    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика
    digitalWrite(SensorINput, HIGH); //Подтянем контакт наличая датчика
    digitalWrite(Gorelka, HIGH); // Выключим горелку
    digitalWrite(Auto, HIGH); //Выключим режим auto
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");
//      plam=0;

    //         BuzzerBeep();
    if(!TN.begin()) SensorsError(NoSensor1);
    
    TN.requestTemperatures();
    delay(1000);
    Ttn = TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
    
    lcd.setCursor(0,0);
    lcd.print("Ttn =");
    lcd.setCursor(4,0);
    lcd.print("            ");
    lcd.setCursor(4,0);
    dtostrf(Ttn, 4/*Полная_длина_строки*/, 1/*Количество_символов_после_запятой*/, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    lastMillis=millis();
    temperatureStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;

    lcdPrintTset(Tset); //Отображаем Tset
    
    digitalWrite(Auto, LOW); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    lightStrobe++;
    sensorStrobe++;

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
  switch (newButton){
    case BUTTON_UP:
      Tset++; //увеличение температуры на 1 градус
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_DOWN:
      Tset--; //уменьшение температуры на 1 градус
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_RIGHT:
      Tset+=5; //уменьшение температуры на 5 градусов
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_LEFT:
      Tset-=5; //уменьшение температуры на 5 градусов
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break; 
    case BUTTON_SELECT:
      lcd.backlight(); //Обнуление времени подсветки
      flagBackLight=true;
      lightStrobe=0;
      break;                         
  }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4) TN.requestTemperatures();
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      Ttn = Ttn_print();
      
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, HIGH); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19) TN.requestTemperatures();

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      
      Ttn = Ttn_print();
      
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, LOW); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe==240){ //Проверяем наличие датчика каждые 240 секунд
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(NoSensor1); //проверяем наличие датчика ТН
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>60){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=61;
  }

    }
 //------------------------------------------------------------------------------------------------------------

 

yucan
Offline
Зарегистрирован: 20.04.2015

Здравствуйте! В данный момент это устройство управляет котлом?

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Внес небольшие косметичесике изменения в программу

//ver. 2.2 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 



#define NoSensor1 0
#define NoSensor2 1

#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define SensorINput 7 //Контакт подключения датчика в помещении. Подтянуть к плюсу. При отсутствии датчика - замкнут на землю
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
#define Led 13 //Светодиодик для мигания - индикатор работы
//#define Buzzer=10; //Порт бузера там есть ШИМ



  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20 TN(&OneWire1); //Создаем экземпляр объекта ТН
  //OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  //DS18B20 TIN(&OneWire2); //Создаем экземпляр объекта TIN






byte newButton;
byte oldButton;

DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки


unsigned long lastMillis;
byte temperatureStrobe;

byte sensorStrobe;
byte backLightStrobe;
byte Tset;
//byte plam;
byte lightStrobe;
float Ttn;
char Ttn_char[6]; //Массив под отображение т-ры теплоносителя
char Tset_char[6]; //Массив под отображение т-ры внутренней




// ***********************ПП ошибки датчиков **************************
void SensorsError(int err) {
  
    digitalWrite(Auto, HIGH); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
    switch (err) {
      case NoSensor1:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
        break; 
      case NoSensor2:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor IN");  
        break;      
    }
   // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран установленной температуры ***********************

void lcdPrintTset(byte Tt){
    float _Tt=Tt;
    lcd.setCursor(0,1);
    lcd.print("Tset=");
    lcd.print("     ");
    lcd.setCursor(5,1);
    dtostrf(_Tt, 3, 0, Tset_char);     
    lcd.print(Tset_char);
    lcd.print((char)223);     
    lcd.print("C");       
}

// ******************** Подпрограмма считывания и выдачи на экран текущей температуры теплоносителя ************************
float Ttn_print(){
   float _Ttn = TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
    
    lcd.setCursor(0,0);
    lcd.print("Ttn =");
    lcd.setCursor(5,0);
    lcd.print("     ");
    lcd.setCursor(5,0);
    dtostrf(_Ttn, 4, 1, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    return _Ttn;
}

// ******************** Сетуп ************************

void setup(void) {
  Serial.begin(9600);
    Tset=EEPROM.read(0);
    if ((Tset <20)|(Tset>80)) { // если в EEPROM не поймешь чего
      Tset=20;
   
      EEPROM.write(0,Tset);
    }
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Led, OUTPUT);
    pinMode(Joystik, INPUT);
//    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика
//    digitalWrite(SensorINput, HIGH); //Подтянем контакт наличая датчика
    digitalWrite(Gorelka, HIGH); // Выключим горелку
    digitalWrite(Auto, HIGH); //Выключим режим auto
    digitalWrite(Led, HIGH); //Включим светодиод
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");
//      plam=0;

    //         BuzzerBeep();
    if(!TN.begin()) SensorsError(NoSensor1);
    
    TN.requestTemperatures();
    delay(1000);
    Ttn = TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
    
    lcd.setCursor(4,0);
    lcd.print("            ");
    lcd.setCursor(4,0);
    dtostrf(Ttn, 4/*Полная_длина_строки*/, 1/*Количество_символов_после_запятой*/, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    lastMillis=millis();
    temperatureStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;

    lcdPrintTset(Tset); //Отображаем Tset
    
    digitalWrite(Auto, LOW); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    lightStrobe++;
    sensorStrobe++;
    digitalWrite(Led,!digitalRead(Led)); //Мигаем светодиодом

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
  switch (newButton){
    case BUTTON_UP:
      Tset++; //увеличение температуры на 1 градус
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_DOWN:
      Tset--; //уменьшение температуры на 1 градус
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_RIGHT:
      Tset+=5; //уменьшение температуры на 5 градусов
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_LEFT:
      Tset-=5; //уменьшение температуры на 5 градусов
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break; 
    case BUTTON_SELECT:
      lcd.backlight(); //Обнуление времени подсветки
      flagBackLight=true;
      lightStrobe=0;
      break;                         
  }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4) TN.requestTemperatures();
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      Ttn = Ttn_print();
      
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, HIGH); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19) TN.requestTemperatures();

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      
      Ttn = Ttn_print();
      
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, LOW); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe==240){ //Проверяем наличие датчика каждые 240 секунд
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(NoSensor1); //проверяем наличие датчика ТН
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>60){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=61;
  }

    }
 //------------------------------------------------------------------------------------------------------------

Ну и фото пациента в действии

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Этот аппарат поработал пару недель и показал, что раз в 2 - 3 дня он при нагреве выходит на значение температуры минус 0,01. И с него не слезает.

Я подумал -"сподобился!" - дождался "великого переполнения millis()!". Но нет - нашел косяки в программе. Исправил, но проблема опять проявилась. Исправленная программа с паранойей:

//ver. 2.2 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 



#define NoSensor1 0
#define NoSensor2 1

#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define SensorINput 7 //Контакт подключения датчика в помещении. Подтянуть к плюсу. При отсутствии датчика - замкнут на землю
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
#define Led 13 //Светодиодик для мигания - индикатор работы
//#define Buzzer=10; //Порт бузера там есть ШИМ



  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20 TN(&OneWire1); //Создаем экземпляр объекта ТН
  //OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  //DS18B20 TIN(&OneWire2); //Создаем экземпляр объекта TIN






uint8_t newButton;
uint8_t oldButton;

DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки
boolean flagRequest; //Флаг запроса данных

unsigned long lastMillis;
uint8_t temperatureStrobe;

uint16_t sensorStrobe;
uint8_t backLightStrobe;
uint8_t Tset;
//uint8_t plam;
uint8_t lightStrobe;
float Ttn;
char Ttn_char[6]; //Массив под отображение т-ры теплоносителя
char Tset_char[6]; //Массив под отображение т-ры внутренней




// ***********************ПП ошибки датчиков **************************
void SensorsError(int err) {
  
    digitalWrite(Auto, HIGH); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
    switch (err) {
      case NoSensor1:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
        break; 
      case NoSensor2:
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor IN");  
        break;      
    }
   // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран установленной температуры ***********************

void lcdPrintTset(uint8_t Tt){
    float _Tt=Tt;
    lcd.setCursor(0,1);
    lcd.print("Tset=");
    lcd.print("     ");
    lcd.setCursor(5,1);
    dtostrf(_Tt, 3, 0, Tset_char);     
    lcd.print(Tset_char);
    lcd.print((char)223);     
    lcd.print("C");       
}

// ******************** Подпрограмма считывания и выдачи на экран текущей температуры теплоносителя ************************
float Ttn_print(){
   float _Ttn = TN.getTempC();
    while (_Ttn == DEVICE_CRC_ERROR) _Ttn=TN.getTempC();
    if(_Ttn<10)_Ttn=80.;
    
    lcd.setCursor(0,0);
    lcd.print("Ttn =");
    lcd.setCursor(5,0);
    lcd.print("     ");
    lcd.setCursor(5,0);
    dtostrf(_Ttn, 4, 1, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    return _Ttn;
}

// ******************** Сетуп ************************

void setup(void) {
  Serial.begin(9600);
    Tset=EEPROM.read(0);
    if ((Tset <20)|(Tset>80)) { // если в EEPROM не поймешь чего
      Tset=20;
   
      EEPROM.write(0,Tset);
    }
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    flagRequest=false;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Led, OUTPUT);
    pinMode(Joystik, INPUT);
//    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика
//    digitalWrite(SensorINput, HIGH); //Подтянем контакт наличая датчика
    digitalWrite(Gorelka, HIGH); // Выключим горелку
    digitalWrite(Auto, HIGH); //Выключим режим auto
    digitalWrite(Led, HIGH); //Включим светодиод
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");
//      plam=0;

    //         BuzzerBeep();
    if(!TN.begin()) SensorsError(NoSensor1);
    
    TN.requestTemperatures();
    delay(1000);
    Ttn = TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
    
    lcd.setCursor(4,0);
    lcd.print("            ");
    lcd.setCursor(4,0);
    dtostrf(Ttn, 4/*Полная_длина_строки*/, 1/*Количество_символов_после_запятой*/, Ttn_char);     
    lcd.print(Ttn_char);
    lcd.print((char)223);     
    lcd.print("C");
    lastMillis=millis();
    temperatureStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;

    lcdPrintTset(Tset); //Отображаем Tset
    
    digitalWrite(Auto, LOW); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    lightStrobe++;
    sensorStrobe++;
    digitalWrite(Led,!digitalRead(Led)); //Мигаем светодиодом

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
  switch (newButton){
    case BUTTON_UP:
      Tset++; //увеличение температуры на 1 градус
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_DOWN:
      Tset--; //уменьшение температуры на 1 градус
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_RIGHT:
      Tset+=5; //уменьшение температуры на 5 градусов
      if (Tset>80) Tset=80;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break;
    case BUTTON_LEFT:
      Tset-=5; //уменьшение температуры на 5 градусов
      if (Tset<20) Tset=20;
      lcdPrintTset(Tset);
      EEPROM.write(0,Tset);
      break; 
    case BUTTON_SELECT:
      lcd.backlight(); //Обнуление времени подсветки
      flagBackLight=true;
      lightStrobe=0;
      break;                         
  }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4) TN.requestTemperatures();
        
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      Ttn = Ttn_print();
      
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, HIGH); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19) {
      flagRequest=true;
      TN.requestTemperatures();
    }

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      
      Ttn = Ttn_print();
      flagRequest=false;
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, LOW); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe>300 && !flagRequest && !flagNagrev){ //Проверяем наличие датчика каждые 300 секунд при условии, если датчик не занят
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(NoSensor1); //проверяем наличие датчика ТН
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>60){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=61;
  }

    }
 //------------------------------------------------------------------------------------------------------------

Теперь думаю заменить датчик.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Заменил датчик - проблема была в нем.

Допилил программу с работой по датчику температуры в помещении. Сутки - полет нормальный.

//ver. 3.1 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // Для DS18B20 поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 


//*********************** Кнопки ***********************
#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5
//******************************************************

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define EEPROM_Kp 0 //Адрес Kp в EEPROM
#define EEPROM_Tset 1
#define EEPROM_Tinset 5
#define EEPROM_init 9


#define ON 0
#define OFF 1

//************************** установка номеров портов **********************************
#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6 // При отсутствии датчика - замкнут на землю
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
#define Led 13 //Светодиодик для мигания - индикатор работы
//#define Buzzer=10; //Порт бузера там есть ШИМ


// ********************************* Инициализации ***********************************************
  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20  TN(&OneWire1); //Создаем экземпляр объекта ТН
  OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  DS18B20  TIN(&OneWire2); //Создаем экземпляр объекта TIN
//***********************************************************************************************






//*********************************** Переменные ******************************************
DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки
boolean flagPID; //Флаг включения режима внутренней температуры
boolean flagRequest; //Флаг запроса температуры

uint8_t newButton;
uint8_t oldButton;

unsigned long lastMillis;
uint8_t temperatureStrobe;
uint8_t temperatureInStrobe;
uint16_t sensorStrobe;
uint16_t sensorInStrobe;
uint8_t backLightStrobe;
uint8_t EEPROM_In;

float Tset;
float Ttn;
float Tinset; //Внутренняя температура установленная
float Tin;//Внутренняя температура

uint8_t Kp;
//byte plam;
uint8_t lightStrobe;


//****************************************************************************************



// ***********************ПП ошибки **************************
void SensorsError() {
  
    digitalWrite(Auto, OFF); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
    // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран температуры***********************

void T_print(float _T, boolean stroka, boolean _PID){ //T_print(Температура,номер строки (0,1), режим) 
  char T_char[6]; //Массив под отображение т-ры
  if(stroka){
    lcd.setCursor(0,1);
    lcd.print("Tset=");
      
  }else{
    lcd.setCursor(0,0);
  }
      if(_PID){
        lcd.print("Tin =");
      }else {
        lcd.print("Ttn =");
    
  }


    lcd.print("     ");
  if(stroka){
    lcd.setCursor(5,1);
  } else {
    lcd.setCursor(5,0);
  }
    dtostrf(_T, 4, 1, T_char);     
    lcd.print(T_char);
    lcd.print((char)223);     
    lcd.print("C");       
}



// ******************** Сетуп ************************

void setup(void) {
//  Serial.begin(9600);

  EEPROM_In=EEPROM.read(EEPROM_init);
  if(EEPROM_In!=22){
    EEPROM.put(EEPROM_Kp,5);
    EEPROM.put(EEPROM_Tset,(float)40.00);
    EEPROM.put(EEPROM_Tinset,(float)23.00);
    EEPROM.put(EEPROM_init,22);
  }
 
// ************************ Чтение установок из памяти ************************************************
    Kp=EEPROM.read(EEPROM_Kp); //Коэффициент пропорциональности. Пока предполагаем не более 15
    if (Kp!=5) { // пока так
      Kp=5;
   
      EEPROM.put(EEPROM_Kp,Kp);
    }

    
    
    EEPROM.get(EEPROM_Tset,Tset); //Установленная температура теплоносителя
   
    if ((Tset <20.00f)||(Tset>80.00f)) { // если в EEPROM не поймешь чего
      Tset=20.00f;
  
      EEPROM.put(EEPROM_Tset,Tset);
    }

    
    EEPROM.get(EEPROM_Tinset,Tinset); //Установленная температура внутренняя
    if ((Tinset <20.00f)||(Tinset>40.00f)) { // если в EEPROM не поймешь чего
      Tset=23.00f;
   
      EEPROM.put(EEPROM_Tinset,Tinset);
    }

    
//Serial.println(Tset);
//Serial.println(Tinset);
//******************************************************************    
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Led, OUTPUT);
    pinMode(Joystik, INPUT);
//    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика

    digitalWrite(Gorelka, OFF); // Выключим горелку
    digitalWrite(Auto, OFF); //Выключим режим auto
    digitalWrite(Led, HIGH); //Включим светодиод
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");


    //         BuzzerBeep();

    
    
// ********************Температура теплоносителя******************
    if(!TN.begin()) SensorsError(); //Проверка наличая датчика теплоносителя
    TN.requestTemperatures();
    delay(1000);
    Ttn=TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
//    Serial.print("Ttn=");
//    Serial.println(Ttn);

//********************Проверка наличая внутреннего датчика **********************************************
    flagPID=TIN.begin();
//    Serial.print("PID=");
//    Serial.println(flagPID);
      lcd.setCursor(0,0);
      lcd.print("Internal sensor");
      lcd.setCursor(2,1);

    if(flagPID){
      lcd.print("is present");
    }else{
      lcd.print("is missing");
    }
    delay(1000);
    lcd.clear();

// ********************Температура внутренняя******************
    if(flagPID){ // При условии подключения внутреннего датчика
        TIN.requestTemperatures();
        delay(1000);
        Tin=TIN.getTempC();
        while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
        T_print(Tin, 0, flagPID);
    }else {
    
        T_print(Ttn, 0, flagPID);
    }

//**************Выдача на экран установленных значений**********************
    if(flagPID){
       T_print(Tinset, 1, flagPID);
    }else{
       T_print(Tset, 1, flagPID);
    }

    

    temperatureStrobe=0;
    temperatureInStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;
    flagRequest=false;


    
    digitalWrite(Auto, ON); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
    
    lastMillis=millis();
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    if(flagPID){
      temperatureInStrobe++;
      sensorInStrobe++;
    }
    lightStrobe++;
    sensorStrobe++;
    digitalWrite(Led,!digitalRead(Led)); //Мигаем светодиодом

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
    if(flagPID){      // Если подключен внутренний датчик
      
      switch (newButton){
        case BUTTON_UP:
          Tinset+=0.1; //увеличение температуры на 0,1 градус
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_DOWN:
          Tinset-=0.1; //уменьшение температуры на 0,1 градус
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_RIGHT:
          Tinset+=0.5; //уменьшение температуры на 0.5 градусов
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_LEFT:
          Tinset-=0.5; //уменьшение температуры на 5 градусов
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break; 
        case BUTTON_SELECT:
          T_print(Ttn, 0, 0); //Выводим температуру теплоносителя
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break; 
      }        
      
    }else { // Если отсутствует внутренний датчик
      
        
      switch (newButton){
        case BUTTON_UP:
          Tset++; //увеличение температуры на 1 градус
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_DOWN:
          Tset--; //уменьшение температуры на 1 градус
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_RIGHT:
          Tset+=5; //уменьшение температуры на 5 градусов
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_LEFT:
          Tset-=5; //уменьшение температуры на 5 градусов
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break; 
        case BUTTON_SELECT:
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break;                         
     }
   }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4) {
      flagRequest=true;
      TN.requestTemperatures();
    }
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, OFF); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
        
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19) {
      flagRequest=true;
      TN.requestTemperatures();
    }

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, ON); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//****************** Запрос внутренней температуры и регулировка температуры теплоносителя раз в 2 минуты ****************************************

  if(flagPID){
    if(temperatureInStrobe==119){
      flagRequest=true;
      TIN.requestTemperatures();
    }
    if(temperatureInStrobe==120){
    
      Tin = TIN.getTempC();
      while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
      flagRequest=false;
      T_print(Tin, 0, flagPID);;
      
      Tset+=(float)Kp*(Tinset-Tin); // Управляем температурой теплоносителя 
      if (Tset>80) Tset=80.;
      if (Tset<20) Tset=20.;
//      Serial.print("Tin=");
//      Serial.println(Tin);
    }
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe>=300 && !flagNagrev && !flagRequest){ //Проверяем наличие датчика теплоносителя каждые 300 секунд
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(); //проверяем наличие датчика ТН
  }
  if(flagPID){
    if (sensorInStrobe>=300 && !flagRequest){ //Проверяем наличие внутреннего датчика каждые 300 секунд
    sensorInStrobe=0;
    if(!TIN.getAddress(SensorIN_add)) { //Если отсутствует - переходим на управление по установленной т-ре теплоносителя
      flagPID=false;
      EEPROM.get(EEPROM_Tset,Tset);
      T_print(Tset, 1, flagPID);
    }
   }
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>60){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=61;
  }

    }
 //------------------------------------------------------------------------------------------------------------

Ну и схема. малость кривовато.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Исправил несколько незначительных косячков:

//ver. 3.1 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // Для DS18B20 поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 


//*********************** Кнопки ***********************
#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5
//******************************************************

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define EEPROM_Kp 0 //Адрес Kp в EEPROM
#define EEPROM_Tset 1
#define EEPROM_Tinset 5
#define EEPROM_init 9


#define ON 0
#define OFF 1

//************************** установка номеров портов **********************************
#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6 // При отсутствии датчика - замкнут на землю
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
#define Led 13 //Светодиодик для мигания - индикатор работы
//#define Buzzer=10; //Порт бузера там есть ШИМ


// ********************************* Инициализации ***********************************************
  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20  TN(&OneWire1); //Создаем экземпляр объекта ТН
  OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  DS18B20  TIN(&OneWire2); //Создаем экземпляр объекта TIN
//***********************************************************************************************






//*********************************** Переменные ******************************************
DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки
boolean flagPID; //Флаг включения режима внутренней температуры
boolean flagRequest; //Флаг запроса температуры
boolean flagRequestIn; //Флаг запроса температуры

uint8_t newButton;
uint8_t oldButton;

unsigned long lastMillis;
uint8_t temperatureStrobe;
uint8_t temperatureInStrobe;
uint16_t sensorStrobe;
uint16_t sensorInStrobe;
uint8_t backLightStrobe;
uint8_t EEPROM_In;

float Tset;
float Ttn;
float Tinset; //Внутренняя температура установленная
float Tin;//Внутренняя температура

uint8_t Kp;
//byte plam;
uint8_t lightStrobe;


//****************************************************************************************



// ***********************ПП ошибки **************************
void SensorsError() {
  
    digitalWrite(Auto, OFF); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
    // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран температуры***********************

void T_print(float _T, boolean stroka, boolean _PID){ //T_print(Температура,номер строки (0,1), режим) 
  char T_char[6]; //Массив под отображение т-ры
  if(stroka){
    lcd.setCursor(0,1);
    lcd.print("Tset=");
      
  }else{
    lcd.setCursor(0,0);
  }
      if(_PID){
        lcd.print("Tin =");
      }else {
        lcd.print("Ttn =");
    
  }


    lcd.print("     ");
  if(stroka){
    lcd.setCursor(5,1);
  } else {
    lcd.setCursor(5,0);
  }
    dtostrf(_T, 4, 1, T_char);     
    lcd.print(T_char);
    lcd.print((char)223);     
    lcd.print("C");       
}



// ******************** Сетуп ************************

void setup(void) {
//  Serial.begin(9600);

  EEPROM_In=EEPROM.read(EEPROM_init);
  if(EEPROM_In!=22){
    EEPROM.put(EEPROM_Kp,3);
    EEPROM.put(EEPROM_Tset,(float)40.00);
    EEPROM.put(EEPROM_Tinset,(float)23.00);
    EEPROM.put(EEPROM_init,22);
  }
 
// ************************ Чтение установок из памяти ************************************************
    Kp=EEPROM.read(EEPROM_Kp); //Коэффициент пропорциональности. Пока предполагаем не более 15
    if (Kp!=3) { // пока так
      Kp=3;
   
      EEPROM.put(EEPROM_Kp,Kp);
    }

    
    
    EEPROM.get(EEPROM_Tset,Tset); //Установленная температура теплоносителя
   
    if ((Tset <20.00f)||(Tset>80.00f)) { // если в EEPROM не поймешь чего
      Tset=20.00f;
  
      EEPROM.put(EEPROM_Tset,Tset);
    }

    
    EEPROM.get(EEPROM_Tinset,Tinset); //Установленная температура внутренняя
    if ((Tinset <20.00f)||(Tinset>40.00f)) { // если в EEPROM не поймешь чего
      Tset=23.00f;
   
      EEPROM.put(EEPROM_Tinset,Tinset);
    }

    
//Serial.println(Tset);
//Serial.println(Tinset);
//******************************************************************    
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Led, OUTPUT);
    pinMode(Joystik, INPUT);
//    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика

    digitalWrite(Gorelka, OFF); // Выключим горелку
    digitalWrite(Auto, OFF); //Выключим режим auto
    digitalWrite(Led, HIGH); //Включим светодиод
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");


    //         BuzzerBeep();

    
    
// ********************Температура теплоносителя******************
    if(!TN.begin()) SensorsError(); //Проверка наличая датчика теплоносителя
    TN.requestTemperatures();
    delay(1000);
    Ttn=TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
//    Serial.print("Ttn=");
//    Serial.println(Ttn);

//********************Проверка наличая внутреннего датчика **********************************************
    flagPID=TIN.begin();
//    Serial.print("PID=");
//    Serial.println(flagPID);
      lcd.setCursor(0,0);
      lcd.print("Internal sensor");
      lcd.setCursor(2,1);

    if(flagPID){
      lcd.print("is present");
    }else{
      lcd.print("is missing");
    }
    delay(1000);
    lcd.clear();

// ********************Температура внутренняя******************
    if(flagPID){ // При условии подключения внутреннего датчика
        TIN.requestTemperatures();
        delay(1000);
        Tin=TIN.getTempC();
        while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
        T_print(Tin, 0, flagPID);
    }else {
    
        T_print(Ttn, 0, flagPID);
    }

//**************Выдача на экран установленных значений**********************
    if(flagPID){
       T_print(Tinset, 1, flagPID);
    }else{
       T_print(Tset, 1, flagPID);
    }

    

    temperatureStrobe=0;
    temperatureInStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;
    flagRequest=false;
    flagRequestIn=false;
    if(flagPID)Tset=Ttn;

    
    digitalWrite(Auto, ON); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
    
    lastMillis=millis();
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    if(flagPID){
      temperatureInStrobe++;
      sensorInStrobe++;
    }
    lightStrobe++;
    sensorStrobe++;
    digitalWrite(Led,!digitalRead(Led)); //Мигаем светодиодом

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
    if(flagPID){      // Если подключен внутренний датчик
      
      switch (newButton){
        case BUTTON_UP:
          Tinset+=0.1; //увеличение температуры на 0,1 градус
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_DOWN:
          Tinset-=0.1; //уменьшение температуры на 0,1 градус
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_RIGHT:
          Tinset+=0.5; //уменьшение температуры на 0.5 градусов
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_LEFT:
          Tinset-=0.5; //уменьшение температуры на 5 градусов
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break; 
        case BUTTON_SELECT:
          T_print(Ttn, 0, 0); //Выводим температуру теплоносителя
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break; 
      }        
      
    }else { // Если отсутствует внутренний датчик
      
        
      switch (newButton){
        case BUTTON_UP:
          Tset++; //увеличение температуры на 1 градус
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_DOWN:
          Tset--; //уменьшение температуры на 1 градус
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_RIGHT:
          Tset+=5; //уменьшение температуры на 5 градусов
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_LEFT:
          Tset-=5; //уменьшение температуры на 5 градусов
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break; 
        case BUTTON_SELECT:
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break;                         
     }
   }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4 && !flagRequest) {
      flagRequest=true;
      TN.requestTemperatures();
    }
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, OFF); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
        
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19 && !flagRequest) {
      flagRequest=true;
      TN.requestTemperatures();
    }

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, ON); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//****************** Запрос внутренней температуры и регулировка температуры теплоносителя раз в 2 минуты ****************************************

  if(flagPID){
    if(temperatureInStrobe==119 && !flagRequestIn){
      flagRequestIn=true;
      TIN.requestTemperatures();
    }
    if(temperatureInStrobe==120){
    
      Tin = TIN.getTempC();
      while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
      flagRequestIn=false;
      T_print(Tin, 0, flagPID);;
      
      Tset+=(float)Kp*(Tinset-Tin); // Управляем температурой теплоносителя 
      if (Tset>80) Tset=80.;
      if (Tset<20) Tset=20.;
//      Serial.print("Tin=");
//      Serial.println(Tin);
    }
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe>=300 && !flagNagrev && !flagRequest){ //Проверяем наличие датчика теплоносителя каждые 300 секунд
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(); //проверяем наличие датчика ТН
  }
  if(flagPID){
    if (sensorInStrobe>=300 && !flagRequestIn){ //Проверяем наличие внутреннего датчика каждые 300 секунд
    sensorInStrobe=0;
    if(!TIN.getAddress(SensorIN_add)) { //Если отсутствует - переходим на управление по установленной т-ре теплоносителя
      flagPID=false;
      EEPROM.get(EEPROM_Tset,Tset);
      T_print(Tset, 1, flagPID);
    }
   }
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>120){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=121;
  }

    }
 //------------------------------------------------------------------------------------------------------------

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

3 недели система проработала и показала свою эффективность. Когда гоню самогон - хорошо снижает нагрев батарей и держит установленную температуру в помещении. Для моего дома ( где - то 300м2) коэффициент получился 3. Предполагаю, что с уменьшением площади коэффициент должен увеличиваться.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Пока температура наруже держалась около нуля - все было в норме. Но вчера температура опустилась и задул ветер. Система стала вести себя странно - повысила температуру в помещении на 0,5 градусов и так и держит. Возможно это связано с инертностью системы отопления и неправильным местом установки датчика внутренней температуры.

Если это инертность - надо переводить Кр во float и вычислять его параметры от того - нагревается или охлаждается. Как мне рассказывали тепловики - там квадратичная зависимость. Т.е. программно решаемо

Если это неправильное место установки датчика, то тут непонятка. Ведь в этом "неправильном" месте прибор тоже должен найти свой "конценсус"? Почему поднимает температуру? 

И третий вариант - американские спецслужбы взломали мою программу. Но это я отношу к "невозможному" и поэтому поставил код защиты - 22.

Дык чего это? Куда копать?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Копать в сторону логов.

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

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:
Копать в сторону логов.

Спасибо - думаю в эту сторону. Комп гонять для записи логов как-то брутальненько. Думаю подключить малинку, как только разберусь с ее com-портами.

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

Подключение  DATA датчиков с подтяжкой  к плюсу через 4.7 К Ом выглядит крайне сомнительно....    Не знаю, может это особенность библиотеки...  чтение через Жэ...

Но могу посоветовать сменить библиотеку управления датчиками.

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

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

progrik
Offline
Зарегистрирован: 30.12.2018

Nord_Air пишет:
Если бы создатели датчика, решили что DATA нужно подтянуть к плюсу, думаю они сами бы поставили резистор.
если бы на каждом датчике висел резистор, а ты их запараллелил штук сто, ты бы получил HI на DATA и более ничего. поэтому производители _правильно_ решили, что если чел захочет поставить 50 датчиков - вот резистор один на всех и припаяет... это требование для ЛИНИИ а не для датчика...
и на dht11/dht22 надо самому ~5-10КОм между + и "дата" цеплять, и вообще вся однопроводная фигня, что я видел, имеет на конце 1 резистор, не зависимо от кол-ва датчиков...
вроде как-то так...

Nord_Air
Offline
Зарегистрирован: 15.06.2020

progrik пишет:

поэтому производители _правильно_ решили, что если чел захочет поставить 50 датчиков - вот резистор один на всех и припаяет... это требование для ЛИНИИ а не для датчика...
 

50 датчиков и все на один DATA пин, (линию по вашему) ? ;)

Ну и самое главное. Я сам точно не знаю, может он реально нужен? Но зачем?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Если не знаете, то Google -> "ds18b20 datasheet", стр.7 к примеру.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

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

sadman41: отдельное спасибо! Ваш совет по поводу логов был исключительно уместен.

Программа без косяка:

//ver. 3.1 arduino nano
// 
#include <Wire.h> 
#include <OneWire.h>  // Для DS18B20 поставить резисторы   4.7K от плюса на дата
#include <LiquidCrystal_I2C.h>
#include <DS18B20.h> //  AUTHOR: Rob.Tillaart@gmail.com расположение https://github.com/RobTillaart/DS18B20
#include <EEPROM.h> 


//*********************** Кнопки ***********************
#define BUTTON_NONE 0
#define BUTTON_RIGHT 1
#define BUTTON_UP 2
#define BUTTON_DOWN 3
#define BUTTON_LEFT 4
#define BUTTON_SELECT 5
//******************************************************

#define TimeStrobe 1000 // Время стробирования 1 секунда
#define Gisteresis 5 //Гистерезис температуры 5 градусов

#define EEPROM_Kp 0 //Адрес Kp в EEPROM
#define EEPROM_Tset 1
#define EEPROM_Tinset 5
#define EEPROM_init 9


#define ON 0
#define OFF 1

//************************** установка номеров портов **********************************
#define SensorTN 2 // Датчик теплоносителя на порту 2
#define SensorIN 6 // Датчик внутренний на порту 6 // При отсутствии датчика - замкнут на землю
#define Joystik 3 //Порт кнопки джойстика
#define Gorelka 5 //Порт горелки используем нормально замкнутый контакт
#define Auto 4 //Порт включения автоматики
#define ValueX A0 //Анлоговый порт подключения джойстика по оси X
#define ValueY A1 //Анлоговый порт подключения джойстика по оси Y
#define Led 13 //Светодиодик для мигания - индикатор работы
//#define Buzzer=10; //Порт бузера там есть ШИМ


// ********************************* Инициализации ***********************************************
  LiquidCrystal_I2C lcd(0x27,16,2); // Инициализация библиотеку LCD на пинах (для arduino nano) SDA – A4, SCL – A5

  OneWire  OneWire1(SensorTN); //Инициализируем датчик ТН
  DS18B20  TN(&OneWire1); //Создаем экземпляр объекта ТН
  OneWire  OneWire2(SensorIN); //Инициализируем датчик внутренний
  DS18B20  TIN(&OneWire2); //Создаем экземпляр объекта TIN
//***********************************************************************************************






//*********************************** Переменные ******************************************
DeviceAddress SensorTN_add; //Адрес датчика ТН
DeviceAddress SensorIN_add; //Адрес датчика внутреннего

boolean flagNagrev; //Флаг нагрева
boolean flagBackLight; //Флаг подсветки
boolean flagPID; //Флаг включения режима внутренней температуры
boolean flagRequest; //Флаг запроса температуры
boolean flagRequestIn; //Флаг запроса температуры

uint8_t newButton;
uint8_t oldButton;

unsigned long lastMillis;
uint8_t temperatureStrobe;
uint8_t temperatureInStrobe;
uint16_t sensorStrobe;
uint16_t sensorInStrobe;
uint8_t backLightStrobe;
uint8_t EEPROM_In;

float Tset;
float Ttn;
float Tinset; //Внутренняя температура установленная
float Tin;//Внутренняя температура

uint8_t Kp;
//byte plam;
uint8_t lightStrobe;


//****************************************************************************************



// ***********************ПП ошибки **************************
void SensorsError() {
  
    digitalWrite(Auto, OFF); //Отключаем автоматику
    lcd.setCursor(15,1);
    lcd.print(" ");
        lcd.clear();
        lcd.setCursor(0, 0);
        lcd.print("No sensor TN");
    // Serial.println("ERROR");
    while (true); //затыкаемся здесь
       
}

  
  //**********************************ПП Считывание нажатия клавиш************************************
  int getPressedButton() {
  //int button;
  int buttonValueX = analogRead(ValueX); // считываем значения с аналогового входа ValueX
  int buttonValueY = analogRead(ValueY); // считываем значения с аналогового входа ValueY 
  boolean JoystikValue = digitalRead(Joystik); //считываем значение кнопки
  if ((buttonValueX > 100)&&(buttonValueX < 950)&& (buttonValueY > 100)&&(buttonValueY < 950)&&JoystikValue)  return BUTTON_NONE;
 
  if (buttonValueX > 950) return BUTTON_LEFT;  
  if (buttonValueX < 100) return BUTTON_RIGHT;
  if (buttonValueY < 100) return BUTTON_DOWN;
  if (buttonValueY > 950) return BUTTON_UP;
  if (!JoystikValue)      return BUTTON_SELECT;
  return BUTTON_NONE; //На всякий случай 
  }


//******************* подпрограмма выдачи на экран температуры***********************

void T_print(float _T, boolean stroka, boolean _PID){ //T_print(Температура,номер строки (0,1), режим) 
  char T_char[6]; //Массив под отображение т-ры
  if(stroka){
    lcd.setCursor(0,1);
    lcd.print("Tset=");
      
  }else{
    lcd.setCursor(0,0);
  }
      if(_PID){
        lcd.print("Tin =");
      }else {
        lcd.print("Ttn =");
    
  }


    lcd.print("     ");
  if(stroka){
    lcd.setCursor(5,1);
  } else {
    lcd.setCursor(5,0);
  }
    dtostrf(_T, 4, 1, T_char);     
    lcd.print(T_char);
    lcd.print((char)223);     
    lcd.print("C");       
}



// ******************** Сетуп ************************

void setup(void) {
//  Serial.begin(9600);

  EEPROM_In=EEPROM.read(EEPROM_init);
  if(EEPROM_In!=22){
    EEPROM.put(EEPROM_Kp,3);
    EEPROM.put(EEPROM_Tset,(float)40.00);
    EEPROM.put(EEPROM_Tinset,(float)23.00);
    EEPROM.put(EEPROM_init,22);
  }
 
// ************************ Чтение установок из памяти ************************************************
    Kp=EEPROM.read(EEPROM_Kp); //Коэффициент пропорциональности. Пока предполагаем не более 15
    if (Kp!=3) { // пока так
      Kp=3;
   
      EEPROM.put(EEPROM_Kp,Kp);
    }

    
    
    EEPROM.get(EEPROM_Tset,Tset); //Установленная температура теплоносителя
   
    if ((Tset <20.00f)||(Tset>80.00f)) { // если в EEPROM не поймешь чего
      Tset=20.00f;
  
      EEPROM.put(EEPROM_Tset,Tset);
    }

    
    EEPROM.get(EEPROM_Tinset,Tinset); //Установленная температура внутренняя
    if ((Tinset <20.00f)||(Tinset>40.00f)) { // если в EEPROM не поймешь чего
      Tset=23.00f;
   
      EEPROM.put(EEPROM_Tinset,Tinset);
    }

    
//Serial.println(Tset);
//Serial.println(Tinset);
//******************************************************************    
    
    lcd.init();

    lcd.clear();
    lcd.backlight();                 // Подключение подсветки
    flagBackLight=true;
    oldButton=BUTTON_NONE;
    pinMode(Gorelka, OUTPUT);
    pinMode(Auto, OUTPUT);
    pinMode(Led, OUTPUT);
    pinMode(Joystik, INPUT);
//    pinMode(SensorINput, INPUT);
    
    digitalWrite(Joystik, HIGH); //Подтянем кнопку джойстика

    digitalWrite(Gorelka, OFF); // Выключим горелку
    digitalWrite(Auto, OFF); //Выключим режим auto
    digitalWrite(Led, HIGH); //Включим светодиод
//    Serial.println("Auto OFF");
//      Serial.println("Gorelka OFF");


    //         BuzzerBeep();

    
    
// ********************Температура теплоносителя******************
    if(!TN.begin()) SensorsError(); //Проверка наличая датчика теплоносителя
    TN.requestTemperatures();
    delay(1000);
    Ttn=TN.getTempC();
    while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
//    Serial.print("Ttn=");
//    Serial.println(Ttn);

//********************Проверка наличая внутреннего датчика **********************************************
    flagPID=TIN.begin();
//    Serial.print("PID=");
//    Serial.println(flagPID);
      lcd.setCursor(0,0);
      lcd.print("Internal sensor");
      lcd.setCursor(2,1);

    if(flagPID){
      lcd.print("is present");
    }else{
      lcd.print("is missing");
    }
    delay(1000);
    lcd.clear();

// ********************Температура внутренняя******************
    if(flagPID){ // При условии подключения внутреннего датчика
        TIN.requestTemperatures();
        delay(1000);
        Tin=TIN.getTempC();
        while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
        T_print(Tin, 0, flagPID);
    }else {
    
        T_print(Ttn, 0, flagPID);
    }

//**************Выдача на экран установленных значений**********************
    if(flagPID){
       T_print(Tinset, 1, flagPID);
    }else{
       T_print(Tset, 1, flagPID);
    }

    

    temperatureStrobe=0;
    temperatureInStrobe=0;
    sensorStrobe=0;
    lightStrobe=0;
    flagNagrev=false;
    flagRequest=false;
    flagRequestIn=false;
    if(flagPID)Tset=Ttn;

    
    digitalWrite(Auto, ON); //Включаем автоматику 
    lcd.setCursor(15,1);
    lcd.print("A");
    
    lastMillis=millis();
 }
 

// ---------------------------------------- Основная программа ---------------------------------------------------------------

void loop(void) {
// ***************Стробирование
  if ((millis()-lastMillis)>= TimeStrobe) { //стробируем раз в TimeStrobe
    lastMillis=millis();
    temperatureStrobe++;
    if(flagPID){
      temperatureInStrobe++;
      sensorInStrobe++;
    }
    lightStrobe++;
    sensorStrobe++;
    digitalWrite(Led,!digitalRead(Led)); //Мигаем светодиодом

  }

// *************Считывание кнопки ***********************************************
  newButton=getPressedButton();
  if (newButton!=oldButton){
    oldButton=newButton;
  if (flagBackLight){ // Если свет горит, то выполняем команды
    if(flagPID){      // Если подключен внутренний датчик
      
      switch (newButton){
        case BUTTON_UP:
          Tinset+=0.1; //увеличение температуры на 0,1 градус
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_DOWN:
          Tinset-=0.1; //уменьшение температуры на 0,1 градус
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_RIGHT:
          Tinset+=0.5; //уменьшение температуры на 0.5 градусов
          if (Tinset>30) Tinset=30.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break;
        case BUTTON_LEFT:
          Tinset-=0.5; //уменьшение температуры на 5 градусов
          if (Tinset<20) Tinset=20.;
          T_print(Tinset, 1, flagPID);
          EEPROM.put(EEPROM_Tinset,Tinset);
          break; 
        case BUTTON_SELECT:
          T_print(Ttn, 0, 0); //Выводим температуру теплоносителя
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break; 
      }        
      
    }else { // Если отсутствует внутренний датчик
      
        
      switch (newButton){
        case BUTTON_UP:
          Tset++; //увеличение температуры на 1 градус
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_DOWN:
          Tset--; //уменьшение температуры на 1 градус
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_RIGHT:
          Tset+=5; //уменьшение температуры на 5 градусов
          if (Tset>80) Tset=80;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break;
        case BUTTON_LEFT:
          Tset-=5; //уменьшение температуры на 5 градусов
          if (Tset<20) Tset=20;
          T_print(Tset, 1, flagPID);
          EEPROM.put(EEPROM_Tset,Tset);
          break; 
        case BUTTON_SELECT:
          lcd.backlight(); //Обнуление времени подсветки
          flagBackLight=true;
          lightStrobe=0;
          break;                         
     }
   }
  } else { // Если свет не горит, то включаем свет
      lcd.backlight(); //Включение подсветки
      flagBackLight=true;
      lightStrobe=0;
    }
  }
// *************Управление горелкой ************************************
  
  if (flagNagrev){   // Если горит
    if (temperatureStrobe==4 && !flagRequest) {
      flagRequest=true;
      TN.requestTemperatures();
    }
    if (temperatureStrobe==5){ //Смотрим каждые 5 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      if (Ttn>=Tset) {
        digitalWrite(Gorelka, OFF); //Выключаем горелку
        flagNagrev=false;
        lcd.setCursor(15,0);
        lcd.print(" ");
        
      }
    }
  } else{   //Если не горит
    if (temperatureStrobe==19 && !flagRequest) {
      flagRequest=true;
      TN.requestTemperatures();
    }

     if (temperatureStrobe==20){ //Смотрим каждые 20 секунд
      temperatureStrobe=0;
      flagRequest=false;
      
      Ttn = Ttn=TN.getTempC();
      while (Ttn == DEVICE_CRC_ERROR) Ttn=TN.getTempC();
      if(!flagPID)T_print(Ttn, 0, flagPID);
//      Serial.print("Tset=");
//        Serial.println(Tset);
//        Serial.print("Ttn=");
//        Serial.println(Ttn);
      
      if ( Ttn <=(Tset-Gisteresis)) {
        digitalWrite(Gorelka, ON); //Включаем горелку
        flagNagrev=true;
        lcd.setCursor(15,0);
        lcd.print("F");
      }    
     } 
  }

//****************** Запрос внутренней температуры и регулировка температуры теплоносителя раз в 2 минуты ****************************************

  if(flagPID){
    if(temperatureInStrobe==119 && !flagRequestIn){
      flagRequestIn=true;
      TIN.requestTemperatures();
    }
    if(temperatureInStrobe==120){

      temperatureInStrobe=0;
    
      Tin = TIN.getTempC();
      while (Tin == DEVICE_CRC_ERROR) Tin=TIN.getTempC();
      flagRequestIn=false;
      T_print(Tin, 0, flagPID);;
      
      Tset+=(float)Kp*(Tinset-Tin); // Управляем температурой теплоносителя 
      if (Tset>80) Tset=80.;
      if (Tset<20) Tset=20.;
//      Serial.print("Tin=");
//      Serial.println(Tin);
    }
  }

//*******************Проверка датчика - для особо опасливых таких как я **************************************
  if (sensorStrobe>=300 && !flagNagrev && !flagRequest){ //Проверяем наличие датчика теплоносителя каждые 300 секунд
    sensorStrobe=0;
    if(!TN.getAddress(SensorTN_add)) SensorsError(); //проверяем наличие датчика ТН
  }
  if(flagPID){
    if (sensorInStrobe>=300 && !flagRequestIn){ //Проверяем наличие внутреннего датчика каждые 300 секунд
    sensorInStrobe=0;
    if(!TIN.getAddress(SensorIN_add)) { //Если отсутствует - переходим на управление по установленной т-ре теплоносителя
      flagPID=false;
      EEPROM.get(EEPROM_Tset,Tset);
      T_print(Tset, 1, flagPID);
    }
   }
  }
  
//**************** Выключение подсветки через 60 секунд ****************************************
  if (lightStrobe>120){
    if (flagBackLight){
      lcd.noBacklight();
      flagBackLight=false;
    }
    lightStrobe=121;
  }

    }
 //------------------------------------------------------------------------------------------------------------

 

progrik
Offline
Зарегистрирован: 30.12.2018

Nord_Air пишет:
50 датчиков и все на один DATA пин, (линию по вашему) ? ;)
не, ну можно больше, если нужно...))
как верно подметил sadman41 - читай мануал... гроу ё брэйн))

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Провел мониторинг данных в течении суток с 16:00 по 17:00. Система вела себя идеально.

Сутки оказались показательными - с 16:00 до полуночи температура снизилась зде-то на 7 градусов, утром начался ветер, днем супруга готовила. Это отражается на поведении термостата. Сначала небольшое увеличение температуры теплоносителя, потом еще увеличение, во время готовки - снижение.

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

В выходные уменьшу коэффициент пропорциональности. Отклик должен уменьшится и раскачивание может уменьшиться, а может и нет.

Проведу эксперимент - посмотрим.

График:

 

progrik
Offline
Зарегистрирован: 30.12.2018

чтобы уменьшить раскачивание, попробуйте юзать не ПИД, а ПИДД. в этой модели учитывается не только скорость изменения значения, но и _ускорение_ этих изменений... по идее, для прилично инерционных систем должно лучше подойти... но это не точно)) нужно пробовать...

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

progrik пишет:

чтобы уменьшить раскачивание, попробуйте юзать не ПИД, а ПИДД. в этой модели учитывается не только скорость изменения значения, но и _ускорение_ этих изменений... по идее, для прилично инерционных систем должно лучше подойти... но это не точно)) нужно пробовать...

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

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Уменьшил коэффициент с 5 до 3. Стало веселее. Раскачивание прекратилось.

Посмотрите сами:

Nord_Air
Offline
Зарегистрирован: 15.06.2020

progrik пишет:

и на dht11/dht22 надо самому ~5-10КОм между + и "дата" цеплять, и вообще вся однопроводная фигня, что я видел, имеет на конце 1 резистор, не зависимо от кол-ва датчиков...
вроде как-то так...

 На DHT22 и 11 подтягивающие на + стоят на уже на самой плате, в варианте исполнения не отдельный датчик, а когда он смонтирован на плату с выводами.  Так же, там (на плате) по совету из даташита на этот датчик, между Data и GND стоит кондер на 100nF, как написано для устранения волн...

Даташит конкретно этот https://www.alldatasheet.com/datasheet-pdf/pdf/1132459/ETC2/DHT22.html

Пусть вас не смущают китайские иероглифы, остальные даташиты и переводы, это переделки с этого.  В даташите расписаны даже эпюры :)))  Но они весьма малое имеют отношение к действительности :) Судя по всему, частично на основе подобных даташитов написана например библиотека iarduino_DHT, нет она отлично работает, я пол года ей пользовался, но при положительных температурах :)))

Хотя переменные и заданы с учетом возможного отрицательного знака... Но этого не достаточно :)))

   Но по факту, реальность отличается от того что написано...  в некой заметке.  Я не могу назвать это даташитом...   Там и тайминги не те...

В зипе с библиотекой, iarduino_DHT лежит pdf, красиво оформлен, на русском языке, всё по пунктам А,Б,В,Г....  Уже чуть ближе к истине, в отличии от китайского даташита, но всё равно мимо :)))) 

 Даже не знаю как подытожить? :)))    Так о каких мануалах вы шепчете мне друзья мои :)))))))  Я надеюсь не о подобных, дырявых? ;)

 

ЗЫ. Что касается темы, меня смутил в основном номинал резистора.  Я честно признаюсь, я не находил точной инфы о том какая должна быть обвязка, каких номиналов... Но в основном, для стягивания применяют 10K, реже 7.5K это что я видел по схемам.  Ставить ниже, это не совсем нормально, как мне кажется... 

sadman41
Offline
Зарегистрирован: 19.10.2016

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

Вот нормальный: https://cdn-shop.adafruit.com/datasheets/DHT11-chinese.pdf , схема на второй странице.
Над ней экспликация: 
2、 接口说明 建议连接线长度短于20米时用5K上拉电阻,大于20米时根据实际情况使 用合适的上拉电阻 (2. Описание интерфейса. Если длина кабеля короче 20 метров, рекомендуется использовать подтягивающий резистор 5K. Если расстояние превышает 20 метров, используйте в соответствии с реальными условиями. Используйте подходящий подтягивающий резистор.)

Не убедил? Давайте посмотрим прямо на сайте производителя AOSONG/ASAIR:  http://aosong.com/products-21.html => 产品说明书下载 , схема и экспликация на стр.3 :
1、典型应用电路中建议连接线长度短于5m时用4.7K上拉电阻,大于5m时根据实际情况降 低上拉电阻的阻值。(1. В типичной прикладной схеме рекомендуется использовать подтягивающий резистор 4,7 кОм, когда длина соединительного провода меньше 5 м. Если длина соединительного провода превышает 5 м, уменьшите сопротивление подтягивающего резистора в соответствии с реальной ситуацией)

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

Что же касается вопроса о том является ли DHTxx датчиком... Нет, это не датчик, а модуль. Непосредственно датчик (сенсор)  - это часть модуля DHTxx. Он вон там, в виде беленькой пластинки со змеёй. Существуют ли клоны DHTxx, выпускаемые не только AOSONG-ом? Скорее всего да, существуют. Вполне возможно, в одни из них положили внутрисхемный подтягивающий резистор, в каких-то - сэкономили. А может и сам разработчик в более ранних релизах его совал, а потом перестал. Всякие фокусы возможны. Т.е. не рассматривая конкретный экземпляр модуля невозможно заранее сказать, что он будет работать без внешней подтяжки или же нет.  

 

Теперь про DS18B20. Сходили на сайт Maxim/Dallas , посмотрели https://datasheets.maximintegrated.com/en/ds/DS18B20.pdf , стр.7? Прочли на стр.5 "The control line requires a weak pullup resistor since all devices are linked to the bus via a 3-state or open-drain port (the DQ pin in the case of the DS18B20)." и на стр. 10 "The 1-Wire bus requires an external pullup resistor of approximately 5kΩ; thus, the idle state for the 1-Wire bus is high. If for any reason a transaction needs to be suspended, the bus MUST be left in the idle state if the transaction is to resume." ?

Есть ещё какие-то фантазии про дырявые даташиты и особенности библиотек?

 

sadman41
Offline
Зарегистрирован: 19.10.2016

99% датчиков DHT продаются в коробках по сотне-другой штук, а "на платах с резистором", устанавливаются модули только для лентяев, коих менее 1%.

Разработчик DHT - китайская контора AOSONG. То, что ты турок или испанец - их не волнует. Оригинальный даташит на пиньине, а далее уже начинается локальный колхоз с переводами импортеров, начитавшись которых кое-кто начинает жопу рвать, доказывая что резистор не нужен, а если и нужен, то на выдуманное лично им сопротивление.

Бред про отрицательные температуры комментировать не буду, с какого перепоя о них зашла речь - не понял.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

sadman41 пишет:
Бред про отрицательные температуры комментировать не буду, с какого перепоя о них зашла речь - не понял.

 Неспособность отображения отрицательных температур является проблемным (дырявым)местом отдельных библиотек.  Я мог бы на этом остановить рассуждения... 

 Но скажу что, "дырявость"  возникла по двум причинам. 1. библиотека писалась по заведомо дырявому даташиту   2.работоспособность библиотеки не была протестирована во всех режимах.

 И в следствии этой проблемы. Я скромно поинтересовался, вы мне к прочтению предлагаете подобные даташиты? Или они  другие, прям с гербовой печатью... прямиком от производителя :)  

sadman41
Offline
Зарегистрирован: 19.10.2016

Лучше Вам остановить свои рассуждения. В проекте mykaida нет никаких DHT и библиотек, которые лично Вам испортили таем или иным способом жизнь. Хотите разобраться со своей проблемой - заведите свой топик.

Те устройства, которые применены автором для измерения параметров окружающей среды подключены рекомендуемым производителем образом.

Лично я же рекомендую Вам не кидаться грудью на амбразуру, полистав первый попавшийся в интернете даташит. Конкретно тот - кривой. Он и мне в свое время крови попил.

Полагаю, что на этом оффтоп дискуссия окончена.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

sadman41 пишет:
Лучше Вам остановить свои рассуждения.

Рассуждений, о смысле бытия здесь и не было.

sadman41 пишет:

В проекте mykaida нет никаких DHT

Справедливо.

Изначально я ответил за замечание

progrik пишет:
и на dht11/dht22 надо самому ~5-10КОм между + и "дата" цеплять, и вообще вся однопроводная фигня, что я видел, имеет на конце 1 резистор, не зависимо от кол-ва датчиков...вроде как-то так...

sadman41 пишет:

В проекте mykaida нет никаких DHT и библиотек, которые лично Вам испортили таем или иным способом жизнь.

Мне никакие библиотеки ничего не портили.  Я изначально решил запилить свою не библиотеку, но функцию чтения датчика, начал типа по правильному, с даташита... Педантично всё переводил... Разбирался, потом скатился до той библиотеки которая ранее работала... Потом и она не заработала, при отрицательных температурах...  уже позже разобрался почему...

sadman41 пишет:

Конкретно тот - кривой. Он и мне в свое время крови попил. Полагаю, что на этом оффтоп дискуссия окончена.

 

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

  Я например уже не воспринимаю статьи, где нет фото (в идеале видео) реально работающего устройства (ардуино). 

sadman41 пишет:

Хотите разобраться со своей проблемой - заведите свой топик.

 

У меня пока проблем нет :)

sadman41 пишет:

Полагаю, что на этом оффтоп дискуссия окончена.

Справедливое замечание ;)

 

 

Nord_Air
Offline
Зарегистрирован: 15.06.2020

  Еще немного накину в тему... В библиотеке указанного автором датчика не разбирался, полагаю что там примерно как и в DHT, только без влажности.

 В DHT22, 5ым битом приходит контрольная сумма всех предыдущих четырех байт. И в библиотке, что от iarduino, что например от амперки, просто тупо складываются все четыре байта.   В том корявом, даташите-переводе, сказано тоже самое.

  Если реально посчитать то всё сойдется...  в 8 случаях из 10 ;)

Но если немного поразмыслить...  Как сумма четырех байт может вмещаться в один байт???? :))) 

  Да ни как! И ни как она не вмещается :) Просто в подавляющем количестве случаев, при положительной температуре, байты 2 и 4 пребывают на уровне 0... 1.. 2...  и как правило сумма двух остальных не превосходит 255. Но когда влажность подкатывает к 50, 75 или 100, сумма перекатывает через 256.  И мы получаем чек сумм еррор, хотя никаких проблем реально нет...  но эта ошибка ни как не обрабатывается.

  И в данном случае, я бы не стал полностью ссылаться на кривой даташит. Так как подобная ошибка могла возникнуть либо в следствии тупого копирования функций библиотеки откуда-то из вне...   либо...

 Так что вполне возможно, у автора, как вариант проблема в сутулой библиотеке, и ошибка чек суммы все таки как-то обрабатывается.

 

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

  И всё это пытается продаваться........

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:

 Как сумма четырех байт может вмещаться в один байт???? :))) 

 Да ни как! 

И всё это пытается продаваться........

Если речь идет о циклическом суммировании, то как. И в даташите этот вопрос конкретно разобран. Когда писал на ассемблере вопросов не было. Конкретную библиотеку на это не проверял - проверю, спасибо!

А что продаваться-то? Датчик? Библиотеки или моя программа? Вот тут не понял.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

mykaida пишет:

Если речь идет о циклическом суммировании, то как. И в даташите этот вопрос конкретно разобран.

Я этот даташит упоминал :)

 

mykaida пишет:

Когда писал на ассемблере вопросов не было. Конкретную библиотеку на это не проверял - проверю, спасибо!

На ассемблере сумма байтов надеюсь от Си сильно не отличается ;)

 

mykaida пишет:

А что продаваться-то? Датчик? Библиотеки или моя программа? Вот тут не понял.

 А что продоваться?...   Тут видишь, люди всё исключительно продают.   Здесь уже нет, того форумного ответа, новичку... Чета не панимашь, обращайся на реализацию ;) Как-то так...

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:

На ассемблере сумма байтов надеюсь от Си сильно не отличается ;)

А что продоваться?...   Тут видишь, люди всё исключительно продают.   Здесь уже нет, того форумного ответа, новичку... Чета не панимашь, обращайся на реализацию ;) Как-то так...

Только тем, что ты сам строишь правила. А так - суммирование и суммирование.

Вот тут Вы не правы. Вы смотрите с другой позиции. Вот не знаю, кто Вы по жизни, но представьте. Мужики в гараже обсуждают нюансы карбюратора. Докапываются до сути. И тут Вы - "а как открутить гайку?". - Представили?

Если свой, то понятно, со смешками расскажут. А чужому сразу намекнут про бутылку.. И тут так - нормальное мужское сообщество (гы какое слово). 

sadman41
Offline
Зарегистрирован: 19.10.2016

Модули DHT из той ценовой категории, в которую нет смысла ставить более мощный МК, умеющий считать многобайтовый CRC по полиному. CRC в нем - лишь приятное дополнение, позволяющее понять, что по шине поперли помехи. Не знаю, как там сделано в библиотеке, но если счёт с переполнением, то после сложения следует сделать & 0xFF и только после этого сравнивать CRC. В этом случае все сойдется.

Для 18x20 же неким неписанным стандартом давно стала DallasTemperature. Все ошибки там давно уж отловлены.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:

Для 18x20 же неким неписанным стандартом давно стала DallasTemperature. Все ошибки там давно уж отловлены.

Не добавить не убавить.Хотя и не нравится мне.

sadman41
Offline
Зарегистрирован: 19.10.2016

Мне тоже. Поэтому я взял оттуда необходимые фрагменты и слепил свою маленькую функцию опроса DS-ки.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:
Мне тоже. Поэтому я взял оттуда необходимые фрагменты и слепил свою маленькую функцию опроса DS-ки.

А посмотреть? Может накосячили :)

Приз в студию!

sadman41
Offline
Зарегистрирован: 19.10.2016
mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

mykaida пишет:
Поэтому я взял оттуда необходимые фрагменты и слепил свою маленькую функцию опроса DS-ки.

А где там про ds18х20? Не - работа изумительная, но где порезаннный объект?

Нашел - прошу извинения.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Гля - неужто Вы считаете это правильным?

static uint8_t isCRCOK(uint8_t* _scratchPad) {
  // '==' here not typo
  //return (dallas_crc8(_scratchPad, DS18X20_SCRATCHPAD_SIZE - 1) == _scratchPad[DS18X20_BYTE_SCRATCHPAD_CRC]);
  return (!dallas_crc8(_scratchPad, DS18X20_SCRATCHPAD_SIZE));
}

 

sadman41
Offline
Зарегистрирован: 19.10.2016

Я проверял. CRC по массиву с суммой даёт 0. Но можете и отдельно вычислять. Я как-то прикидывал - теоретически особого выигрыша какой-либо из способов не имеет. Так что дело вкуса.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:

Я проверял. CRC по массиву с суммой даёт 0. Но можете и отдельно вычислять. Я как-то прикидывал - теоретически особого выигрыша какой-либо из способов не имеет. Так что дело вкуса.

Как говорит мой внук - "деда - надо лучше стараться". Я сам хреново проверял. Особенно в минусах.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

mykaida пишет:

 

Вот тут Вы не правы. Вы смотрите с другой позиции. Вот не знаю, кто Вы по жизни, но представьте. Мужики в гараже обсуждают нюансы карбюратора. Докапываются до сути. И тут Вы - "а как открутить гайку?". - Представили?

 

 Представил, мужики разбирают...  Пытаются разобрать крбюратор...  Я говорю, ребята, вы не в ту сторонц гайку откручиваете...  А они хихикают и продолжают срывать на шпильке резьбу ;) 

 Хорошее сравнение? ;)

 

Nord_Air
Offline
Зарегистрирован: 15.06.2020

sadman41 пишет:
Модули DHT из той ценовой категории, в которую нет смысла ставить более мощный МК, умеющий считать многобайтовый CRC по полиному.

 

Более мощный МК стоит ставить авторам библиотек, которые читают из этого мк. :)))

sadman41 пишет:

Не знаю, как там сделано в библиотеке, но если счёт с переполнением, то после сложения следует сделать & 0xFF

Там это есть в коде, но это не помагает :))) Это видимо из категории советов об обнулении переменных. Полезно, сам пользуюсь :)))

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:
продолжают срывать на шпильке резьбу

Вот это сомнительно. Тут народ за базар отвечает - кто степенями научными, а кто и поделками чудовыми. Левую от правой резьбы по-любому отличат.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:

sadman41 пишет:
Модули DHT из той ценовой категории, в которую нет смысла ставить более мощный МК, умеющий считать многобайтовый CRC по полиному.

 

Более мощный МК стоит ставить авторам библиотек, которые читают из этого мк. :)))

sadman41 пишет:

Не знаю, как там сделано в библиотеке, но если счёт с переполнением, то после сложения следует сделать & 0xFF

Там это есть в коде, но это не помагает :))) Это видимо из категории советов об обнулении переменных. Полезно, сам пользуюсь :)))

 

Вы че - охренели? Я на PIC16 на 33 кгц запускал.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

mykaida пишет:

Nord_Air пишет:
продолжают срывать на шпильке резьбу

Вот это сомнительно. Тут народ за базар отвечает

Пункт первый.  Я пока еще никого к ответу не привлекал...

mykaida пишет:

Левую от правой резьбы по-любому отличат.

Я искрене надеюсь, так как это была некоторого рода форма сарказма.

 

Пункт второй:  О сумме байтов на ассемблере. Я внятного ответа так к сожалению и не получил ;) Не могли бы вы как-то разъяснить этот момент. О циклическом суммировании :))) Без далекого отхода от 5ого байта датчика DHT $)

 

 

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:
О циклическом суммировании :)))

К сожалению - прямо сейчас Вам не представлю пример (просто на другом железе лежит). Завтра представлю в ассемблере для  pic16f628a.

Nord_Air
Offline
Зарегистрирован: 15.06.2020

mykaida пишет:

Nord_Air пишет:
О циклическом суммировании :)))

К сожалению - прямо сейчас Вам не представлю пример (просто на другом железе лежит). Завтра представлю в ассемблере для  pic16f628a.

 Я не тороплю вас,  я с глубоким почтением отношусь к вашему примеру. Если вам нужно  например полнолуния дождаться - да без проблем! =)

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Nord_Air пишет:

 Если вам нужно  например полнолуния дождаться - да без проблем! =)

Вы, сэр, меня безосновательно оскорбили! Ну не ставится на мой стол третий компьютер. Но вызов брошен! Я предлагаю дуэль на ассемблере pic16. Как своего секунданта выставляю дона rumata (он правда про это не знает).

Nord_Air
Offline
Зарегистрирован: 15.06.2020

  Да без проблем, начнем соревнование :)

С этого заголовка...

"Только тем, что ты сам строишь правила. А так - суммирование и суммирование."

5-й байт датчика DHT...  имеет если так можно назвать ваше так называемое суммирование.  Вот вы на ассемблере и можете проссумировать перввые 4 байта если не доверяете си.

Или вы хотите самостоятельно анонсировать соревнование? И вне всякого сомнения лично в нём участвовать, а не аутсорсить задачу на сторону?

sadman41
Offline
Зарегистрирован: 19.10.2016

Вы оба накатили что ли...

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

sadman41 пишет:
Вы оба накатили что ли...

Конечно.

Но как там "утсёртить" задачу не буду - некому. На 33кгц тактовой частоты очень мало кто программирует.