tobiasfaust / SolaxModbusGateway

Modbus RTU to MQTT Gateway
GNU General Public License v3.0
55 stars 17 forks source link

Problem with RTS line #2

Closed uham999 closed 1 year ago

uham999 commented 1 year ago

In the function void modbus::QueryQueueToInverter() there is missing code before the delay(100); which causes no data to be returned.

RS485Serial->flush();

delay(100);

if (rwtype == WRITE) {

Pin pin_RTS needs to be set to receive before the delay(100); Without doing this, no data is returned in function ReceiveSetData. I tend to avoid using delay() because I suspect this causes problems in some of my code because of blocking. To avoid bocking yield in a timeout loop. It's just personal preference. delay(100) works.

Code should be something like:-

RS485Serial->flush();

digitalWrite(this->pin_RTS, RS485Receive);     // init Receive
unsigned long timeout=millis()+100;
while (millis()<=timeout) { yield(); }
//delay(100);

if (rwtype == WRITE) {

My test setup took much longer to wire up than first predicted. It is working now. I have a Growatt SPH3000 and Solax X1 Hybrid working now so in a position to test things for you.

tobiasfaust commented 1 year ago

in function modbus::ReceiveSetData(std::vector<byte>* SendHexFrame) you will find
digitalWrite(this->pin_RTS, RS485Receive); // init Receive

i changed the delay(100)

You can test if readdata from growatt works properly for you and after that, if set function works for you too. For setters you have to add such items in JSON section of register.h

uham999 commented 1 year ago

I have ordered an adaptor so I can 'T' into the Rs485 port on the growatt. This will arrive tomorrow so I will test it soon.

There is obviously a chance of a collision on the Rs485 bus because there are multiple masters (at least in the Growatt case). This is not much of an issue in read mode where the data read is repeated regularly. However, it is a problem when writing because the command may not get through due to collision. I'm sure that you have thought of this but haven't checked the write code to see if it retries a failed write. I thought that I would mention it just in case.

On Fri, 13 Jan 2023, 13:56 tobiasfaust, @.***> wrote:

in function modbus::ReceiveSetData(std::vector* SendHexFrame) you will find digitalWrite(this->pin_RTS, RS485Receive); // init Receive

i changed the delay(100)

You can test if readdata from growatt works properly for you and after that, if set function works for you too. For setters you have to add such items in JSON section of register.h

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1381891075, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCQYCPYZXVPZLYMLXKTWSFNHFANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

Oh, it Must only 1 Master and Not More. Your Inverter should have an extra Modbus for Communication and one for Battery and one for smartmeter

uham999 commented 1 year ago

That is the way it works on the Solax. However, on the Growatt SPH3000 there are two types of battery options. One works on a CAN bus and the other on RS485. They have separate RJ45 sockets. The battery I have is controlled using the RS485 port so there is no other bus to connect and ESP device too. The CAN bus socket might have RS485 pins but there is no documentation. The Growatt operation manual is very bad. It doesn't have schematic diagrams for any of the RJ45 ports we need. I will have to find a more technical manual on the internet before I can test it at all. If I disconnect the battery from the Growatt then I'm sure I could then talk to it using the RS485 but obviously not ideal because the battery has to be disconnected and I still need the wiring schematic for the pins. Multiple devices should be able to connect to RS485 as long as all devices are in receive mode and a protocol for detecting collisions is used. There is a separate port for smart meter or CT clamp connection. My inverter has a CT clamp rather than a meter. It is possible that the RS485 port on that interface could be used if the software within the inverter routes the incoming data to its command interface.

On Fri, 13 Jan 2023, 14:20 tobiasfaust, @.***> wrote:

Oh, it Must only 1 Master and Not More. Your Inverter should have an extra Modbus for Communication and one for Battery and one for smartmeter

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1381924804, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCU4DHANBU4NXXHVYPLWSFQCLANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

Hi, can you use the example https://github.com/tobiasfaust/SolaxModbusGateway/tree/master/examples/test_RS485_Solax_ESP32 to test your connection? Unfortunally i haven´t any half-dublex module. so i´m not able to test. Can you test and give me any feedback? Maybe please feel free to change the example script if there are any mistakes regarding direction control pin handling

uham999 commented 1 year ago

Hi, I've tested it and it didn't work. If you replace the loop() function with the following, it works.

void loop() {

byte request[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x07, // 0x0D - 14 stellen, Inverter + Modulname 0x00, 0x00 }; //

uint16_t crc = Calc_CRC(request, sizeof(request)-2); request[sizeof(request)-1] = highByte(crc); request[sizeof(request)-2] = lowByte(crc);

Serial.println("Schreibe Daten ...."); for(uint8_t i=0; i<sizeof(request); i++){ Serial.print(Hex2String(request[i]));Serial.print(' '); } Serial.println("");

digitalWrite(RTS_pin, RS485Transmit); Serial2.write(request, sizeof(request)); Serial2.flush();

digitalWrite(RTS_pin,RS485Receive); delay(100); Serial.println("Lese Daten ...."); while(Serial2.available()) { Serial.print(Serial2.read(), HEX); Serial.print(" "); } Serial.println(""); delay(2000); }

On Wed, 18 Jan 2023 at 09:42, tobiasfaust @.***> wrote:

Hi, can you use the example https://github.com/tobiasfaust/SolaxModbusGateway/tree/master/examples/test_RS485_Solax_ESP32 to test your connection? Unfortunally i haven´t any half-dublex module. so i´m not able to test. Can you test and give me any feedback? Maybe please feel free to change the example script if there are any mistakes regarding direction control pin handling

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1386761703, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCU7SCSJTUVPAOV6FEDWS63J7ANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

Its a little bit confusing. There are no big differences. Can you post the complete script as attachment? I try to get a SP3485 halfdublex module for testing purposes.

uham999 commented 1 year ago

/* Script to test a RS485 connection

from an idea of https://arduino.stackexchange.com/questions/62327/cannot-read-modbus-data-repetitively https://www.cupidcontrols.com/2015/10/software-serial-modbus-master-over-rs485-transceiver/

*/

define RX 16

define TX 17

define RTS_pin 5 //RS485 Direction control

define RS485Transmit HIGH

define RS485Receive LOW

void setup() {

pinMode(RTS_pin, OUTPUT); digitalWrite(RTS_pin,RS485Receive);

// Start the built-in serial port, for Serial Monitor Serial.begin(115200); Serial.println("Test RS485 Connection"); Serial.println("Test RS485 Connection"); Serial.println("Test RS485 Connection");

// Start the Modbus serial Port Serial2.begin(19200, SERIAL_8N1, RX, TX); delay(1000); }

uint16_t Calc_CRC(uint8_t* message, uint8_t len) { //Calc the raw_msg_data_byte CRC code

uint16_t crc = 0xFFFF; for (int pos = 0; pos < len; pos++) { crc ^= (uint16_t)message[pos]; // XOR byte into least sig. byte of crc for (int i = 8; i != 0; i--) { // Loop over each bit if ((crc & 0x0001) != 0) { // If the LSB is set crc >>= 1; // Shift right and XOR 0xA001 crc ^= 0xA001; } else // Else LSB is not set crc >>= 1; // Just shift right } }

return crc; }

String Hex2String(uint8_t num) { char hexCar[2];

sprintf(hexCar, "0x%02X", num); return hexCar; }

void loop() {

byte request[] = {0x01, 0x03, 0x00, 0x00, 0x00, 0x07, // 0x0D - 14 stellen, Inverter + Modulname 0x00, 0x00 }; //

uint16_t crc = Calc_CRC(request, sizeof(request)-2); request[sizeof(request)-1] = highByte(crc); request[sizeof(request)-2] = lowByte(crc);

Serial.println("Schreibe Daten ...."); for(uint8_t i=0; i<sizeof(request); i++){ Serial.print(Hex2String(request[i]));Serial.print(' '); } Serial.println(""); digitalWrite(RTS_pin, RS485Transmit); Serial2.write(request, sizeof(request)); Serial2.flush();

digitalWrite(RTS_pin,RS485Receive); delay(100); Serial.println("Lese Daten ...."); while(Serial2.available()) { Serial.print(Serial2.read(), HEX); Serial.print(" "); } Serial.println(""); delay(2000); }

On Wed, 18 Jan 2023 at 13:07, tobiasfaust @.***> wrote:

Its a little bit confusing. There are no big differences. Can you post the complete script as attachment? I try to get a SP3485 halfdublex module for testing purposes.

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1387045407, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCXHDTCGDPRANTCKOQTWS7TI5ANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

i have got now a SP3485 board. I use exactly your modified sketch, pins 16/17 and D2 but i didn´t get any response. I haven´t any idea why it doesn´t work.

Actually i strongly recommend to use a fulldublex RS485 board HW-0519. I will continue the test if a have new idea whats wrong

btw: your Growatt has a RS232 communication port. Maybe you can test it with a RS232 Module instead of an RS485 module. But then, you need programming knowHow to test it and (maybe) to make some changes in my code

RS232 zu TTL Konverter Modul Board MAX3232 Seriell Serial Port DB9 Buchse https://www.ebay.de/itm/122242761844

uham999 commented 1 year ago

Did you link the ground pins?

On Tue, 24 Jan 2023 at 06:46, tobiasfaust @.***> wrote:

i have got now a SP3485 board. I use exactly your modified sketch, pins 16/17 and D2 but i didn´t get any response. I haven´t any idea why it doesn´t work.

Actually i strongly recommend to use a fulldublex RS485 board HW-0519. I will continue the test if a have new idea whats wrong

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1401462455, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCU7GE2KK2PNKXRZ3CDWT53EXANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

yes, of course ;) Either i got nothing or i got not readable stuff (not a well formed error message!)

uham999 commented 1 year ago

Hi The DE and RE lines need to be connected together and connected to a single RTS pin on the ESP. You have probably tried this but DI needs to connect to RX on the ESP and RO needs connecting to TX on the ESP. It is easy to get these the wrong way round.

On Wed, 25 Jan 2023 at 08:43, tobiasfaust @.***> wrote:

yes, of course ;) Either i got nothing or i got not readable stuff (not a well formed error message!)

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1403266541, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCU3KEFYBOQAHM2T4XDWUDRTDANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

I Use the Board SP3485 please see https://github.com/tobiasfaust/SolaxModbusGateway/wiki/wiring-the-circuit#board-sp3485 DE and RE pins don´t exist RX and TX are correct wired, the onboard led shows me by blinking.

uham999 commented 1 year ago

Hi The datasheet for the sp3485 is here

https://www.google.com/url?sa=t&source=web&rct=j&url=https://www.maxlinear.com/ds/sp3485.pdf&ved=2ahUKEwio6v2xguP8AhXpTUEAHS5_B7oQFnoECBcQAQ&usg=AOvVaw2bPfv3NwfirxbQxeJiEGwo

The breakout board exposes all the pins. RO is pin 1 on the chip RE is pin 2 on the chip DE is pin 3 on the chip DI is pin 4 on the chip

You can use a multimeter or visually determine which of the outputs on the board are connected to these pins. I don't have one of those boards so can't check it myself.

On Wed, 25 Jan 2023, 11:41 tobiasfaust, @.***> wrote:

I Use the Board SP3485 please see https://github.com/tobiasfaust/SolaxModbusGateway/wiki/wiring-the-circuit#board-sp3485 DE and RE pins don´t exist RX and TX are correct wired, the onboard led shows me by blinking.

— Reply to this email directly, view it on GitHub https://github.com/tobiasfaust/SolaxModbusGateway/issues/2#issuecomment-1403479058, or unsubscribe https://github.com/notifications/unsubscribe-auth/AR53TCUUOI6YL65X5I5ATNLWUEGM7ANCNFSM6AAAAAATZGV54Q . You are receiving this because you authored the thread.Message ID: @.***>

tobiasfaust commented 1 year ago

thanks, now it works and i committed ca0dc30 to fix the RTS-Line Bug I updated also the wiki https://github.com/tobiasfaust/SolaxModbusGateway/wiki/wiring-the-circuit