1-Wire mit ESP32 und Modbus

Einklappen
X
 
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge
  • Sebastian Lorenzen
    Dumb Home'r
    • 13.02.2017
    • 12

    #1

    1-Wire mit ESP32 und Modbus

    Hallo zusammen,

    ich möchte temporär (wobei ja nichts länger hält als ein Provisorium...) ein paar Temperaturen messen und da sich hierfür aus meiner Sicht eine 1-Wire Extension nicht lohnt (und die Kabelverlegung schwierig wäre), habe ich mir ein paar günstige Temperatursensoren (DS18B20) und ein ESP32 DEVKIT besorgt.

    Hiermit kann ich nun die Temperaturen auslesen, auf dem ESP32 in ein Modbus-Register schreiben und mit Loxone auslesen (der ESP32 hängt im WLAN).

    Falls jemand ähnliches sucht:
    1. Den Temperatursensor an 3,3V, Ground und mit dem 1-Wire an PIN4 des DEVKITS anschließen.

    2. Folgenden Sketch in ArduinoIDE flashen und ausführen, der zeigt Euch die Seriennummer(n) des(r) angeschlossenen Temperatursensors(en) in der seriellen Konsole (die brauchen wir, damit nach einem Neustart -bei Verwendung mehrerer Sensoren- die IDs nicht durcheinander kommen):


    Code:
    #include <OneWire.h>
    #include <DallasTemperature.h>
    
    #define ONE_WIRE_BUS 4  // Pin D4 (GPIO4)
    
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    DeviceAddress tempDeviceAddress;
    
    void printAddress(DeviceAddress deviceAddress) {
      for (uint8_t i = 0; i < 8; i++) {
        if (deviceAddress[i] < 16) Serial.print("0");
        Serial.print(deviceAddress[i], HEX);
      }
    }
    
    void setup() {
      Serial.begin(115200);
      delay(1000);
    
      Serial.println("Starte Sensor-Suche...");
      sensors.begin();
    
      int sensorCount = sensors.getDeviceCount();
      Serial.print("Sensoren gefunden: ");
      Serial.println(sensorCount);
    
      for (int i = 0; i < sensorCount; i++) {
        if (sensors.getAddress(tempDeviceAddress, i)) {
          Serial.print("Sensor ");
          Serial.print(i + 1);
          Serial.print(": ");
          printAddress(tempDeviceAddress);
          Serial.println();
        } else {
          Serial.print("Sensor ");
          Serial.print(i + 1);
          Serial.println(": Adresse konnte nicht gelesen werden.");
        }
      }
    }
    
    void loop() {
      // nichts zu tun
    }
    3. Aus der seriellen Konsole der IDE die Seriennummer(n) kopieren.

    4. Die jeweilige(n) Seriennummer(n) in 2er Blöcke aufteilen; aus 280A039D54220894 wird also 28 0A 03 9D 54 22 08 94. Nun vor diese 2er Blöcke jeweils noch 0x dran hängen, ergibt also: 0x28, 0x0A, 0x03, 0x9D, 0x54, 0x22, 0x08, 0x94 -diese Seriennummer wie unten im Code unter "TempSensor knownSensors[] = {" sichtbar einfügen. Wie auch unten im Code zu sehen, kann davor noch der Name des Sensors angegeben werden und am Ende das Modbus-Register.

    5. In den Anführungszeichen hinter ssid und password Eure WLAN-SSID und das dazugehörige Passwort einfügen, nach dem Start und der Verbindung mit dem WLAN wird die zugewiesene IP-Adresse ebenfalls in der seriellen Konsole ausgegeben:


    Code:
    #include <WiFi.h>
    #include <OneWire.h>
    #include <DallasTemperature.h>
    #include <ModbusIP_ESP8266.h>
    
    // WLAN-Zugangsdaten
    const char* ssid = "******";
    const char* password = "*********";
    
    // 1-Wire Bus
    #define ONE_WIRE_BUS 4
    OneWire oneWire(ONE_WIRE_BUS);
    DallasTemperature sensors(&oneWire);
    
    // Modbus
    ModbusIP mb;
    
    // Sensorstruktur
    struct TempSensor {
      const char* name;
      DeviceAddress address;
      uint16_t modbusRegister;
    };
    
    TempSensor knownSensors[] = {
      { "VL_Nele",        { 0x28, 0x0A, 0x03, 0x9D, 0x54, 0x22, 0x08, 0x94 }, 101 },
      { "RL_Nele",        { 0x28, 0x5C, 0x44, 0x81, 0x54, 0x22, 0x09, 0xC4 }, 102 },
      { "VL_SZ",          { 0x28, 0xAE, 0x5E, 0x6D, 0x61, 0x22, 0x07, 0xB6 }, 103 },
      { "RL_SZ",          { 0x28, 0x30, 0xFE, 0x35, 0x61, 0x22, 0x07, 0xE3 }, 104 },
      { "VL_Tom",         { 0x28, 0xE7, 0x0C, 0x54, 0x61, 0x22, 0x07, 0x98 }, 105 },
      { "RL_Tom",         { 0x28, 0xCA, 0xCF, 0x38, 0x61, 0x22, 0x07, 0x8A }, 106 },
      { "VL_Bad",         { 0x28, 0xBB, 0x70, 0x71, 0x61, 0x22, 0x07, 0x76 }, 107 },
      { "RL_Bad",         { 0x28, 0xFC, 0x93, 0x42, 0x61, 0x22, 0x07, 0xD2 }, 108 },
      { "VL_Diele",       { 0x28, 0xAD, 0x9A, 0x5F, 0x61, 0x22, 0x07, 0x9D }, 109 },
      { "RL_Diele",       { 0x28, 0xFE, 0x96, 0xC0, 0x00, 0x00, 0x00, 0x6D }, 110 },
      { "VL_WZ_links",    { 0x28, 0xCE, 0xB0, 0xBC, 0x00, 0x00, 0x00, 0x5E }, 111 },
      { "RL_WZ_links",    { 0x28, 0x0B, 0x6E, 0xBB, 0x00, 0x00, 0x00, 0x50 }, 112 },
      { "VL_WZ_rechts",   { 0x28, 0x6E, 0x8C, 0xC0, 0x00, 0x00, 0x00, 0x1D }, 113 },
      { "RL_WZ_rechts",   { 0x28, 0x44, 0x82, 0x50, 0x00, 0x00, 0x00, 0x27 }, 114 },
      { "VL_Küche",       { 0x28, 0x19, 0x17, 0x52, 0x00, 0x00, 0x00, 0x21 }, 115 },
      { "RL_Küche",       { 0x28, 0x85, 0x6F, 0xBC, 0x00, 0x00, 0x00, 0xE2 }, 116 },
      { "VL_Flur",        { 0x28, 0x9A, 0x68, 0xBC, 0x00, 0x00, 0x00, 0xCC }, 117 },
      { "RL_Flur",        { 0x28, 0xFC, 0x49, 0xBB, 0x00, 0x00, 0x00, 0x0E }, 118 },
      { "VL_HKV",         { 0x28, 0x57, 0x7B, 0xBC, 0x00, 0x00, 0x00, 0x2B }, 119 },
      { "RL_HKV",         { 0x28, 0x47, 0xC0, 0xBC, 0x00, 0x00, 0x00, 0x4F }, 120 },
    };
    
    const int NUM_SENSORS = sizeof(knownSensors) / sizeof(knownSensors[0]);
    
    void setup() {
      Serial.begin(115200);
      delay(500);
    
      WiFi.begin(ssid, password);
      Serial.print("Verbinde mit WLAN...");
      while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
      }
      Serial.println("\n WLAN verbunden!");
      Serial.print("IP-Adresse: ");
      Serial.println(WiFi.localIP());
    
      sensors.begin();
      mb.server();  // Modbus TCP Port 502
    
      for (int i = 0; i < NUM_SENSORS; i++) {
        mb.addHreg(knownSensors[i].modbusRegister, 0);
        Serial.printf("Sensor '%s' auf Register %d vorbereitet\n", knownSensors[i].name, knownSensors[i].modbusRegister);
      }
    }
    
    void loop() {
      mb.task();
    
      static unsigned long lastUpdate = 0;
      if (millis() - lastUpdate > 60000) {
        lastUpdate = millis();
        sensors.requestTemperatures();
    
        for (int i = 0; i < NUM_SENSORS; i++) {
          float tempC = sensors.getTempC(knownSensors[i].address);
          int16_t value;
    
          if (tempC != DEVICE_DISCONNECTED_C) {
            value = (int16_t)(tempC * 10.0);  // z. B. 21.3°C → 213
            Serial.printf("%s: %.1f °C → Reg %d\n", knownSensors[i].name, tempC, knownSensors[i].modbusRegister);
          } else {
            value = 1000;  // 1000,0 °C als Fehlerwert
            Serial.printf("%s:  Sensor nicht erreichbar → Reg %d = 1000°C\n", knownSensors[i].name, knownSensors[i].modbusRegister);
          }
    
          mb.Hreg(knownSensors[i].modbusRegister, value);
        }
      }
    }

    6. Der ESP32 liest nun also jede 60sek die Temperatursensoren aus und schreibt diesen Wert in das entsprechende Modbus-Register. Sollte ein Wert nicht gelesen werden können, schreibt er 1000°C in das Register (zur Fehlervisualisierung in Loxone)....

    7. In Loxone die IP Adresse des ESPs mit dem Port 502 verwenden, und als Geräteadresse die 1.

    Viel Spass!
    Gruss,
    Sebastian
    Zuletzt geändert von Sebastian Lorenzen; vor einer Woche.
  • Prof.Mobilux
    Supermoderator
    • 25.08.2015
    • 4986

    #2
    Coole Idee mit dem Modbus. Wusste gar nicht, dass der ESP das so OutOfTheBox kann. Aber wäre es nicht einfacher, die Temperaturen einfach per UDP an Loxone zu senden?
    🇺🇦 Hilfe für die Menschen der Ukraine: https://www.loxforum.com/forum/proje...Cr-die-ukraine


    LoxBerry - Beyond the Limits

    Kommentar

    • Sebastian Lorenzen
      Dumb Home'r
      • 13.02.2017
      • 12

      #3
      Zitat von Prof.Mobilux
      Aber wäre es nicht einfacher, die Temperaturen einfach per UDP an Loxone zu senden?
      Berechtigter Einwand! …aber warum einfach, wenn es auch per Modbus geht? 😂

      Kommentar

      • Thosch
        Dumb Home'r
        • 28.03.2021
        • 22

        #4
        Ich hatte die gleiche Aufgabenstellung und habe dazu den Shelly Uni verwendet. Der kann 1wire Temp Sensoren direkt einlesen.
        Ich kann jetzt über WLAN die Werte einlesen.

        Kommentar

        • Noschvie
          MS Profi
          • 24.09.2018
          • 566

          #5
          Warum nicht mittels Tasmota?

          Kommentar

          Lädt...