Помощь в доработке функций помогите пожалуйста с проектом на библиотеках Settings, GyverDB, GyverNTP, EncButton,

Daniel19

✩✩✩✩✩✩✩
19 Окт 2024
1
0
Привет, сообщество!

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

Вот основные задачи, с которыми я столкнулся:
1.Автоматическое управление мотором: Я хочу, чтобы мотор открывался или закрывался автоматически в соответствии с сохраненным временем в базе данных. Мне нужна помощь в написании функции, которая будет проверять текущее время и инициировать действия открытия или закрытия мотора.

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

3.Дополнительное поле в веб-интерфейсе: У меня уже есть поля для настройки времени открытия и закрытия мотора в веб-интерфейсе. Мне нужно добавить еще одно поле, которое позволит пользователю задавать время работы мотора (например, как долго он должен работать после нажатия кнопки и при сробатывание по таймеру).




Если у кого-то есть идеи или примеры кода для реализации этих функций, буду очень признателен за помощь!

Заранее спасибо!








C++:
const char* ssid     = "Vodafone-946C_plus";
const char* password = "19191919";

#ifdef ESP8266
#include <ESP8266WiFi.h>
#else
#include <WiFi.h>
#endif

#include <LittleFS.h>
#include <GyverDBFile.h>
#include <SettingsGyver.h>
#include <GyverNTP.h>

IPAddress local_IP(192, 168, 0, 125);
IPAddress gateway(192, 168, 0, 1);

IPAddress subnet(255, 255, 255, 0);
IPAddress primaryDNS(8, 8, 8, 8);
IPAddress secondaryDNS(8, 8, 4, 4);

// ===== Инициализация NTP клиента =====
GyverNTP ntp(1);  // Время UTC+1 для зимнего времени Берлина

// База данных для хранения настроек
GyverDBFile db(&LittleFS, "/data.db");

// Указывается заголовок меню, подключается база данных
SettingsGyver sett("ЖАЛЮЗИ", &db);

// Ключи для хранения в базе данных
enum kk : size_t {
  lbl1,    // часы реал. времени
  lbl2,
  timew1,  // Часы открытия
  timew2,  // Часы закрытия
  minw1,   // Минуты открытия
  minw2,   // Минуты закрытия
  datime,
  btn1,
  btn2,
};

// Пины для управления мотором
const int IN1 = 0;  // Замените на нужный пин
const int IN2 = 1;  // Замените на нужный пин

unsigned long startTime = 0;
bool timerActive = false;

unsigned long previousMillis = 0;  // Для отслеживания времени между циклами
const unsigned long interval = 10; // Интервал задержки (раньше 10 мс в delay)

int i = 0;  // Для контроля значений в циклах открытия и закрытия

// Проверка, включено ли летнее время
bool isDST(int day, int month, int hour) {
  if (month < 3 || month > 10) return false;  // Зима, без летнего времени
  if (month > 3 && month < 10) return true;   // Лето, с летним временем
 
  int lastSunday;
 
  // Рассчитываем последнее воскресенье марта
  if (month == 3) {
    lastSunday = 31 - ((5 + (ntp.year() + ntp.year() / 4 + 5) % 7) % 7);
    return (day > lastSunday || (day == lastSunday && hour >= 2));
  }
  // Рассчитываем последнее воскресенье октября
  if (month == 10) {
    lastSunday = 31 - ((2 + (ntp.year() + ntp.year() / 4 + 5) % 7) % 7);
    return !(day > lastSunday || (day == lastSunday && hour < 2));
  }
 
  return false;
}

// Открыть мотор
void handleOpenButton() {
  Serial.println("open");
  digitalWrite(IN1, HIGH);  // Направление вперед
  i = 0;  // Начинаем с 0, чтобы нарастить значение в цикле

  startTime = millis();
  timerActive = true;
}

// Закрыть мотор
void handleCloseButton() {
  Serial.println("close");
  digitalWrite(IN1, LOW);  // Направление назад
  i = 255;  // Начинаем с 255, чтобы уменьшить значение в цикле

  startTime = millis();
  timerActive = true;
}

// Проверка таймера для остановки мотора
void checkTimer() {
  if (timerActive) {
    unsigned long currentMillis = millis();  // Получаем текущее время

    // Если прошло больше 5 секунд, остановить мотор
    if (currentMillis - startTime >= 5000) {
      digitalWrite(IN1, LOW);
#ifdef ESP8266
      ledcWrite(channel, 0);  // Используйте ledcWrite для ESP8266
#else
      analogWrite(IN2, 0);
#endif
      Serial.println("5 seconds passed, stopping motor");
      timerActive = false;
    }

    // Контролируем изменение PWM-сигнала через каждые 10 мс
    if (currentMillis - previousMillis >= interval) {
      previousMillis = currentMillis;

      if (digitalRead(IN1) == HIGH && i <= 255) {
        // Увеличиваем значение для открытия
#ifdef ESP8266
        ledcWrite(channel, i);
#else
        analogWrite(IN2, i);
#endif
        i++;
      } else if (digitalRead(IN1) == LOW && i >= 0) {
        // Уменьшаем значение для закрытия
#ifdef ESP8266
        ledcWrite(channel, i);
#else
        analogWrite(IN2, i);
#endif
        i--;
      }
    }
  }
}

             //====== Билдер настроек======//
void build(sets::Builder& b) {


  b.Label(kk::lbl1, "Время/Дата");
  b.Label(kk::lbl2, "millis()", "", sets::Colors::Red);

  if (b.beginGroup("")) {
    if (b.beginMenu("таймер")) {
      b.Time(kk::timew1, "Открыть в");
      b.Time(kk::timew2, "Закрыть в");
      b.endMenu();
    }
    b.endGroup();
  }

  if (b.beginButtons()) {
    if (b.Button(kk::btn1, "Открыть")) {
      handleOpenButton();
    }

    if (b.Button(kk::btn2, "Закрыть", sets::Colors::Blue)) {
      handleCloseButton();
    }
  }

  b.endButtons();
}

             // ======Апдейтер====== //
void update(sets::Updater& upd) {
 
  upd.update(kk::lbl1, NTP.toString());  // Обновляем lbl1 текущим временем
  upd.update(kk::lbl2, millis());
}


             // ======Инициализация======//
void setup() {
  Serial.begin(115200);
  Serial.println();

  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);

                     // Инициализация LittleFS
  LittleFS.begin();

// Настраивает статический IP-адрес
  if (!WiFi.config(local_IP, gateway, subnet, primaryDNS, secondaryDNS)) {
    Serial.println("STA Failed to configure");
  }

                       // ======Инициализация Wi-Fi====== //
// WiFi.mode(WIFI_AP_STA);
  WiFi.begin(ssid, password);
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    delay(500); // здесь задержка допустима, так как это при подключении Wi-Fi
  }
    
 
  Serial.println();
  Serial.print("Connected: ");
  Serial.println(WiFi.localIP());

   NTP.begin(1);

                        // Инициализация базы данных и настроек
  sett.begin();
  sett.onBuild(build);
  sett.onUpdate(update);

  db.begin();
  db.init(kk::timew1, 6);
}

void loop() {                     
  checkTimer();
  sett.tick();
  NTP.tick();
}
Забыл удалить ключи лишних данных из базы. В строках 37 и 38 (minw1, minw2) эти ключи больше не нужны, так как, насколько я понял, база данных может сохранять время целиком.
 
Изменено:

VAF

✩✩✩✩✩✩✩
15 Июл 2023
49
1
Москва
Я примерно сталкиваюсь с такими же вопросами. Мой вывод: надо по возможности избегать использования специальных библиотек, тогда становятся понятны основы. Так с работой шагового двигателя без библиотеки обойтись очень легко. Легко найти пример с устранением дребезга для кнопки и т. п. Поняв основы скетч складывается как пазл.
 
  • Ахах! +1
Реакции: Daniel19