OK this one has stumped me.
Basically I am wanting to read data from a JBD battery BMS which I've done successfully many times although not with this exact model.
If I use the specific application on a PC (Overkill solar) this communicates and displays data on the screen proving the RS485 shield on the UART port of the BMS and the RS485 dongle and wiring are all correct. I then connected a Mega with a RS485/TTL shield to act as a 'sniffer' I can see all traffic going to and from the BMS. Se below schematic (drawn from memory);
The received traffic is;
The short message is the data request from the PC, 0xDD being the start bit and 0x77 the stop bit. The long string being the reply, again 0xDD as the start and 0x77 as the stop bit. The second byte is 0xA5 for requesting data and 0x5A for the returned data packet. 3 different sets of registers are being called for.
The RS485 shield on the battery BMS is the XY-017 type that uses timing rather than a hardware transmit pin as the UART port does not have that facility.
Now then, if I try to send the exact same HEX string from the Arduino the BMS does not respond, I know the hardware is OK as the Mega can see the traffic, the TX enable has to be working as it will block the request from the PC if set incorrectly and I can see the the RX led flicker on the battery RS485 shield every time the Arduino sends the request. The Baud rate is 9600 which has to be correct as traffic can be seen, the BMS protocol calls for no parity, 8 bits and 1 stop bit which I believe is standard for the Arduino serial. I remove the dongle from the PC when trying.
Here is the code,
/* This code uses an Arduino Mega and RS485 shield to communicate with a JBD battery BMS
* transmit and receive using the Serial1 port, transmit enable connected to pin 17
* With the 'request' call commented out this works as a data sniffer
*/
int tx_en = 17; // transmit enable pin
unsigned long previousMillis = 0;
const long interval = 1000; // transmit request repaet time
void setup() {
pinMode(tx_en, OUTPUT); // set transmit enable pin as output
Serial.begin(115200); // serial output to console
Serial1.begin(9600); // RS485 serial
digitalWrite(tx_en, LOW);// Set transmit enable low (debugging)
delay(1000); // Add delay for debugging
Serial.print("Starting");// this just prints something on the console to show things are alive and the baud is correct
delay(100); // another debuggung delay
}
void loop() {
//-------------- untimed code -------------------------------------------------
// this part taken from the standard multi serial sketch
// read from port 1, send to port 0:
if (Serial1.available()) {
int inByte = Serial1.read();
//Serial.write(inByte);
Serial.print(inByte, HEX);
if (inByte == 0x77) Serial.println(" "); // new line at stop bit for reading clarity
}
//--------------- end of untimed code ------------------------------------------------------
unsigned long currentMillis = millis(); // sets transmit repeat time
if (currentMillis - previousMillis >= interval) {
// save the last time you blinked the LED
previousMillis = currentMillis;
//------------------timed code---------------------------------------------------
request(); // call the data request routine
}
}
//------------------- end of loop ----------------------------------------------------
//----------------- request routine ----------------------------------------------
void request() {
digitalWrite(tx_en, HIGH); // Set RS485 shield to transmit mode
Serial1.write(0xDD); // start bit
Serial1.write(0xA5); // status bit A5=read 5A=write
Serial1.write(0x30); // error status 03=OK 80=error
Serial1.write(0xFF); // Data sent
Serial1.write(0xFD); // possible check sum
Serial1.write(0x77); // stop bit
delay(3); // short delay so serial can finish sending
digitalWrite(tx_en, LOW); // set RS485 shield to receive mode
}
So, what an earth am I overlooking??