ABB B23 Modbus Stromzählerwerte Mit ESP8266 in Datenbank Schreiben

by Minecrafter211 in Circuits > Microcontrollers

1223 Views, 0 Favorites, 0 Comments

ABB B23 Modbus Stromzählerwerte Mit ESP8266 in Datenbank Schreiben

Screenshot 2023-02-03 at 23-42-33 localhost _ 127.0.0.1 _ iot _ gatewayabb phpMyAdmin 5.2.0.png

Nach elendigem Versuch und Irrtum möchte ich hier mein erlangtes Wissen an Interessierte weitergeben wie man mit einem ESP8266-Microcontroller einen ABB Modbus Stromzähler ausliest und die Werte in eine MySQL-Datenbank schreibt.

Supplies

WhatsApp Image 2023-02-03 at 23.40.54.jpg
  • ESP8266 (z.B. NodeMCU V3)
  • RS485 zu TTL Converter (Ich empfehle die Module OHNE DE/RE Pin)
  • 5V Netzteil (es ginge auch ein 3.3V Netzteil, 5V Netzteile sind aber einfach besser zu kriegen)
  • ABB B23 Stromzähler (Ich verwende den B23 112-100)
  • Drähte, Lötmaterial
  • 2-Fach und 3-Fach Leiterplattenklemmen
  • 2 1x15er Buchsenleisten
  • Lochrasterplatine

Zusammenlöten

WhatsApp Image 2023-02-03 at 23.45.40.jpg
WhatsApp Image 2023-02-03 at 23.45.40-1.jpg
WhatsApp Image 2023-02-03 at 23.45.40-2.jpg

Zuerst alles zusammen bauen, an den RS485 zu TTL Converter empfehle ich eine 3-Fach Leiterplattenklemme zu löten da man dann die RS485-Busleitung bequem anschließen und ggf. auch umändern kann.

Als nächstes die 2 15er Buchsenleisten auf die Stiftleisten des ESP8266 stecken und dann das ganze in die Platine stecken, so sind die Buchsenleisten am Ende grade und genau in dem nötigen Abstand für den ESP.

Im nächsten Schritt eine 2-Fach Leiterplattenklemme in die Nähe des Vin und G-Pins löten und die Brücken löten:

ESP - G an eine Klemme

Bei 5V Netzteil: ESP - Vin an den zweiten Kontakt der Klemme

Bei 3.3V Netzteil: ESP - 3V and den zweiten Klemmenkontakt

Der ESP arbeitet auf 3.3V, hat aber einen 3.3V Regler verbaut um auch über USB bzw. den Vin-Pin die 3.3V zu beziehen.

Dann entweder 2 2-Fach Klemmen zusammenstecken oder eine 4-Fach-Klemme nehmen und parallel zum ESP auf die Platine löten, sodass die Klemmen relativ nah an den Kontakten 3V / G / TX / RX sind (neben dem MicroUSB Anschluss).

Auch hier wieder von den Klemmenkontakten zu den 4 Kontakten am ESP kleine Brücken löten.

Zuletzt 4 möglichst verschiedenfarbige Adern nehmen (ich benutze gerne 0.6/0.8mm Drähte aus Telefonkabel J-Y(St)Y) und an die 4 Kontakte des RS485 Converters löten.

Stromzähler Anschließen

WhatsApp Image 2023-02-03 at 23.49.41.jpg

Achtung: Arbeiten in Unterverteilung oder an 230V/400V können lebensgefährlich sein und sollten nur von Fachpersonal ausgeführt werden. Es sind immer die 5 Sicherheitsregeln einzuhalten!

Ich spreche da aus Erfahrung (selbst mir als Elektriker ist schonmal ein Draht vom RS485 Bus auf die 230V gekommen und hat meinen PC getoastet).

Also zuerst einmal über den Hauptschalter oder den SLS im Zählerschrank die gesamte Verteilung spannungsfrei schalten und mit einem 2-Poligen Spannungsprüfer allpolig die Spannungsfreiheit feststellen oder direkt einen Elektriker beautragen den Zähler einzubauen und entsprechend eine Datenleitung anzuschließen.

Nun die 3 Adern vom Stromzähler an den RS485 Converter anschließen, leider druckt ABB seit Jahren die Klemmbelegung falsch auf die Zähler. Klemme 35 ist GND, Klemme 36 ist A(+) und Klemme 37 ist B(-), ABB hat hier A und B verdreht!

Am Converter sollte der Anschluss selbsterklärend sein an A+, B- und GND auf der dritten Klemme.

Spannungsvesorgung Am ESP Anschließen

WhatsApp Image 2023-02-03 at 23.53.26.jpg

Nun noch einen einfachen Schritt zwischendurch, das Netzteil an die 2-Fach Klemme anschließen welche wir an G ind Vin/3V vom ESP gelötet haben. Auf richtige Polarität achten!

Den ESP Programmieren

ard.PNG

Dafür muss zuerst der ESP von aus den Buchsenleisten gezogen werden, sachte und senkrecht da sonst die Stiftleisten verbiegen und die zu tauschen ist keine schöne Arbeit.

Der ESP muss abgenommen werden da die serielle Schnittstelle die wir für die Kommunikation zum RS485-Converter benutzen auch die ist die mit dem USB-Anschluss den ESP verbunden ist wodurch es beim programmieren mit angeschlossenem RS485-Converter zu Timeouts beim programmieren kommt.

Ich benutze eine Fork von Reaper7's Code zum auslesen von SDM-Stromzählern:

ABB_B23_Energy_Meter-Bibliothek von steefan85

Sollte die Bibliothek nach einem Update Probleme verursachen, schreibt das gerne in die Kommentare dann versuche ich den Code zu updaten.

In der ABB_B23_Config_User.h sind folgende Einstellungen vorgenommen:

#define USE_HARDWARESERIAL
#define ABB_B23_UART_BAUD          9600
#define DERE_PIN                   NOT_A_PIN
#define ABB_B23_UART_CONFIG        SERIAL_8N1

9600 ist die Baudrate die im Stromzähler eingestellt ist für die Kommunikation zwischen dem ESP und dem Zähler, den DERE_Pin benötigen wir bei dem verwendeten RS485-Board nicht da wir dort nicht extra zwischen Empfangen und Senden umschalten müssen.

Nun der Code für den ESP selbst, dafür habe ich das mitgelieferte Beispiel umgeschrieben und ergänzt.

/**
   BasicHTTPClient.ino

    Created on: 24.05.2015

*/

#include <Arduino.h>
#include <ABB_B23.h>              //import ABB_B23 library

#include <ESP8266WiFi.h>
#include <ESP8266WiFiMulti.h>

#include <ESP8266HTTPClient.h>

#include <WiFiClient.h>

ESP8266WiFiMulti WiFiMulti;

#if defined ( USE_HARDWARESERIAL )                                                  //for HWSERIAL
    ABB_B23 ABB_B23(Serial, ABB_B23_UART_BAUD, DERE_PIN, ABB_B23_UART_CONFIG);      //config ABB_B23
#endif

void setup() {
  ABB_B23.begin();              //initialize ABB_B23 communication
  WiFi.mode(WIFI_STA);
  WiFiMulti.addAP("SSID", "PASSWORT");

}

void loop() {
    float U_L1 = ABB_B23.readVal(ABB_U_LN_P1, 2);
    float U_L2 = ABB_B23.readVal(ABB_U_LN_P2, 2);
    float U_L3 = ABB_B23.readVal(ABB_U_LN_P3, 2);
    float U_L12 = ABB_B23.readVal(ABB_U_LL_P12, 2);
    float U_L23 = ABB_B23.readVal(ABB_U_LL_P23, 2);
    float U_L31 = ABB_B23.readVal(ABB_U_LL_P31, 2);
    float I_L1 = ABB_B23.readVal(ABB_I_P1, 2);
    float I_L2 = ABB_B23.readVal(ABB_I_P2, 2);
    float I_L3 = ABB_B23.readVal(ABB_I_P3, 2);
    float P = ABB_B23.readVal(ABB_P_SYSTEM, 2);
    float P_L1 = ABB_B23.readVal(ABB_P_P1, 2);         //P_P1
    float P_L2 = ABB_B23.readVal(ABB_P_P2, 2);         //P_P2
    float P_L3 = ABB_B23.readVal(ABB_P_P3, 2);         //P_P3
    float F = ABB_B23.readVal(ABB_F, 1);         //F
    float P_total = ABB_B23.readVal(ABB_IMPORT_P, 4);   //Total active kWh
    yield();
  // wait for WiFi connection
  if ((WiFiMulti.run() == WL_CONNECTED)) {
    WiFiClient client;
    HTTPClient http;
    Serial.print("[HTTP] begin...\n");
    if (http.begin(client, "http://10.0.0.10/gateway.php?U_L1="+String(U_L1)+"&U_L2="+String(U_L2)+"&U_L3="+String(U_L3)+"&U_L12="+String(U_L12)+"&U_L23="+String(U_L23)+"&U_L31="+String(U_L31)+"&I_L1="+String(I_L1)+"&I_L2="+String(I_L2)+"&I_L3="+String(I_L3)+"&P="+String(P)+"&P_L1="+String(P_L1)+"&P_L2="+String(P_L2)+"&P_L3="+String(P_L3)+"&F="+String(F)+"&P_total="+String(P_total))){
      // start connection and send HTTP header
      int httpCode = http.GET();
      // httpCode will be negative on error
      if (httpCode > 0) {
        // HTTP header has been send and Server response header has been handled
        Serial.printf("[HTTP] GET... code: %d\n", httpCode);
        // file found at server
        if (httpCode == HTTP_CODE_OK || httpCode == HTTP_CODE_MOVED_PERMANENTLY) {
          String payload = http.getString();
          Serial.println(payload);
        }
      } else {
        Serial.printf("[HTTP] GET... failed, error: %s\n", http.errorToString(httpCode).c_str());
      }
      http.end();
    } else {
      Serial.printf("[HTTP} Unable to connect\n");
    }
  }

  delay(10000);
}

Die Funktion ABB_B23.readVal(ABB_......, x) liest über Modbus den gewünschten Wert vom Zähler aus, die insgesamt möglichen Werte sind in der ABB_B23.h zu finden. Anstelle des x wird die Anzahl der Register eingetragen in denen der gewünschte Wert gespeichert ist, ABB gibt diese im B23_User_Manual an (Communication with Modbus).

Der Block

if (http.begin(client, "http://10.0.0.10/gateway.php?U_L1="+String(U_L1)+"&U_L2="+String(U_L2)+"&U_L3="+String(U_L3)+"&U_L12="+String(U_L12)+"&U_L23="+String(U_L23)+"&U_L31="+String(U_L31)+"&I_L1="+String(I_L1)+"&I_L2="+String(I_L2)+"&I_L3="+String(I_L3)+"&P="+String(P)+"&P_L1="+String(P_L1)+"&P_L2="+String(P_L2)+"&P_L3="+String(P_L3)+"&F="+String(F)+"&P_total="+String(P_total))){

ist die HTTP-GET-REQUEST welche der ESP an eine PHP-Datei schickt um die ausgelesenen Daten zu übertragen. Die PHP Datei "gateway.php" liegt bei mir auf meinem PC mit der festen IP-Adresse 10.0.0.10.

Die einzelnen Werte werden zu Strings umgewandelt und in den gesamten abzusendenden String eingefügt. Das PHP-Skript empfängt die Anfrage und zerstückelt diese dann wieder in einzelne Werte welche dann in eine MySQL Datenbank geschrieben werden.

<?php

$servername = "localhost";        //name des Servers, da das Skript auf dem selben Server liegt wie die Datenbank ist hier localhost eingetragen
$username = "datenbank-nutzer";
$password = "datenbank-passwort";
$dbname = "datenbank-name";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
  die("Connection failed: " . $conn->connect_error);
}

$timestamp = time();
$U_L1 = $_GET['U_L1'];
$U_L2 = $_GET['U_L2'];
$U_L3 = $_GET['U_L3'];
$U_L12 = $_GET['U_L12'];
$U_L23 = $_GET['U_L23'];
$U_L31 = $_GET['U_L31'];
$I_L1 = $_GET['I_L1'] / 10;
$I_L2 = $_GET['I_L2'] / 10;
$I_L3 = $_GET['I_L3'] / 10;
$P = $_GET['P'] / 10;
$P_L1 = $_GET['P_L1'] / 10;
$P_L2 = $_GET['P_L2'] / 10;
$P_L3 = $_GET['P_L3'] / 10;
$F = $_GET['F'];
$P_total = $_GET['P_total'];

$sql = "INSERT INTO gatewayabb (U_L1, U_L2, U_L3, U_L12, U_L23, U_L31, I_L1, I_L2, I_L3, P, P_L1, P_L2, P_L3, F, P_total) VALUES ($U_L1, $U_L2, $U_L3, $U_L12, $U_L23, $U_L31, $I_L1, $I_L2, $I_L3, $P, $P_L1, $P_L2, $P_L3, $F, $P_total)";
if ($conn->query($sql) === TRUE) {
  echo "New record created successfully";
} else {
  echo "Error: " . $sql . "<br>" . $conn->error;
}

$conn->close();

?>

Einige ausgelesene Werte müssen noch durch 10 geteilt werden damit die Einheit Volt/Ampere/Watt stimmt.

Jetzt sollte der ESP den Stromzähler auslesen können, wenn der ESP liest sollte der Stromzähler ein Kommunikationssymbol oben links anzeigen und die beiden LED's des RS485 Moduls blinken immer nacheinander (TX -> Anfrage an Zähler, RX -> Antwort vom Zähler).

Die Einträge in der Datenbank könnten nun zB in eine Grafik umgewandelt werden oder per Skript der Stromverbrauch pro Tag/Monat angezeigt werden


Sollten sich irgendwo Fehler eingeschlichen haben oder noch fragen sein gerne in den Kommentaren schreiben, ich werde versuchen zeitnah darauf einzugehen.