Supla na Waveshare ESP32-S3-8DI-8RO

User avatar
klew
Posts: 13905
Joined: Thu Jun 27, 2019 12:16 pm
Location: Wrocław
Has thanked: 134 times
Been thanked: 137 times

Post

Tego typu ekspandery dodaje się jako klasa dziedzicząca po Supła::Io::Base i wtedy normalnie podłączasz sobie gpio z ekspandera do Relay czy do innych klas. Nie trzeba wtedy ręcznie stanów sprawdzać i synchronizować.
Najlepsze suple dla Twojego domu :mrgreen:
radzik_r
Posts: 468
Joined: Sun Aug 11, 2019 5:32 pm
Has thanked: 1 time
Been thanked: 2 times

Post

Dla początkujących osób, które dopiero wchodzą w temat Supli temat kodu i składania tego jak Lego nie jest zapewne łatwe.
To trzeba zrozumieć. Poznać podstawy programowania.
AI (free) jest dobre, żeby przyśpieszyć zabawę, ale nie zastąpi wypluwania gotowego kodu takiego jakiego chcemy za pierwszym razem.
Trzeba Cierpliwości.

Poniżej przykład kanałów wraz z prosta klasą dla ekspandera.

Code: Select all

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

  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.
*/

/**
   @supla-example
   @file RollerShutter.ino
   @brief Example of controlling a roller shutter directly with an ESP8266/ESP32 for SUPLA integration.
   This example demonstrates how to control a roller shutter using dedicated GPIO pins on an ESP device
   for motor control (up/down/stop) and physical buttons for local operation.
   It also includes status LEDs to indicate the state of the roller shutter.
   The system integrates with the SUPLA cloud via Wi-Fi and includes a web server for configuration.
   Network settings are configured via the web interface.
   Users need to adjust GPIO pins for motor control, buttons, and status LEDs in the code.

   @tags roller_shutter, button, relay, esp, esp32, esp8266, wifi, web_interface
*/
/*
  Copyright (C) AC SOFTWARE SP. Z O.O.

  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.
*/

#include <SuplaDevice.h>
#include <supla/control/button.h>
#include <supla/control/pin_status_led.h>
#include <supla/control/relay.h>
#include <supla/control/roller_shutter.h>
#include <supla/device/status_led.h>
#include <supla/element.h>
#include <supla/io.h>
#include <supla/log_wrapper.h>
#include <supla/network/esp32ethspi.h>
#include <supla/network/esp_web_server.h>
#include <supla/network/esp_wifi.h>
#include <supla/network/html/device_info.h>
#include <supla/network/html/ethernet_parameters.h>
#include <supla/network/html/protocol_parameters.h>
#include <supla/network/html/status_led_parameters.h>
#include <supla/network/html/wifi_parameters.h>
#include <supla/storage/littlefs_config.h>

#include <Adafruit_XCA9554.h>


// klasa ekspandera TCA9554AF
namespace Supla {
namespace Io {
class TCA9554AF : public Supla::Io::Base, Supla::Element {
  public:
    TCA9554AF(int32_t address = 0x20, bool pullUp = false)
      : address(address), Supla::Io::Base() {
      if (!expander.begin(address)) {
        SUPLA_LOG_DEBUG("Unable to find TCA9554AF");
      } else {
        SUPLA_LOG_DEBUG("TCA9554AF is connected at address: 0x%x", address);
        isConnected = true;
      }
    }
    void customPinMode(int channelNumber, uint8_t pin, uint8_t mode) override {
      if (isConnected) {
        expander.pinMode(pin, mode);
      }
    }
    void customDigitalWrite(int channelNumber, uint8_t pin, uint8_t val) override {
      if (isConnected) {
        expander.digitalWrite(pin, val);
      }
    }
    int customDigitalRead(int channelNumber, uint8_t pin) override {
      return isConnected ? expander.digitalRead(pin) : 0;
    }

  protected:
    int32_t address;
    ::Adafruit_XCA9554 expander;
    bool isConnected = false;
};
}  // namespace Io
}  // namespace Supla


Supla::ESPWifi wifi;
Supla::LittleFsConfig configSupla;

#define STATUS_LED_GPIO 43
Supla::Device::StatusLed statusLed(STATUS_LED_GPIO, true);  // Inverted state
Supla::EspWebServer suplaServer;

Supla::ESPETHSPI *eth = nullptr;
Supla::Io::TCA9554AF *exp_TCA9554AF = nullptr;

Supla::Control::RollerShutter *rs1 = nullptr;
Supla::Control::RollerShutter *rs2 = nullptr;

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

Supla::Control::Button *buttonOpen1  = nullptr;
Supla::Control::Button *buttonClose1 = nullptr;
Supla::Control::Button *buttonOpen2  = nullptr;
Supla::Control::Button *buttonClose2 = nullptr;

Supla::Control::Button *button1 = nullptr;
Supla::Control::Button *button2 = nullptr;
Supla::Control::Button *button3 = nullptr;
Supla::Control::Button *button4 = nullptr;


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

  // piny magistrali I2C SDA-42, SCL-41
  Wire.begin(42, 41);
  Wire.setClock(400000);

  eth = new Supla::ESPETHSPI(ETH_PHY_W5500, 1, 16, 12, -1, SPI3_HOST, 15, 14, 13);

  exp_TCA9554AF = new Supla::Io::TCA9554AF(0x20);

  new Supla::Html::DeviceInfo(&SuplaDevice);
  new Supla::Html::WifiParameters;
  new Supla::Html::EthernetParameters;
  new Supla::Html::ProtocolParameters;
  new Supla::Html::StatusLedParameters;

  // 2 rolety na pinach ekspandera (Roleta 1: piny 0, 1 i Roleta 2: piny 2, 3)
  rs1 = new Supla::Control::RollerShutter(exp_TCA9554AF, 0, 1);
  rs2 = new Supla::Control::RollerShutter(exp_TCA9554AF, 2, 3);
  rs1->setInitialCaption("roleta-1");
  rs2->setInitialCaption("roleta-2");

  // 4 przekaźniki na pozostałych pinach ekspandera (piny 4, 5, 6, 7)
  relay1 = new Supla::Control::Relay(exp_TCA9554AF, 4, true);
  relay2 = new Supla::Control::Relay(exp_TCA9554AF, 5, true);
  relay3 = new Supla::Control::Relay(exp_TCA9554AF, 6, true);
  relay4 = new Supla::Control::Relay(exp_TCA9554AF, 7, true);

  relay1->getChannel()->setDefault(SUPLA_CHANNELFNC_LIGHTSWITCH);
  relay2->getChannel()->setDefault(SUPLA_CHANNELFNC_LIGHTSWITCH);
  relay3->getChannel()->setDefault(SUPLA_CHANNELFNC_LIGHTSWITCH);
  relay4->getChannel()->setDefault(SUPLA_CHANNELFNC_LIGHTSWITCH);

  relay1->setInitialCaption("przekaźnik-5");
  relay2->setInitialCaption("przekaźnik-6");
  relay3->setInitialCaption("przekaźnik-7");
  relay4->setInitialCaption("przekaźnik-8");

  // Przyciski sterujące roletami piny ESP32 (piny 4, 5, 6, 7)
  buttonOpen1  = new Supla::Control::Button(4, true, true);
  buttonClose1 = new Supla::Control::Button(5, true, true);
  buttonOpen2  = new Supla::Control::Button(6, true, true);
  buttonClose2 = new Supla::Control::Button(7, true, true);

  buttonOpen1->addAction(Supla::OPEN_OR_STOP,   *rs1, Supla::ON_PRESS);
  buttonClose1->addAction(Supla::CLOSE_OR_STOP, *rs1, Supla::ON_PRESS);
  buttonOpen2->addAction(Supla::OPEN_OR_STOP,   *rs2, Supla::ON_PRESS);
  buttonClose2->addAction(Supla::CLOSE_OR_STOP, *rs2, Supla::ON_PRESS);

  // Przyciski piny ESP32 (piny 8, 9, 10, 11)
  button1 = new Supla::Control::Button(8,  true, true);
  button2 = new Supla::Control::Button(9,  true, true);
  button3 = new Supla::Control::Button(10, true, true);
  button4 = new Supla::Control::Button(11, true, true);

  button1->addAction(Supla::TOGGLE, *relay1, Supla::ON_PRESS);
  button2->addAction(Supla::TOGGLE, *relay2, Supla::ON_PRESS);
  button3->addAction(Supla::TOGGLE, *relay3, Supla::ON_PRESS);
  button4->addAction(Supla::TOGGLE, *relay4, Supla::ON_PRESS);

  SuplaDevice.setName("Waveshare-ESP32S3-8DI-8RO");

  SuplaDevice.setInitialMode(Supla::InitialMode::StartInCfgMode);
  SuplaDevice.begin();
}

void loop() {
  SuplaDevice.iterate();
}
User avatar
george1255
Posts: 426
Joined: Fri Sep 02, 2022 8:48 pm
Location: Włodawa
Has thanked: 12 times
Been thanked: 7 times

Post

J4c0PL wrote: Sat Aug 15, 2026 12:13 pm Cześć!

Przepraszam, że temat nie monitorowany, ale udało mi się wypocić wraz z AI taki oto kod. Nie ma strony konfiguracyjnej, więc wszystko tylko z pliku, ale działa, działają wszystkie wejścia w trybie monostabilnym (łączniki dzwonkowe, przyciski, co kto woli) do tego wszystkie wyjścia są sterowane, reszty nie potrzebowałem ale myślę, że coś tam by się udało pewnie wskórać. Wrzucam to co mi się udało wypocić i życzę wszystkim zainteresowanym miłej zabawy z tym fajnym sprzętem :D
Wrzucałem za pomocą Arduino IDE 2.3.7


#include <Arduino.h>
#include <Wire.h>
#include <WiFi.h>
#include <Adafruit_XCA9554.h>

#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/control/virtual_relay.h>
#include <supla/control/button.h>
#include <supla/device/supla_ca_cert.h>

// ------------------- KONFIGURACJA -------------------
const char* ssid = "xxx";
const char* password = "xxx";
#define SUPLA_SERVER "sxxx.supla.org"
#define EMAIL "xxx"

const char AUTHKEY[16] = {xxx};
const char GUID[16] = {xxx};

// DEFINICJA PINÓW DLA WAVESHARE ESP32-S3-ETH-8DI-8RO
#define I2C_SDA 42
#define I2C_SCL 41
#define TCA9554_ADDR 0x20

Adafruit_XCA9554 tca;

const int diPins[8] = {4, 5, 6, 7, 8, 9, 10, 11};

Supla::ESPWifi suplaWifi(ssid, password);

// Używamy standardowego VirtualRelay
Supla::Control::VirtualRelay* myRelays[8];
Supla::Control::Button* myButtons[8];

void setup() {
Serial.begin(115200);
delay(1000);
Serial.println("\n--- START ---");

Wire.begin(I2C_SDA, I2C_SCL);
if (!tca.begin(TCA9554_ADDR, &Wire)) {
Serial.println("❌ Brak ekspandera!");
}

for(int i=0; i<8; i++) {
tca.pinMode(i, OUTPUT);
tca.digitalWrite(i, LOW); // Wyłączone na starcie

// Tworzymy zwykły przekaźnik wirtualny
myRelays = new Supla::Control::VirtualRelay();

// Wejścia DI
pinMode(diPins, INPUT_PULLUP);
myButtons = new Supla::Control::Button(diPins, true, true);
myButtons->addAction(Supla::TOGGLE, myRelays, Supla::ON_PRESS);
}

SuplaDevice.begin(GUID, SUPLA_SERVER, EMAIL, AUTHKEY);
}

void loop() {
SuplaDevice.iterate();

// --- RĘCZNA SYNCHRONIZACJA (To zastępuje niedziałające funkcje) ---
static bool lastStates[8] = {false};
static unsigned long lastSync = 0;

// Sprawdzaj co 50ms czy stan w Supli się zmienił
if (millis() - lastSync > 50) {
lastSync = millis();
for (int i = 0; i < 8; i++) {
bool currentState = myRelays->isOn();
if (currentState != lastStates) {
lastStates = currentState;

// FIZYCZNE STEROWANIE
if (currentState) {
tca.digitalWrite(i, HIGH); // Załącz
Serial.printf("PRZEKAŹNIK %d: FIZYCZNIE ON\n", i);
} else {
tca.digitalWrite(i, LOW); // Wyłącz
Serial.printf("PRZEKAŹNIK %d: FIZYCZNIE OFF\n", i);
}
}
}
}
}


uzywaj
to prezentacji wszelkiego kodu

Return to “Pomoc”