I've been at this project for months and have decided I need help. Using an Arduino Uno to read specific holding registers on my generator's controller, but keep getting a timeout error. 485MAX chip is in use. I think the code is fine, compiles and runs, but I am wondering if i need to convert the modbus registers in my code to hexadecimal format for it to work properly. Would anyone like to guide me? I've scoured online resources for awhile with no progress to be had. Using Pin 2 of the Uno to control DE/RE on the 485MAX, Uno TX->DI 485MAX, Uno RX->RO 485MAX
#include <ModbusMaster.h>
#include <SoftwareSerial.h> // If using SoftwareSerial for Modbus communication
//Define Pins and Objects.
#define RS485_DE_RE_PIN 2 // Example pin for DE/RE control
#define MODBUS_RX_PIN 8 // Example pin for Modbus RX
#define MODBUS_TX_PIN 7 // Example pin for Modbus TX
SoftwareSerial modbusSerial(MODBUS_RX_PIN, MODBUS_TX_PIN); // If using SoftwareSerial
ModbusMaster node; // Modbus Master object
//• //Pre/Post Transmission Callbacks: Define functions to control the RS485 transceiver's data direction (DE/RE pin):
void preTransmission() {
digitalWrite(RS485_DE_RE_PIN, HIGH); // Enable transmit
}
void postTransmission() {
digitalWrite(RS485_DE_RE_PIN, LOW); // Enable receive
}
//Setup Function.
void setup() {
Serial.begin(19200); // Initialize Serial for debugging output
pinMode(RS485_DE_RE_PIN, OUTPUT);
digitalWrite(RS485_DE_RE_PIN, LOW); // Start in receive mode
modbusSerial.begin(19200); // Initialize SoftwareSerial for Modbus communication (match slave's baud rate)
node.begin(1, modbusSerial); // Initialize ModbusMaster with slave ID (e.g., 1) and serial object(may have to change to just "Serial")
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
//Loop Function (Reading and Printing).
void loop() {
uint8_t result;
uint16_t data[5];//array to store 5 register values
// Example: Read a holding register (function code 0x03)
// Replace 0x01 with the actual register address and 1 with the number of registers to read
result = node.readHoldingRegisters(401102, 1);//holding register for oil pressure
if (result == node.ku8MBSuccess) {
data[0] = node.getResponseBuffer(0); // Get the data from the response buffer (index 0 for the first register)
Serial.print("Engine Oil Pressure: ");
Serial.println(data[0]);
} else {
Serial.print("Modbus read error: ");
Serial.println(result, HEX); // Print error code in hexadecimal
}
delay(500); // Delay between readings
result = node.readHoldingRegisters(401107, 1);//holding register for battery voltage
if (result == node.ku8MBSuccess) {
data[1] = node.getResponseBuffer(1); // Get the data from the response buffer (index 1 for the 2nd register)
Serial.print("Battery Voltage: ");
Serial.println(data[1]);
} else {
Serial.print("Modbus read error: ");
Serial.println(result, HEX); // Print error code in hexadecimal
}
delay(500);//delay between readings
result = node.readHoldingRegisters(401340, 1);//holding register for L-L avg
if (result == node.ku8MBSuccess) {
data[2] = node.getResponseBuffer(2); // Get the data from the response buffer (index 2 for the 3rd register)
Serial.print("AVG L-L Voltage: ");
Serial.println(data[2]);
} else {
Serial.print("Modbus read error: ");
Serial.println(result, HEX); // Print error code in hexadecimal
}
delay(500);//delay between readings
result = node.readHoldingRegisters(401103, 1);//holding register for coolant temp
if (result == node.ku8MBSuccess) {
data[3] = node.getResponseBuffer(3); // Get the data from the response buffer (index 3 for the 4th register)
Serial.print("Coolant Temp: ");
Serial.println(data[3]);
} else {
Serial.print("Modbus read error: ");
Serial.println(result, HEX); // Print error code in hexadecimal
}
delay(500);//delay between readings
result = node.readHoldingRegisters(401506, 1);//holding register for run time
if (result == node.ku8MBSuccess) {
data[4] = node.getResponseBuffer(4); // Get the data from the response buffer (index 4 for the 5th register)
Serial.print("Run Time: ");
Serial.println(data[4]);
} else {
Serial.print("Modbus read error: ");
Serial.println(result, HEX); // Print error code in hexadecimal
}
delay(500);//delay between readings
}
type or paste code here
Then Post your code (using code tags) and how you have your 485Max chip connected and it will greatly improve your chances of someone being able to help you.
Begin by dealing with all the warnings that crop up when you turn the compiler's warning level to ALL.
arduino-cli compile -b arduino:avr:uno --warnings all --output-dir ~/tmp --no-color (in directory: /home/me/Documents/sketchbook/Uno_R3/test)
/home/me/Documents/sketchbook/Uno_R3/test/test.ino: In function 'void loop()':
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:38:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
result = node.readHoldingRegisters(401102, 1);//holding register for oil pressure
^
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:55:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
result = node.readHoldingRegisters(401107, 1);//holding register for battery voltage
^
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:71:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
result = node.readHoldingRegisters(401340, 1);//holding register for L-L avg
^
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:87:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
result = node.readHoldingRegisters(401103, 1);//holding register for coolant temp
^
/home/me/Documents/sketchbook/Uno_R3/test/test.ino:103:51: warning: large integer implicitly truncated to unsigned type [-Woverflow]
result = node.readHoldingRegisters(401506, 1);//holding register for run time
^
In file included from /home/me/Documents/sketchbook/libraries/ModbusMaster/src/ModbusMaster.h:58:0,
from /home/me/Documents/sketchbook/Uno_R3/test/test.ino:1:
/home/me/Documents/sketchbook/libraries/ModbusMaster/src/util/crc16.h: At global scope:
/home/me/Documents/sketchbook/libraries/ModbusMaster/src/util/crc16.h:71:17: warning: 'uint16_t crc16_update(uint16_t, uint8_t)' defined but not used [-Wunused-function]
static uint16_t crc16_update(uint16_t crc, uint8_t a)
^~~~~~~~~~~~
/home/me/Documents/sketchbook/libraries/ModbusMaster/src/ModbusMaster.cpp: In member function 'uint8_t ModbusMaster::requestFrom(uint16_t, uint16_t)':
/home/me/Documents/sketchbook/libraries/ModbusMaster/src/ModbusMaster.cpp:84:44: warning: unused parameter 'address' [-Wunused-parameter]
uint8_t ModbusMaster::requestFrom(uint16_t address, uint16_t quantity)
^~~~~~~
/home/me/Documents/sketchbook/libraries/ModbusMaster/src/ModbusMaster.cpp:94:27: warning: 'read' is used uninitialized in this function [-Wuninitialized]
_u8ResponseBufferLength = read;
~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~
Sketch uses 7996 bytes (24%) of program storage space. Maximum is 32256 bytes.
Global variables use 691 bytes (33%) of dynamic memory, leaving 1357 bytes for local variables. Maximum is 2048 bytes.
Compilation finished successfully.
Okey, thanks. What does the table say at the head? As You said in the post, are they hexadecimal numbers? In Your code they appear as integers but they are too big to fit in a standard integer, -32768 to + 32767 for a 16 bit.
Signed, or unsigned long could be important as well as adding the hex suffix.
Reckon my code should say 1339 instead of 401340? That's what I'm gathering from the manual description anyway. It appears they're saying its 0 based, so -1 from what it's displayed as and omit the 40 prefix as that designates its a holding register and nothing more, am I getting warmer here or not so much?
I'm learning new things already, lol. Thanks. I don't know how to turn on the "ALL" function on my compiler, just using the Arduino IDE. Might try it through Eclipse later when I'm home. Appreciate the help.
so I changed the registers in my code, omitted the 40 and my theory proved incorrect. still no communication between devices. I'm open to any ideas at this point. I didn't think this would be a difficult project....
When you get timeout, it's quite surely not related to wrong address. Correctly made slave should give an other exception if address is not valid.
Also, 401506 can only translate to 0x05E1 or 0x05E2. Try them both.
Post more info about your wiring, length, soldered or not, powering, termination resistors used etc...
There are several different ModbusMaster libraries. Which one are you using? The one referenced by @van_der_decken allows you to use SoftwareSerial as your Stream. Others do not. They only allow hardware Serial ports.
Another thing you may try is this. Since your proprietary documentation mentions that the leading digit (or digits) still represent the type of Modbus register, 04 = an Input Register, not a Holding Register.
I believe the one I'm using allows for SoftwareSerial. I did try to use 1102 as a holding register with no change in status. Wiring does not use a terminating resistor, wiring is about 1 foot, I'm operating at the back of the controller. I removed the remote serial annunciator currently in use before hooking up to the generator controller. The annunciator works fine, but it is programmed to be a Modbus master and you can't have 2 masters on the same line.
changed to a long and enabled all warnings on the compiler, this is what i get. What does this mean? I understand its maybe expecting a larger integer than what the register is, but this shouldn't affect how the program runs, right?