Szkic termostatu z histerezą i sterowaniem zaworem.

User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Cześć, poniżej wklejam szkic termostatu, z ustawianiem w aplikacji temperatury włączenia/wyłączenia przekaźnika z histerezą wyłączenia, oraz sterowaniem zaworem z osobnym ustawianiem temperatury jego otwarcia i zamknięcia.
Generalnie działa jak na filmie poniżej:
https://youtu.be/3M-RukZ2VA8
tylko z tego szkicu usunąłem wyświetlacz LCD, jeśli ktoś będzie zainteresowany wkleję też szkic z jego obsługą.

Code: Select all

#include <Wire.h> 
#include <SuplaDevice.h>
#include <supla/sensor/DS18B20.h>
#include <supla/control/relay.h>
#include <supla/network/esp_wifi.h>

#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom(0);

#include <supla/storage/storage.h>
#include <supla/control/virtual_relay.h>
#include <supla/sensor/virtual_thermometer.h>
 Supla::ESPWifi wifi("xx", "xx");

#include <OneWire.h>
#include <DallasTemperature.h>
#include <Timers.h>



int temp;


int przek1 = 0;
int przek2 = 0;
int tempON = 5;
int histereza = 3;
int wyslanoON = 0;
int wyslanoOFF = 0;

int valveON =20;
int valveOFF = 15;
int wyslanoONvalve = 0;
int wyslanoOFFvalve = 0;

OneWire oneWire0(D7);//D1
DallasTemperature t1(&oneWire0);
DeviceAddress ds1 = {0x28, 0xE8, 0x9D, 0x57, 0x04, 0xE1, 0x3C, 0xA1};

Timer sekund5;
Timer sekund30;

Supla::Control::Relay *relay1 = nullptr;
Supla::Control::Relay *relay2 = nullptr;

class RelayAsInput : public Supla::Control::VirtualRelay {//temp wł pompy
 public:
  explicit RelayAsInput(int step = 1) : step(step) {
  }
  virtual ~RelayAsInput() {}
  void onInit() override {}
  void turnOn(_supla_int_t duration = 0) override {

    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > 90) {
      newTemp = 90;
    }
    temp.setValue(newTemp);//newTemp
    tempON = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp < 5) {
      newTemp = 5;
    }
    temp.setValue(newTemp);
    tempON = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  int getValue() {
    return temp.getValue();
  }

  void setValue(int value) {
    temp.setValue(value);
    Supla::Storage::ScheduleSave(2000);
  }

  void onLoadState() override {
    int temperature = 0;
    Supla::Storage::ReadState(reinterpret_cast<unsigned char *>(&temperature),
                              sizeof(int));
    temp.setValue(temperature);
    tempON = temperature;
  }

  void onSaveState() override {
    int temperature = temp.getValue();
    Supla::Storage::WriteState(reinterpret_cast<unsigned char *>(&temperature),
                               sizeof(int));
  }

 protected:
  Supla::Sensor::VirtualThermometer temp;
  int step = 1;
};

class RelayAsInput1 : public Supla::Control::VirtualRelay {//////////HISTEREZA
 public:
  explicit RelayAsInput1(int step = 1) : step(step) {
  }
  virtual ~RelayAsInput1() {}
  void onInit() override {}
  void turnOn(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > 20) {
      newTemp = 20;
    }
    temp.setValue(newTemp);
    histereza = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp < 1) {
      newTemp = 1;
    }
    temp.setValue(newTemp);
    histereza = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  int getValue() {
    return temp.getValue();
  }

  void setValue(int value) {
    temp.setValue(value);
    Supla::Storage::ScheduleSave(2000);
  }

  void onLoadState() override {
    int temperature = 0;
    Supla::Storage::ReadState(reinterpret_cast<unsigned char *>(&temperature),
                              sizeof(int));
    temp.setValue(temperature);
    histereza = temperature;
  }

  void onSaveState() override {
    int temperature = temp.getValue();
    Supla::Storage::WriteState(reinterpret_cast<unsigned char *>(&temperature),
                               sizeof(int));
  }

 protected:
  Supla::Sensor::VirtualThermometer temp;
  int step = 1;
};

class RelayAsInput2 : public Supla::Control::VirtualRelay { ///zawór ON
 public:
  explicit RelayAsInput2(int step = 1) : step(step) {
  }
  virtual ~RelayAsInput2() {}
  void onInit() override {}
  void turnOn(_supla_int_t duration = 0) override {

    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > 95) {
      newTemp = 95;
    }
    temp.setValue(newTemp);
    valveON = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp1 = temp.getValue() - step;
    if(newTemp1 < tempON){
      newTemp1 = tempON;
    }
    else if(newTemp1 < (valveOFF + 3)){
      newTemp1 = valveOFF + 3;
    }
    
    temp.setValue(newTemp1);
    valveON = newTemp1;
    Supla::Storage::ScheduleSave(2000);
  }

  int getValue() {
    return temp.getValue();
  }

  void setValue(int value) {
    temp.setValue(value);
    Supla::Storage::ScheduleSave(2000);
  }

  void onLoadState() override {
    int temperature = 0;
    Supla::Storage::ReadState(reinterpret_cast<unsigned char *>(&temperature),
                              sizeof(int));
    temp.setValue(temperature);
    valveON = temperature;
  }

  void onSaveState() override {
    int temperature = temp.getValue();
    Supla::Storage::WriteState(reinterpret_cast<unsigned char *>(&temperature),
                               sizeof(int));
  }

 protected:
  Supla::Sensor::VirtualThermometer temp;
  int step = 1;
};

class RelayAsInput3 : public Supla::Control::VirtualRelay { ////zawor OFF
 public:
  explicit RelayAsInput3(int step = 1) : step(step) {
  }
  virtual ~RelayAsInput3() {}
  void onInit() override {}
  void turnOn(_supla_int_t duration = 0) override {

    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > (valveON - 3)) {
      newTemp = (valveON - 3);
    }
    temp.setValue(newTemp);
    valveOFF = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp < 5) {
      newTemp = 5;
    }
    temp.setValue(newTemp);
    valveOFF = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  int getValue() {
    return temp.getValue();
  }

  void setValue(int value) {
    temp.setValue(value);
    Supla::Storage::ScheduleSave(2000);
  }

  void onLoadState() override {
    int temperature = 0;
    Supla::Storage::ReadState(reinterpret_cast<unsigned char *>(&temperature),
                              sizeof(int));
    temp.setValue(temperature);
    valveOFF = temperature;
  }

  void onSaveState() override {
    int temperature = temp.getValue();
    Supla::Storage::WriteState(reinterpret_cast<unsigned char *>(&temperature),
                               sizeof(int));
  }

 protected:
  Supla::Sensor::VirtualThermometer temp;
  int step = 1;
};



void setup() {
  
  Serial.begin(9600);
  sekund30.begin(29898);

  Wire.begin(4, 5); //4, 5
 // Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
  char GUID[SUPLA_GUID_SIZE] = {0xBC,0x49,0xD5,0x36,0x49,0x4E,0x64,0x26,0x3F,0x0C,0x75,0xC8,0xCA,0x22,0x4F,0xB7};

  // Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {0xF0,0x35,0xEF,0x39,0x78,0xC7,0xF7,0x6B,0x18,0xEC,0x23,0x52,0xF0,0x44,0x18,0x2C};

  new Supla::Sensor::DS18B20(D7, ds1);
  new RelayAsInput();
  new RelayAsInput1();
  new RelayAsInput2();
  new RelayAsInput3();

  relay1 = new Supla::Control::Relay(D5, false);////zawór
  relay2 = new Supla::Control::Relay(D6, false);////GNIAZDKO
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    "svrxx.supla.org",  // SUPLA server address 
                    "[email protected]",   // Email address used to login to Supla Cloud 
                    AUTHKEY); 
t1.begin();        

dsSTART();

}
void loop() {
SuplaDevice.iterate();
ds();
relayOnOff();
valveOnOff();
}


void ds(){
  if(sekund30.available()){
  t1.requestTemperatures(); 
  temp = (t1.getTempC(ds1));
  sekund30.restart();
  }
}
void dsSTART(){
  t1.requestTemperatures(); 
  temp = (t1.getTempC(ds1));
}
void relayOnOff(){
  if(temp>=tempON){
    przek1=1;
  }
  else if(temp<=(tempON - histereza)){
    przek1=0;
  }

  if((przek1 == 1) && (wyslanoON == 0)){
   relay2->turnOn();
   wyslanoON = 1;
   wyslanoOFF = 0;
  }
  else if((przek1==0) && (wyslanoOFF==0)){
   relay2->turnOff();
   wyslanoOFF = 1;
   wyslanoON = 0;
  }
}
void valveOnOff(){

  if(temp >= valveON){
    przek2=1;
  }
  else if(temp <= valveOFF){
    przek2=0;
  }

  if((przek2 == 1) && (wyslanoONvalve == 0)){
   relay1->turnOn();
   wyslanoONvalve = 1;
   wyslanoOFFvalve = 0;
  }
  else if((przek2==0) && (wyslanoOFFvalve==0)){
   relay1->turnOff();
   wyslanoOFFvalve = 1;
   wyslanoONvalve = 0;
  }
}
Szkic kompiluje się w tej postaci na płytkę nodeMCU.
Szkic napisany z ogromną pomocą kolego @klew za co dziękuję. Proszę o uwagi i propozycje :D
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
Maniek913
Posts: 594
Joined: Thu Feb 22, 2018 9:46 pm
Been thanked: 3 times

Post

Dzieki, chętnie to przetestuję, ale wklej proszę tez kod z obsługą LCD
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Generalnie, po wstępnym ustawieniu w kodzie początkowych wartości zmiennych odpowiedzialnych za temperatury wł/wył, histerezy, urządzenie może pracować poprawnie bez dostępu do sieci.
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79

Return to “Projekty użytkowników”