sterowanie dzwonkiem sygnałowym

User avatar
malarz
Posts: 506
Joined: Wed Jan 27, 2021 4:04 pm
Been thanked: 2 times

Post

klew wrote: Thu Dec 05, 2024 10:12 am Zasadnicze pytanie brzmi, czy umiesz programować w jakikolwiek języku, a najlepiej w C++?
Zdarzyło mi się :-) To nie będzie problemem w odróżnianiu od lutowania PCB.
Próbuję przerobić pomysły na działające projekty w ArduinoIDE.
User avatar
malarz
Posts: 506
Joined: Wed Jan 27, 2021 4:04 pm
Been thanked: 2 times

Post

Efekt krótkiej analizy kodu SuplaDev i trochę zabawy - nowa klasa AlarmRelay:
* stan na bazie zmiennej (a nie stanu przekaźnika, jak w Relayu)
* stan przekaźnika wykorzystuję do liczenia przełączeń
* brak pamięci (jak padnie podczas nadawania to raczej nie ma sensu kontynuować tylko trzeba jeszcze raz aktywować)
* czas długości pracy przekaźnika (jak czas włączenia schodowego) używam dla całkowitego czasu alarmu (wszystkich powtórzeń)

Code: Select all

/*
 Copyright (C) AC SOFTWARE SP. Z O.O. & malarz

 This program is free software; you can redistribute it and/or
 modify it under the terms of the GNU General Public License
 as published by the Free Software Foundation; either version 2
 of the License, or (at your option) any later version.
 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.
 You should have received a copy of the GNU General Public License
 along with this program; if not, write to the Free Software
 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
*/

/* AlarmRelay class
 * This class is used to turn on the alarm signal
 * by switching relay on and off on selected GPIO
 *   durationAlarm - siren activation time (in sec.)
 *   durationPause - break between sirens (in sec.)
 *   times         - number of signal repetitions
 */

namespace Supla {
namespace Control {
class AlarmRelay : public Relay {
 public:
  AlarmRelay(int pin, int durationAlarm, int durationPause, int times);

  void turnOn(_supla_int_t duration) override;
  void turnOff(_supla_int_t duration) override;
  virtual bool isOn() override;

  void iterateAlways() override;

 protected:
  int AlarmDuration = 0;
  int PauseDuration = 0;
  int AlarmTimes = 0;
  int AlarmOn = 0;
  int CountedSignals = 0;

  uint32_t durationSwitchMs = 0;
};

AlarmRelay::AlarmRelay(int pin, int durationAlarm, int durationPause, int times)
    : Relay(pin){
  AlarmDuration = durationAlarm;
  PauseDuration = durationPause;
  AlarmTimes = times;
}

void AlarmRelay::iterateAlways() {
  if (durationMs && millis() - durationTimestamp > durationMs) {
    toggle();
  }
  if (AlarmOn) {
    if (millis() - durationTimestamp > durationSwitchMs) {
      if (Supla::Io::digitalRead(channel.getChannelNumber(), pin, io) == pinOnValue()) {
        // rzeczywiście włączony
        Supla::Io::digitalWrite(channel.getChannelNumber(), pin, pinOffValue(), io);
        durationSwitchMs += PauseDuration * 1000;
        CountedSignals++;
      } else {
        // rzeczywiście wyłączony
        Supla::Io::digitalWrite(channel.getChannelNumber(), pin, pinOnValue(), io);
        durationSwitchMs += AlarmDuration * 1000;

        // to chyba zbędne, ale umieszczam wyłącznik po odliczeniu
        if (CountedSignals >= AlarmTimes) {
          toggle();
        }
      }
    }
  }
}

void AlarmRelay::turnOn(_supla_int_t duration = 0) {
  SUPLA_LOG_INFO(
            "AlarmRelay[%d] turn ON (%d/%d ms x %d)",
            channel.getChannelNumber(),
            AlarmDuration,
            PauseDuration,
            AlarmTimes);

  durationMs = (AlarmDuration+PauseDuration)*AlarmTimes * 1000;
  durationTimestamp = millis();

  CountedSignals = 0;
  durationSwitchMs = AlarmDuration * 1000;

  Supla::Io::digitalWrite(channel.getChannelNumber(), pin, pinOnValue(), io);

  AlarmOn = 1;
  channel.setNewValue(true);
}

void AlarmRelay::turnOff(_supla_int_t duration) {
  SUPLA_LOG_INFO(
            "AlarmRelay[%d] turn OFF (%d/%d ms x %d)",
            channel.getChannelNumber(),
            AlarmDuration,
            PauseDuration,
            AlarmTimes);

  durationMs = 0;
  durationTimestamp = millis();

  Supla::Io::digitalWrite(channel.getChannelNumber(), pin, pinOffValue(), io);

  AlarmOn = 0;
  channel.setNewValue(false);
}

bool AlarmRelay::isOn() {
  return AlarmOn;
}

};  // namespace Control
};  // namespace Supla
i aktywacja (z przykładu WebInterface):

Code: Select all

  auto r1 = new Supla::Control::AlarmRelay(RELAY_GPIO, 2, 1, 3);
  auto at1 = new Supla::Control::ActionTrigger();
  auto buttonCfgRelay = new Supla::Control::Button(BUTTON_CFG_RELAY_GPIO, true, true);
  buttonCfgRelay->configureAsConfigButton(&SuplaDevice);
  buttonCfgRelay->addAction(Supla::TOGGLE, r1, Supla::ON_CLICK_1);
  at1->setRelatedChannel(r1);
  at1->attach(buttonCfgRelay);
W przykładzie są dwusekundowe sygnały z jednosekundowymi przerwami powtórzone 3 razy. Podpiąłem w cloudzie jako zwykłą lampę. Muszę zmienić sobie ikonkę.

Jak znajdę chwilę to może powalczę aby parametry alarmu wprowadzać przez WebInterface. Przydałoby się pewnie zorganizować coś dla sygnałów o różnej długości elementów, ale chyba na razie tego nie potrzebuję, więc pewnie poczeka na kogoś innego.

Być może czegoś z klas nie uwzględniłem tak jak powinienem, ale przeanalizowałem tylko mały fragment kodu SuplaDev. Testowałem chwilę (w końcu na Sonoff Basic R3 - łatwiej flaschować :-) i chyba jest ok.

malarz
Próbuję przerobić pomysły na działające projekty w ArduinoIDE.

Return to “Ogólna dyskusja”