I need get Arduino to be at the same time Modbus master and slave towards to devices. In a way Arduino should be sort of mediator between.
I am familiar with ModbusMaster library which is quite ok but it does not support slave at all.
ArduinoModbus (which uses ArduinoRS485) can be hacked to use HW serial by modifying RS485.cpp but in that it can only be used with one serial port.
Is there library capable for two HW serial ports, one for master and pone for slave?
ArduinoModbus shouldn't be used on AVR Arduinos, it's designed to be used on MKR Arduinos. It supports multiple serial connections although the usage isn't straightforward then.
Modbus-Master-Slave-for-Arduino (often called ModbusRTU.h) is a rather lightweight implementation of both master and slave in one library. As you didn't specify what requirements you have, recommending a specific library is difficult if not impossible.
Keep in mind that usually the slave part isn't available on the bus while the master part is active on the other bus (to enforce the rather strict timing of Modbus).
The point is to have two separate RS485 busses. One where Arduino behaves as master and another where master. These are with separate HW serial ports too. So, Arduino is real mediator.
The problem is that ArduinoModbus library either is not capable to be used as two instances or that documentation is not sufficient (is there any).
I could not find any example where having two instances.
I tried it in this way (below the names and numbers are examples only)
RS485Class Dev1_RS485(Serial1, 4, 3, 2);
ModbusRTUClientClass Dev1(Dev1_RS485);
This compiles but using Dev1 or Dev2 instances does not work.
I inherited the idea from library code. If using the default ModbusRTUClient instance which is presented inside library code it works fine with Mega and DUE but I need two instances.
It does not work because the code seems to made to support one instance only.
At first I planned to fix the code but library is quite messy and it has some basic problems too. it is not actually made for Modbus because it does not have functions to access the typical data types used by Modbus devices. Of course it is quite easy to make them but this tells about the library.
Libarary has only the traditional single bit and 16bit register types supported while in pretty much every modern device has signed and unsigned 16, 32 and 64bit types as well on top of the basic 16bit registers. Also the string type is not supported as such even though it is used typically for the serial number and firmware version information.
Finally I decided to use two different libraries. One for client and onw for master.
I haven't found any hint in that direction yet. Why do you think that?
I'm quite sure this isn't true. What data types do you miss that a Modbus device should support?
But that stuff isn't part of the Modbus standard and every device manufacturer implements it's own version if it needs such support. You can only hope that he documents that otherwise you'll be surprised when you have to adapt to it.
I've seen quite a few Modbus devices but I found only one device yet to have a string output to Modbus. So expect that feature to be used extremely seldom and definitely not worth supporting it in a general Modbus library.
Might make sense, especially if you're using an AVR Arduino.
More problems with Arduino modbus libraries. Now trying to find slave library that supports more than one range for slave device holding registers. And the library should also work
For example the device I need to use have registers here and there in the register number range in small groups. I need to be able to pretend that device and none of the libraries I tried (and I did read the code) does not support it.
Does anyone know slave library that could be used?
The latest I tried is "Arduinomodbus" which works if all registers are in one range.
I am not sure what do you mean. I mean, I do not see why do you ask such.
But here are some "groups" of the device.
1000...1032H
5000...5034H
5B00..5B32H
8900..8908H
As you can see as one list covering all of them would mean out of memory.
There is need only for holding registers (read by master). So, pretty simple.
because in the post above you didn't specify if you want to read from or write to the slave.
I have a lib which can write to individual registers (FC6/FC16) which don't need to be ascending and can have gaps in the registers. And I just thought if it were worth to invest some more time to add that feature to read from (FC3) also.
Now when xmas holiday is just about to begin I might just pick one library and rewrite it partly.
I have tested that "Arduinomodbus" -library works fine except this one-range limitation. It also uses dynamic memory allocation which is ... if not stupid but anyway odd for such as adruino or other similar fully embedded system without operating system. I mean I as designer know exactly how many registers I need to have there and it is no problem to use some compiler constants to define.
So, removing all such things would simplify implementation too.
so without using a big array of predefined registeres, a user could use two callbacks:
one callback for validation of "valid" (additional, virtual - how ever these could be called) registers
one callback should deliver values to these additional registers
// demo
bool cbIsValidAddress(const uint16_t reg)
{
switch (reg)
{
case 0x1000 ... 0x1032 :
case 0x5000 ... 0x5034 :
case 0x5B00 ... 0x5B32 :
case 0x8900 ... 0x8908 :
return true;
default :
return false;
}
}
// return a value for a register
uint16_t cbRegisterViewed(const uint16_t reg)
{
Serial.print(F("requested additional register adress:")); Serial.println(reg);
switch (reg)
{
case 0x1000: return 0;
case 0x1001: return 1;
case 0x1002: return 2;
case 0x1003: return 3;
case 0x5000: return 0x50;
case 0x5B00: return 0x5B;
case 0x8900: return 0x89;
default: return 0xEEEE;
}
}
Sure such way would work fine but the library I have tries does not support it.
I would rather use table (reg-addr, reg-value) as interface between Modbus "demon" and my code.
The way yo presented is not easy because most of the actual holding register reads are as 2 or 4 words (registers) long (size). I think it is easier to convert logical level values (like uint_64 or uint_32) to Modbus registers and write into register table which can then be used to find value for requested Modbus register. This of course would require more clock cycles than your example.