rjflatley / vat1300

Arduino nRF24L01+ data logger for Juntek VAT-1300 wireless battery monitor
13 stars 10 forks source link

Command overviw #3

Open DTSchneiderlein opened 2 years ago

DTSchneiderlein commented 2 years ago

I'm trying to communicate with the VAT1100 via RS-485 (the "USB"-Port). I can send and receive unreadable shit with htern using a RS485 to USB converter. Unfortunately, I'm not able to extract the needed commands from your .ino-file (I’m not so good in programming). Could you give an overview for the commands you sniffed and the format to reed them? My goal is to use a Bluetooth module directly to the UART of the STM 8 and connect it to an android device.

codewise-nicolas commented 2 years ago

Did you still need help communicating with the VAT1100 ?

DTSchneiderlein commented 2 years ago

Hi Nick, thx for your offer. I decided to use Junctec KG-F Series via BLE instead.

kasul commented 1 year ago

Hello I have the same problem. Also VAT1100 via RS485 and I am receiving only garbage. How do I code this? It would be enough if I can read current and voltage. Trying with an Arduino Nano, but i dont know how to get readable results.

DTSchneiderlein commented 1 year ago

Hello Kasul, I stopped this project. Perhaps you could ask codewise-nicolas. If there are any results please post here. Thx.

codewise-nicolas commented 1 year ago

First try to "listen" to the bus, by tapping into the A/B lines (D-/D+) between the controller and the lcd screen. This will hopefully get you some actual data before you try and sending commands. Sending commands is a whole other problem if the LCD is connected since the LCD will send out its own queries super fast and if your trying to send commands at the same time you will get into bus contention and corruption.

For the reading of the data, make sure you are looking at hex data. The bus runs at 57600 (when using a RS485 to Serial setup) Use a serial port monitor app to see the data. You will start to see patterns in the data and thats when you will start to see the commands/packets. Look for 0XAA as thats the begining of the packet. (0xAA, length of data after header (including length and checksum), commands/data, checksum)

kasul commented 1 year ago

Hi Nicolas, thanks for your reply! I only want to receive the actual current and voltage values. Sending commands is not necessary at the moment. I already got some messages but couldnt read them because I had the wrong baudrate. I will try again with 57600 but it will take a few days because my shunt is already in use in my off-grid cabin.

Is this the correct way to read out the values:

` byte aRX_PAYLOAD[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00, 0X00 }; //in loop: if (Serial1.available()) { aRX_PAYLOAD[] = Serial1.read(); }

if (aRX_PAYLOAD == '0XAA') { float voltage = (int16_t)(aRX_PAYLOAD[4] << 8 | aRX_PAYLOAD[5]) / 100.0; float amperage = (int16_t)(aRX_PAYLOAD[6] << 8 | aRX_PAYLOAD[7]) / 10.0;

String sSensorValue = String("BatteryVoltage=") + String(voltage, 2)
                          + String(",LoadCurrent=")         + String(amperage, 1) + "\n\r";

Serial.print(sSensorValue);

} ` Or do I have to Serial1.read() byte by byte in a for-loop (32 times?) when Serial1.available() is true? Do you have a Arduino-Code-Snippet where I can see how to get the payload when using a RS485 to Serial setup?

codewise-nicolas commented 1 year ago

While RS485 tends to be packet based, the way the RS485 to serial adapter works inherently, its a serial stream so you wont have all the packet/data available at once. You will need to read in the data byte by byte into a buffer and then process the data. Thus your latter idea of .read().

However each packet varies in length and you may get corruption or issues on the bus, so you cant always read 32 bytes and assume you have the packet in there properly.

There may be a library available that can read the serial data and give you a packet to work, but I didnt dig much into it so I just wrote something from scratch. Its possible the VAT is using Modbus, but I never verified.

The approach I took was in the loop() function check if serial data is available, if it is, then read a byte and do some basic processing and store the data into a buffer. Once we reach an end, or we see the magic byte or a timeout occurs, try to process the packet.

if (RS485Serial.available()){
        loopCount = 0;

        tmpByte = RS485Serial.read();
        //Serial.print("Data: ");
        //Serial.print(tmpByte, HEX);
        //Serial.println();

        if(tmpByte == 0xAA){
          if(bufferPos && possiblePacket){
            //last packet finished, lets process it

            parsePacket(buffer, bufferPos);
          }

          possibleStartOfHeader = true;
          possiblePacket = false;
          bufferPos = 0;

          buffer[bufferPos] = tmpByte;
          bufferPos++;

          //Serial.println("got AA");

        }else{
          if(possibleStartOfHeader && (tmpByte == 0x1C || tmpByte == 0x04)){  //we assume we only want packets with length 0x1c or 0x04 since those are packets we look for)
            possiblePacket = true;

            //Serial.println("got 1C");

            buffer[bufferPos] = tmpByte;
            bufferPos++;

          }else if(possiblePacket){
            buffer[bufferPos] = tmpByte;
            bufferPos++;

          }else{
            //not start of header
            possibleStartOfHeader = false;
            possiblePacket = false;
            bufferPos = 0;
          }
        }

    }else{
      if(loopCount > 10000){  //timeout waiting for next packet, if we have possible packet, process it.
        loopCount = 0;
        //Serial.print(".");
        //Serial.print(bufferPos);
        if(bufferPos && possiblePacket){
            parsePacket(buffer, bufferPos);
        }
      }
    }

    loopCount++;
  }

Essentially we check for the 0xAA header and if we have it, then it must be the start of the packet, so lets start storing the bytes into our buffer. Keep checking the bytes for a byte we know we want, in this case the lenght byte of 1c or 04 (very bad way to do it since you could get data that has this value in the packet data, but it works for me) then we keep track that this is a possible packet of data. Then keep storing the bytes in our buffer until we see the header again or the loop count is over 1000. If we see the header again, then the packet we have in our buffer is probably a complete packet starting at 0 and continuing.

Once you have the packet, then go ahead and parse it based on the rules I posted before about what the 0th 1th 2nd etc bytes mean.

codewise-nicolas commented 1 year ago

One more thing, while figuring out the packets and such I ended up connecting the rs485-serial adapter to my computer and wrote a node.js app to inspect the data and try out some ideas on how to parse the packets. It allowed me to quickly try things and see the results without having to re-compile an arduino project and flash it to an arduino/esp to test out. Also trying to parse the VAT packets and also send the data to the pc terminal can overload the ESP serial ports when developing, so the pc/node.js app was much quicker flow. If you know python, that would also work.

kasul commented 1 year ago

You are my hero! I could try it yesterday and it is working, my VAT1100 is now talking to home assistant. Thank you so much!