GyverHUB, обсуждение библиотеки

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@UA6EM,
Изучать тщательно и вдумчиво это:

И смотреть, как в моём примере автоматически обновляется состояние пина. Точно так же, по таймеру, обновлять параметр для Guagе... Копать - это громко сказано, надо всего лишь аккуратно повторить, воспользовавшись суперметодом всех "программмистов" ctrl-C, ctrl-V
:)
color:
// Индикаторная шкала. Параметры: value (значение), range, unit, color + параметры виджета
Widget& Gauge(AnyPtr ptr);
Widget& Gauge_(AnyText name, AnyPtr ptr);
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@UA6EM,
Вам повезло, как раз учу пацана 12-ти лет этой мутной фигне, смотрите как надо:
кнопки и виджеты:
#include <Arduino.h>

//=========TEMPERATURE AHT20 SENSOR===================
#include "Wire.h"
#include "Adafruit_BMP280.h"
#include "Adafruit_AHTX0.h"
Adafruit_BMP280 bmp;
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
Adafruit_AHTX0 aht20;
//----------------------------------------------------

#define AP_SSID "PASSAT-3X3"
#define AP_PASS ""

#define GH_INCLUDE_PORTAL
#include <GyverHub.h>
//#include <EEPROM.h>
//GyverHub hub;
//GyverHub hub("MyDevices", "ESP32", "");
GyverHub hub("MyDevices", "ESP32", "f0f3");

#define relay 4
#define sensor1 13

bool startButtonValue = false;
bool sensorVal = false;
bool sensor = false;

float tempAHT20;
float humidityAHT20;
float BMP280pressure;

// билдер
void build(gh::Builder& b) {
    b.Title("My Home");
if (b.beginRow()) {

  //b.Label("INDICATOR").size(1);
  static uint32_t stamp;
  b.Time_("Time", &stamp);

b.endRow();
    }

   b.LED_("Indicator1").hint("Индикатор состояния двери").label("Дверь открыта"); // светодиодный индикатор


// Если по Click, то обновляется здесь!
  if(b.SwitchIcon_("Button1").hint("Выключатель в ванной").label("Выключатель Ванная").size(30,60).square(false).click())
  {
    startButtonValue = !startButtonValue;
    if(startButtonValue)
      hub.update("Button1").color(gh::Colors::Green);
    else
      hub.update("Button1").color(gh::Colors::Red);

    digitalWrite(relay, startButtonValue);
  }

//-----------
// Индикаторная шкала. Параметры: value (значение), range, unit, color + параметры виджета
//Widget& Gauge(AnyPtr ptr);
b.Gauge_("Temperature", &tempAHT20).range(-20,100,0.5).unit("C").color(gh::Colors::Red);
b.Gauge_("Humidity", &humidityAHT20).range(0,100,1).unit("%").color(gh::Colors::Orange);
b.Gauge_("Pressure", &BMP280pressure).range(600,1500,1).unit("ммHg").color(gh::Colors::Blue);

}


void setup()
{
    Serial.begin(115200);

#ifdef GH_ESP_BUILD
    // подключение к роутеру
    WiFi.mode(WIFI_STA);
    WiFi.begin(AP_SSID, AP_PASS);
    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    Serial.println();
    Serial.println(WiFi.localIP());

    // hub.mqtt.config("test.mosquitto.org", 1883);
    hub.mqtt.config("секрет");  // + MQTT

    ///+++++++
pinMode (relay, OUTPUT);
pinMode (sensor1, INPUT_PULLUP);
    ///+++++++

    // режим точки доступа
    //WiFi.mode(WIFI_AP);
    //WiFi.softAP("My Hub");
    //Serial.println(WiFi.softAPIP());
#endif

    hub.config(F("MyDevices"), F("ESP"));
    hub.onBuild(build);
    hub.begin();

//=========TEMPERATURE AHT20 SENSOR voidsetup===================
  aht20.begin();
  bmp.begin();
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
//---------TEMPERATURE AHT20 SENSOR voidsetup--------------------

}

void loop()
{
    hub.tick();

    static unsigned long timer;
  if (millis() - timer >= 2000)
  {
    timer = millis();

   sensor = digitalRead(sensor1); // исли изменения по pin, то обновление- строго в loop!!!
   //Serial.println(sensor);
   // индикация по состоянию пина 13 (sensor1)
if (sensor == HIGH)
   hub.update("Indicator1").value(1);
   else
   hub.update("Indicator1").value(0);
//________________________________
  //@@@@@@@@@@ Датчик BMP280+AHT20 **************************************************

  sensors_event_t humidity, temp;
  aht20.getEvent(&humidity, &temp);
  sensors_event_t temp_event, pressure_event;
  bmp_temp->getEvent(&temp_event);
  bmp_pressure->getEvent(&pressure_event);

    tempAHT20 = temp.temperature;
    humidityAHT20 = humidity.relative_humidity;
   //BMP280temp = temp_event.temperature; //Это температура в датчике давления
    BMP280pressure = pressure_event.pressure*0.75;

//________________________________

  }

}
 
Изменено:

UA6EM

✩✩✩✩✩✩✩
25 Фев 2020
9
1
Посмотрел!
Так же всё и делаю!
Проблема не в том, что не обновляется, а в том, что не обновляются данные в автоматическом режиме, по таймеру видимо, а вот если нажимаешь
на значок обновления ручками, то всё обновляется.
ws-1.png
ws-2.png

да, насчёт цвета, RAINBOW возможен?
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Я нафига давал ссылку с документацией?? "Изучать тщательно и вдумчиво это"\
помещаем в loop:

static gh::Timer tmr(2000);
if (tmr) hub.update("Temperature").value(tempAHT20);
// либо так:
//if (tmr) hub.sendUpdate("Temperature", tempAHT20); //( обязательно с указанием переменной, которую хотим обновлять!!!)
2. можно и радугу, для этого долго и напряжённо маемся условиями if и задаём проценты шкалы и цвета для этих участков.
 
Изменено:

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Украл у умного человека: https://github.com/kolabse

сопоставление цветов температуре:
// сопоставление цветов температуре
gh::Colors tempColor(uint8_t temp) {
    gh::Colors colors[] = {
        gh::Colors::Pink,
        gh::Colors::Violet,
        gh::Colors::Blue,
        gh::Colors::Aqua,
        gh::Colors::Mint,
        gh::Colors::Green,
        gh::Colors::Yellow,
        gh::Colors::Orange,
        gh::Colors::Red
    };
    return colors[map(temp, minTargetTemp, maxTargetTemp, 0, sizeof(colors)/sizeof(*colors)-1)];
}
 

ivliz

✩✩✩✩✩✩✩
9 Янв 2022
3
0
Доброго времени суток , подскажите пожалуйста как можно получить текущее время и дату
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@ivliz,
для самых маленьких и ленивых: дата и время в HUB:
#include <GyverNTP.h>

GyverNTP ntp(defaultGMT);


void build(gh::Builder& b) {

       b .label_(ntp.timeString());

       b .label_(ntp.dateString());

hub.update_(F("main")).label(ntp.timeString()).label(ntp.dateString());

                                               }

void setup() {

ntp.begin();

}

void loop() {

    ntp.tick();

}
 
  • Лойс +1
Реакции: javachess

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Продолжим конструировать наш домашний полоумный домик.
Добавим меню и ввод логина и пароля wifi. После запуска подключаемся к новой ТД (смотри пароль в коде), входим 192.168.4.1, вводим логин-пароль в разделе меню "wifi", нажимаем "Сохранить", подключаемся.
Разумеется, имеется костыль, немаловажный: сначала в setup для хаба запускаем свою сеть, начинает работать файловая система, появляется возможность прочесть данные в файле pairs, затем запускается код подключения к wifi сети роутера. Иначе- никак...
меню+ возможность ввода логина и пароля wifi:
// пример с хранением данных в базе Pairs + menu
#include <Arduino.h>


#if defined(ARDUINO_ARCH_ESP8266)
#include <ESP8266WiFi.h>

#elif defined(ARDUINO_ARCH_ESP32)
#include <WiFi.h>
#endif

#define GH_INCLUDE_PORTAL  // ОБЯЗАТЕЛЬНО!!! открывает свой портал по адресу 192.168.4.1 при своей локальной ТД

#include <GyverHub.h>
GyverHub hub;

#include <PairsFile.h>
// pairsfile - автоматически сохраняет базу данных в файл
PairsFile data(&GH_FS, "/data.dat", 3000);
// Pairs data;  // есть без привязки к файлу

     String wifi_SSID;
     String wifi_PASS;
      bool cnfWiFiUpd;


//=========TEMPERATURE AHT20 SENSOR===================
#include "Wire.h"
#include "Adafruit_BMP280.h"
#include "Adafruit_AHTX0.h"
Adafruit_BMP280 bmp;
Adafruit_Sensor *bmp_temp = bmp.getTemperatureSensor();
Adafruit_Sensor *bmp_pressure = bmp.getPressureSensor();
Adafruit_AHTX0 aht20;
//----------------------------------------------------
#define relay 4
#define sensor1 13

bool startButtonValue = false;
bool sensorVal = false;
bool sensor = false;

float tempAHT20;
float humidityAHT20;
float BMP280pressure;

// для меню создадим структуру, чтоб было красиво и понятно
enum MenuItems {
  MainItem,
  WifiItem,
  TermostatItem,
  SwitchersItem,
  IndicatorsItem,
  TimersItem
};


// билдер
void build(gh::Builder& b) {
  b.Menu("Main;Wifi;Termostat;Switchers;Indicators;Timers");
  b.show(b.menu() == MainItem); // главное окно, выводится сразу

  b.LED_("Indicator1").hint("Индикатор состояния двери").label("Дверь закрыта");  // светодиодный индикатор состояния двери
  b.Gauge_("Temperature", &tempAHT20).range(-20, 100, 0.5, 1).unit("C").color(gh::Colors::Red).label("Температура воздуха");
  b.Gauge_("Humidity", &humidityAHT20).range(0, 100, 1).unit("%").color(gh::Colors::Orange).label("Влажность воздуха");
  b.GaugeLinear_("Pressure", &BMP280pressure).range(720, 790, 1).unit("").color(gh::Colors::Blue).label("Атмосферное давление");

  b.show(b.menu() == WifiItem);

    // Форма ввода настроек wifi
    b.beginRow();

    b.beginCol(2);
    b.Label("SSID").noLabel().noTab().fontSize(20).align(gh::Align::Left);
    b.Label("Password").noLabel().noTab().fontSize(20).align(gh::Align::Left);
    b.endCol();

    b.beginCol(2);
    b.Input_(F("ssid"), &wifi_SSID).label("Введи имя сети WiFi").noTab();
    b.Pass_(F("pass"), &wifi_PASS).label("Введи пароль сети WiFi").noTab();
    b.endCol();

    b.beginCol(1);

    // кнопка подтверждения сохранения новых настроек wifi
    if (b.Confirm_("wifiUpd", &cnfWiFiUpd).noLabel().click()) {
        if (cnfWiFiUpd) {
            data.set("ssid", wifi_SSID);
            data.set("pass", wifi_PASS);
       
            hub.sendNotice(F("Настройки wifi обновлены"));
        }
    }

    if (b.Button().fontSize(25).label("SAVE!").noTab().size(2, 100).click()) {
        if (!wifi_SSID.isEmpty()) {
            hub.sendAction("wifiUpd");
        } else {
            hub.sendAlert(F("Имя точки доступа не должно быть пустым!"));
        }
    }

    // обновить текст при действиях на странице
    if (b.changed()) hub.update("pairs").value(data);
    b.endCol();
    b.endRow();
// b.Text_("pairs", data);

b.show(b.menu() == TermostatItem);
  if (b.Button_("savewifi").click()) { Serial.println("click button6 in menu termostat");}
  b.Label("Termostat temperature").size(3);
  b.Slider_("Termostat");



  b.show(b.menu() == SwitchersItem);
  b.SwitchIcon_("Button2").hint("Выключатель Бойлер").label("Выключатель Бойлера"); // этот меняет цвет при вкл. и большой!!! ОК!
  b.LED_("Switchers").hint("Индикатор состояния двери").label("Дверь открыта");  // светодиодный индикатор
  b.Button_("").label(F("my button switch")).color(gh::Colors::Orange);// нихера не работает
  b.widget.color(gh::Colors::Blue);


  b.show(b.menu() == IndicatorsItem);
  b.LED_("Indicator1").hint("Индикатор состояния двери").label("Дверь открыта");

b.show(b.menu() == TimersItem);
   static uint32_t stamp;
   b.Time_("Time1", &stamp); //ввод времени

    b.show(); // отвечает за показ вызванных из меню окон
     //+++++++++++++++
}

void setup() {
    Serial.begin(115200);

#ifdef GH_ESP_BUILD

WiFi.softAP("ESP_WIFI_PORTAL", "smarthome");  // 192.168.4.1 - адрес своей ТД
//Serial.println (WiFi.localIP());
Serial.println(WiFi.softAPIP());


//   hub.mqtt.config("test.mosquitto.org", 1883, "putinhuylo", "putinhuylo");  // + MQTT

#endif

  //=========TEMPERATURE AHT20 SENSOR voidsetup===================
  aht20.begin();
  bmp.begin();
  bmp.setSampling(Adafruit_BMP280::MODE_NORMAL,     /* Operating Mode. */
                  Adafruit_BMP280::SAMPLING_X2,     /* Temp. oversampling */
                  Adafruit_BMP280::SAMPLING_X16,    /* Pressure oversampling */
                  Adafruit_BMP280::FILTER_X16,      /* Filtering. */
                  Adafruit_BMP280::STANDBY_MS_500); /* Standby time. */
  //---------TEMPERATURE AHT20 SENSOR voidsetup--------------------

   hub.config(F("MyDevices"), F("ESP"));
    hub.onBuild(build);
    hub.begin();


    wifi_connect();  // смотри wifi.ino, там инициализируется подключение

}

void loop() {
    hub.tick();

    // файл в памяти сам обновится по указанному в параметрах в начале скетча таймауту, 3 сек
    data.tick();

  //------------------------------------------
    static unsigned long timer;
  if (millis() - timer >= 2000)
  {
    timer = millis();

   sensor = digitalRead(sensor1); // исли изменения по pin, то обновление- строго в loop!!!
   //Serial.println(sensor);
   // индикация по состоянию пина 13 (sensor1)
if (sensor == HIGH)
   hub.update("Indicator1").value(1);
   else
   hub.update("Indicator1").value(0);

   //@@@@@@@@@@ Датчик BMP280+AHT20 **************************************************

    sensors_event_t humidity, temp;
    aht20.getEvent(&humidity, &temp);
    sensors_event_t temp_event, pressure_event;
    bmp_temp->getEvent(&temp_event);
    bmp_pressure->getEvent(&pressure_event);

    tempAHT20 = temp.temperature;
    humidityAHT20 = humidity.relative_humidity;
    //BMP280temp = temp_event.temperature; //Это температура в датчике давления
    BMP280pressure = pressure_event.pressure * 0.75;

    hub.update("Temperature").value(tempAHT20);
    hub.update("Humidity").value(humidityAHT20);
    hub.update("Pressure").value(BMP280pressure);

    //________________________________
  }
}
[CODE lang="cpp" title="wifi.ino"]

void wifi_connect() {

Serial.println("Reading wifi settings from FS");
data.begin();

//Serial.println ("data size: ");
//Serial.println (data.getSize()); Проверка размера файла Pairs

Serial.println ();

     wifi_SSID = data.get("ssid").toString();
     wifi_PASS = data.get("pass").toString();
Serial.println (wifi_SSID);
Serial.println (wifi_PASS);

byte tries = 20; //20 раз ожидаем подключения к wifi, пытаясь к нему...
WiFi.mode(WIFI_STA); // режим клиента
WiFi.begin(wifi_SSID, wifi_PASS); // берём из долговременной памяти логин и пароль wifi
while (--tries && WiFi.status() != WL_CONNECTED) {

    Serial.print (".");
    delay(500);
    //____________

     if((WiFi.status() == WL_CONNECTED))           //If WiFi connected to hot spot then start
  {
    Serial.println (WiFi.localIP());
   // softAP = true;
  }
}
//=================
if (WiFi.status() != WL_CONNECTED) // Если не удалось подключиться запускаем в режиме AP


{

    Serial.println ("Хрен там, нет заданной сети!");
         WiFi.disconnect();
//#define ssidAP "ESP_WIFI_PORTAL"
//#define passAP "smarthome"  // не менее 8 символов

WiFi.softAP("ESP_WIFI_PORTAL", "smarthome");  // 192.168.4.1 - адрес своей ТД
//Serial.println (WiFi.localIP());
Serial.println(WiFi.softAPIP());
}[URL='https://community.alexgyver.ru/threads/gyverhub-obsuzhdenie-biblioteki.8755/page-2#footer']Снизу
Снизу[/URL]

}

}[/CODE]
 
Изменено:

ivliz

✩✩✩✩✩✩✩
9 Янв 2022
3
0
@gidiara666, Спасибо большое конечно , но без подключения дополнительной библиотеки не получится получить текущее время тк это было возможно в Gyverportal?
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
@ivliz,
В Portal и я нарезвился вдоволь с получением времени и даты и получил множество проблем именно с этой функцией...
Мои скромные выводы, которые могут не совпадать с замыслом "программистов" по этому поводу:

1. если использовать стандартные библиотеки от Fabrice Weinberg либо Stefan Staub, то в режиме автономной точки доступа либо при отсутствии интернета при запуске они "завешивают" всю ESP нахрен при попытке достучаться до сервера ntp.
2. если использовать библиотеку GyverNTP, то без инета возможно использование, а время можно задавать самому, часовой пояс указывать так: GyverNTP ntp(gmt); // часовой пояс в часах (например Иерусалим это 2)
3. Мне необходимо было указать для умного дома срабатывание по дням недели. Вроде обычная функция uint8_t dayWeek(); // получить день недели (пн.. вс = 1.. 7), но почему-то это поделие получает дату не как время, с обновлением по указанному периоду, а "долбит" сервер своими запросами постоянно, что тоже со временем "завешивает" ESP.
4. Получение времени из браузера - это тоже очень плохая идея, требующая от страдальца периодического обновления страницы в браузере и обязательного доступа в инет прибора, который этот браузер открывает.
Итого, самым оптимальным и безглючным оказалось получение времени через сервер Telegram, что я и рекомендую. Ведь всё равно понадобится звуковое оповещение событий в реальном времени (безальтернативный вариант, если не юзаете Blynk), интерактивное управление из меню без всяких приложений, дублирование сервера MQTT на случай отказа, так что включать в проект Telegram - просто обязательно.
Итого:
// Это Telegram1 вначале______________________
#include <FastBot.h>
FastBot bot;
//________________________________________________

// Это Telegram1 в setup
bot.setToken(mem.TelegramBOTID);
#define CHAT_ID (mem.TelegramID1)
//-----------------------------------------------------------------------------
// подключаем функцию-обработчик после завершения void setup()

bot.setChatID(CHAT_ID);
bot.sendMessage("Привет!", CHAT_ID); // отправить сообщение, чтобы получить время startUnix = bot.getUnix(); // запомнили }
bot.attach(newMsg);
startUnix = bot.getUnix(); // получение времени при соединении с сервером и при получении любого сообщения

в void loop() :

// получаем времечко и дату из телеги
// FB_Time t = bot.getTime(2);
FB_Time t = bot.getTime(mem.TimePoyas);
realtime = t.timeString();
d = t.dateString();

Всё, время и даты получены без гемороя! Легко и просто, да ещё и систему не завешивает, если вдруг не может достучаться до сервера.
Для экспериментов рекомендую обратиться к классу gh::Timer, см. https://github.com/GyverLibs/GyverHub/wiki, но это уже, скорей, для удовлетворения мазохистских устремлений личного организма.
 
Изменено:

ivliz

✩✩✩✩✩✩✩
9 Янв 2022
3
0
@gidiara666,спасибо большое за столь развернутый ответ )!
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
Итого, самым оптимальным и безглючным оказалось получение времени через сервер Telegram, что я и рекомендую.
О Боги! О Зевс громовержец! За что ты наказываешь людей такими страданиями... Дай им силы изменить то, что можно изменить, дай им терпение принять то, что изменить нельзя, и дай им мудрости отличить одно от другого.

Не могу на это спокойно смотреть...

В SDK esp8266/esp32 уже есть ВСЕ необходимые библиотеки и АПИ для работы с датой/временем через стандартный С апи, синхронизация времени с НТП серверами (несколькими, автоматически), коллбеком на обновление времени, работа с часовыми поясами, автопереходом на летнее/зимнее время, калькуляция дат/интервалов с учетом этих переходов и т.д. и т.п.
@ivliz, вы если сами изобретаете кривые велосипеды, то хотя бы не советуйте другим идти этим же путём ведущим в пропасть. Хоть бы в примеры из официальной документации заглянули.

Время через Телеграм... я всё...
 
  • Лойс +1
Реакции: Haaans

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Всегда рад надругаться над староверами, привыкшими всё делать по правилам: получение времени - только с NTP сервера, строго по пятницам :).
Для тех, кто жаждет экспериментов - милости просим глянуть код для простейших действий в HUB:
получение информации с порта от датчика и отображение этого факта на экране, нажатие кнопки и реакция на экране,
включение реле по времени. Критика приветствуется, можете разносить весь код в пух и прах. Моё дело -помочь начинающим и выслушать обоснованные аргументы для улучшения. :).. Не стесняйтесь выкладывать свой код, это поможет многим. Жлобству - бой!

Что не доделано пока:
1. не исчезает запрос на ввод пароля при входе в админку. Приветствуются предложения как скрыть это дело
2. в телеграм не открываются нормально пункты меню, задействованные в коде (Switches. HUB) и невозможно управление реле. А что вы хотели, это же - пример. Выдирал из большого кода, проморгал... Пусть это будет домашним заданием.
3. Аларм "дверь открыта"/ - закрыта отображается в телеге и на экране в HUB.
3. Включение по Timer имеет больший приоритет, чем главная кнопка "Бойлер", это некорректно. Исправлению приветствуются, мелочь, тоже проглядел в процессе копипаста, но важная.
Всем хорошего настроения!
 

Вложения

  • 14.1 KB Просмотры: 16
  • 8.7 KB Просмотры: 11

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
Всегда рад надругаться над староверами, привыкшими всё делать по правилам: получение времени - только с NTP сервера, строго по пятницам
толстовато :) маскировать нигилизм под невежество надо потоньше.

давайте вместе попробуем?

tFlag1 = (data.get("BoilerTime1") == 1) ? true : false;

вот это можно заменить на tFlag1 = data.get("BoilerTime1");,
но гораздо интереснее для читателя будет вот так:
Код:
Sting result = data.get("BoilerTime1") ? String("true") : String("false");
tFlag1 = (result == String("true"));
идём дальше...
Код:
int daySeconds = (t.hour*3600 + t.minute*60 + t.second);
int t1 = data.get("T1boilerON");
int t2 = data.get("T1boilerOFF");
int t3 = data.get("T2boilerON");
int t4 = data.get("T2boilerOFF");
// проверка времени срабатывания: T1boilerON Serial.println(String("time1:   ") + time1);
if (t1 - daySeconds < 0) {digitalWrite(boiler1Relay, ON);}
if (t2 - daySeconds < 0) {digitalWrite(boiler1Relay, OFF);}
if (t3 - daySeconds < 0) {digitalWrite(boiler1Relay, ON);}
if (t4 - daySeconds < 0) {digitalWrite(boiler1Relay, OFF);}
`
допустим задали включить реле в 0:10, выключить в 0:15 и второй раз включить реле в 0:20, выключить в 0:25.
Теперь после 0:25 будем 4 раза щелкать релешкой туда-сюда каждую секунду, что положительно скажется на её износе и поддержит китайского производителя. Но проблема в том что пин будет переключаться слишком быстро, и реле может не успевать дергать якорь что бы контакты замкнулись и возникла надежная искра, поэтому необходимо вставить задержку между переключениями что бы дать возможность реле хлопнуть туда-сюда и увеличить время прождения дуги между контактами. Время лучше подобрать согласно даташиту реле, но условно возмем 25 мс.
Код:
if (t1 - daySeconds < 0) {digitalWrite(boiler1Relay, ON);}
delay(25);
if (t2 - daySeconds < 0) {digitalWrite(boiler1Relay, OFF);}
delay(25);
if (t3 - daySeconds < 0) {digitalWrite(boiler1Relay, ON);}
delay(25);
if (t4 - daySeconds < 0) {digitalWrite(boiler1Relay, OFF);}

чего бы ещё... здесь вот очень удачное решение обновлять хаб каждый цикл, даже не знаю чем еще это можно улучшить. Было бы здорово и в телегу слать апдейт, но тут могу забанить за спам, поэтому надо подумать над реализацией.
Код:
if(boiler1RelayI.isPressed())
   {hub.update("IBoiler1Relay").value(1); } // ВОТ ЭТО ВОТ ВЕРНО!!!! для low relay
if(boiler1RelayI.isReleased())
   {hub.update("IBoiler1Relay").value(0); } // ВОТ ЭТО ВОТ domRelF = false;ВЕРНО!!!! для low relay
может вы чего еще придумаете?
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
Огромное спасибо за ответ. И за второй и третий уровень ёрничества, в нём.
1. Массовый читатель будет счастлив лёгкости прочтения кода, но процессору от сравнения стрингов в Loop может и поплохеть...
2. Сильно надеюсь, что delay в Loop Вы порекомендовали условно, либо как шутку. Искру в контактах в и обмотке реле предотвращает диод, включённый параллельно обмотке. Никакая задержка в 0.25 сек эту искру не уберёт в принципе, так как предназначена для програмной борьбы с дребезгом контактов кнопок... Почему
"допустим задали включить реле в 0:10, выключить в 0:15 и второй раз включить реле в 0:20, выключить в 0:25.
Теперь после 0:25 будем 4 раза щелкать релешкой туда-сюда каждую секунду" реле поведёт себя вопреки программному коду - я не понял. Ибо реле включится в 0:10, выключится в 0:15 и т.д. :).
3. Вы невнимательны, апдейт шлётся в HUB и в Telegram по прерыванию, происходящему только в момент CHANGE состояния сенсора. Крайне сложно физически открывать и закрывать дверь более динамично, чем 1 секунда, что и является ограничением телеграм на отсылку сообщений для ботов. :). Опять же, Вы не внимательны: обновляется не весь хаб, а только 1 индикатор. Смотрите в сюда: hub.update("IBoiler1Relay").value(1);
Исходя из этого рекомендую Вам упражнения на развитие внимания. Начните с простого. https://logiclike.com/razvitie-rebenka/vnimanie
Ну и, затаив дыхание, ожидаю Вашего гениального кода, связанного с HUB. Поможем этому миру стать лучше вместе.
 
Изменено:

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
у почему бы не по ёрничать-то... если уж время из телеги можно брать, то почему бы еще не придумать чего можно тут сделать вопреки здравому смыслу :) В конце концов на этом тоже можно чему-то научиться

Искру в контактах в и обмотке реле предотвращает диод
не предотвращает. Диод ставят в реле совсем для других целей, к искре в контактах это никакого отношения не имеет.

Почему реле поведёт себя вопреки программному коду - я не понял
почемуже вопреки? Как раз благодаря. Давайте по шагам, допустим сейчас 0:25:01, т.е. daySeconds=1501
t1 = 600
t2 = 900
t3 = 1200
t4 = 1500
берём ваш код

Код:
if (600 -1501 < 0) {digitalWrite(boiler1Relay, ON);}      // условие истино - включаем реле
if (900 - 1501 < 0) {digitalWrite(boiler1Relay, OFF);}    // условие истино - вЫключаем реле
if (1200 - 1501 < 0) {digitalWrite(boiler1Relay, ON);}   // условие истино - включаем реле
if (1500 - 1501 < 0) {digitalWrite(boiler1Relay, OFF);}   // условие истино - вЫключаем реле
т.е. релюшкой пощелкали туда-сюда, и ждём следующую секунду, потом повторяем. Задержка нужна для того чтобы реле успело надежно переключиться и щелкания не прошли даром. Всё таки реле не успевает переключаться мгновенно, а вы же хотите послушать как оно приятно пощелкивает 4 раза в секунду, правда? :)


апдейт шлётся в HUB и в Telegram по прерыванию, происходящему только в момент CHANGE состояния сенсора
а где здесь прерывание-то?

Код:
void loop() {
if(boiler1RelayI.isPressed())
   {hub.update("IBoiler1Relay").value(1); } // ВОТ ЭТО ВОТ ВЕРНО!!!! для low relay
if(boiler1RelayI.isReleased())
   {hub.update("IBoiler1Relay").value(0); } // ВОТ ЭТО ВОТ domRelF = false;ВЕРНО!!!! для low relay
}
луп выполняется бесконечно в цикле без всяких прерываний. Функции boiler1RelayI.isPressed(), boiler1RelayI.isReleased() возвращают какое-то значение - хаб обновляется. С учетом того что луп выполняется (при условии нормально написанного кода) десятки тысяч раз в секунду, думайте сколько раз в секунду вы обновите эти индикаторы. Не 10 тысяч раз и даже не тысячу, но скоре всего три, три и три... до дырки :)

ожидаю Вашего гениального кода, связанного с HUB
я не пользуюсь гайверхабом, смотрел его код - мне не понравилось. Фронтенд симпатичный, спору нет, но движек для контроллера слишком громоздкий и тащит кучу повторяющихся литералов в код. Как-нибудь обойдусь.
 
  • Лойс +1
Реакции: gidiara666

poty

★★★★★★✩
19 Фев 2020
3,261
948
маскировать нигилизм под невежество надо потоньше.
Справедливости ради нужно сказать, что историю писал автор, далёкий от физики, так как во всех предложенных воображаемым Нильсом Бором способов требовался другой измерительный инструмент, помимо барометра (линейка, секундомер, уже проведенные измерения...). Так что все эти методы: а) не соответствуют условию; б) будут давать погрешность, потенциально превышающую измерения барометром.

@gidiara666, если Вы не поняли - все ответы
@vortigont, являются стёбом, но в них есть и рациональное зерно.
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
а) не соответствуют условию; б) будут давать погрешность, потенциально превышающую измерения барометром.
ну если уж углубляться, то для барометра тоже нужны и доп инструменты и данные - как минимум точный градусник и таблицы плотности воздуха, а для точности еще и показания влажности и разности температур внизу и вверху. Так что да, в основном это стёб и разминка для ума )
 

poty

★★★★★★✩
19 Фев 2020
3,261
948

@vortigont, если это инструмент (я про барометр), то он должен включать всё нужное.
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
@poty, ну нееет, барометр, значит барометр - на выходе паскали ) А всё-в-одном это вот у меня на руке часы с ABC - altimeter, barometer, compass, сразу высоту/глубину в метрах показывает.
 

poty

★★★★★★✩
19 Фев 2020
3,261
948

@vortigont, если он показывает Паскали, значит, их уже пересчитывать не нужно. Не требуется ничего более.
 

gidiara666

★✩✩✩✩✩✩
5 Май 2023
63
14
По поводу кода, могу доложить следующее:
1. Переключений реле при указанных выше условиях не происходит, потому что выходной транзистор, подающий питание на порт, имеет время включения больше, чем время исполнения рядом стоящих строк в коде. Потому никаких переключений реле при, как Вы правильно заметили, возможных теоретически при определённых обстоятельствах - не происходит, я проверял и ставил многократные опыты. Беспокойство оказалось напрасным, но я обязательно усовершенствую код.
2. Вам следует изучить, что такое прерывания и как они обрабатываются. Подсказка: они обрабатываются только в момент события. Соответственно, событие if(boiler1RelayI.isPressed()), if(boiler1RelayI.isReleased()) - это условия функции аппаратного прерывания, которое, повторюсь, происходит только в момент изменения функции ( См. библиотеку ezButton.h ), соответственно, утверждение "в loop эти значения обрабатываются каждый такт и возвращают в HUB какое-то значение" - является ложным, ибо они работают только по факту изменения CHANGE, о чём я уже упоминал, но Вы не обратили внимание (см. ссылку на упражнения для развития внимательности). "А где здесь прерывания-то?" Вот здесь они обрабатываются:
ezButton lockI(33); // create ezButton object that attach to pin 33;
ezButton boiler1RelayI(5); // create ezButton object that attach to pin 5;
3. Действительно, я позабыл основы электроники и диод предназначен для другого, в этом Вы совершенно правы. Обеспечение безискрового переключения можно обеспечить только благодаря схеме, определяющей "момент перехода через нуль" и только при работе с переменным током
4. Рад, что помог расширить Ваше сознание на примере отвергания создания лишних сущностей, на примере "раз юзаем телеграм- берём время из него и не плодим лишнего". Очень рад, что Вы оценили полёт фантазии.
5. Где можно посмотреть Ваш бесплатный код, загрузить его в целях образования для повышения квалификации? Мне не терпится увидеть эти гениальные строки.
 

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
Не требуется ничего более
насколько я помню физику из школы паскали в метры напрямую не переводятся, только через плотность, молярную массу и температуру. Но давайте оставим уже этот оффтопик в стороне.

@gidiara666,
Ладно, стёб в стону.
Вы, к сожалению, сами не понимаете свой код. Так писать нельзя, я вам рассказал почему. Попробуйте перечитать и вдуматься в то что написано.
Дрыгать ножкой реле и считать что "и так сойдет" потомучто транзистор медленный, вы так далеко в программировании не уедете.
Про прерывания вы тоже чушь какую-то написали. Вот код метода ezButton::isPressed()
Код:
bool ezButton::isPressed(void) {
    if(previousSteadyState == HIGH && lastSteadyState == LOW)
        return true;
    else
        return false;
}
это обычная неблокирующая функция, она ВСЕГДА мгновенно возвращает результат. Вызов этой функции стоит у вас в loop() значит условие отрабатывает в каждом цикле независимо от никаких прерываний. Вам нужно написать код, который будет сравнивать значение функции на предыдущем шаге с нынешним, и, если, оно изменилось, то тогда и только тогда отправлять обновку в хаб и в телегу.

Где можно посмотреть Ваш бесплатный код, загрузить его в целях образования для повышения квалификации?
Вот здесь посмотрите. В частности можете поглядеть библиотеку асинхронной работы с кнопками, там и про прерывания есть и про то как не дроч дергать вызов состояния кнопки в каждом цикле loop()
 
  • Лойс +1
Реакции: gidiara666

vortigont

★★★★★★✩
24 Апр 2020
1,022
543
Saint-Petersburg, Russia
@gidiara666,
P.S. поглядел код библиотеки ezButton, она вообще не умеет работать с прерываниями от пинов, в ней это не заявлено и в коде нет ничего связанного с обработкой прерываний. Откуда вы вообще это взяли-то?