Hello
I am setting up an Arduino micro with a ENC28J60 Ethernet module to control a solenoid valve using Modbus. I want the valve to close when the value on a sensor I have setup that is outputting its values using Modbus TCP . My question is using this hardware and this Modbus Library, how do I read in the value coming off my other Modbus device?
Is your other ModBus device a client or a server? Post a link to the manual of that device.
Its a Honeywell Midas Gas Detector
That sensor is a ModBus TCP server, so to get the values you need a ModBus TCP client on your Arduino. The linked library has only support for the server part (in ModBus RTU that part is called a slave).
Are there any other TCP based Arduino Modbus libraries that would work? I am mainly trying to keep things on the network so I can remotely trigger things.
Would this library be suitable? GitHub - luizcantoni/mudbus: Automatically exported from code.google.com/p/mudbus
hairem:
Would this library be suitable? GitHub - luizcantoni/mudbus: Automatically exported from code.google.com/p/mudbus
No, same problem, only implements (part) of a ModBus TCP server.
Are there any other TCP based Arduino Modbus libraries that would work?
I'm only using ModBus RTU (serial variant) myself, so I'm not up-to-date with libraries for the networked version of the protocol.
/*
* return
* - 0 is success
* - negative is comm error
* - positive value is modbus protocol exception code
*/
int modbusRequest(byte uid, unsigned int addr, byte len, short *regs) {
const byte CODE_IX = 7;
const byte ERR_CODE_IX = 8;
const byte LENGTH_IX = 8;
const byte DATA_IX = 9;
int err = modbusConnection();
if (err != 0)
return err;
byte request[] = {0, 1, 0, 0, 0, 6, uid, FNC_READ_REGS, (byte) (addr / 256), (byte) (addr % 256), 0, len};
modbus.write(request, sizeof(request));
int respDataLen = len * 2;
byte response[max((int) DATA_IX, respDataLen)];
int readLen = modbus.readBytes(response, DATA_IX);
if (readLen < DATA_IX) {
modbus.stop();
return MODBUS_NO_RESPONSE;
}
switch (response[CODE_IX]) {
case FNC_READ_REGS:
break;
case (FNC_ERR_FLAG | FNC_READ_REGS):
return response[ERR_CODE_IX]; // 0x01, 0x02, 0x03 or 0x11
default:
return -3;
}
if (response[LENGTH_IX] != respDataLen)
return -2;
readLen = modbus.readBytes(response, respDataLen);
if (readLen < respDataLen)
return -4;
for (int i = 0, j = 0; i < len; i++, j += 2) {
regs[i] = response[j] * 256 + response[j + 1];
}
return 0;
}
int modbusWriteSingle(unsigned int address, int val) {
const byte CODE_IX = 7;
const byte ERR_CODE_IX = 8;
const byte RESPONSE_LENGTH = 9;
int err = modbusConnection();
if (err != 0)
return err;
byte req[] = { 0, 1, 0, 0, 0, 6, 1, FNC_WRITE_SINGLE, // header
(byte) (address / 256), (byte) (address % 256),
(byte) (val / 256), (byte) (val % 256)};
modbus.write(req, sizeof(req));
byte response[RESPONSE_LENGTH];
int readLen = modbus.readBytes(response, RESPONSE_LENGTH);
if (readLen < RESPONSE_LENGTH) {
modbus.stop();
return MODBUS_NO_RESPONSE;
}
switch (response[CODE_IX]) {
case FNC_WRITE_SINGLE:
break;
case (FNC_ERR_FLAG | FNC_WRITE_SINGLE):
return response[ERR_CODE_IX]; // 0x01, 0x02, 0x03, 0x04 or 0x11
default:
return -3;
}
while (modbus.read() != -1); // 4 more bytes address and reg value
return 0;
}
int modbusConnection() {
if (!modbus.connected()) {
modbus.stop();
if (!modbus.connect(symoAddress, 502))
return MODBUS_CONNECT_ERROR;
modbus.setTimeout(2000);
msg.print(F(" modbus reconnect"));
}
return 0;
}
global variable modbus is EthernetClient or WiFiClient