Очередной термостат

evgta
Offline
Зарегистрирован: 02.09.2016

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

теплоемкость отопителя очень велика, так после выключения отопителя температура еще несколько минут растет, и соответственно после включения несколько минут падает.

ПИД отпадает т.к (а неполучилось, в системе постоянно меняется скорость вентиляции, и нагрев стен помещения)

решил попробовать такой алгоритм:

До температуры 20 нарев идет постоянно

затем если между двумя измерениями (1 мин ) температура растет то отопитель выключается, если падает включается

при температуре  выше 22 нагрев отключается

Готовых решений на 5в ненашел, поэтому творю)) 

пока работу реле от термистора проверил на протеусе, работу дисплея TM1637 вживую на макетке

развел плату. Питание NANO предусматривается только от USB 2А, включение возможно только через реле.

Посмотрите в чем есть просчеты? или может есть какие предложения? пока снова по 5 раз плату травить не пришлось

#include "TM1637.h"                   /// библиотека дисплея
#define CLK 3//pins definitions for the module and can be changed to other ports       
#define DIO 2
TM1637 disp(CLK, DIO);


unsigned long zzz = 0;
unsigned long yyy = 0;
unsigned long zzz1 = 0;
unsigned long yyy1 = 0;
unsigned long zzz2 = 0;
unsigned long yyy2 = 0;
unsigned long zzz3 = 0;
unsigned long yyy3 = 0;

boolean flag3 = 0;
boolean flag1 = 0;
boolean flag2 = 0;
boolean flag11 = 0;
boolean flag12 = 0;

float ind = 0;
float tdisp = 0;
int tempres = 0;
int deltaT = 0;
int temp1 = 0;
double voltage = 0;
double r1 = 0;
double TempRes = 0;                      // всякие разнве переменные

int relay = 6;            // выход на реле
int buttonUP = 5;        // вход клвиши вверх
int buttonDOWN = 4;     // вход клавиши вниз
int ntc = A0;           // вход с термистора
int Tust = 200;         // заданная температура (уставки)
int klav = 600;          // зажатия кнопки чтобы каждые Х мс добавлялось +10
int diap = 20;           // диапазон где идет регулирование по дельте   2 градуса "20/10"
int dreb = 30;           // значение антидребезга = 30 мс
unsigned int Trelay = 15000;     // значение задержки времени между срабатываниями реле в мс
double Vin = 5.0;       // напряжение





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

  pinMode(relay, OUTPUT);
  digitalWrite(relay, LOW);
  pinMode(buttonUP, INPUT);
  pinMode(buttonDOWN, INPUT);
  digitalWrite(buttonUP, HIGH);
  digitalWrite(buttonDOWN, HIGH);

  disp.set(BRIGHT_TYPICAL);//BRIGHT_TYPICAL = 2,BRIGHT_DARKEST = 0,BRIGHTEST = 7;   //настройки дисплея
  disp.init(D4056A);//D4056A is the type of the module
}

void loop()
{

  button();      // опрос клавиш

  // Serial.println(tempres);
  // Serial.println(Tust);
  //  Serial.println("-----------");

  yyy3 = millis() - zzz3;
  if (yyy3 > 500) {
    readtemp();  // опрос датчика температуры                     // вывод значений текущая:установленная температура, вывод раз в 500мс
    zzz3 = millis();
    tdisp = tempres / 10;
    tdisp = tdisp * 100;
    tdisp = tdisp + Tust;
    if ( flag3 == 1) {                                                 // если реле включено, тогда горит разделитель
      ind = tdisp / 100;
      disp.display(ind);
    } else {
      disp.display(tdisp);
    }
  }




  yyy = millis() - zzz;
  if (yyy > Trelay) {                                                      //если прошло более Х mc, тогда  переход на void relay()
    zzz = millis();                                             
    relay1();
  }

}
//-------------------------------------------------------------------------------------------------------------------------------------------------------------------
void button()     //опрос клавиш
{

  zzz1 = millis() - yyy1;
  if (zzz1 > dreb) {
    flag2 = 0;                                                     // антидребезг
  }
  if (flag2 == 0) {
    if (digitalRead( buttonUP) == LOW && flag1 == 0) {
      Tust = Tust + 10;                                         // добавление  +10 c последующей блокировкой набора
      yyy1 = millis();
      flag1 = 1;
      flag2 = 1;
    }
    if (zzz1 > klav) {
      if (digitalRead( buttonUP) == LOW) {
        Tust = Tust + 10;                                           //обработка зажатия кнопки чтобы каждые Х мс добавлялось +10
        yyy1 = millis(); 
      }
    }
    if (digitalRead( buttonUP) == HIGH) {
      flag1 = 0;
    }
  }

  zzz2 = millis() - yyy2;
  if (zzz2 > dreb) {
    flag12 = 0;                                                    // антидребезг
  }
  if (flag12 == 0) {
    if (digitalRead( buttonDOWN) == LOW && flag11 == 0) {
      Tust = Tust - 10;                                          // добавление  +10 c последующей блокировкой набора
      yyy2 = millis();
      flag11 = 1;
      flag12 = 1;
    }
    if (zzz2 > klav) {
      if (digitalRead( buttonDOWN) == LOW) {
        Tust = Tust - 10;                                      //обработка зажатия кнопки чтобы каждые Х мс добавлялось +10
        yyy2 = millis();
      }
    }
    if (digitalRead( buttonDOWN) == HIGH) {
      flag11 = 0;
    }
  }

}

//-----------------------------------------------------------------------------------------------------------------------------------------------------------------------
void relay1()
{
  deltaT = tempres - temp1;
  {
    if (tempres >= Tust) {                                         //если температура выше уставки выключаю реле
      digitalWrite(relay, LOW); flag3 = 0;
    } else {                                                         // если температура ниже температуры уставки на 2 градуса реле постоянно включено
      if (tempres < Tust - diap) {                                      // если дельта температуры положительная и температура в пределах ноль -2 градуса от уставки реле выключается и наоборот
        digitalWrite(relay, HIGH); flag3 = 1;
      }  else {
        if (deltaT <= 0) {
          digitalWrite(relay, HIGH); flag3 = 1;
        } else {
          digitalWrite(relay, LOW); flag3 = 0;
        }
      }
    }
  }
  temp1 = tempres;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------------
void readtemp()                                                                             //  расчет температуры по формуле Стейнхарта — Харта
{

  voltage = analogRead(ntc) * Vin / 1023;
  r1 = voltage * 100000.0 / (Vin - voltage);                                            // 100 кОм -  резистор моста
  TempRes = (1.0 / (1.0 / (3950.0) * log(r1 / 100000.0) + 1.0 / (273.0 + 25.0))) - 273.0;  // двнные NTC
  tempres = TempRes * 10;

}

alex_r61
Offline
Зарегистрирован: 20.06.2012

R1 1-2K, с базы на землю 10К и кнопки подпереть 4.7-10К.

evgta
Offline
Зарегистрирован: 02.09.2016

включен внутренний подтяг, а зачем резистор на транзистор? на базу всегда либо - либо + приходить будет

MaksVV
Offline
Зарегистрирован: 06.08.2015

и то и другое для помехоустойчивости. (Внутренний подтяг на 100 кОм - многовато). 

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

evgta пишет:

включен внутренний подтяг, а зачем резистор на транзистор? на базу всегда либо - либо + приходить будет

А хрена там в момент перезагрузки. Тоже так думал, теперь бузер воет (сцука).

evgta
Offline
Зарегистрирован: 02.09.2016

bwn пишет:

А хрена там в момент перезагрузки. Тоже так думал, теперь бузер воет (сцука).

 

как-то непонял фразы?

что такое бузер?

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

Недавно собирал себе подобный девайс для электрокаменки.

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

Еще замечание из личного опыта - параллельно контактам реле поставить РЦ цепочку (снабер).

У меня без неё при комутации пускателя (размыкании) контроллер подвисал.

А еще при питании схемы от зарядки мобильника 1200мА/ч 5В переодически отваливалось самопроизвольно реле (непонятно почему но после этого его клинило в разомкнутом состоянии), после чего оно безжалостно было заменено на симистор.

Вот схема

Печатку не разрабатывал, собрал всё навесом.

b707
Онлайн
Зарегистрирован: 26.05.2017

evgta, кнопки SW1 и SW2 правильнее будет замыкать на массу через резисторы в 100 - 300 Ом. Причины подробно изложены в прикрепленной теме "Ардуино для новичков - работа с кнопками" в разделе Программирование

evgta
Offline
Зарегистрирован: 02.09.2016

Решил зажать 2 резистора)) подумал что длинна дорожек к кнопкам короткая и индукция в них наводится будет слабая и хватит внутреннего подтяга, но коль советуете, еще думаю от плюса реле к земле поставить супрессор на 5V1. еще как вариант к базе транзистора супрессор повесить чтобы выход наны прикрыть.  оптопару как-то невижу смысл ставить, т.к питание с одного места,

Симистр не воткнуть, т.к постоянка 55В с кучей помех, и мосфет тоже неполучится, там на этих 55В куча контакторов с токами 2-5А живут

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

evgta пишет:

bwn пишет:

А хрена там в момент перезагрузки. Тоже так думал, теперь бузер воет (сцука).

 

как-то непонял фразы?

что такое бузер?

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

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

evgta пишет:

включен внутренний подтяг, а зачем резистор на транзистор? на базу всегда либо - либо + приходить будет

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

b707
Онлайн
Зарегистрирован: 26.05.2017

evgta пишет:

Решил зажать 2 резистора)) подумал что длинна дорожек к кнопкам короткая и индукция в них наводится будет слабая и хватит внутреннего подтяга,

Индукция тут не при чем. никакой внутренний подтяг не поможет, если на выход, подключенный к нажатой кнопке, случайно подать HIGH