Codesys Kommunikation mit ESP8266 über Modbus

JaBot

Level-1
Beiträge
2
Reaktionspunkte
0
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo zusammen,
ich bin schon seid längerem dabei meine Wohnung zum Automatisieren. Hierfür nutze ich einen Raspberry auf dem Codesys läuft, sowie mehrere ESP8266 als dezentrale Peripherie. Bislang habe ich ausschließlich Ausgänge gebraucht. Diese habe ich über den Funktionscode 6 (Write Single Regsiter) an die ESP´s weitergegeben. Soweit alles gut.
Nun möchte ich allerdings auch Eingänge in Codesys verarbeiten.
Für die ESP´s habe ich folgenden Code verwendet:
https://domoticx.com/esp8266-wifi-modbus-tcp-ip-slave/
Wenn ich nun die Werte der Holding Register mit einem Modbus Master Simulator beobachte, bekomme ich auch die richtigen Werte heraus (Züfällige Zahl zwischen 0 und 12).
Unbenannt.PNG
Wenn ich mir aber in Codesys über den Funktionscode 3 (Write Holding Register) die Werte anzeigen lasse, bekomme ich keine Werte heraus.
Benutze ich den falsche Funktionscode oder muss ich einen Offset wählen???
Vielen Dank für eure Hilfe. Ich bin mittlerweile echt am verzweifeln...:-|
Grüße Jannik
 
Zuletzt bearbeitet:
Lösung Gefunden:
Der Funktionscode 3 ist doch der richtige. Codesys braucht anscheinend eine Variable, die den Wert des Registers in der POU verarbeitet...
 
Zuviel Werbung?
-> Hier kostenlos registrieren
hallo jannik,

Ich versuche schon seit einiger zeit mit einem ESP32 oder mit einem ESP8266 zu kommunizieren im codesys.

Der Code am ESP läuft, mit Seriell monitor kommen auch werte aber wenn ich dann in meiner SChrittkette den ESP als Modbus TCP hizufüge kommt immer wieder das grüne Symbol mit Socket Error oder Connecting Error.

Nun hab ich deinen Code getestet.. läuft alles stabil obwohl dieselben Biblotheken in meinen Projekt verwendet werden.
(also es werden keine Error Counter gezählt)

Ich möchte eigentlich nur einen DHT11 auswerten und an Codesys übergeben. zusätzlich noch 3 DOUT schalten.

Lässt sich dein Code dafür einfach anpassen oder kannst du mir mal bei meinem Code drüber schauen ob du den Fehler findest?

SG
Wolfi_SPS
 
Hallo,,

Ich hab den code nun grob umgebaut, die verbindung läuft stabil, es gehen keine counter verloren. Nur sollten die Messwerte nach einer Zeit neu aktualisiert werden. dies passiert aber leider nicht. ich hab schon einiges getestet vielleicht hat jemand eine Idee wo der Fehler liegen könnte?

Welches Tool kann ich verwenden um die Modbus TCP Register auszulesen und zu setzen für Tests?

Vielen Dank vorab!

Mein Code:

#include <ESP8266WiFi.h>
#include "DHT.h"

const char* ssid = "----";
const char* password = "----";
int ModbusTCP_port = 502;

///////////////////////DEF Output
const int DOutput1 = 5;//d5 pin board
const int DOutput2 = 4;//d6 pin board
const int DOutput3 = 14;//d7 pin board

#define DHTPIN 5 // Digital PIN D1 !!!!!!!
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);

unsigned long previousMillis = 500; // will store last time DHT was updated

const long interval = 1000; // Updates DHT readings every 10 seconds

float t = 0.0;
float h = 0.0;
float T_max = 0.0;
float T_min = 0.0;
int T_Reg = 0;
int F_Reg = 0;

//////// Required for Modbus TCP / IP /// Requerido para Modbus TCP/IP /////////
#define maxInputRegister 20
#define maxHoldingRegister 20

#define MB_FC_NONE 0
#define MB_FC_READ_REGISTERS 3 //implemented
#define MB_FC_WRITE_REGISTER 6 //implemented
#define MB_FC_WRITE_MULTIPLE_REGISTERS 16 //implemented
//
// MODBUS Error Codes
//
#define MB_EC_NONE 0
#define MB_EC_ILLEGAL_FUNCTION 1
#define MB_EC_ILLEGAL_DATA_ADDRESS 2
#define MB_EC_ILLEGAL_DATA_VALUE 3
#define MB_EC_SLAVE_DEVICE_FAILURE 4
//
// MODBUS MBAP offsets
//
#define MB_TCP_TID 0
#define MB_TCP_PID 2
#define MB_TCP_LEN 4
#define MB_TCP_UID 6
#define MB_TCP_FUNC 7
#define MB_TCP_REGISTER_START 8
#define MB_TCP_REGISTER_NUMBER 10

byte ByteArray[260];
unsigned int MBHoldingRegister[maxHoldingRegister];
//////////////////////////////////////////////////////////////////////////

WiFiServer MBServer(ModbusTCP_port);

void setup() {

pinMode(DOutput1,OUTPUT);
pinMode(DOutput2,OUTPUT);
pinMode(DOutput3,OUTPUT);

Serial.begin(115200); ///9600
dht.begin();

WiFi.begin(ssid, password);
delay(1000);
Serial.println(".");
dht.begin();

while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print("."); }

MBServer.begin();
Serial.println("Connected ");
Serial.print("ESP8266 Slave Modbus TCP/IP ");
Serial.print(WiFi.localIP()); Serial.print(":"); Serial.println(String(ModbusTCP_port));
Serial.println("Modbus TCP/IP Online");
}

void loop() {

unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you updated the DHT values
previousMillis = currentMillis;

float newT = dht.readTemperature();

if (isnan(newT)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
if (T_max < newT ) {
T_max = t;
}
if (newT < T_min ) {
T_min = newT;
}
if (T_min = 0.0) {
T_min = newT;
}

t = newT;
T_Reg = newT * 10;
//MBHoldingRegister[1] = (new_T*10);
//Serial.print("akt.Temp ");
// Serial.println(t);
// Serial.print("max Temp ");
// Serial.println(T_max);
// Serial.print("min Temp ");
//Serial.println(T_min);
//Serial.println("REGISTERWERT");
//Serial.println(T_Reg);
//Serial.println();
}
// Read Humidity
float newH = dht.readHumidity();
// if humidity read failed, don't change h value
if (isnan(newH)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
h = newH;

F_Reg = newH * 10;
//Serial.print("akt.Humidity ");
//Serial.println(h);
//Serial.println();
}
}

// Check if a client has connected // Modbus TCP/IP
WiFiClient client = MBServer.available();
if (!client) { return; }

boolean flagClientConnected = 0;
byte byteFN = MB_FC_NONE;
int Start;
int WordDataLength;
int ByteDataLength;
int MessageLength;

// Modbus TCP/IP
while (client.connected()) {
if(client.available()) {
flagClientConnected = 1;
int i = 0;
while(client.available()) {
ByteArray = client.read();
i++;
}
client.flush();

///// code here --- codigo aqui

///////// Holding Register [0] A [9] = 10 Holding Registers Escritura
///////// Holding Register [0] A [9] = 10 Holding Registers Writing

MBHoldingRegister[0] = currentMillis;
MBHoldingRegister[1] = T_Reg;
MBHoldingRegister[2] = F_Reg;
MBHoldingRegister[3] = random(0,12);
MBHoldingRegister[4] = random(0,12);
MBHoldingRegister[5] = random(0,12);
MBHoldingRegister[6] = random(0,12);
MBHoldingRegister[7] = random(0,12);
MBHoldingRegister[8] = random(0,12);
MBHoldingRegister[9] = random(0,12);

///////// Holding Register [10] A [19] = 10 Holding Registers Lectura
///// Holding Register [10] A [19] = 10 Holding Registers Reading

/// Enable Output

digitalWrite (DOutput1,MBHoldingRegister[3]);
digitalWrite (DOutput2,MBHoldingRegister[4]);
digitalWrite (DOutput3,MBHoldingRegister[5]);

//// debug
for (int i = 0; i < 10; i++) {
Serial.print("[");
Serial.print(i);
Serial.print("] ");
Serial.print(MBHoldingRegister);
}
Serial.println("");
Serial.print("akt.Temp ");
Serial.println(t);
Serial.print("akt.Humidity ");
Serial.println(h);
Serial.println("");

//// end code - fin

//// routine Modbus TCP
byteFN = ByteArray[MB_TCP_FUNC];
Start = word(ByteArray[MB_TCP_REGISTER_START],ByteArray[MB_TCP_REGISTER_START+1]);
WordDataLength = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
}

// Handle request
switch(byteFN) {

case MB_FC_NONE:
break;

case MB_FC_READ_REGISTERS: // 03 Read Holding Registers
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
ByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
for(int i = 0; i < WordDataLength; i++) {
ByteArray[ 9 + i * 2] = highByte(MBHoldingRegister[Start + i]);
ByteArray[10 + i * 2] = lowByte(MBHoldingRegister[Start + i]);
}
MessageLength = ByteDataLength + 9;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;

case MB_FC_WRITE_REGISTER: // 06 Write Holding Register
MBHoldingRegister[Start] = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
ByteArray[5] = 6; //Number of bytes after this one.
MessageLength = 12;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;

case MB_FC_WRITE_MULTIPLE_REGISTERS: //16 Write Holding Registers
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
for(int i = 0; i < WordDataLength; i++) {
MBHoldingRegister[Start + i] = word(ByteArray[ 13 + i * 2],ByteArray[14 + i * 2]);
}
MessageLength = 12;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;
}
}
}
 
Hallo,

so wie das programmiert ist, muß der Modbus TCP Client nach jeder Anfrage disconnecten damit die DHT Werte aktualisiert werden, da er sonst in der inneren Schleife (while (client.connected())) hängen bleibt.

Das ist normalerweise so nicht vorgesehen und wird von Codesys wohl auch nicht gemacht.

Der Modbus Server ist sehr minimalistisch aufgebaut und so schlecht eingebunden (Dauerschleife in Loop()). Das würde in Codesys etc. zu eine Zykluszeitüberschreitung führen.

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Hallo,

nach 2 harte nächten bin ich nun zur selben erkenntnis gekommen.

Ich hab meine dht abfrage mit eigenem zeit intervall (2sek) in die while schleife integriert sodass die register schnell aktualisiert werden jedoch die messwerte vom dht nur alle 2 sek aktualisiert werden.

Läuft soweit stabil.

Jetzt gibt es nur noch das problem dass mein raspi master der mit dem esp8266 kommuniziert die ntp-zeit nicht mehr kennt.

Komisch auch das der update befehl am raspi nicht mehr funkt. Ich hoffe es ist nur das raspi datensystem zerstört...
 
das auslesen der messwerte funktioniert soweit laut auswertung im codesys verliert der modbus slave keine Counter. nur gibt es das Problem das der Messerwert nur ca. für 20min stimmt dann wieder einige stunde nicht mehr. vermutlich wirklich wegen der While schleife.

gibt es eine andere programmierung um die while schleife zu ersetzen?
 
Hallo,

ich würde mal versuchen while (client.connected()) durch ifclient.connected() zu ersetzen. Die loop sorgt ja schon für einen regelmäßigen Durchlauf.

Dann kommt es noch darauf an ob Du mit ESP32 oder ESP8266 arbeitest, ersterer hat natürlich etwas mehr Power besonders wenn es einer mit zwei Kernen ist.

Dazu kommt, daß das schreiben auf die serielle Schnittstelle auch Zeit benötigt, unter anderem auch abhängig von der eingestellten Geschwindigkeit.

Auch ist die Frage wie oft und wieviel Dein Client Daten abfragt.

Eventuell auch mal überlegen auf eine andere Bibliothek umzuisteigen. Diese hier ist ja sehr rudimentär. Habe z.B. diese hier gefunden: https://github.com/eModbus/eModbus auf dem ersten Blick sieht die ganz gut aus.

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke für den input!

Ich werde mal alles auf einen esp32 packen und die baud rate wieder von 115200 auf 9600 stellen. Ich musste eben erhöhen da sonst im serial monitor keine messwerte ankommen am modbus register sind immer konstant messwert angekommen aber eben manchmal die falschen.

Die schrittkette die meine 5 modbusteilnehmer abfragt hat ca. einen takt von 1500 msek.
 
Hi,

höhere baud rate ist hier eigentlich besser als niedrige, da die Daten schneller zur Schnittstelle geliefert werden. Hatte das jetzt oben im Code überlesen. Abfrage alle 1500ms scheint mir jetzt auch nicht so schnell

Sonst zeige noch einmal Deinen aktuellen Code (aber bitte in Code Tags).

Habe hier zufällig noch einen ESP8266 mit DHT22 rumliegen.

Gruß
 
Ich hab jetzt mal alles auf einen ESP 32 gepackt.. bringt auch keine Verbesserung.

//#include <ESP8266WiFi.h> //ESP8266
#include <WiFi.h> //ESP32
#include "DHT.h"

const char* ssid = "xxx";
const char* password = "xxx";
int ModbusTCP_port = 502;
//DEF Output ESP8266
//const int DOutput1 = 14;//d5 pin board
//const int DOutput2 = 0;//d6 pin board
//const int DOutput3 = 2;//d7 pin board
//DEF Output ESP32
const int DOutput1 = 14;// pin board
const int DOutput2 = 13;// pin board
const int DOutput3 = 12;// pin board
unsigned long previousMillis = 0; // will store last time DHT was updated
unsigned long currentMillis = 0;
const long interval = 5000;
#define DHTPIN 5 // Digital PIN D1 ESP8266!!!!!!!
#define DHTPIN 27 // Digital PIN D1 ESP32!!!!!!!
#define DHTTYPE DHT11 // DHT 11 oder DHT 22
DHT dht(DHTPIN, DHTTYPE);
float temp = 0.0;
float hum = 0.0;
float T_max = -100.0;
float T_min = 100.0;
int T_Reg = 0;
int F_Reg = 0;
//////// Required for Modbus TCP / IP /// Requerido para Modbus TCP/IP /////////
#define maxInputRegister 20
#define maxHoldingRegister 20

#define MB_FC_NONE 0
#define MB_FC_READ_REGISTERS 3 //implemented
#define MB_FC_WRITE_REGISTER 6 //implemented
#define MB_FC_WRITE_MULTIPLE_REGISTERS 16 //implemented
//
// MODBUS Error Codes
//
#define MB_EC_NONE 0
#define MB_EC_ILLEGAL_FUNCTION 1
#define MB_EC_ILLEGAL_DATA_ADDRESS 2
#define MB_EC_ILLEGAL_DATA_VALUE 3
#define MB_EC_SLAVE_DEVICE_FAILURE 4
//
// MODBUS MBAP offsets
//
#define MB_TCP_TID 0
#define MB_TCP_PID 2
#define MB_TCP_LEN 4
#define MB_TCP_UID 6
#define MB_TCP_FUNC 7
#define MB_TCP_REGISTER_START 8
#define MB_TCP_REGISTER_NUMBER 10

byte ByteArray[260];
unsigned int MBHoldingRegister[maxHoldingRegister];

WiFiServer MBServer(ModbusTCP_port);
void setup() {

pinMode (DOutput1, OUTPUT);
pinMode (DOutput2, OUTPUT);
pinMode (DOutput3, OUTPUT);
Serial.begin(115200);
WiFi.begin(ssid, password);
//delay(1000);
// Serial.println(".");

while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }

MBServer.begin();
Serial.println("Connected ");
Serial.print("ESP8266 Slave Modbus TCP/IP ");
Serial.print(WiFi.localIP()); Serial.print(":"); Serial.println(String(ModbusTCP_port));
Serial.println("Modbus TCP/IP Online");
}

void loop() {

/////////////////////
//Parada.attach_ms(2000,monitoring);
// temp = dht.readTemperature();

// if (isnan(temp)) {
// Serial.println("Failed to read from DHT sensor!");
// }
// else {
// if (T_max < temp ) {
// T_max = temp;
// }
// if (temp < T_min ) {
// T_min = temp;
// }
// T_Reg = temp * 10;

// Serial.print("akt.Temp ");
// Serial.println(temp);
// // Serial.print("max Temp ");
// // Serial.println(T_max);
// // Serial.print("min Temp ");
// //Serial.println(T_min);
// //Serial.println("REGISTERWERT");
// //Serial.println(T_Reg);
// //Serial.println();
// }
// // Read Humidity
// hum = dht.readHumidity();
// // if humidity read failed, don't change h value
// if (isnan(hum)) {
// Serial.println("Failed to read from DHT sensor!");
// }
// else {
// F_Reg = hum * 10;
// Serial.print("akt.Humidity ");
// Serial.println(hum);
// Serial.println();
//}
//////////////////////////////
// Check if a client has connected // Modbus TCP/IP
WiFiClient client = MBServer.available();
if (!client) { return; }

bool flagClientConnected = 0;
byte byteFN = MB_FC_NONE;
int Start;
int WordDataLength;
int ByteDataLength;
int MessageLength;

// Modbus TCP/IP
while (client.connected()) {
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you updated the DHT values
previousMillis = currentMillis;

temp = dht.readTemperature();

if (isnan(temp)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
if (T_max < temp ) {
T_max = temp;
}
if (temp < T_min ) {
T_min = temp;
}
T_Reg = temp * 10;

//Serial.print("akt.Temp ");
//Serial.println(temp);
// Serial.print("max Temp ");
// Serial.println(T_max);
// Serial.print("min Temp ");
//Serial.println(T_min);
//Serial.println("REGISTERWERT");
//Serial.println(T_Reg);
//Serial.println();
}
// Read Humidity
hum = dht.readHumidity();
// if humidity read failed, don't change h value
if (isnan(hum)) {
Serial.println("Failed to read from DHT sensor!");
}
else {
F_Reg = hum * 10;
//Serial.print("akt.Humidity ");
//Serial.println(hum);
//Serial.println();
}
//if (MBHoldingRegister[3] > 0) {
// digitalWrite(DOutput1, HIGH);
// }
}
if (client.available()) {
flagClientConnected = 1;
int i = 0;
while(client.available()) {
ByteArray = client.read();
i++;
}
client.flush();
MBHoldingRegister[0] = T_Reg;;
MBHoldingRegister[1] = F_Reg;
MBHoldingRegister[2] = (2);
digitalWrite(DOutput1, MBHoldingRegister[3]);
digitalWrite(DOutput2, MBHoldingRegister[4]);
digitalWrite(DOutput3, MBHoldingRegister[5]);
MBHoldingRegister[6] = (6);
MBHoldingRegister[7] = (7);
MBHoldingRegister[8] = (8);
MBHoldingRegister[9] = (8);

// Ausgabe MBregister, die benuetzt wurden
for (int i = 0; i < 10; i++) {
Serial.print("[");
Serial.print(i);
Serial.print("] ");
Serial.print(MBHoldingRegister);
}
Serial.println("\n");

//// routine Modbus TCP
byteFN = ByteArray[MB_TCP_FUNC];
Start = word(ByteArray[MB_TCP_REGISTER_START],ByteArray[MB_TCP_REGISTER_START+1]);
WordDataLength = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
}

// Handle request
switch(byteFN) {

case MB_FC_NONE:
break;

case MB_FC_READ_REGISTERS: // 03 Read Holding Registers
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
ByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
for(int i = 0; i < WordDataLength; i++) {
ByteArray[ 9 + i * 2] = highByte(MBHoldingRegister[Start + i]);
ByteArray[10 + i * 2] = lowByte(MBHoldingRegister[Start + i]);
}
MessageLength = ByteDataLength + 9;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;

case MB_FC_WRITE_REGISTER: // 06 Write Holding Register
MBHoldingRegister[Start] = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
ByteArray[5] = 6; //Number of bytes after this one.
MessageLength = 12;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;

case MB_FC_WRITE_MULTIPLE_REGISTERS: //16 Write Holding Registers
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
for(int i = 0; i < WordDataLength; i++) {
MBHoldingRegister[Start + i] = word(ByteArray[ 13 + i * 2],ByteArray[14 + i * 2]);
}
MessageLength = 12;
client.write((const uint8_t *)ByteArray,MessageLength);
byteFN = MB_FC_NONE;
break;
}
}
}
 
Hallo,

mußte gestern erst einmal den Code sortieren und bin dann nicht mehr zum testen gekommen.

Einen Fehler habe ich hier gefunden:
Code:
if (client.available()) {
     flagClientConnected = 1;
     int i = 0;
     while(client.available()) {
       ByteArray = client.read();
        i++;
      }
das muß so heißen
Code:
       ByteArray[i] = client.read();

mehr erst heute Abend

Gruß
 
So, dies hier funktioniert jetzt bei mir:
Code:
#include <ESP8266WiFi.h> //ESP8266
// #include <WiFi.h> //ESP32
#include "Adafruit_Sensor.h"
#include "DHT.h"
const char* ssid = "**";
const char* password = "***";
int ModbusTCP_port = 502;
//DEF Output ESP8266
const int DOutput1 = 14;//d5 pin board
const int DOutput2 = 0;//d6 pin board
const int DOutput3 = 2;//d7 pin board
// DEF Output ESP32
// const int DOutput1 = 14;// pin board
// const int DOutput2 = 13;// pin board
// const int DOutput3 = 12;// pin board
unsigned long previousMillis = 0; // will store last time DHT was updated
unsigned long currentMillis = 0;
const long interval = 5000;
// #define DHTPIN 5 // Digital PIN D1 ESP8266!!!!!!!
#define DHTPIN 4 // Digital PIN D2 ESP8266!!!!!!!
// #define DHTPIN 27 // Digital PIN D1 ESP32!!!!!!!
#define DHTTYPE DHT22 // DHT 11 oder DHT 22
DHT dht(DHTPIN, DHTTYPE);
float temp = 0.0;
float hum = 0.0;
float T_max = -100.0;
float T_min = 100.0;
int T_Reg = 0;
int F_Reg = 0;
//////// Required for Modbus TCP / IP /// Requerido para Modbus TCP/IP /////////
#define maxInputRegister 20
#define maxHoldingRegister 20
#define MB_FC_NONE 0
#define MB_FC_READ_REGISTERS 3 //implemented
#define MB_FC_WRITE_REGISTER 6 //implemented
#define MB_FC_WRITE_MULTIPLE_REGISTERS 16 //implemented
//
// MODBUS Error Codes
//
#define MB_EC_NONE 0
#define MB_EC_ILLEGAL_FUNCTION 1
#define MB_EC_ILLEGAL_DATA_ADDRESS 2
#define MB_EC_ILLEGAL_DATA_VALUE 3
#define MB_EC_SLAVE_DEVICE_FAILURE 4
//
// MODBUS MBAP offsets
//
#define MB_TCP_TID 0
#define MB_TCP_PID 2
#define MB_TCP_LEN 4
#define MB_TCP_UID 6
#define MB_TCP_FUNC 7
#define MB_TCP_REGISTER_START 8
#define MB_TCP_REGISTER_NUMBER 10
byte ByteArray[260];
unsigned int MBHoldingRegister[maxHoldingRegister];
WiFiServer MBServer(ModbusTCP_port);
WiFiClient client;
void setup() {
  pinMode (DOutput1, OUTPUT);
  pinMode (DOutput2, OUTPUT);
  pinMode (DOutput3, OUTPUT);
  Serial.begin(115200);
  dht.begin();
  WiFi.begin(ssid, password);
  //delay(1000);
  // Serial.println(".");
  while (WiFi.status() != WL_CONNECTED) { delay(1000); Serial.print("."); }
  MBServer.begin();
  Serial.println("Connected ");
  Serial.print("ESP8266 Slave Modbus TCP/IP ");
  Serial.print(WiFi.localIP()); Serial.print(":"); Serial.println(String(ModbusTCP_port));
  Serial.println("Modbus TCP/IP Online");
}
void loop() {
  /////////////////////
  //Parada.attach_ms(2000,monitoring);
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis >= interval) {
    // save the last time you updated the DHT values
    previousMillis = currentMillis;
    temp = dht.readTemperature();
    if (isnan(temp)) {
      Serial.println("Failed to read from DHT sensor (temp)!");
    }
    else {
      if (T_max < temp ) {
        T_max = temp;
      }
      if (temp < T_min ) {
        T_min = temp;
      }
      T_Reg = temp * 10;
      
      Serial.print("akt.Temp ");
      Serial.println(temp);
      // Serial.print("max Temp ");
      // Serial.println(T_max);
      // Serial.print("min Temp ");
      //Serial.println(T_min);
      //Serial.println("REGISTERWERT");
      //Serial.println(T_Reg);
      //Serial.println();
      // Read Humidity
      hum = dht.readHumidity();
      // if humidity read failed, don't change h value
      if (isnan(hum)) {
        Serial.println("Failed to read from DHT sensor (hum)!");
      }
      else {
        F_Reg = hum * 10;
        Serial.print("akt.Humidity ");
        Serial.println(hum);
        Serial.println();
      }
    }
  }
  //////////////////////////////
  // Check if a client has connected // Modbus TCP/IP
  // WiFiClient client = MBServer.available();
  // WiFiClient client = MBServer.accept();
  
  if (!client) { client = MBServer.accept(); }
  if (!client) { return; }
  bool flagClientConnected = 0;
  byte byteFN = MB_FC_NONE;
  int Start;
  int WordDataLength;
  int ByteDataLength;
  int MessageLength;
  // Modbus TCP/IP
  if (client.connected()) {
    // Serial.println("Client connected");
    if (client.available()) {
      flagClientConnected = 1;
      int i = 0;
      while(client.available()) {
        ByteArray[i] = client.read();
        i++;
      }
      client.flush();
      
      MBHoldingRegister[0] = T_Reg;;
      MBHoldingRegister[1] = F_Reg;
      MBHoldingRegister[2] = 2;
      MBHoldingRegister[3] = 3;
      MBHoldingRegister[4] = 4;
      MBHoldingRegister[5] = 5;
      MBHoldingRegister[6] = 6;
      MBHoldingRegister[7] = 7;
      MBHoldingRegister[8] = 8;
      MBHoldingRegister[9]++;
      // Ausgabe MBregister, die benuetzt wurden
      for (int i = 0; i < 10; i++) {
        Serial.print("[");
        Serial.print(i);
        Serial.print("]:");
        Serial.print(MBHoldingRegister[i]);
        Serial.print("  ");
      }
      Serial.println("\n");

      //// routine Modbus TCP
      byteFN = ByteArray[MB_TCP_FUNC];
      Start = word(ByteArray[MB_TCP_REGISTER_START],ByteArray[MB_TCP_REGISTER_START+1]);
      WordDataLength = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
    }
    // Handle request
    switch(byteFN) {
      case MB_FC_NONE:
        break;
      case MB_FC_READ_REGISTERS: // 03 Read Holding Registers
        ByteDataLength = WordDataLength * 2;
        ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
        ByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
        for(int i = 0; i < WordDataLength; i++) {
          ByteArray[ 9 + i * 2] = highByte(MBHoldingRegister[Start + i]);
          ByteArray[10 + i * 2] = lowByte(MBHoldingRegister[Start + i]);
        }
        MessageLength = ByteDataLength + 9;
        client.write((const uint8_t *)ByteArray,MessageLength);
        byteFN = MB_FC_NONE;
        break;
      case MB_FC_WRITE_REGISTER: // 06 Write Holding Register
        MBHoldingRegister[Start] = word(ByteArray[MB_TCP_REGISTER_NUMBER],ByteArray[MB_TCP_REGISTER_NUMBER+1]);
        ByteArray[5] = 6; //Number of bytes after this one.
        MessageLength = 12;
        client.write((const uint8_t *)ByteArray,MessageLength);
        byteFN = MB_FC_NONE;
        break;
      case MB_FC_WRITE_MULTIPLE_REGISTERS: //16 Write Holding Registers
        ByteDataLength = WordDataLength * 2;
        ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
        for(int i = 0; i < WordDataLength; i++) {
        
        }
        MessageLength = 12;
        client.write((const uint8_t *)ByteArray,MessageLength);
        byteFN = MB_FC_NONE;
        break;
    }
  }
}

Ist jetzt für ESP8266 mit DHT22 auf D2.

So wie das jetzt programmiert ist, wird nur *ein* Client zur Zeit akzeptiert. Teste hier mit qModMaster, der hält die Verbindung immer geöffnet. Problem war damit, das mit WiFiClient client = MBServer.available(); in loop() jedes Mal ein neuer Client erzeugt wurde, daher hatteich zu Anfang Probleme mit client.connected(). Zusätzlich muß für .available() auch noch Daten anliegen, was bei nur Erstellen einer Verbindung nicht der Fall ist. Daher bin ich auf .accept() ausgewichen.

Probier erst mal aus wie es bei Dir funktioniert.

Ansonsten mal überlegen auf die eModbus Bibliothek von oben umzusteigen.

Gruß
 
Zuviel Werbung?
-> Hier kostenlos registrieren
Danke. Ich habe leider übersehen das du mir was geschickt hast. Ich hab nun auch einiges probiert es scheint nun alles grün zu sein im codesys... Es geht auch keine counter verloren..

Ich werde mal deinen code testen und schauen wo der unterschied liegt. Emodbus wäre natürlich sehr interesant wenn es stabiler läuft.. 👍

Ich werde nun mehrere esp einbinden in mein projekt. Problem nur noch dass sich immer wieder die ip adresse ändert. Kann ich die auf dem esp fixieren oder im codesys das ip array über einen parameter anpassen sodass ich nicht immer den code neu hochladen muss...

Vielen dank erstmal.. 👍
 
Hi,

da waren schon diverse Fehler in dem Code von Dir. Hattest Du da Teile von Deinem Originalcode für das Forum zusammenkopiert? Ist ja egal, Du hast es zum Laufen bekommen.

Grundsätzlich ist der ganze Code recht unterdurchschnittlich, das beginnt schon mit der Basis des Code. Da ist der Rest nur Anfängerfehler.

Ich habe nur erst einmal versucht das Programm zum Laufen zu bekommen und habe die Behandlung von Anfragen etwas zu verbessern. Aber da sind noch weitere schwerwiegende Fehler im Code, so werden die Daten nicht darauf geprüft ob es wirklich Modbus konforme Anfragen sind. Des weiteren wird bei Bytearray nicht die Länge des Array geprüft. Wenn ein Client nun mehr als 260 Byte schickt wird irgendetwas im Speicher überschrieben. Auch werden die Registeradressen nicht überprüft, so das auch dort auf beliebigen Speicher zum Lesen oder Schreiben zugegriffen werden kann.

Gruß
 
Was läuft denn da nicht? Hatte jetzt einen ESp8266 und DHT22 auf einem anderen Pin verwendet.

Wenn Du nach ESP32 WIFI fixed ip suchst findest Du Beispiele für eine feste IP oder Du machst es über den DHCP Server.

Ich versuch mal ein Beispiel mit emodbus zu machen.

Gruß
 
Hallo,

Anbei sende ich nochmals den aktuelle code der bei mir einwandfrei läuft. es stimmt schon das beim alten code wild kopiert wurde und dadurch vielleicht einige fehler entstanden sind..

Also bei dem Code kommen aktuelle Messdaten die Stimmen und im Codesys wird der Modbus-Slave durchaus grün angezeigt. Es gehen keine Counter verloren...

Ich hab zuletzt nur irgendwie herum probiert plötzlich war es das richtige.(y)

Zum Code:

/* Einbindung von Libraries:
mit <LIBRARYNAME> sucht der Präprozessor nach den libraries nur libraries-Ordner (wo sie beim Installieren über den Library Manager abgespeichert werden)
mit "LIBRARYNAME" sucht der Präprozessor nach den libraries zuerst im Ordner, wo das aktuell konmpilierte Programm abgespeichert ist.
Findet er da nichts, sucht er auch im Standard-libraries-Ordner (Libraries im Ordner des aktuellen Programms haben also Priorität,
falls bestimmte Libraries dort und im Standardordner existieren!)
*/
#include <ESP8266WiFi.h> // für ESP8266
//#include <WiFi.h> // ESP32
#include <DHT.h>
const char *ssid = "---";
const char *password = "---";
int ModbusTCP_port = 502;
//DEF Output ESP8266
const int DOutput1 = 14; // d5 pin board
const int DOutput2 = 0; // d6 pin board
const int DOutput3 = 2; // d7 pin board
//DEF Output ESP32
//const int DOutput1 = 14; // d5 pin board
//const int DOutput2 = 12; // d6 pin board
//const int DOutput3 = 13; // d7 pin board
unsigned long previousMillis = 0; // will store last time DHT was updated
unsigned long currentMillis = 0;
const long interval = 3000; // update interval DHT sensor data
#define DHTPIN 5 // Digital PIN D1 ESP8266!!!!!!!
//#define DHTPIN 27 // Digital PIN D1 ESP32!!!!!!!
#define DHTTYPE DHT11 // DHT 11
DHT dht(DHTPIN, DHTTYPE);
float temp = 0.0;
float hum = 0.0;
float T_max = -100.0;
float T_min = 100.0;
//////// Required for Modbus TCP / IP
const byte clientAddress = 1;
const byte maxInputRegister = 20;
const byte maxHoldingRegister = 20;

// Functions: 03/06/16 are 16 bit (analog) input/output registers, 0 is a broadcast to all bus members
const byte MB_FC_NONE = 0;
const byte MB_FC_READ_REGISTERS = 3; //implemented
const byte MB_FC_WRITE_REGISTER = 6; //implemented
const byte MB_FC_WRITE_MULTIPLE_REGISTERS = 16; //implemented

// MODBUS Error Codes (not imlemented here!)
//#define MB_EC_NONE 0
//#define MB_EC_ILLEGAL_FUNCTION 1
//#define MB_EC_ILLEGAL_DATA_ADDRESS 2
//#define MB_EC_ILLEGAL_DATA_VALUE 3
//#define MB_EC_SLAVE_DEVICE_FAILURE 4
// MODBUS MBAP offsets
//const byte MB_TCP_TID = 0; // transaction number, bytes 0+1, not used
//const byte MB_TCP_PID = 2; // protocoll ID (always 0x0000), bytes 2+3, not used
//const byte MB_TCP_LEN = 4; // number of bytes to follow + 2, bytes 4+5, not used here
const byte MB_TCP_UID = 6; // address of the client the message is send to, byte 6
const byte MB_TCP_FUNC = 7; // function, byte 7
const byte MB_TCP_REGISTER_START = 8; // data, 2 bytes (8+9), i.e. 16 bit
const byte MB_TCP_REGISTER_NUMBER = 10; // register, byte 10
int MBHoldingRegister[maxHoldingRegister]; // must not be unsigned if we want to store negative temperature values in here!
WiFiServer MBServer(ModbusTCP_port);

void connectWiFi() {
Serial.println(F("Connecting to WiFi"));
WiFi.begin(ssid, password);
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
MBServer.begin();
Serial.println(F("connected!"));
Serial.print(F("ESP8266 Slave Modbus TCP/IP "));
Serial.print(WiFi.localIP());
Serial.print(":");
Serial.println(String(ModbusTCP_port));
Serial.println(F("Modbus TCP/IP Online"));
}
void setDOutputs() {
digitalWrite(DOutput1, MBHoldingRegister[3]);
digitalWrite(DOutput2, MBHoldingRegister[4]);
digitalWrite(DOutput3, MBHoldingRegister[5]);
}

void readDHT() {
temp = dht.readTemperature();
if (isnan(temp)) {
Serial.println(F("Failed to read temperature from DHT sensor!"));
} else {
if (T_max < temp) {
T_max = temp;
}
if (temp < T_min) {
T_min = temp;
}
MBHoldingRegister[0] = temp * 10;
Serial.print("akt. Temperatur: ");
Serial.print(temp);
Serial.print("\t[Max.: ");
Serial.print(T_max);
Serial.print(" degC\tMin.: ");
Serial.print(T_min);
Serial.println(" degC]");
}
// Read Humidity
hum = dht.readHumidity();
// if humidity read failed, don't change h value
if (isnan(hum)) {
Serial.println(F("Failed to read humidity from DHT sensor!"));
} else {
MBHoldingRegister[1] = hum * 10;
Serial.print("akt. Luftfeuchte: ");
Serial.print(hum);
Serial.println(" %");
}
}
void setup() {
pinMode(DOutput1, OUTPUT);
pinMode(DOutput2, OUTPUT);
pinMode(DOutput3, OUTPUT);
pinMode(LED_BUILTIN, OUTPUT); // LED als Output definieren
digitalWrite(LED_BUILTIN, HIGH); // Switch onboard LED off
Serial.begin(115200);
delay(100);
dht.begin();
connectWiFi();
}

void loop() {
if (WiFi.status() != WL_CONNECTED) {
connectWiFi(); // reconnect to WiFi in case connection has been lost
}
/* Check if a client has connected / Modbus TCP/IP
server.available() gets a client that is connected to the server and has data available for reading.
The connection persists when the returned client object goes out of scope; you can close it by calling client.stop().
*/
WiFiClient client = MBServer.available();
if (!client) {
return; // no client connection available
}
// Modbus TCP/IP
while (client.connected()) {
// read temp and humidity sensor at a predefined interval
currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
// save the last time you updated the DHT values
previousMillis = currentMillis;
readDHT();
}
byte ByteArray[260];
byte commandByte = MB_FC_NONE;
int Start;
int WordDataLength;
int ByteDataLength;
int MessageLength;
int i = 0;
while (client.available()) {
if (i > 259) {
Serial.println(F("Error: Client data does not fit into ByteArray variable!\n"));
return;
}
ByteArray = client.read();
i++;
}
if (i == 0) { // got no data from PLC, skip rest of loop
continue;
}
// Ausgabe MB-Register, die benuetzt wurden (optional, kann weggelassen werden)
// Serial.print("Modbus register: ");
// for (int i = 0; i < 10; i++) {
// Serial.print("[");
// Serial.print(i);
// Serial.print("] ");
// Serial.print(MBHoldingRegister);
// }
// Serial.println();
//// routine Modbus TCP
if (ByteArray[MB_TCP_UID] == clientAddress) {
digitalWrite(LED_BUILTIN, LOW); // turn onboard LED on
Serial.print("Got commands addressed to me...");
commandByte = ByteArray[MB_TCP_FUNC]; // this byte tells the ESP what the Beckhoff wants it to do
Start = word(ByteArray[MB_TCP_REGISTER_START], ByteArray[MB_TCP_REGISTER_START + 1]);
WordDataLength = word(ByteArray[MB_TCP_REGISTER_NUMBER], ByteArray[MB_TCP_REGISTER_NUMBER + 1]);
// Handle request
switch (commandByte) {
case MB_FC_NONE: // do nothing
Serial.println("Nothing to do.");
break;
case MB_FC_READ_REGISTERS: // 03 Read Holding Registers
Serial.println("Read holding registers.");
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
ByteArray[8] = ByteDataLength; //Number of bytes after this one (or number of bytes of data).
for (int i = 0; i < WordDataLength; i++) {
ByteArray[9 + i * 2] = highByte(MBHoldingRegister[Start + i]);
ByteArray[10 + i * 2] = lowByte(MBHoldingRegister[Start + i]);
}
MessageLength = ByteDataLength + 9;
client.write((const uint8_t *)ByteArray, MessageLength);
commandByte = MB_FC_NONE;
break;
case MB_FC_WRITE_REGISTER: // 06 Write Holding Register
Serial.println("Write holding registers.");
MBHoldingRegister[Start] = word(ByteArray[MB_TCP_REGISTER_NUMBER], ByteArray[MB_TCP_REGISTER_NUMBER + 1]);
ByteArray[5] = 6; //Number of bytes after this one.
MessageLength = 12;
client.write((const uint8_t *)ByteArray, MessageLength);
commandByte = MB_FC_NONE;
setDOutputs();
break;
case MB_FC_WRITE_MULTIPLE_REGISTERS: //16 Write Holding Registers
Serial.println("Write multiple holding registers.");
ByteDataLength = WordDataLength * 2;
ByteArray[5] = ByteDataLength + 3; //Number of bytes after this one.
for (int i = 0; i < WordDataLength; i++) {
MBHoldingRegister[Start + i] = word(ByteArray[13 + i * 2], ByteArray[14 + i * 2]);
}
MessageLength = 12;
client.write((const uint8_t *)ByteArray, MessageLength);
commandByte = MB_FC_NONE;
setDOutputs();
break;
}
digitalWrite(LED_BUILTIN, HIGH); // turn onboard LED off
}
Serial.println();
}
}
 
Zurück
Oben