Welcome!
This community is for professionals and enthusiasts of our products and services. Share and discuss the best content and new marketing ideas, build your professional profile and become a better marketer together.
Ardbox Modbus RTU Slave. Solved
Solved.
The input/output names needed to be changed to work with this model. ( Q0_0 -> R1 ).
This fault caused the available number of inputs/outputs to be zero and that's why I couldn't write to the outputs for example.
This code for testing the outputs works:
#include <RS485.h> #include <ModbusRTUSlave.h> #define RS485_RATE 9600UL int digitalOutputsPins[] = {R1, R2, R3, R4, R5, R6}; #define numDigitalOutputs int(sizeof(digitalOutputsPins) / sizeof(int)) bool digitalOutputs[numDigitalOutputs]; // Define the ModbusRTUSlave object with Modbus RTU slave address: 1 ModbusRTUSlave modbus(RS485, 1); void setup() { // put your setup code here, to run once: Serial.begin(9600) ; // Init RS485 RS485.begin(RS485_RATE, HALFDUPLEX, SERIAL_8E1); // Init ModbusTCPSlave object modbus.begin(RS485_RATE); modbus.setCoils(digitalOutputs, numDigitalOutputs); } void loop() { // Process modbus requests modbus.update(); // put your main code here, to run repeatedly: for (int i = 0; i < numDigitalOutputs; ++i) { digitalWrite(digitalOutputsPins[i], digitalOutputs[i]); } }
The test results:
./modpoll -b 9600 -p even -m rtu -a1 -c6 -t0 /dev/ttyUSB0 1 1 0 1 1 1 modpoll 3.9 - FieldTalk(tm) Modbus(R) Master Simulator Copyright (c) 2002-2020 proconX Pty Ltd Visit https://www.modbusdriver.com for Modbus libraries and tools. Protocol configuration: Modbus RTU, FC15 Slave configuration...: address = 1, start reference = 1, count = 6 Communication.........: /dev/ttyUSB0, 9600, 8, 1, even, t/o 1.00 s, poll rate 1000 ms Data type.............: discrete output (coil) Written 6 references.
Old question:
Hello,
I Bought a Ardbox Relay HF+ and was going to use it as a Modbus RTU Slave.
I found some programming examples on github but I can't get it to work.
I had some success when I used the RTU Master examples and could see data being transmitted but when configured as slave I get "Illegal Data Address exception response!". Can't seem to read any data from the slave device.
I have been using modpoll and diagslave from modbusdriver(dot)com and a Schneider PLC for testing.
Is there any more information to find for the modbus slave functions or is the examples the only documentation?
Any tips on how to get it to work?
Regards
Tobias
I tried the example on that page and got it to send traffic as master, but I need to run it as slave.
I tried this code from github and made some smaller adjustment in the communication settings.
Should I specify the registers that I use? I read that reg 9 is linked to 40008. But can't read any?
/*
Copyright (c) 2018 Boot&Work Corp., S.L. All rights reserved
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <RS485.h>
#include <ModbusRTUSlave.h>
#define RS485_RATE 38400UL
// Modbus registers mapping
// This example uses the M-Duino21+ mapping
int digitalOutputsPins[] = {
#if defined(PIN_Q0_4)
Q0_0, Q0_1, Q0_2, Q0_3, Q0_4,
#endif
};
int digitalInputsPins[] = {
#if defined(PIN_I0_6)
I0_0, I0_1, I0_2, I0_3, I0_4, I0_5, I0_6,
#endif
};
int analogOutputsPins[] = {
#if defined(PIN_A0_7)
A0_5, A0_6, A0_7,
#endif
};
int analogInputsPins[] = {
#if defined(PIN_I0_12)
I0_7, I0_8, I0_9, I0_10, I0_11, I0_12,
#endif
};
#define numDigitalOutputs int(sizeof(digitalOutputsPins) / sizeof(int))
#define numDigitalInputs int(sizeof(digitalInputsPins) / sizeof(int))
#define numAnalogOutputs int(sizeof(analogOutputsPins) / sizeof(int))
#define numAnalogInputs int(sizeof(analogInputsPins) / sizeof(int))
bool digitalOutputs[numDigitalOutputs];
bool digitalInputs[numDigitalInputs];
uint16_t analogOutputs[numAnalogOutputs];
uint16_t analogInputs[numAnalogInputs];
// Define the ModbusRTUSlave object with Modbus RTU slave address: 11
ModbusRTUSlave modbus(RS485, 11);
////////////////////////////////////////////////////////////////////////////////////////////////////
void setup() {
Serial.begin(9600UL);
Serial.println("Test!");
// Init variables, inputs and outputs
for (int i = 0; i < numDigitalOutputs; ++i) {
digitalOutputs[i] = false;
digitalWrite(digitalOutputsPins[i], digitalOutputs[i]);
}
for (int i = 0; i < numDigitalInputs; ++i) {
digitalInputs[i] = digitalRead(digitalInputsPins[i]);
}
for (int i = 0; i < numAnalogOutputs; ++i) {
analogOutputs[i] = 0;
analogWrite(analogOutputsPins[i], analogOutputs[i]);
}
for (int i = 0; i < numAnalogInputs; ++i) {
analogInputs[i] = analogRead(analogInputsPins[i]);
}
// Init RS485
RS485.begin(RS485_RATE, HALFDUPLEX, SERIAL_8E1);
// Init ModbusTCPSlave object
modbus.begin(RS485_RATE);
modbus.setCoils(digitalOutputs, numDigitalOutputs);
modbus.setDiscreteInputs(digitalInputs, numDigitalInputs);
modbus.setHoldingRegisters(analogOutputs, numAnalogOutputs);
modbus.setInputRegisters(analogInputs, numAnalogInputs);
}
////////////////////////////////////////////////////////////////////////////////////////////////////
void loop() {
// Update inputs
for (int i = 0; i < numDigitalInputs; ++i) {
digitalInputs[i] = digitalRead(digitalInputsPins[i]);
}
for (int i = 0; i < numAnalogInputs; ++i) {
analogInputs[i] = analogRead(analogInputsPins[i]);
}
// Process modbus requests
modbus.update();
// Update outputs
for (int i = 0; i < numDigitalOutputs; ++i) {
digitalWrite(digitalOutputsPins[i], digitalOutputs[i]);
}
for (int i = 0; i < numAnalogOutputs; ++i) {
analogWrite(analogOutputsPins[i], analogOutputs[i]);
}
}
The test I tried with:
./modpoll -b 38400 -p even -m rtu -a 11 -r 1 /dev/ttyUSB0
modpoll 3.9 - FieldTalk(tm) Modbus(R) Master Simulator
Copyright (c) 2002-2020 proconX Pty Ltd
Visit https://www.modbusdriver.com for Modbus libraries and tools.
Protocol configuration: Modbus RTU, FC3
Slave configuration...: address = 11, start reference = 1, count = 1
Communication.........: /dev/ttyUSB0, 38400, 8, 1, even, t/o 1.00 s, poll rate 1000 ms
Data type.............: 16-bit register, output (holding) register table
-- Polling slave... (Ctrl-C to stop)
Illegal Data Address exception response!
the "Illegal Data Address exception response" is raised when data address of some or all the required entities are not allowed or do not exist in salve. Make sure that you have properly configured the RS-485 parameters (in our examples RS485 is working at a 38400 baud rate for example).
I hope this helps! If not do not hesitate in reaching us at Contact Us
Keep Informed
About This Community
Question tools
Stats
Asked: 1/18/21, 4:27 AM |
Seen: 126 times |
Last updated: 3/4/21, 6:39 AM |
On the following blog you can see all the specifications on which our library is based on. It is explained the format frame of the packets and the Modbus function codes. Although the code is for the Master connections, using the provided example and the code that you have got from the GitHub, you should be able to make some progress.
- Modbus RTU library for industrial automation blog: https://www.industrialshields.com/blog/arduino-industrial-1/post/modbus-rtu-master-library-for-industrial-automation-200
If not, feel free to contact us at support@industrialshields.com