[PORADNIK] Arduino IDE

[email protected]
Posts: 1584
Joined: Mon Feb 06, 2023 8:56 am
Has thanked: 18 times
Been thanked: 26 times

Post

krzychunh wrote: Sat Jan 17, 2026 8:40 pm Wyrzuciłem wpis sps30 i oto jest efekt. Zastanawiam się w czym może być problem

Image
A masz go ? Może jest na innym adresie
User avatar
Bania
Posts: 107
Joined: Wed Jul 24, 2024 5:03 pm
Location: Bielsko-Biała
Has thanked: 5 times
Been thanked: 5 times

Post

Z jakiej biblioteki korzystasz dla sps30?
https://github.com/Sensirion/arduino-av ... -i2c-sps30
https://github.com/anarhbania/Supla
User avatar
malarz
Posts: 506
Joined: Wed Jan 27, 2021 4:04 pm
Been thanked: 2 times

Post

krzychunh wrote: Sat Jan 17, 2026 12:09 pm
klew wrote: Sat Jan 17, 2026 10:10 am Problem widać w:
-> LittleFsConfig: init called on non empty database. Aborting

Pokaż kod tych Twoich klas, które dodałeś do Supli.

Zgaduję że w konstruktorze coś do Config dodajesz I potem się sypie.

Kilka dni temu ktoś miał podobny problem.
Wydaje mi się że dodałem zabezpieczanie na tą sytuację.
Sprawdź na źródłach z brancha main z repo
LightSensor.h

Code: Select all

#include <supla/channel_element.h>
#include "Adafruit_LTR390.h"
#include <supla/sensor/general_purpose_measurement.h>
namespace Supla
{
    namespace Sensor
    {

        class LightSensor : public GeneralPurposeMeasurement
        {
        public:
            LightSensor()
            {
                this->setInitialCaption("Natężenie światła");
                this->setDefaultUnitAfterValue("lx");
            };

            void onInit()
            {
#ifdef normalMode
                ltr = Adafruit_LTR390();
                ltr.begin();
                ltr.setGain(LTR390_GAIN_3);
                ltr.setResolution(LTR390_RESOLUTION_16BIT);
                ltr.setThresholds(100, 1000);
                ltr.configInterrupt(true, LTR390_MODE_ALS);
                ltr.setMode(LTR390_MODE_ALS);
#endif
            }

            double getValue()
            {
                /*
                if (ltr.newDataAvailable())
                {
                  ltr.setMode(LTR390_MODE_UVS);
                  Serial.print("UV data: ");
                  Serial.println(ltr.readUVS());
                }
                */
               #ifdef normalMode
                return ltr.readALS();
                #else
                return 0.0;
                #endif
            
            }

        protected:
            Adafruit_LTR390 ltr;
        };
    };
};
Czy ten kod jest Twojego autorstwa? Może chciałbyś to przerobić na PR do supla-dev?
Reszta chyba jest z GG.
Próbuję przerobić pomysły na działające projekty w ArduinoIDE.
krzychunh
Posts: 53
Joined: Mon Jul 12, 2021 6:23 am

Post

Kod nie jest mojego autorstwa kod pochodzi od rkalwak, https://github.com/rkalwak/WeatherStation , ja staram się ogarnąć to pod suplę 25.11 ;). Jutro posiedzę nad dodaniem Sps30 do kodu w Arduino. Tu na forum są chłopaki, którzy robią czary z kodem, ale niestety nie zawsze mają czas, jak najbardziej to rozumiem i szanuje. Ale zawsze dzięki za choć najmniejszą wskazówkę.

Szkoda, że nie można podejrzeć wygenerowanych kodów źródłowych z Supla Builder -> Krycha, wtedy wszystko było by prostsze.
krzychunh
Posts: 53
Joined: Mon Jul 12, 2021 6:23 am

Post

Bania wrote: Sat Jan 17, 2026 9:40 pm Z jakiej biblioteki korzystasz dla sps30?
https://github.com/Sensirion/arduino-av ... -i2c-sps30
Próbowałem wiele bibliotek, nawet tych z github'a Supla Builder
User avatar
malarz
Posts: 506
Joined: Wed Jan 27, 2021 4:04 pm
Been thanked: 2 times

Post

krzychunh wrote: Sun Jan 18, 2026 9:07 pm Kod nie jest mojego autorstwa kod pochodzi od rkalwak, https://github.com/rkalwak/WeatherStation , ja staram się ogarnąć to pod suplę 25.11 ;). Jutro posiedzę nad dodaniem Sps30 do kodu w Arduino. Tu na forum są chłopaki, którzy robią czary z kodem, ale niestety nie zawsze mają czas, jak najbardziej to rozumiem i szanuje. Ale zawsze dzięki za choć najmniejszą wskazówkę.

Szkoda, że nie można podejrzeć wygenerowanych kodów źródłowych z Supla Builder -> Krycha, wtedy wszystko było by prostsze.
A masz takie same wszystkie czujniki? Usuń z kodu wszystko, czego i tak nie masz w rzeczywistości, bo nie ma sensu abyś je poprawiał.
Próbuję przerobić pomysły na działające projekty w ArduinoIDE.
[email protected]
Posts: 1584
Joined: Mon Feb 06, 2023 8:56 am
Has thanked: 18 times
Been thanked: 26 times

Post

krzychunh wrote: Sun Jan 18, 2026 9:07 pm Kod nie jest mojego autorstwa kod pochodzi od rkalwak, https://github.com/rkalwak/WeatherStation , ja staram się ogarnąć to pod suplę 25.11 ;). Jutro posiedzę nad dodaniem Sps30 do kodu w Arduino. Tu na forum są chłopaki, którzy robią czary z kodem, ale niestety nie zawsze mają czas, jak najbardziej to rozumiem i szanuje. Ale zawsze dzięki za choć najmniejszą wskazówkę.

Szkoda, że nie można podejrzeć wygenerowanych kodów źródłowych z Supla Builder -> Krycha, wtedy wszystko było by prostsze.
https://github.com/krycha88/GUI-Generic ... sirion-sps

Wygląda na to że zmienili nazwę biblioteki ale tu jest ta której użyłem

https://github.com/Sensirion/arduino-av ... properties a tu oryginalna
krzychunh
Posts: 53
Joined: Mon Jul 12, 2021 6:23 am

Post

Chciałbym podzielić się podzielić kodem źródłowym dla Arduino działający pod Supla 25.11 dla SPS30 dla ESP32 Wroom 32, jedynie co pozostaje do skonfigurowania to przycisk konfiguracji
Biblioteka która została użyta to ta, którą wskazał @rkalwak ->

https://github.com/krycha88/GUI-Generic ... sirion-sps

Jeśli macie jakieś uwagi, poprawki chętnie wprowadze.
Dziękuję

Code: Select all

/*
  WebInterface + SPS30 I2C PM Sensory
  SUPLA Device with SPS30 Particulate Matter Sensor
  Copyright (C) AC SOFTWARE SP. Z O.O.
*/

#define STATUS_LED_GPIO 2
#define BUTTON_CFG_RELAY_GPIO 0

// ============================================
// SUPLA DEVICE INCLUDES
// ============================================
#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/control/button.h>
#include <supla/device/status_led.h>
#include <supla/storage/littlefs_config.h>
#include <supla/network/esp_web_server.h>
#include <supla/network/html/device_info.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/events.h>

// ============================================
// PERSISTENT STORAGE
// ============================================
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom;

// ============================================
// SPS30 I2C SENSOR INCLUDES (sensirion-sps)
//  - to jest biblioteka "sensirion-sps" (SPS30)
// ============================================
#include <Wire.h>
#include <sps30.h>                       // sensirion-sps
#include <sensirion_common.h>
#include <sensirion_i2c.h>

// ============================================
// SUPLA: kanały GPM (żeby nie używać GUI-Generic SPS30Sensor.h)
// ============================================
#include <supla/sensor/general_purpose_measurement.h>

// ============================================
// GLOBAL OBJECTS
// ============================================
Supla::ESPWifi wifi;
Supla::LittleFsConfig configSupla;
Supla::Device::StatusLed statusLed(STATUS_LED_GPIO, true);
Supla::EspWebServer suplaServer;

// ============================================
// SUPLA AUTHKEY
// ============================================
// Generate from: https://www.supla.org/arduino/get-authkey
char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {
  0xE2, 0x5C, 0xD7, 0x8D, 0xF1, 0xD1, 0xA7, 0x38,
  0xE1, 0xB9, 0xAF, 0xB6, 0xC1, 0x5A, 0x30, 0xEF
};

// ============================================
// SPS30: pomiary i kanały
//  UWAGA: SPS30 zwraca wartości "kumulacyjne" (<= rozmiar).
//  Dlatego różnice (bin-y) liczymy odejmowaniem:
//    0.5 bin:  NC0p5
//    1.0 bin:  NC1p0 - NC0p5
//    2.5 bin:  NC2p5 - NC1p0
//    4.0 bin:  NC4p0 - NC2p5
//    10 bin:   NC10p0 - NC4p0
// ============================================
static Supla::Sensor::GeneralPurposeMeasurement *chPM005 = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM01  = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM025 = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM04  = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM10  = nullptr;

static bool spsReady = false;
static unsigned long lastSpsReadMs = 0;

// Prosta ochrona przed NaN/INF i “śmieciami”
static double sane(double v) {
  if (isnan(v) || isinf(v)) return NAN;
  // jeśli biblioteka zwróci ewidentny kosmos, utnij
  if (v < 0) return 0;
  if (v > 1000000.0) return NAN; // bardzo wysoko -> potraktuj jako błąd
  return v;
}

static void sps30Init() {
  Serial.println();
  Serial.println("🔥 Initializing SPS30 (sensirion-sps) ...");

  // I2C na ESP32 – nie ruszam Twoich połączeń: SDA=21, SCL=22
  Wire.begin(21, 22);
  Wire.setClock(100000);

  // init warstwy i2c sensirion (używa Wire)
  sensirion_i2c_init();

  // mały delay często pomaga na starcie
  delay(200);

  int16_t ret = sps30_probe();
  if (ret) {
    Serial.print("❌ SPS30 probe failed, ret="); Serial.println(ret);
    spsReady = false;
    return;
  }
  Serial.println("✅ SPS30 found (probe OK)");

  // Start pomiaru (SPS30 startuje i po ~kilku sekundach daje dane)
  ret = sps30_start_measurement();
  if (ret) {
    Serial.print("❌ sps30_start_measurement failed, ret="); Serial.println(ret);
    spsReady = false;
    return;
  }

  Serial.println("✅ SPS30 measurements started");
  spsReady = true;
}

static void sps30ReadAndPublish() {
  if (!spsReady) return;

  // odczyt co 5s (możesz zmienić)
  const unsigned long intervalMs = 5000;
  if (millis() - lastSpsReadMs < intervalMs) return;
  lastSpsReadMs = millis();

  struct sps30_measurement m;
  int16_t ret = sps30_read_measurement(&m);

  // w tej bibliotece często “-2” oznacza “data not ready”
  if (ret) {
    // nie spamuj – ale pokaż czasem
    static uint8_t errCnt = 0;
    if ((errCnt++ % 10) == 0) {
      Serial.print("⚠️ SPS30 read ret="); Serial.println(ret);
    }
    return;
  }

  // Number concentrations (kumulacyjne)
  double nc005  = sane(m.nc_0p5);
  double nc01c  = sane(m.nc_1p0);
  double nc025c = sane(m.nc_2p5);
  double nc04c  = sane(m.nc_4p0);
  double nc10c  = sane(m.nc_10p0);

  // Różnicowe “bin-y” jak w Twoim opisie kanałów
  double bin005 = nc005;
  double bin01  = (isnan(nc01c)  || isnan(nc005))  ? NAN : sane(nc01c  - nc005);
  double bin025 = (isnan(nc025c) || isnan(nc01c))  ? NAN : sane(nc025c - nc01c);
  double bin04  = (isnan(nc04c)  || isnan(nc025c)) ? NAN : sane(nc04c  - nc025c);
  double bin10  = (isnan(nc10c)  || isnan(nc04c))  ? NAN : sane(nc10c  - nc04c);

  // Wysyłka do kanałów SUPLA
  if (chPM005) chPM005->setValue(bin005);
  if (chPM01)  chPM01->setValue(bin01);
  if (chPM025) chPM025->setValue(bin025);
  if (chPM04)  chPM04->setValue(bin04);
  if (chPM10)  chPM10->setValue(bin10);

  // Log kontrolny
  Serial.print("SPS30 bins [#/cm3]: ");
  Serial.print("0.5=");  Serial.print(bin005);
  Serial.print(" 1.0="); Serial.print(bin01);
  Serial.print(" 2.5="); Serial.print(bin025);
  Serial.print(" 4.0="); Serial.print(bin04);
  Serial.print(" 10=");  Serial.println(bin10);
}

// ============================================
// SETUP
// ============================================
void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("========================================");
  Serial.println("🚀 SUPLA WebInterface + SPS30 I2C PM");
  Serial.println("========================================");

  // HTML configuration pages (accessible at 192.168.4.1)
  Serial.println("📱 Creating web config pages...");
  new Supla::Html::DeviceInfo(&SuplaDevice);
  new Supla::Html::WifiParameters;
  new Supla::Html::ProtocolParameters;
  new Supla::Html::StatusLedParameters;

  // Configuration button (GPIO0 = BOOT pin)
  Serial.println("🔘 Setting up config button (GPIO0)...");
  new Supla::Control::Button(BUTTON_CFG_RELAY_GPIO, true, true);

  // ============================================
  // ADD SPS30 PM SENSOR CHANNELS TO SUPLA
  // (bez GUI-Generic SPS30Sensor.h – używamy GPM)
  // ============================================
  Serial.println();
  Serial.println("📊 Adding PM sensor channels to SUPLA...");

  chPM005 = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM01  = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM025 = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM04  = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM10  = new Supla::Sensor::GeneralPurposeMeasurement();

  // Opisy/jednostki (opcjonalnie)
  chPM005->setInitialCaption("PM0.5 bin");
  chPM01 ->setInitialCaption("PM1.0 bin");
  chPM025->setInitialCaption("PM2.5 bin");
  chPM04 ->setInitialCaption("PM4.0 bin");
  chPM10 ->setInitialCaption("PM10 bin");
  // to są liczbowe koncentracje (bin-y) – możesz zmienić na np. "#/cm3"
  chPM005->setDefaultUnitAfterValue("#/cm3");
  chPM01 ->setDefaultUnitAfterValue("#/cm3");
  chPM025->setDefaultUnitAfterValue("#/cm3");
  chPM04 ->setDefaultUnitAfterValue("#/cm3");
  chPM10 ->setDefaultUnitAfterValue("#/cm3");

  Serial.println("   ✅ PM channels added (5x GPM)!");

  // ============================================
  // SPS30 init (sensirion-sps)
  // ============================================
  sps30Init();

  // ============================================
  // (Opcjonalnie) I2C Scanner – zostawiam jak miałeś
  // ============================================
  Serial.println("🔍 I2C Scanner...");
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("I2C device found: 0x"); Serial.println(addr, HEX);
    }
  }
  Serial.println("I2C scan END");
  delay(500);

  // ============================================
  // SUPLA DEVICE CONFIGURATION
  // ============================================
  Serial.println("⚙️  Configuring SUPLA Device...");

  // Force AP mode for initial WiFi setup
  SuplaDevice.setInitialMode(Supla::InitialMode::StartInCfgMode);

  // Start SUPLA Device
  SuplaDevice.begin();

  Serial.println("✅ SUPLA Device started!");

  // ============================================
  // STARTUP COMPLETE
  // ============================================
  Serial.println();
  Serial.println("========================================");
  Serial.println("🌐 SUPLA Configuration AP Ready!");
  Serial.println("   SSID: supla-XXXX (find in WiFi list)");
  Serial.println("   Password: supla123");
  Serial.println("   Web: 192.168.4.1");
  Serial.println();
  Serial.println("📱 Channels:");
  Serial.println("   Ch0: PM0.5  (bin: <=0.5um, number conc.)");
  Serial.println("   Ch1: PM1.0  (bin: 0.5-1.0um, number conc.)");
  Serial.println("   Ch2: PM2.5  (bin: 1.0-2.5um, number conc.) ⭐");
  Serial.println("   Ch3: PM4.0  (bin: 2.5-4.0um, number conc.)");
  Serial.println("   Ch4: PM10   (bin: 4.0-10um, number conc.)");
  Serial.println("   Ch5: LED    (Status)");
  Serial.println("   Ch6: Button (Config)");
  Serial.println("========================================");
  Serial.println();
  Serial.println("⏳ SPS30: pierwsze sensowne dane zwykle po kilku–kilkunastu sekundach od start_measurement()");
}

// ============================================
// MAIN LOOP
// ============================================
void loop() {
  // regularna obsługa SUPLA
  SuplaDevice.iterate();

  // odczyt SPS30 i publikacja do kanałów
  sps30ReadAndPublish();
}
User avatar
Zibi_007
Posts: 3985
Joined: Tue Oct 31, 2023 10:06 pm
Has thanked: 10 times
Been thanked: 31 times

Post

krzychunh wrote: Sat Jan 24, 2026 12:23 pm Chciałbym podzielić się podzielić kodem źródłowym dla Arduino działający pod Supla 25.11 dla SPS30 dla ESP32 Wroom 32, jedynie co pozostaje do skonfigurowania to przycisk konfiguracji
Biblioteka która została użyta to ta, którą wskazał @rkalwak ->

https://github.com/krycha88/GUI-Generic ... sirion-sps

Jeśli macie jakieś uwagi, poprawki chętnie wprowadze.
Dziękuję

Code: Select all

/*
  WebInterface + SPS30 I2C PM Sensory
  SUPLA Device with SPS30 Particulate Matter Sensor
  Copyright (C) AC SOFTWARE SP. Z O.O.
*/

#define STATUS_LED_GPIO 2
#define BUTTON_CFG_RELAY_GPIO 0

// ============================================
// SUPLA DEVICE INCLUDES
// ============================================
#include <SuplaDevice.h>
#include <supla/network/esp_wifi.h>
#include <supla/control/button.h>
#include <supla/device/status_led.h>
#include <supla/storage/littlefs_config.h>
#include <supla/network/esp_web_server.h>
#include <supla/network/html/device_info.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/events.h>

// ============================================
// PERSISTENT STORAGE
// ============================================
#include <supla/storage/eeprom.h>
Supla::Eeprom eeprom;

// ============================================
// SPS30 I2C SENSOR INCLUDES (sensirion-sps)
//  - to jest biblioteka "sensirion-sps" (SPS30)
// ============================================
#include <Wire.h>
#include <sps30.h>                       // sensirion-sps
#include <sensirion_common.h>
#include <sensirion_i2c.h>

// ============================================
// SUPLA: kanały GPM (żeby nie używać GUI-Generic SPS30Sensor.h)
// ============================================
#include <supla/sensor/general_purpose_measurement.h>

// ============================================
// GLOBAL OBJECTS
// ============================================
Supla::ESPWifi wifi;
Supla::LittleFsConfig configSupla;
Supla::Device::StatusLed statusLed(STATUS_LED_GPIO, true);
Supla::EspWebServer suplaServer;

// ============================================
// SUPLA AUTHKEY
// ============================================
// Generate from: https://www.supla.org/arduino/get-authkey
char AUTHKEY[SUPLA_AUTHKEY_SIZE] = {
  0xE2, 0x5C, 0xD7, 0x8D, 0xF1, 0xD1, 0xA7, 0x38,
  0xE1, 0xB9, 0xAF, 0xB6, 0xC1, 0x5A, 0x30, 0xEF
};

// ============================================
// SPS30: pomiary i kanały
//  UWAGA: SPS30 zwraca wartości "kumulacyjne" (<= rozmiar).
//  Dlatego różnice (bin-y) liczymy odejmowaniem:
//    0.5 bin:  NC0p5
//    1.0 bin:  NC1p0 - NC0p5
//    2.5 bin:  NC2p5 - NC1p0
//    4.0 bin:  NC4p0 - NC2p5
//    10 bin:   NC10p0 - NC4p0
// ============================================
static Supla::Sensor::GeneralPurposeMeasurement *chPM005 = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM01  = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM025 = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM04  = nullptr;
static Supla::Sensor::GeneralPurposeMeasurement *chPM10  = nullptr;

static bool spsReady = false;
static unsigned long lastSpsReadMs = 0;

// Prosta ochrona przed NaN/INF i “śmieciami”
static double sane(double v) {
  if (isnan(v) || isinf(v)) return NAN;
  // jeśli biblioteka zwróci ewidentny kosmos, utnij
  if (v < 0) return 0;
  if (v > 1000000.0) return NAN; // bardzo wysoko -> potraktuj jako błąd
  return v;
}

static void sps30Init() {
  Serial.println();
  Serial.println("🔥 Initializing SPS30 (sensirion-sps) ...");

  // I2C na ESP32 – nie ruszam Twoich połączeń: SDA=21, SCL=22
  Wire.begin(21, 22);
  Wire.setClock(100000);

  // init warstwy i2c sensirion (używa Wire)
  sensirion_i2c_init();

  // mały delay często pomaga na starcie
  delay(200);

  int16_t ret = sps30_probe();
  if (ret) {
    Serial.print("❌ SPS30 probe failed, ret="); Serial.println(ret);
    spsReady = false;
    return;
  }
  Serial.println("✅ SPS30 found (probe OK)");

  // Start pomiaru (SPS30 startuje i po ~kilku sekundach daje dane)
  ret = sps30_start_measurement();
  if (ret) {
    Serial.print("❌ sps30_start_measurement failed, ret="); Serial.println(ret);
    spsReady = false;
    return;
  }

  Serial.println("✅ SPS30 measurements started");
  spsReady = true;
}

static void sps30ReadAndPublish() {
  if (!spsReady) return;

  // odczyt co 5s (możesz zmienić)
  const unsigned long intervalMs = 5000;
  if (millis() - lastSpsReadMs < intervalMs) return;
  lastSpsReadMs = millis();

  struct sps30_measurement m;
  int16_t ret = sps30_read_measurement(&m);

  // w tej bibliotece często “-2” oznacza “data not ready”
  if (ret) {
    // nie spamuj – ale pokaż czasem
    static uint8_t errCnt = 0;
    if ((errCnt++ % 10) == 0) {
      Serial.print("⚠️ SPS30 read ret="); Serial.println(ret);
    }
    return;
  }

  // Number concentrations (kumulacyjne)
  double nc005  = sane(m.nc_0p5);
  double nc01c  = sane(m.nc_1p0);
  double nc025c = sane(m.nc_2p5);
  double nc04c  = sane(m.nc_4p0);
  double nc10c  = sane(m.nc_10p0);

  // Różnicowe “bin-y” jak w Twoim opisie kanałów
  double bin005 = nc005;
  double bin01  = (isnan(nc01c)  || isnan(nc005))  ? NAN : sane(nc01c  - nc005);
  double bin025 = (isnan(nc025c) || isnan(nc01c))  ? NAN : sane(nc025c - nc01c);
  double bin04  = (isnan(nc04c)  || isnan(nc025c)) ? NAN : sane(nc04c  - nc025c);
  double bin10  = (isnan(nc10c)  || isnan(nc04c))  ? NAN : sane(nc10c  - nc04c);

  // Wysyłka do kanałów SUPLA
  if (chPM005) chPM005->setValue(bin005);
  if (chPM01)  chPM01->setValue(bin01);
  if (chPM025) chPM025->setValue(bin025);
  if (chPM04)  chPM04->setValue(bin04);
  if (chPM10)  chPM10->setValue(bin10);

  // Log kontrolny
  Serial.print("SPS30 bins [#/cm3]: ");
  Serial.print("0.5=");  Serial.print(bin005);
  Serial.print(" 1.0="); Serial.print(bin01);
  Serial.print(" 2.5="); Serial.print(bin025);
  Serial.print(" 4.0="); Serial.print(bin04);
  Serial.print(" 10=");  Serial.println(bin10);
}

// ============================================
// SETUP
// ============================================
void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial.println();
  Serial.println("========================================");
  Serial.println("🚀 SUPLA WebInterface + SPS30 I2C PM");
  Serial.println("========================================");

  // HTML configuration pages (accessible at 192.168.4.1)
  Serial.println("📱 Creating web config pages...");
  new Supla::Html::DeviceInfo(&SuplaDevice);
  new Supla::Html::WifiParameters;
  new Supla::Html::ProtocolParameters;
  new Supla::Html::StatusLedParameters;

  // Configuration button (GPIO0 = BOOT pin)
  Serial.println("🔘 Setting up config button (GPIO0)...");
  new Supla::Control::Button(BUTTON_CFG_RELAY_GPIO, true, true);

  // ============================================
  // ADD SPS30 PM SENSOR CHANNELS TO SUPLA
  // (bez GUI-Generic SPS30Sensor.h – używamy GPM)
  // ============================================
  Serial.println();
  Serial.println("📊 Adding PM sensor channels to SUPLA...");

  chPM005 = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM01  = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM025 = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM04  = new Supla::Sensor::GeneralPurposeMeasurement();
  chPM10  = new Supla::Sensor::GeneralPurposeMeasurement();

  // Opisy/jednostki (opcjonalnie)
  chPM005->setInitialCaption("PM0.5 bin");
  chPM01 ->setInitialCaption("PM1.0 bin");
  chPM025->setInitialCaption("PM2.5 bin");
  chPM04 ->setInitialCaption("PM4.0 bin");
  chPM10 ->setInitialCaption("PM10 bin");
  // to są liczbowe koncentracje (bin-y) – możesz zmienić na np. "#/cm3"
  chPM005->setDefaultUnitAfterValue("#/cm3");
  chPM01 ->setDefaultUnitAfterValue("#/cm3");
  chPM025->setDefaultUnitAfterValue("#/cm3");
  chPM04 ->setDefaultUnitAfterValue("#/cm3");
  chPM10 ->setDefaultUnitAfterValue("#/cm3");

  Serial.println("   ✅ PM channels added (5x GPM)!");

  // ============================================
  // SPS30 init (sensirion-sps)
  // ============================================
  sps30Init();

  // ============================================
  // (Opcjonalnie) I2C Scanner – zostawiam jak miałeś
  // ============================================
  Serial.println("🔍 I2C Scanner...");
  for (byte addr = 1; addr < 127; addr++) {
    Wire.beginTransmission(addr);
    if (Wire.endTransmission() == 0) {
      Serial.print("I2C device found: 0x"); Serial.println(addr, HEX);
    }
  }
  Serial.println("I2C scan END");
  delay(500);

  // ============================================
  // SUPLA DEVICE CONFIGURATION
  // ============================================
  Serial.println("⚙️  Configuring SUPLA Device...");

  // Force AP mode for initial WiFi setup
  SuplaDevice.setInitialMode(Supla::InitialMode::StartInCfgMode);

  // Start SUPLA Device
  SuplaDevice.begin();

  Serial.println("✅ SUPLA Device started!");

  // ============================================
  // STARTUP COMPLETE
  // ============================================
  Serial.println();
  Serial.println("========================================");
  Serial.println("🌐 SUPLA Configuration AP Ready!");
  Serial.println("   SSID: supla-XXXX (find in WiFi list)");
  Serial.println("   Password: supla123");
  Serial.println("   Web: 192.168.4.1");
  Serial.println();
  Serial.println("📱 Channels:");
  Serial.println("   Ch0: PM0.5  (bin: <=0.5um, number conc.)");
  Serial.println("   Ch1: PM1.0  (bin: 0.5-1.0um, number conc.)");
  Serial.println("   Ch2: PM2.5  (bin: 1.0-2.5um, number conc.) ⭐");
  Serial.println("   Ch3: PM4.0  (bin: 2.5-4.0um, number conc.)");
  Serial.println("   Ch4: PM10   (bin: 4.0-10um, number conc.)");
  Serial.println("   Ch5: LED    (Status)");
  Serial.println("   Ch6: Button (Config)");
  Serial.println("========================================");
  Serial.println();
  Serial.println("⏳ SPS30: pierwsze sensowne dane zwykle po kilku–kilkunastu sekundach od start_measurement()");
}

// ============================================
// MAIN LOOP
// ============================================
void loop() {
  // regularna obsługa SUPLA
  SuplaDevice.iterate();

  // odczyt SPS30 i publikacja do kanałów
  sps30ReadAndPublish();
}
Dzięki, przyda się. Dobra robota :)

Sprawdzałeś wskazania z czymś wiarygodnym?
W sieci opinie są mieszane, a nawet bym powiedział skrajne.
Jedni chwalą, drudzy ganią.
Te kilkadziesiąt złotych to niewiele, ale zanim wydał, to z chęcią posłucham Twojej opinii...
Image Wiesz, że Supla obsługuje Zigbee? Wstąp do Klubu Promila: https://forum.supla.org/viewtopic.php?t=18018
Image Szukasz nowego GG? Jest tutaj: https://forum.supla.org/viewtopic.php?t=18036
[email protected]
Posts: 1584
Joined: Mon Feb 06, 2023 8:56 am
Has thanked: 18 times
Been thanked: 26 times

Post

@Zibi_007 u mnie sądząc po węchu i tym jak słabo widać sąsiadów to dość dobrze pokazywał, ale cena spora

Return to “FAQ / Jak to zrobić”