Termostat bojlera, włączający i wyłączający grzałkę, tryb AUTO i MANUAL

User avatar
YoMan
Posts: 3521
Joined: Thu Apr 30, 2020 5:18 pm
Location: Częstochowa
Has thanked: 3 times
Been thanked: 3 times

Post

krycha88 wrote: Fri Jun 16, 2023 12:07 pm
YoMan wrote: Fri Jun 16, 2023 11:53 am Wolałeś się sam bawić skoro było na wczoraj?
To czego przy okazji się nauczył to jego ;)
A ja to rozumiem i szanuję ...
YoMan
________________________________________
Wziąłem udział w SOP2023 & SOP2024
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Co się nauczyłem to moje. Tak już wolę. Ciągle próbuję polubić Suplę bardziej, a to forum fajnie działa i bardziej doświadczeni koledzy pomagają.
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

lukfud wrote: Fri Jun 16, 2023 7:20 am
SOYER wrote: Fri Jun 16, 2023 6:22 am Robię to dla kolegi. Chciał wszystko ustawiane z apk. Nie zna się na scripts, cloud itd.
kolega @lukasz06 miał na myśli (tak mi się wydaje) warunki w kodzie.

Twój szkic lekko zmodyfikowany. Nie sprawdzałem działania.

Code: Select all

#include <SuplaDevice.h>
#include <supla/control/relay.h>
#include <supla/sensor/DS18B20.h>
#include <supla/storage/eeprom.h>
#include <supla/control/virtual_relay.h>
#include <supla/sensor/virtual_thermometer.h>
#include <supla/network/esp_wifi.h>

#define DS_PIN D1
int tempON, tempOFF;

Supla::Eeprom eeprom();
Supla::ESPWifi wifi("x","y");
Supla::Control::Relay *heater = nullptr;
Supla::Control::VirtualRelay *vrelay = nullptr;
Supla::Sensor::DS18B20 *temperature_sensor = nullptr;
class RelayAsInput1;
RelayAsInput1 *autoOntemperature = nullptr;
class RelayAsInput;
RelayAsInput *autoOfftemperature = nullptr;

class RelayAsInput : public Supla::Control::VirtualRelay { //temp wył. grzałki
 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);
    tempOFF = newTemp;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp <= (tempON +3)) {
      newTemp = tempON +3;
    }
    temp.setValue(newTemp);
    tempOFF = 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);
    tempOFF = 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 { //temp wł. grzałki
 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 >= (tempOFF -3)) {
      newTemp = tempOFF -3;
    }
    temp.setValue(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;
};

enum auto_actions {
  AUTO_TURN_ON,
  AUTO_TURN_OFF
};

class addedActionsClass : public Supla::ActionHandler {
 public: addedActionsClass() {}
  void handleAction(int event, int action) {
    if (action == AUTO_TURN_ON && vrelay->isOn()) {
      heater->turnOn();
    }
    if (action == AUTO_TURN_OFF && vrelay->isOn()) {
      heater->turnOff();
    }
  }
};

addedActionsClass *custAct = new addedActionsClass;

void setup() {
  Serial.begin(115200);
  char GUID[SUPLA_GUID_SIZE] = {};
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {};

  heater = new Supla::Control::Relay(D5, false);
  vrelay = new Supla::Control::VirtualRelay();
  temperature_sensor = new Supla::Sensor::DS18B20(DS_PIN);
  autoOntemperature = new RelayAsInput1();
  autoOfftemperature = new RelayAsInput();
  
  SuplaDevice.begin(GUID, "svrXX.supla.org", "@", AUTHKEY);

  temperature_sensor->addAction(AUTO_TURN_ON, custAct,
                                        OnLess(autoOntemperature->getValue()));
  temperature_sensor->addAction(AUTO_TURN_OFF, custAct,
                                    OnGreater(autoOfftemperature->getValue()));
}

void loop() {
   SuplaDevice.iterate();
}
Pobieranie wartości z czujnika temperatury, w przypadku DS'a

Code: Select all

double temperature = temperature_sensor->getChannel()->getValueDouble();
Bardzo ciekawe @lukfud, daj jakiegoś fajnego linka gdzie w prosty sposób poczytam o action handler.
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Jeszcze jedno pytanie, dlaczego po pierwszym wgraniu szkicu z tymi RelayAsInput pierwsze wartości to zdaje się minus 200 coś, nie pamiętam, pewnie -256, zapewne ma to związek z typem zmiennej(int). Jak to na przyszłość zmienić, by inicjować do z jakąś sensowną wartością.
Dopisać wartość inicjującą tu:
void onInit() override {???}
?
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
User avatar
lukfud
Posts: 2480
Joined: Thu Nov 23, 2017 11:33 pm
Location: Warszawa
Has thanked: 13 times
Been thanked: 11 times

Post

SOYER wrote: Fri Jun 16, 2023 3:18 pm Jeszcze jedno pytanie, dlaczego po pierwszym wgraniu szkicu z tymi RelayAsInput pierwsze wartości to zdaje się minus 200 coś, nie pamiętam, pewnie -256, zapewne ma to związek z typem zmiennej(int). Jak to na przyszłość zmienić, by inicjować do z jakąś sensowną wartością.
Dopisać wartość inicjującą tu:
void onInit() override {???}
?
Dopisz i zobacz co się pokaże ;)
https://www.facebook.com/groups/supladiy
https://www.facebook.com/groups/suplazamel
https://www.facebook.com/groups/suplaauraton
https://smartnerzeczy.pl
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Nie mam teraz gdzie tego sprawdzić, napisz jak to rozwiązać. Z int to się wygłupiłem.
Gdzie poczytać o action handler?
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
User avatar
lukfud
Posts: 2480
Joined: Thu Nov 23, 2017 11:33 pm
Location: Warszawa
Has thanked: 13 times
Been thanked: 11 times

Post

SOYER wrote: Fri Jun 16, 2023 6:21 pm Nie mam teraz gdzie tego sprawdzić, napisz jak to rozwiązać. Z int to się wygłupiłem.
Gdzie poczytać o action handler?

Code: Select all

void onInit() override {
  if (temperature == TEMPERATURE_NOT_AVAILABLE) {
    temp.setValue(25);
  }
}
O action_handler poczytasz na forum, musisz poszukać.
Ten wątek już widziałeś ;) viewtopic.php?p=93007#p93007
https://www.facebook.com/groups/supladiy
https://www.facebook.com/groups/suplazamel
https://www.facebook.com/groups/suplaauraton
https://smartnerzeczy.pl
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Cześć, nowa wersja termostatu bojlera:

Code: Select all

#include <SuplaDevice.h>
#include <supla/control/relay.h>
#include <supla/sensor/DS18B20.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>
#include <Timers.h>

#define ONE_WIRE D1

Supla::ESPWifi wifi(xxx", "xxx);/////"xx
Timer sekund30;
Supla::Control::Relay *relay1 = nullptr;
Supla::Control::Relay *relay2 = nullptr;
Supla::Control::VirtualRelay *vrelay = nullptr;
Supla::Sensor::DS18B20 *tempBojler = nullptr;

double temp;
int przek1 = 0;
int tempON = 30;
int tempOFF = 65;
int histereza = 3;
int wyslanoON = 0;
int wyslanoOFF = 0;
int stanVirtuala = 0;
int stanGrzalki = 0;

class RelayAsInput : public Supla::Control::VirtualRelay {//temp wył. grzałki
 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);
    tempOFF = newTemp;
    wyslanoON = 0;
    wyslanoOFF = 0;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp <= (tempON +3)) {
      newTemp = tempON +3;
    }
    temp.setValue(newTemp);
    tempOFF = newTemp;
    wyslanoON = 0;
    wyslanoOFF = 0;
    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);
    tempOFF = 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 {//////////temp wł. grzałki
 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 >= (tempOFF -3)) {
      newTemp = tempOFF -3;
    }
    temp.setValue(newTemp);
    tempON = newTemp;
    wyslanoON = 0;
    wyslanoOFF = 0;
    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;
    wyslanoON = 0;
    wyslanoOFF = 0;
    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;
};

void setup() {
  Serial.begin(9600);
   sekund30.begin(14898);
// Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
  char GUID[SUPLA_GUID_SIZE] = {xx};

  // Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {xx};

  relay1 =   new Supla::Control::Relay(D5, false);
  relay2 =   new Supla::Control::Relay(D6, false);
  vrelay = new Supla::Control::VirtualRelay();
  tempBojler = new Supla::Sensor::DS18B20(ONE_WIRE);
  new RelayAsInput1();
  new RelayAsInput();
  
       dsSTART();
  SuplaDevice.begin(GUID,              // Global Unique Identifier 
                    "svrxx.supla.org",  // SUPLA server address//////////xx.supla.org
                    "xxxx",   // Email address used to login to Supla Cloud/////////////xx
                    AUTHKEY);          // Authorization key
}

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

void ds(){
  if(sekund30.available()){
    temp = tempBojler->getChannel()->getValueDouble();
  }
}
void dsSTART(){
  temp = tempBojler->getChannel()->getValueDouble();
}
void relayOnOff(){
  stanV();
  if(temp>=tempOFF){
    przek1=0;
  }
  else if(temp<tempON){
    przek1=1; 
  }
 if(!vrelay->isOn()){
  if((przek1 == 1) && (wyslanoON==0)){
   relay2->turnOn();
   wyslanoON=1;
   wyslanoOFF=0;
  }
  else if((przek1==0) && (wyslanoOFF==0)){
   relay2->turnOff();
   wyslanoON=0;
   wyslanoOFF=1;
  }
}
}
void stanV(){
    int r2 = relay2->isOn();
    if(r2 != stanGrzalki){
      stanGrzalki = r2;
      wyslanoON=0;
      wyslanoOFF=0;
    }
    int vr = vrelay->isOn();
    if(vr != stanVirtuala){
      stanVirtuala = vr;
      wyslanoON=0;
      wyslanoOFF=0;
    }
    if(vrelay->isOn()){
      if(relay2->isOn()){
        przek1=1; 
      }
      else if(!relay2->isOn()){
        przek1=0; 
      }
    }
}
Dzięki @lukfud za info jak pobierać temperaturę.
Co do actionHandlera to jeszcze nie miałem czasu się zagłębić, a jako, że niespecjalnie lubię wstawiać kluczowe linijki na zasadzie ctrl+v, kiedy nie rozumiem jak to działa, to na razie pominąłem.
W powyższym kodzie dodałem też kilka linijek odpowiedzialnych za trochę inną logike działania trybu auto/manual. Teraz nawet kiedy termostat jest w fazie wychładzania/grzania to można przestawić się na manual, zmienić mu wychładzanie<->grzanie i od razu znowu włączyć trym AUTO.
To tylko te kilka linijek:

Code: Select all

if(vrelay->isOn()){
      if(relay2->isOn()){
        przek1=1; 
      }
      else if(!relay2->isOn()){
        przek1=0; 
      }
    }
Mam jeszcze pytanie, mam takie dwie funkcje:
ds() i dsSTART(), ta druga robi odczyt na starcie, w SETUP, a druga co określony czas nadpisuje zmienną temp odczytem z czujnika.
Ja wiem, że to się pewnie da zrobić inaczej, za pomocą actionHandlera na przykład, ale czy mógłbym pominąć tą funkcję ds() co 30s czytającą czujnik ds18 i nadpisać w ramach supli również moją zmienną temp?
Last edited by SOYER on Tue Jun 20, 2023 5:51 pm, edited 1 time in total.
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
User avatar
SOYER
Posts: 1623
Joined: Wed Aug 10, 2022 12:29 pm
Location: Kryry
Been thanked: 2 times

Post

Tutaj film o termostacie:

https://youtu.be/Mkyeuw1QzYQ
https://youtube.com/@tomaszhamer8134?si=_J1cT_QWsXxgt1Fm
https://kryry01.aqi.eco/pl
https://app.weathercloud.net/d4311785603
https://github.com/Soyer79
konstal2004
Posts: 2
Joined: Sun Aug 27, 2023 2:07 pm

Post

Witam
Od dłuższego czasu właśnie taki projekt siedział mi w głowie, a teraz rozpocząłem jego realizację. Nadmienię tylko, że jest to mój pierwszy projekt na Supli, a w programowaniu miałem prawie 20 lat przerwy..
Zmodyfikowałem nieco kod pod siebie, uzupełniłem o "onInit()" przypisującą jakieś "normalne" wartości temperatur, o której wspominał lukfud.
Chcę to jeszcze rozbudować o wykorzystanie autokonsumpcji prądu z fotowoltaiki. W tym celu do Wemosa podpiąłem płytkę PZEM-004.
Idea jest taka, że gdy wartość napięcia odczytana na PZEM przekroczy określony próg, to automatyka załączy grzałkę w zasobniku CWU.
Grzałka sterowana grupowo, za pomocą przekaźnika SSR. Stanąłem na odczytaniu wartości napięcia z PZEM.
Przypuszczam, że jest możliwość pobrania napięcia w podobny sposób, jak temperaturę, tzn:

Code: Select all

 double temperature = temperature_sensor->getChannel()->getValueDouble(); 
Niestety nie wiem jak to zaimplementować w przypadku napięcia.

Poniżej kod z moimi modyfikacjami

Code: Select all

#include <SuplaDevice.h>
#include <supla/control/relay.h>
#include <supla/sensor/DS18B20.h>
#include <supla/sensor/PzemV3.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>
#include <Timers.h>

#define ONE_WIRE D3

Supla::ESPWifi wifi("", "");

Timers sekund10;
//Supla::Control::Relay *SSR = nullptr;
//Supla::Control::Relay *relay2 = nullptr;
Supla::Control::VirtualRelay *vrelay = nullptr;
Supla::Sensor::DS18B20 *tempBojler = nullptr;

const int SSR = 14;   ///GPIO14 = D5
double temp;
double napiecie;
int przek1 = 0;
int tempON = 40;
int tempOFF = 45;
int histereza = 3;
//int wyslanoON = 0;
//int wyslanoOFF = 0;
int stanVirtuala = 0;
int stanGrzalki = 0;
int napiecie_ust = 245;
int delta_U = 3;
int temperatura_fotowoltaiki = 80;
int time_H=0;
int time_L=250;

class RelayAsInput : public Supla::Control::VirtualRelay //temperatura wyłączenia grzałki przy korzystaniu z prądu sieciowego 
{
 public:
  explicit RelayAsInput(int step = 1) : step(step) {}
  virtual ~RelayAsInput() {}
  void onInit() override
  {
    if (temp.getValue() == TEMPERATURE_NOT_AVAILABLE)
      temp.setValue(tempOFF);
  }
  void turnOn(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > 85)
      newTemp = 85;
    temp.setValue(newTemp);
    tempOFF = newTemp;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    if (newTemp <= (tempON +3)) 
      newTemp = tempON +3;
    temp.setValue(newTemp);
    tempOFF = newTemp;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    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);
    tempOFF = 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 //temperatura włączenia grzałki przy korzystaniu z prądu sieciowego 
{
 public:
  explicit RelayAsInput1(int step = 1) : step(step) {}
  virtual ~RelayAsInput1() {}
  void onInit() override
  {
    if (temp.getValue() == TEMPERATURE_NOT_AVAILABLE)
      temp.setValue(tempON);
  }
  void turnOn(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp >= (tempOFF -3))
      newTemp = tempOFF -3;
    temp.setValue(newTemp);
    tempON = newTemp;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    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;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    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 Napiecie_ustawione : public Supla::Control::VirtualRelay // ustawione napięcie graniczne, powyżej którego następuje załączenie grzałki CWU
{
 public:
  explicit Napiecie_ustawione(int step = 1) : step(step) {}
  virtual ~Napiecie_ustawione() {}
  void onInit() override
  {
//    if (temp.getValue() == TEMPERATURE_NOT_AVAILABLE)
      temp.setValue(napiecie_ust);
  }
  void turnOn(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int new_U = temp.getValue() + step;
    temp.setValue(new_U);
    napiecie_ust = new_U;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    Supla::Storage::ScheduleSave(2000);
  }
  void turnOff(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int new_U = temp.getValue() - step;
    temp.setValue(new_U);
    napiecie_ust = new_U;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    Supla::Storage::ScheduleSave(2000);
  }
  int getValue() 
  {
    return temp.getValue();
  }
  void setValue(int value) 
  {
    temp.setValue(value);
    Supla::Storage::ScheduleSave(2000);
  }
  void onLoadState() override 
  {
    int napiecie = 0;
    Supla::Storage::ReadState(reinterpret_cast<unsigned char *>(&napiecie),sizeof(int));
    temp.setValue(napiecie);
    napiecie_ust = napiecie;
  }
  void onSaveState() override 
  {
    int napiecie = temp.getValue();
    Supla::Storage::WriteState(reinterpret_cast<unsigned char *>(&napiecie),sizeof(int));
  }
 protected:
  Supla::Sensor::VirtualThermometer temp;
  int step = 1;
};


class temp_fotowoltaika : public Supla::Control::VirtualRelay //temperatura wyłączenia grzałki przy korzystaniu z fotowoltaiki
{
 public:
  explicit temp_fotowoltaika(int step = 1) : step(step) {}
  virtual ~temp_fotowoltaika() {}
  void onInit() override
  {
    if (temp.getValue() == TEMPERATURE_NOT_AVAILABLE)
      temp.setValue(temperatura_fotowoltaiki);
  }
  void turnOn(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int newTemp = temp.getValue() + step;
    if (newTemp > 85)
      newTemp = 85;
    temp.setValue(newTemp);
    temperatura_fotowoltaiki = newTemp;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    Supla::Storage::ScheduleSave(2000);
  }

  void turnOff(_supla_int_t duration = 0) override 
  {
    (void)(duration);
    int newTemp = temp.getValue() - step;
    temp.setValue(newTemp);
    temperatura_fotowoltaiki = newTemp;
//    wyslanoON = 0;
//    wyslanoOFF = 0;
    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);
    temperatura_fotowoltaiki = 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);
  sekund10.start(15000);
  // Replace the falowing GUID with value that you can retrieve from https://www.supla.org/arduino/get-guid
  char GUID[SUPLA_GUID_SIZE] = {};

  // Replace the following AUTHKEY with value that you can retrieve from: https://www.supla.org/arduino/get-authkey
  char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {};

  pinMode(SSR, OUTPUT);

//  relay2 =   new Supla::Control::Relay(D6, false);
  vrelay = new Supla::Control::VirtualRelay();        //wyłącznik grzałki
  tempBojler = new Supla::Sensor::DS18B20(ONE_WIRE);  // temperatura bojlera
  new RelayAsInput1();                                // temperatura załączania grzałki przy korzystaniu z prądu sieciowego 
  new RelayAsInput();                                 // temperatura wyłączania grzałki przy korzystaniu z prądu sieciowego 
  new temp_fotowoltaika();                            // temperatura wyłączania grzałki przy korzystaniu z fotowoltaiki
  new Napiecie_ustawione();                           // ustawione napięcie graniczne, powyżej którego następuje załączenie grzałki CWU
  new Supla::Sensor::PZEMv3(5, 4);                    // (RX,TX)  "PZEM Addr default to 0xF8"
  
  dsSTART();
  SuplaDevice.begin(GUID,                           // Global Unique Identifier 
                    "",              // SUPLA server address
                    "",        // Email address used to login to Supla Cloud
                    ""); 
}

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

void ds()
{
  if(sekund10.available())
  {
    temp = tempBojler->getChannel()->getValueDouble();
    temp = 45;
    napiecie=240;
  }
  ////obliczenie długości czasu załączenia i czasu przerwy przekaźnika SSR
  if (napiecie > (napiecie_ust + delta_U))
    if (time_H<250)
      time_H+=10;
  if (napiecie < (napiecie_ust - delta_U))
    if (time_H>0)
      time_H-=10;    
  time_L=250-time_H;  
}

void dsSTART()
{
  temp = tempBojler->getChannel()->getValueDouble();
  temp = 45;
  napiecie=240;
}



void relayOnOff()
{
//  stanV();
  if (!vrelay->isOn())                //jeżeli grzałka wyłączona, SSR wyłączony 
    digitalWrite(SSR, LOW);
  else if (vrelay->isOn())            //jeżeli grzałka włączona  
  {
    if (time_H==0)                    //jeżeli napięcie nie przekracza napięcia ustawionego
    {
      if (temp>tempOFF)               //jeżeli temperatura wyższa od temperatury wyłączenia to wyłącz grzałkę
        digitalWrite(SSR, LOW);
      if (temp<tempON)                //jeżeli temperatura niższa od temperatury załączenia to załącz grzałkę
        digitalWrite(SSR, HIGH);
    }
    if (time_H>0)                     //jeżeli napięcie przekracza napięcie ustawione
    {
      if (temp<temperatura_fotowoltaiki)  //jeżeli temperatura niższa od temperatury ustawionej przy podgrzewaniu wody prądem z fotowoltaiki
      {
        digitalWrite(SSR, HIGH);
        delay(time_H);
        digitalWrite(SSR, LOW);
        delay(time_L);
      }
      if (temp>temperatura_fotowoltaiki)
        digitalWrite(SSR, LOW);
    }   
  }
}


Return to “Projekty użytkowników”