-
Notifications
You must be signed in to change notification settings - Fork 191
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Modbus pass through from TCP to RTU (gateway) #101
Comments
Hello, By the way, if the library if working with |
Hi Your library works great with Thank you for taking my use case into consideration. I imagine the I appreciate your effort and look forward to following and supporting potential progress. Br Eskild |
Adding onGetAny/onSetAny implementation requires massive internal logic changes and additional code that will executed on each request. It's not good approach for this very specific case. Instead I've added some slight helpers to the library code and suggest a bit hacky way.
#include <ModbusRTU.h>
#define SLAVE_ID 1
// Register
#define REGN 10
ModbusRTU mbRTU;
#if defined(ESP32)
#include <WiFi.h>
#include <ModbusTCP.h>
class ModbusMap : public ModbusTCP {
#else
// Ethernet
//#include <UIPEthernet.h> // Replace by Ethernet.h if NOT using ENC28J60 Ethernet adaptor
#include <Ethernet.h>
#include <ModbusEthernet.h>
byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
IPAddress ip(192, 168, 1, 9);
class ModbusMap : public ModbusEthernet {
#endif
public:
TAddress lastRegister;
protected:
TRegister* searchRegister(TAddress addr) override {
lastRegister = addr; // Save real register requested
#if defined(ESP32)
if (addr.isHreg()) // This version overrides only Hregs
return ModbusTCP::searchRegister(HREG(REGN)); // Always return specific register. Next read or write callback will be called against this register.
return ModbusTCP::searchRegister(addr);
#else
return ModbusEthernet::searchRegister(addr);
#endif
}
};
ModbusMap mbTCP;
uint16_t callbackGet(TRegister* reg, uint16_t val) {
uint16_t res = 0xBEEF;
if ( !mbRTU.slave() ) {
mbRTU.readHreg(SLAVE_ID, mbTCP.lastRegister.address, &res); // Note that readHreg is called against saved original register not register passed to callback parameter
while( mbRTU.slave() ) {
mbRTU.task();
}
}
return res;
}
uint16_t callbackSet(TRegister* reg, uint16_t val) {
if ( !mbRTU.slave() ) {
uint16_t res = val;
mbRTU.writeHreg(SLAVE_ID, mbTCP.lastRegister.address, res);
while( mbRTU.slave() ) {
mbRTU.task();
}
}
return val;
}
void setup() {
#if defined(ESP32)
Serial.begin(115200);
Serial1.begin(9600, SERIAL_8N1, 19, 18);
mbRTU.begin(&Serial1, 17);
#else
Serial.begin(9600, SERIAL_8N1);
mbRTU.begin(&Serial);
#endif
mbRTU.master();
#if defined(ESP32)
WiFi.begin("E2", "fOlissio92");
while (WiFi.status() != WL_CONNECTED) {
delay(500);
Serial.print(".");
}
Serial.println("");
Serial.println("WiFi connected");
Serial.println("IP address: ");
Serial.println(WiFi.localIP());
#else
Ethernet.begin(mac, ip);
#endif
mbTCP.server();
mbTCP.addHreg(REGN);
mbTCP.onGetHreg(REGN, callbackGet);
mbTCP.onSetHreg(REGN, callbackSet);
}
void loop() {
mbTCP.task();
delay(50);
} |
Hello, I'm very interested in this topic, the code works so well with default slave unit ID 1. Moreover, Is there any way to set the SLAVE_ID to another value if the UnitID in the MBAP header isn't 01 ? |
There is no easy way to do it with current library version. |
Hi
Thank you for this library. It is very nice to use. I appreciate your effort!
I have an application in mind which is to use an Arduino with Ethernet shield as a pass through device from TCP to RTU (gateway).
This is realized in the sketch below, however it is quite limited due to the max number of registers which can fit into Arduino memory.
Do you think it is possible to use this library to construct a transparent Modbus gateway that does not require pre-definition of registers in the Arduino, but only configuration of slave ID and network configuration (IP, MAC, gateway...)?
I imagine amending the code to implement
OnGetAny
andOnSetAny
callbacks and using these much in the same fashion as my currentcallbackGet
andcallbackSet
. This would eliminate the need to store register information and thus reduce the memory requirement such that it is feasible on an Arduino.Once again thank you for this library.
Br Eskild
How to
Snippet 1: Arduino Gateway
Snippet 2: Arduino RTU slave
Snippet 3: Python test snippet
The text was updated successfully, but these errors were encountered: