Has anyone had any success receiving register information over modbus RTU with device "AZ-Delivery NodeMCU Lolin V3" ESP 8266?
I looked online and someone said it is not possible to get it to work because the pin drops before the full packet has been sent.
I'm trying to get information from my Sunsynk 5K (Deye) holding register but just receiving rubbish.
I have connect with my laptop using modscan64 with Haljia USB to RS485 successfully.
My equipment to connect to inverter is:
ESP 8266 NodeMCU Lolin V3
HALJIA 5V MAX485 Module
Library used MODBUSMASTER.
I'd like to minimise devices so don't want to use Arduino Uno if possible, any help would be greatly appreciated.
Code below:-
#include <ModbusMaster.h>
#define MAX485_DE 3
#define MAX485_RE_NEG 2
// instantiate ModbusMaster object
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()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Modbus communication runs at 115200 baud
Serial.begin(9600);
// Modbus slave ID 1
node.begin(1, Serial);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
bool state = true;
void loop()
{
uint8_t result;
uint16_t data[6];
result = node.readHoldingRegisters(0x4187, 2);
if (result == node.ku8MBSuccess)
{
Serial.print("PV1: ");
Serial.println(node.getResponseBuffer(0x00));
Serial.print("PV2: ");
Serial.println(node.getResponseBuffer(0x01));
}
delay(1000);
}
if that were the case, add a Serial.flush before you release MAX485_RE_NEG and MAX485_RE in the post transmission CB.
print the result of the transmission in HEX and check in the library what the error code says.
This will tell what really happens.
Advice: use Softserial for the Modbus line and keep Serial for debugging output!
P.S.: please edit your post titel and move it to a more appropriate place like
Using Arduino / Networking, Protocols & Devices
How do I print the result in Hex? I'm completely new to this, but learning quickly, so I don't know how to get the result in hex.
This is the last stage of my project. First stage was connecting to the network. Second stage is sending json requests to a sonoff switch in DIY mode, so this is the last leg, although the most difficult.
result = node.readHoldingRegisters(0x4187, 2);
if (result == node.ku8MBSuccess)
{
Serial.print("PV1: ");
Serial.println(node.getResponseBuffer(0x00));
Serial.print("PV2: ");
Serial.println(node.getResponseBuffer(0x01));
}
Serial.println(result, HEX); // and then check in the library files, what the code means
see libraries\ModbusMaster\src\ModbusMaster.h
I think my problem is the pin assignment. I noticed the little LED on the ESP 8266 was fully on after uploading the sketch and I know the LED is pin 2. (If I'm talking rubbish then tell me)
If I have DE pin on the MAX 485 to D1 on the ESP 8266 and RE (MAX 485) to D2 (ESP 8266) then what pin numbers are these?
If I'm reading the pinout correctly D1 = 5 & D2 = 4?
I changed to 5 and 4 and still no joy. I'm just getting a load of squares accross the serial monitor.
I don't think I'm even getting to the MAX 485 because when I remove it I'm still getting the same result.
please google for "nodemcu schematic" and see the pin mapping.
if you just get "squares" - check if you have set up your serial monitor to 9600 as written in the sketch.
If you have added the printout of the result you must be able to see some kind of error code 0, 1, 2, E0, E1, E2 ... something like that.
I did google it and that's how I found pins 5 and 4. I am new to this so POI meant nothing to me, but doesn't take a degree to work out what it was. This low level electrics does need a degree and I know nothing so this idiot really does rely on the expert knowledge of you guys. (I do try)
I'm completely stuck with this so I'll do a wiring diagram and repost updated code and maybe someone can point out where I'm going wrong.
Is this a simple typo error?
Yes was picked up by compiler
Here is the code I'm trying just to get the connection correct.
#include <ModbusMaster.h>
#define MAX485_DE 5
#define MAX485_RE_NEG 4
// instantiate ModbusMaster object
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()
{
pinMode(MAX485_RE_NEG, OUTPUT);
pinMode(MAX485_DE, OUTPUT);
// Init in receive mode
digitalWrite(MAX485_RE_NEG, 0);
digitalWrite(MAX485_DE, 0);
// Modbus communication runs at 9600 baud
Serial.begin(9600);
// Modbus slave ID 1
node.begin(1, Serial);
// Callbacks allow us to configure the RS485 transceiver correctly
node.preTransmission(preTransmission);
node.postTransmission(postTransmission);
}
bool state = true;
void loop()
{
uint8_t PVresult;
uint16_t data[6];
PVresult = node.readHoldingRegisters(0x4187, 2);
if (PVresult == node.ku8MBSuccess)
{
//Serial.print("PV1: ");
//Serial.println(node.getResponseBuffer(0x00)/100.0f);
//Serial.print("PV2: ");
//Serial.println(node.getResponseBuffer(0x01)/100.0f);
//Serial.print("Pload: ");
//Serial.println((node.getResponseBuffer(0x0D) +
//node.getResponseBuffer(0x0E) << 16)/100.0f);
Serial.println(PVresult, HEX);
}
PVresult = node.readHoldingRegisters(0x4179, 1);
if (PVresult == node.ku8MBSuccess)
{
//Serial.print("Load: ");
//Serial.println(node.getResponseBuffer(0x01)/100.0f);
//Serial.print("Pload: ");
//Serial.println((node.getResponseBuffer(0x0D) +
//node.getResponseBuffer(0x0E) << 16)/100.0f);
Serial.println(PVresult, HEX);
}
delay(1000);
}
Here's my drawing.
What does the user manual say the address should be? I think the addresses passed into the readHoldingRegisters function are usually quite low values - and less than 10,000 decimal.
This is correct as I've had my laptop with modscan64 app connecting ok.
Unless the function readHoldingRegisters kows it is in the 4001 range? Then I'll need to minus by 4001.
should be OUTSIDE of the if, otherwise it will only be printed if you have success.
You want the error code also in case you are not successful.
See again post #5
I think that what was being described there occurs when using a hardware serial port and the RS485 module gets switched back to Rx mode before the Tx buffer has emptied. A call to the flush function would prevent that happening.
EDIT: Ignore this - I see it was covered in post #3!
I stumbled across a piece of python code in this github repository which looked interesting:
In the sunsynk folder, there is a definitions.py that looks like it lists a lot of the parameters and what could be their modbus addresses. Lines 64 and 73 in that file appear to associate the number 186 (decimal) to PV1 Power and 187 (decimal) to PV2 Power.
Is it a coincidence that the address you are using is 0x4187?
Not a coincidence at all.
I want to add these two together minus house load.
When remainder greater than 2000 then i have a function to turn on a sonoff in diy mode via json api.
Ok, re your code at post #12, move the printing of PVresult outside the if statement so we can see what result code is being returned by the modbus library. (See post #5 as it was suggested there, and again in post #16)
I'm guessing slightly here, but if you were to do a:
PVresult = node.readHoldingRegisters( 79, 1);
then what is the value of PVresult? Is it 0 (= success)? If it is, then what value is returned by getResponseBuffer(0)?
I'm not familiar with your ESP8266, but is the serial port that is connected to the TX and RX pins also the serial port that is connected to the USB serial interface? If it is, then it is very likely that those squares are the binary modbus data bytes that are being sent to the RS485 module. What you describe is also seen on an Arduino UNO when the TX and RX pins are used for modbus comms, as the single hardware serial port is being used for both modbus comms and debug printing.