emelianov / modbus-esp8266

Most complete Modbus library for Arduino. A library that allows your Arduino board to communicate via Modbus protocol, acting as a master, slave or both. Supports network transport (Modbus TCP) and Serial line/RS-485 (Modbus RTU). Supports Modbus TCP Security for ESP8266/ESP32.

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

TCP/IP connection issue

SanPlatano opened this issue · comments

Hi.

Ill try to make a bridge for RTU to TCP but when i use the modbus poll, to check the Modbus TCP, i cant connect with modbus TCP, only with UDP. And i really lost in the port selection, because the modbus poll need this in modbus tcp (or udp). The modbus poll in UDP, always says "timeout error"

`#ifdef ESP8266
#include <ESP8266WiFi.h>
#else ESP32
#include <WiFi.h>
#endif
#include <ModbusIP_ESP8266.h>
#include <ModbusRTU.h>

#define tcp_preg 4
#define tcp_flame 1
#define tcp_rst 1

#define rtu_preg 2
#define rtu_flame 5
#define rtu_rst 0

#define ciclonik_slave 10

ModbusRTU mb;
ModbusIP mbtcp;

bool cb(Modbus::ResultCode event, uint16_t transactionId, void* data) { // Callback to monitor errors
if (event != Modbus::EX_SUCCESS) {
Serial.print("Request result: 0x");
Serial.print(event, HEX);
}
return true;
}

void setup() {
Serial.begin(115200);
pinMode(8,OUTPUT);
Serial1.begin(19200,8E1,18,17);
WiFi.begin("SSID", "PASS);

while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());

mb.begin(&Serial1,8);
mb.client();
mbtcp.server();
mbtcp.addHreg(tcp_preg);
mbtcp.addIsts(tcp_flame);
mbtcp.addCoil(tcp_rst);
}

void loop() {

if (!mb.slave()) {

mb.pullHreg(ciclonik_slave, rtu_preg, tcp_preg); //(slave id, del registro, hacia el registro)
mb.pullIsts(ciclonik_slave, rtu_flame, tcp_flame);
mb.pullCoil(ciclonik_slave, rtu_rst, tcp_rst);
}

mb.task();
mbtcp.task();

}
`

I've make it to work -use example RTU to TCP -i had to made some modification to start working..., but i also want to make bridge work transparently and simultanopusly with program initiated read/write ;)
To make bridge working you must catch raw and transmit it to RTU/TCP

examples/Bridge/TCP-to-RTU-Simulator/TCP-to-RTU-Simulator.ino
(I've removed Stream parts as what i see it isn't used and after below mod it start worked -change mb_tcp to tcp ;))
emodbus library have bridge implemented and it is working, but i've missing there api like addhreg...

This is my changes to example:
Modbus::ResultCode cbTcpRaw(uint8_t* data, uint8_t len, void* custom) {
auto src = (Modbus::frame_arg_t*) custom;
if (disable_MBTCP.state) { //this part check if bool diable_MBTCP.state is true than local transmition is active and return busy to tcp modbus
sprintf(log_chars, PSTR("BUSY BUSY BUSY Bridge Ask from TCP IP: %s MB_ID: %d, Fn: %02X, len: %d"),IPAddress(src->ipaddr).toString(), slaveRunning, data[0], len);
transRunning = 0;
slaveRunning = 0;
mb_tcp.setTransactionId(src->transactionId); // Set transaction id as per incoming request
mb_tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], Modbus::EX_SLAVE_DEVICE_BUSY);
mb_tcp.disconnect(MODBUS_TCP.eventSource());
log_message(log_chars); //send to logs Serial1 and webserial etc...
return Modbus::EX_SLAVE_DEVICE_BUSY;
}

if (transRunning) { // Note that we can't process new requests from TCP-side while waiting for responce from RTU-side.
mb_tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
mb_tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], Modbus::EX_SLAVE_DEVICE_BUSY);
return Modbus::EX_SLAVE_DEVICE_BUSY;
}
bool result_MB_RTU_trans = false;
result_MB_RTU_trans = mb.rawRequest(src->slaveId, data, len, cbRtuTrans);

if (!result_MB_RTU_trans) { //i've added this to reset transrunning and slaverunning to 0
Serial.println("Wrong RTU response");
mb_tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
//Modbus::FunctionCode datatmp = data[0];
mb_tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], cbRtuTransEvent);
mb_tcp.disconnect(mb_tcp.eventSource());
transRunning = 0;
slaveRunning = 0;
return cbRtuTransEvent;
}
if (transRunning) {
mb_tcp.setTransactionId(transRunning); // Set transaction id as per incoming request
#ifndef debugbridge
sprintf(log_chars,PSTR("ERR2 Bridge function src->unitId: %d and send error acknowledge. Trans: %d %d"),src->unitId, transRunning, src->transactionId);
log_message(log_chars);
#endif
//uint16_t succeed = tcp.rawResponce(src->ipaddr, data, len, slaveRunning);
mb_tcp.errorResponce(src->ipaddr, (Modbus::FunctionCode)data[0], Modbus::EX_ACKNOWLEDGE);
return Modbus::EX_ACKNOWLEDGE;
}
transRunning = src->transactionId;
slaveRunning = src->slaveId;
srcIp = src->ipaddr;
log_message((char*)PSTR("Bridge cbTCP_RAW Completed OK. transrunningi claverunning set..."));
return Modbus::EX_SUCCESS;
}

Rest is the same as in example and it works in MODBUS TCP to MODBUS_RTU -all IDs ;)