The problem is I only receive errors while trying to read two registers to make sure the communication works.
The errors I receive is either "Invalid CRC" or "Response not from requested slave". Only those two every other message.
I have measured with oscilloscope which shows the electricity meter receives and responds to the data. I have tried different ids, but then the meter does not respond.
I did also measure the rx/tx with the oscilloscope which also seems to work fine. DE/RE is working when sending and receiving. But somehow the arduino does not like the data it receives from the module. I have tried to print the raw data, but I wasn't able to access it deep down in the libraries.
I've no experience of the modbus library you are using. I have played with another library called ModbusMaster on an UNO and have been able to talk to a Modbus simulator. Maybe that library would be worth a look.
Another thought, this line:
if (!modbusRTU->requestFrom(ID_ELECTRICALMETER, HOLDING_REGISTERS, 40007, 2)) {
could be wrong, specifically the register address 40007. If it's similar to other modbus style function calls, then accessing a holding register, I think, implies the 40000 part of the address. Off the top if my head, if you want to read address 40007, the address you pass in the function call may be just 7, or it could be 6 as I recall the actual address is out by 1.
Sorry it's a bit vague, but hopefully it will help you out.
I'm not that familiar with some of your serial code techniques. Here's a version that I've run on an UNO (just quickly edited for a MEGA2560 - similar to your Nano Every):
// Arduino MEGA2560 + ModbusMaster
//
// RS485 module wired up as:
// RS485 DI signal to pin 9
// RS485 RO signal to pin 8
// RS485 RE signal to pin 7
// RS485 DE signal to pin 6
// RS485 VCC to 5V
// RS485 GND to GND
#include <ModbusMaster.h>
#define MAX485_DE 6
#define MAX485_RE_NEG 7
ModbusMaster node;
void preTransmission()
{
digitalWrite(MAX485_RE_NEG, 1);
digitalWrite(MAX485_DE, 1);
}
void postTransmission()
{
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
}
void setup() {
Serial.begin( 9600 );
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Modbus communication runs at 9600 baud
Serial1.begin(9600);
// Modbus slave ID of NPK sensor is 1
node.begin(1, Serial1);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
void loop() {
uint8_t result;
// NITROGEN
result = node.readHoldingRegisters(0x1E, 1);
if (result == node.ku8MBSuccess)
{
Serial.print(" Nitrogen: ");
Serial.print(node.getResponseBuffer(0x0));
Serial.println(" mg/kg");
}
Serial.println();
delay(2000);
}
It's slightly different from your code.
That looks like a valid modbus message - checksum is OK.
That's wrong. It should be something like: 2D 03 04 AA BB CC DD C1 C2, where AA & BB are the 1st 16-bit word, CC & DD are the 2nd 16-bit word and C1 & C2 are the CRC16 checksum.
I can understand the "Wrong Slave ID" as it thinks slave 00 has responded, but not why you are getting that.
Yes, I can't figure out why it responds with the wrong slave ID.
Just tried your code, but does still get the same error.
The frame I send is fine, but the frame I receive back is "corrupted".
The answer frame looks like the following: 00 4b 20 20 0E.
I think the last byte (0E) is right, but everything before is wrong.
Regarding the "corrupted" frame, I thought the reason could be the clock speed. I tried with 16MHz and 20MHz but nothing changed. I have also added resistors (120Ohm) on both ends.
Could it be the RS-485 transciever module don't support the atmega4809 on the arduino nano every?
If it were clock speed, then I would expect all the serial ports to be affected as the baud rate divisor would be off - perhaps by some margin.
A quick look and the Nano Every is a 5V board, just like an UNO or MEGA2560 board. That RS485 module should work fine.
Getting back fewer bytes than you expect is usually a sign that the RS485 module isn't being put back into receive mode quickly enough before the remote node starts transmitting.
Do you have an independent way of monitoring the RS485 bus, perhaps a USB-RS485 dongle or another Arduino + RS485 module?
split debug outputs from Modbus - Bus.
Meaning, either use a Mega with several HW Serial or SoftSerial.
but split Modbus and debug!
depending on the library, play around with the correct function code and register address.
for example, if I see the line 40001 0x01 in your document, I assume this is a FC3 Read Multiple Holding register at address 0x01 (or even 0x00).
if they write 30000 0x00 ... I would assume FC4 Read input register
if you use DocWalkers Modbus Master Library, read back and print the error code in HEX (!) so you can see if or what is responding or if the library reports an Error. See the .h file for an explanation of the errorcodes (0xE2, 0xE1, ... 1, 2...)
snief the bus with an USB-RS458 with your PC so you can see what is happening on the Modbus
If the above few bytes are the end of a complete modbus reply message, then the 20 & 0E are the CRC16 checksum. What makes you think that the 0E is right?
If I "patch in" the few bytes you get - assuming that they are indeed the tail end of a valid modbus response, then the message I construct is:
2D 03 04 xx 00 4B 20 20 0E
The xx would be the unknown byte in the response message. I could put some code together to cycle through all 256 possible values of xx to try and determine the missing byte, but that's not the issue here. If what you detect is indeed the tail end of a modbus reply, then you are missing the first 4 bytes.
As suggested, a USB-RS485 dongle is pretty much a required piece of test kit when playing with RS485.
Sorry for the delayed answer, did not work on this until today.
I have found the error. Thank you for every input. It is very appreciated.
The first error was located somewhere on the modbus module. The second error was the electricity meter, which made the error hard to detect.
Guess I was very unlucky at some point, but in the future I'll always check every component (if possible). Thanks again for your help. I'll write the rest with modbusmaster since I realized it is simpler.