Help With VBUS Payload data

261 views
Skip to first unread message

Simon Coates

unread,
Oct 2, 2017, 7:20:17 AM10/2/17
to Resol Vbus
Hi There,

How do I reference the Payload data frames against the known packets found here: https://drive.google.com/file/d/0B4wMTuLGRPi2RnU0Vm1tTG5wM1k/edit

I am having trouble trying to decode the payload data.. It doesnt appear to represent current sensor temps


I have a Deltasol BS209

Hex capture:

AA //Start
0015  //Dest
427B  //Source (DeltaSol BS 2009)
10  //Protocol
00  //Header command
01  //Header command
0A //(Payload Frames) - 10
12  // (Checksum)
01 08 00 00 00 76  //payload 1
00 00 7F 7F 0C 75 //payload 2
02 0A 00 00 00 73 //payload 3
58 01 14 01 00 11 //payload 4
00 00 00 00 00 7F //payload 5
01 0B 00 00 00 73 //payload 6
00 00 00 00 00 7F //payload 7
02 01 00 0B 00 71 //payload 8
58 01 14 01 00 11 //payload 9
2F 01 38 22 05 70 //paylload 10

Any help appreciated in trying to understand how to represent each payload frame above to sensor temps as found below:

DFA (0x0010) <= DeltaSol BS 2009 (0x427B), command 0x0100


OffsetMaskNameFactorUnit
0Temperatur Sensor 11.0°C
1Temperatur Sensor 1256.0°C
2Temperatur Sensor 21.0°C
3Temperatur Sensor 2256.0°C
4Temperatur Sensor 31.0°C
5Temperatur Sensor 3256.0°C
6Temperatur Sensor 41.0°C
7Temperatur Sensor 4256.0°C
8Drehzahl Relais 11%
10Betriebsstunden Relais 11h
11Betriebsstunden Relais 1256h
12Drehzahl Relais 21%
14Betriebsstunden Relais 21h
15Betriebsstunden Relais 2256h
16UnitType1
17System1
20ErrorMask1
200x01Sensor 1 defekt1
200x02Sensor 2 defekt1
200x04Sensor 3 defekt1
200x08Sensor 4 defekt1
21ErrorMask256
22Systemzeit1
23Systemzeit256
24Statusmask1
25Statusmask256
26Statusmask65536
27Statusmask16777216
28Wärmemenge1Wh
29Wärmemenge256Wh
30Wärmemenge65536Wh
31Wärmemenge16777216Wh
32SW-Version1.00
33SW-Version256.00
34Variante1
35Variante256

Regards

Simon

Daniel Wippermann

unread,
Oct 27, 2017, 1:05:07 AM10/27/17
to resol...@googlegroups.com
Hi Simon,

you already split the data behind the VBus header (the first 10 bytes) into groups of 6 bytes to form VBus packet frames. In the case of the second frame it contains:

00 <- first data byte without MSB
00 <- second data byte without MSB
7F <- third data byte without MSB
7F <- fourth data byte without MSB
0C <- septet byte (collection of MSBs removed from data bytes above)
75 <- checksum

Each VBus packet frame only transport 4 bytes of payload that get expanded to 6 bytes during transmission to be able to check its integrity. So you would have to reverse the steps done by the sender to extract the 4 bytes of payload from the 6 bytes of the frame. After making sure the checksum matches the contents of the five bytes before it (which it does in this case) you would need to reinject the septet byte into the 4 data bytes before it. An example C function is provided in the VBus specification (e.g. http://danielwippermann.github.io/resol-vbus/vbus-specification.html in section "Septet-Bytes"). The four steps involve:

1. If the septet byte is greater than or equal to 8, subtract 8 from it and add 128 to the fourth data byte
2. If the septet byte is greater than or equal to 4, subtract 4 from it and add 128 to the third data byte
3. If the septet byte is greater than or equal to 2, subtract 2 from it and add 128 to the second data byte
4. If the septet byte is greater than or equal to 1, subtract 1 from it and add 128 to the first data byte

Lets convert the hex numbers above to decimal first (ignoring the checksum):

00 -> 0
00 -> 0
7F -> 127
7F -> 127
0C -> 12

After step 1: septet byte = 4, fourth data byte = 255
After step 2: septet byte = 0, third data byte = 255
After step 3: septet byte = 0, second data byte = 0
After step 4: septet byte = 0, first data byte = 0

Resulting in the four data bytes:

0
0
255
255

Basically you would have to repeat that process for each of the VBus packet frames you received. At the end you should have (number of frames announced in the header) * 4 bytes of payload left. You would then have to find the corresponding VBus packet specification matching the destination and source addresses in the VBus header as well as the command. The offsets and factors in the packet specification tell you which data bytes to pick and scale.

And that is where the table you pasted in your mail comes in. Or at least: should...

Because that specific table has two problems:

1) It contains several errors that I was alerted to a couple of days ago. The table has since been corrected and now looks more like this (copied from http://danielwippermann.github.io/resol-vbus/vbus-packets.html#0010_427B_0100):

DFA (0x0010) <= DeltaSol BS 2009 (0x427B), command 0x0100

Offset Mask Name Factor Unit
0   Temperatur Sensor 1 0.1 °C
1   Temperatur Sensor 1 25.6 °C
2   Temperatur Sensor 2 0.1 °C
3   Temperatur Sensor 2 25.6 °C
4   Temperatur Sensor 3 0.1 °C
5   Temperatur Sensor 3 25.6 °C
6   Temperatur Sensor 4 0.1 °C
7   Temperatur Sensor 4 25.6 °C
20
0x01 Sensor 1 defekt 1  
20 0x02 Sensor 2 defekt 1  
20 0x04 Sensor 3 defekt 1  
20 0x08 Sensor 4 defekt 1  
20   ErrorMask 1  
32   SW-Version 0.01  
33   SW-Version 2.56  
34   Variante 1  
35   Variante 256  

As you can see the factors for the temperatures were wrong by a factor of 10. 

But...

2) The table you referenced does not fit to the header hex dump you provided. The hex dump contains a destination address of 0x0015 where the table describes a packet addressed to 0x0010.

So, to make use of the table above you would have to receive and process the packet from 0x427B to 0x0010 with command 0x0100.

The packet in the hex dump cannot be decoded using a table like the one above because its structure is different. Packets addressed to 0x0015 are a special kind of packet to allow controller-independent support of VBus accessory like the AM1 alarm module or the SD3 smart display. So you are better off using the packet addressed to 0x0010 since it contains far more interesting data and is stable over time.

I hope that helped a bit in understanding how to decode the packet payload. If there are additional questions don't hesitate to contact me.

Best regards,
Daniel
--
You received this message because you are subscribed to the Google Groups "Resol Vbus" group.
To unsubscribe from this group and stop receiving emails from it, send an email to resol-vbus+...@googlegroups.com.
To post to this group, send email to resol...@googlegroups.com.
Visit this group at https://groups.google.com/group/resol-vbus.
For more options, visit https://groups.google.com/d/optout.

Manu rod

unread,
Mar 26, 2023, 6:56:23 AM3/26/23
to Resol Vbus
Hello, I have a similar problem, and I don't know what to do.
Hello , good morning to all; I am going to tell you about my problem. My system is Deltasol BXL,
DFA (0x0010) <= DeltaSol BXL (0x7428), command 0x0100. Hardware the "VBUSa Uart" adapter with Arduino Mega, and Seale Logic Analyzer, with "Sigrok Pulse View" to see the frames.
I have used the software from "FatBeard" (exemple readvbus) and "bbqkees vbus-arduino-domoticz", and also the documentation from "Daniel Wippermanhttp://danielwippermann.github.io/"
At first the result was all zeros, but then I noticed that I am getting frames with destination ("0x0000"), ("0x0015"), ("0x0010"). But almost always, it catches the frames with destination address (0x0015), which contains no useful data, WHEN IT CATCHES FRAMES WITH DESTINATION (0x0010), it decodes the data correctly, I can read the data from three temperature sensors, (Relays don't) , (because I have to adapt the section, decode, to the controller (0x7428) and I am not a developer, but I am an electronic technician and my level of programming is beginning, beginner in basic. Very old, many years ago, I have managed to put a filter to decode "0x0010" frames in the Command Filter. Here:

// Only analyse Commands 0x100 = Packet Contains data for slave
    // with correct length = 10 bytes for HEADER and 6 Bytes  for each frame
       
    if ((Command == 0x0100) && (Destination_address == 0x0010) && (Bufferlength == 10 + Framecnt * 6))
     // && (Checksum == VBus_CalcCrc(Buffer, 1, 8) ) )
     // && (Destination_address == 0x0010)
    {......
And I have managed to decode more frames (0x0010) and temperatures. But Strangely it keeps syncing mainly to the frames with destination (0x0015) and also, when I receive the correct data, from the correct frame,
he only reads them sometimes; In other words, I reset the arduino Mega in successive attempts, and after a few attempts, it takes the correct data. But the data always remains fixed, immutable, does not change over time, until I reset several times, and it returns to take the correct and updated data. Sometimes the first time, other times in 2 or 4 tries.

I have seen the frames in the logic analyzer, and they arrive as I have explained. The frames with destination (0x0010)
They are accompanied with 15 data packets with payload, x 6 bytes of payload, total 90 bytes.
I don't know what to do, I'm at a standstill. I think some code needs to be changed in (VbusRead()) But I don't quite understand the algorithm of the Code or the Code itself. My level of English is medium, but I use translation.
I need help please.
Example of decoded data.

TRAMAS DESTINO (0X0015)
204.90
0.00
16
------Decoded VBus data------
Destination: 15
Source: 7428
Protocol Version: 1
Command: 100
Framecount: 7
Checksum: 54
------Values------
Sensor 1: 204.90
Sensor 2: 0.00
Sensor 3: 0.00
Sensor 4: 0.00
Relay 1: 0
Relay 2: 0
Minute of Day: 0
Notifications: 0
------END---

FRAME  (0X0010)

Sync found
Sync found
---------------
Destination: 10
Source: 7428
Protocol Version: 1
Command: 100
Framecount: 15
Checksum: 51
---------------
-------by manu--------
Now decoding for 0x7428
---------------
0x77 00 91 01
0xB8 22 F7 01
0xB8 22 48 DD
0xF1 D8 48 DD
0xF1 D8 00 00
0x0B 00 00 00
0x00 00 00 00
0x49 5E 28 05
------Values------
Sensor 1: 54.90
Sensor 2: 46.50
Sensor 3: 0.00
Sensor 4: 57.40
Relay 1: 1
Relay 2: 16
Minute of Day: 0
Notifications: 0


Daniel Wippermann

unread,
Mar 26, 2023, 7:19:03 AM3/26/23
to resol...@googlegroups.com
Hi!

You are right: you have to ignore all other packets and focus on those that are addressed to 0x0010.

But I have no real idea why your app only receives data sometimes. Normally the controller sends its data regularly in intervals of max. a couple of seconds.

My best guess currently is that the data gets corrupted during reception and that the packet addressed to 0x0010 only seldomly gets received as a whole and unharmed.

Could you do me a favor? Could you add a debug output right after the „c = Serial1.read();“ in


Something like

...
c = Serial1.read();

// new code starts here
Serial.print(„RX: ");
Serial.println(c, HEX);
// new code ends here

if (c == sync1)

Then let that example run some time and paste the output in a reply. 

We can then try to figure out what happens…

Best regards,
Daniel







Manu rod

unread,
Mar 26, 2023, 11:46:04 AM3/26/23
to Resol Vbus
Hello Daniel, I will do it, and I will send the data, thank you very much for your answer. In any case, I will tell you that I have changed a parameter, in this section in Vbus(Read). Changed 20 to "90", and it is already reading the data, after synchronizing with about 5 or 6 SYNCs in a row. else { if (Bufferlength < 90 ) { lastTimeTimer = 0; lastTimeTimer = millis(); bufferlength=0; I still need to configure the "relays" and the "system alert"; and DateTime. Because I don't know how to do it with the BXL Package List. And transfer it to the decoder code, introducing the offset, Frame, Masck error, etc...

Daniel Wippermann

unread,
Mar 26, 2023, 4:12:41 PM3/26/23
to resol...@googlegroups.com
Hi!

Hmmm, that code you changed should restart reception if a SYNC byte is received although another reception was in progress…

I don’t know why this code is there in the first place because you should always restart reception in that case, regardless of the amount of data received previously.

You said your BXL announces 15 frames which in total with the header would be 10 + 15 * 6 = 100 bytes between one SYNC and the other. But the „Buffer“ variable is only 80 bytes large:


That might be another reason why your reception does silly things from time to time: you might actually write outside your Buffer’s bounds to the variables right after it.

The maximum packet length is 10 bytes header + 127 frame with 6 bytes each = 772 bytes. Please adapt that buffer size to at least 100 in your case or (to be sure) 772 or higher for future use.

And please change the data type „Bufferlength“ from „unsigned char“ to „size_t“ or „unsigned int“ or so.

Best regards,
Daniel






Manu rod

unread,
Mar 27, 2023, 5:55:01 PM3/27/23
to Resol Vbus
Honestly, I can't find a reason why the code is there. I would like to understand the algorithm
of the Function "VBusRead", at least of each section of the code. I have tried, but the variables "Bool"
"STAR" "STOP" "QUIT" confuse me a lot, I don't know when it is false or true and when it is not, and why and
What value are they compared to?

(You said that your BXL announces 15 frames which in total with the header would be 10 + 15 * 6 = 100 bytes between one SYNC and the other. But the „Buffer“ variable is only 80 bytes in size:)

Yes, yes, that's it, 100 bytes, And checked, with the Pulse View, (Logic Analyzer: 10+30 Pause 30 pause 30 bytes)
And also change the "Buffer" variable to 90 in my example, which works, but it's true, I have to change it to 100)
It's curious, but, in the example that works for me, after having changed the code, Buffer to 90, and the aforementioned code from 20 to 90, All the packages that the program reads, after approximately 5 "Sync",
They are all correct, with DESTINATION 0x0010, I imagine it is because of the filter that I put.
// Only analyze Commands 0x100 = Packet Contains data for slave // with correct length = 10 bytes for HEADER and 6 Bytes for each frame

if ((Command == 0x0100) && (Destination_address == 0x0010) && (Bufferlength == 10 + Framecnt * 6))
I will make the changes you tell me.
Attached I am sending you the buffering of the arduino, Mega, of the "Serial" output. I don't know how to pass it to a file.
So I have built it myself, with Cut and Paste. Two cycles: I hope it works for you. Let's keep talking.

Thanks and regards.

Debug 2 Frame to 0x0000  2 to 0x0015  2 to 0x0010

RX: FFFFFFAA
Sync found
RX: 0
RX: 0
RX: 28
RX: 74
RX: 20
RX: 0
RX: 5
RX: 0
RX: 0
RX: 3E
RX: FFFFFFAA
Sync found
RX: 15
RX: 0
RX: 28
RX: 74
RX: 10
RX: 0
RX: 1
RX: 7
RX: 36
RX: 1
RX: 8
RX: 0
RX: 0
RX: 0
RX: 76
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 2
RX: A
RX: 0
RX: 0
RX: 0
RX: 73
RX: 5A
RX: 0
RX: 6B
RX: 1
RX: 5
RX: 34
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 1
RX: B
RX: 0
RX: 0
RX: 0
RX: 73
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: FFFFFFAA
Sync found
RX: 10
RX: 0
RX: 28
RX: 74
RX: 10
RX: 0
RX: 1
RX: F
RX: 33
RX: 5A
RX: 0
RX: 6B
RX: 1
RX: 5
RX: 34
RX: 38
RX: 22
RX: 6B
RX: 2
RX: 1
RX: 37
RX: 38
RX: 22
RX: 5D
RX: B
RX: 33
RX: B
RX: 0
RX: 0
RX: 0
RX: 0
RX: 74
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 1
RX: 6A
RX: 29
RX: 0
RX: 0
RX: D
RX: 1
RX: 0
RX: 0
RX: 1
RX: 70
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 0
RX: 0
RX: 0
RX: 0
RX: 4
RX: 0
RX: FFFFFFAA
Sync found
RX: 0
RX: 0
RX: 28
RX: 74
RX: 20
RX: 0
RX: 5
RX: 0
RX: 0
RX: FFFFFFAA
Sync found
RX: 15
RX: 0
RX: 28
RX: 74
RX: 10
RX: 0
RX: 1
RX: 7
RX: 36
RX: 1
RX: 8
RX: 0
RX: 0
RX: 0
RX: 76
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 2
RX: A
RX: 0
RX: 0
RX: 0
RX: 73
RX: 5A
RX: 0
RX: 6B
RX: 1
RX: 5
RX: 34
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 1
RX: B
RX: 0
RX: 0
RX: 0
RX: 73
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: FFFFFFAA
Sync found
RX: 10
RX: 0
RX: 28
RX: 74
RX: 10
RX: 0
RX: 1
RX: F
RX: 33
RX: 5A
RX: 0
RX: 6B
RX: 1
RX: 5
RX: 34
RX: 38
RX: 22
RX: 6B
RX: 2
RX: 1
RX: 37
RX: 38
RX: 22
RX: 9
RX: 6
RX: B
RX: 0
RX: 0
RX: 0
RX: 0
RX: 74
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 1
RX: 6A
RX: 29
RX: 5
RX: 0
RX: 0
RX: D
RX: 1
RX: 0
RX: 0
RX: 1
RX: 70
RX: 0
RX: 0
RX: 0
RX: 0
RX: 0
RX: 7F
RX: 0
RX: 0
RX: 0
RX: 0
RX: 4
RX: 26
RX: FFFFFFAA
Sync found







Daniel Wippermann

unread,
Mar 30, 2023, 1:40:09 PM3/30/23
to resol...@googlegroups.com
Hi!

Thanks for the RX output. I fed the data you recorded into my VBus parser and it is clear that your VBus receiver is skipping / missing / ... some bytes.

As an example: directly at the start of your recording there is a byte sequence

AA 00 00 28 74 20 00 05 00 00 3E

This should be the bus offer from your controller and as a VBus version 2.0 datagram it should be 16 bytes in length. But your code only recorded 11 bytes. In that special case it is missing five bytes with value 0 right before the terminating 3E. If I manually add them to

AA 00 00 28 74 20 00 05 00 00 00 00 00 00 00 3E

this decodes just fine as a datagram.  But it does not only miss 00 bytes. In a later occasion you recorded the same datagram as above, but with even more bytes missing:

AA 00 00 28 74 20 00 05 00 00 …………….

So now six bytes from the end are missing to form a valid datagram.

So the first thing to solve is fixing the VBus / UART receiver to not miss bytes. It can be a hardware or FIFO problem, that is hard to tell from a distance.

Best regards,
Daniel









Manu rod

unread,
Apr 4, 2023, 2:20:54 PM4/4/23
to Resol Vbus
Hello Daniel,
You are right, the byte frames were being trimmed, *GOOD THE PROBLEM WAS IN THE PRINT SERIAL*, however in the logic analyzer, at the output of the Vbus-Uart Adapter they are correct.
In the logic analyzer the frames always appear as follows:
Destination 0x0000 16 Bytes
Destination 0x0015 52 Bytes
Destination 0x0010 100 Bytes
Anyway, the Controller Protocol Version, is it Version 1? Is not true?
Because when it reads the data with destination 0x0010 it reads it correctly and displays the temperature correctly.
------Decoded VBus data------

Destination: 10
Source: 7428
Protocol Version: 1
Command: 100
Framecount: 15
Checksum: 51;
*Although I made the changes that he told me; "Buffer[100]" and "Bufferlength" "unsigned int". Still having clipping issues.
*THE PROBLEM WAS SENDING TO THE SERIAL MONITOR, when several processes try to print data to the Serial Monitor, the frames sent are cut off, I don't know if it's because of the Buffer, or I don't know.
My Hardwre is KEYESTUIDO Mega 2560 plus Board, processor core ATMEGA2560-16AU, is fully compatible with ARDUINO MEGA 2560 REV3. USB to TTL chip:CP2102.
https://wiki.keyestudio.com/KS0499_KEYESTUDIO_Mega_2560_Plus_Board#Specification.

Example; With the example that you proposed to me, for the debug, I must remove from the sending to the Serial monitor, Serial.Print("RX: "); And I must remove the sending of Values, and Decode, while the code that you sent me is executed.

// new code starts here
//Serial.print("RX: "); "Do not execute this line"

Serial.println(c, HEX);
// new code ends here
Once this is done, the data collected is correct. I have also used a "RealTerm" External Serial Monitor, and the same thing happens; I have used a SerialPassthrough, which makes the code Transparent, and it has also worked well.
The strangest thing is that the most significant change, which has made the program work independently of the clipping of the frames in the Serial Monitor, is this code;
"Changed Buferlenght from 20 to 90. I don't know why"
https://github.com/FatBeard/vbus-arduino-library/blob/a48b57627c5aa31ca21d07eff98c98a4e37318e9/src/VBUSDecoder.cpp#L265

*I already get correct temperatures, what remains is to assign the "VBus Specification" table with the correct Variables, in the correct "Frame Decode". Especially Relay 1 and Relay 2, and System Notification.
Structure: DFA (0x0010) <= DeltaSol BXL (0x7428), command 0x0100 (00_0010_7428_10_0100)
http://danielwippermann.github.io/resol-vbus/#/vsf/bytes/00_0010_7428_10_0100

*And these are the New Data Extracted;

FFFFFFAA
10
0
28
74
10
0
1
F
33
1A
0
57
1
5
8
38
22
12
2
1
10
38
22
48
5D
9
77
71
58
48
5D
B
6
71
58
0
0
3
33
B
0
0
0
0
74
0
0
0
0
0
7F
10
39
2D
5
0
4
0
0
0
0
0
7F
0
0
0
0
0
7F
D
1
0
0
1
70
0
0
0
0
0
7F
0
0
0
0
0
7F
64
0
58
1
0
42
44
6A
32
1
0
1E
FFFFFFAA
0
0
28
74
20
0
5
0
0
0
0
0
0
0
3E
FFFFFFAA
15
0
28
74
10
0
1
7
36
1
8
0
0
0
76
0
0
0
0
0
7F
2
A
0
0
0
73
1A
0
57
1
5
8
0
0
0
0
0
7F
1
B
0
0
0
73
0
0
0
0
0
7F
FFFFFFAA
10
0
28
74
10
0
1
F
33
1A
0
57
1
5
8
38
22
12
2
1
10
38
22
48
5D
9
77
71
58
48
5D
B
6
71
58
0
0
3
33
B
0
0
0
0
74
0
0
0
0
0
7F
10
39
2D
5
0
4
0
0
0
0
0
7F
0
0
0
0
0
7F
D
1
0
0
1
70
0
0
0
0
0
7F
0
0
0
0
0
7F
64
0
58
1
0
42
44
6A
32
1
0
1E
FFFFFFAA
0
0
28
74
20
0
5
0
0
0
0
0
0
0
3E
FFFFFFAA
15
0
28
74
10
0
1
7
36
1
8
0
0
0
76
0
0
0
0
0
7F
2
A
0
0
0
73
1A
0
57
1
5
8
0
0
0
0
0
7F
1
B
0
0
0
73
0
0
0
0
0
7F
FFFFFFAA
10
0
28
74
10
0
1
F
33
1A
0
57
1
5
8
38
22
12
2
1
10
38
22
48
5D
9
77
71
58
48
5D
B
6
71
58
0
0
3
33
B
0
0
0
0
74
0
0
0
0
0
7F
10
39
2D
5
0
4
0
0
0
0
0
7F
0
0
0
0
0
7F
D
1
0
0
1
70
0
0
0
0
0
7F
0
0
0
0
0
7F
64
0
58
1
0
42
44
6A
32
1
0
1E
FFFFFFAA
0
0
28
74
20
0
5
0
0
0
0
0
0
0
3E
FFFFFFAA

Daniel Wippermann

unread,
Apr 5, 2023, 12:55:31 PM4/5/23
to resol...@googlegroups.com
Hi!

Great, you made good progress!

Decoding the data you sent actually yields valid packets (version 1.0) and datagrams (version 2.0)!

00_0010_7428_10_0100
00_0000_7428_20_0500_0000
00_0015_7428_10_0100
00_0010_7428_10_0100
00_0000_7428_20_0500_0000
00_0015_7428_10_0100
00_0010_7428_10_0100
00_0000_7428_20_0500_0000

> Anyway, the Controller Protocol Version, is it Version 1? Is not true?

Hmmm, no. The controller speaks both versions, version 1.0 and 2.0. It uses 1.0 for sending its measurement values etc. And it uses version 2.0 to offer remote parameterization. But for your use case you can focus on version 1.0 as well as destination address 0x0010 and ignore the rest.

> Example; With the example that you proposed to me, for the debug, I must remove from the sending to the Serial monitor, Serial.Print("RX: "); And I must remove the sending of Values, and Decode, while the code that you sent me is executed.

Ah, okay. Makes sense.

> The strangest thing is that the most significant change, which has made the program work independently of the clipping of the frames in the Serial Monitor, is this code;
> "Changed Buferlenght from 20 to 90. I don't know why"

Hmmm, as far as I understand the code (and I do not pretend to fully understand it…) the code you cited does the following:

- it sets „start“ to „true“
    - „start" will be reset to „false“ once the first SYNC byte was received
- it sets „stop“ to „false“
    - „stop" will be set to „true“, if a another SYNC byte is received after the first one AND it received more than XXX (20 or 90) bytes after the previous SYNC byte
- it sets „quit“ to „false“
    - „quit“ will be set to „true“ if a „timerInterval“ is configured AND the time between the last SYNC byte and now exceeds that „timerInterval“
    - I have not found a code location that actually sets „timerInterval“, so I assume we can ignore the „quit“ flag

If either „stop“ or „quit“ is set to true, reception is ended, regardless of whether a VBus data fragment was received.

So, lets see what happened when „vBusRead“ is called and XXX still was 20. If we assume you receive the same sequence of bytes like you recorded the function would have behaved like this:

- The first 0xAA is detected as a SYNC byte. „start“ is set to „false“
- The code receives the next 15 bytes and stores them in the buffer
- It then receives the second 0xAA. Since „start“ is already „false“, it checks whether less than 20 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The code then receives the next 51 bytes and stores them in the buffer
- It then receives the third 0xAA. Since „start“ is already „false“, it checks whether less than 20 bytes have been stored to the buffer -> no, so end reception by setting „stop“ to „true“

This yields the packet addressed to 0x0015.

When the „vBusRead“ function is called again, it behaves like this:

- The code receives the remaining 99 bytes that belonged to the third 0xAA SYNC byte from last function call, but since „start“ is „true“ the whole time it ignores these bytes
- The fourth 0xAA is received. That again belongs to the same sequence of bytes like the first 0xAA
- From here on the code behaves like in the first call above

But as you can see your 100 byte packet is ignored, because your first call to „vBusRead“ already consumed the SYNC byte, so the the second call thinks that the remaining 99 bytes it receives are junk.

What happened when you changed XXX to 90:

- The first 0xAA is received, detected as a SYNC byte. „start“ is set to „false“
- The next 15 bytes are received and stored in the buffer
- The second 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less than 90 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The next 51 bytes are received and stored in the buffer
- The first 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less then 90 bytes have been stored to the buffer -> yes, so it resets the buffer and starts a new reception
- The next 99 bytes are received and stored in the buffer
- The fourth 0xAA is received, detected as a SYNC byte, but since „start“ already is „false“, it checks whether less than 90 bytes have been stored to the buffer -> no, so it ends reception by setting „stop“ to „true“

This yields the packet addressed to 0x0010!

When the „vBusRead“ function is called again, it behaved like this:

- The remaining 15 bytes that belong to the fourth 0xAA from the previous function call are received, but since „start“ is „true“ they are ignored
- The fifth 0xAA is received, detected as a SYNC byte. „start“ is set to „false“
- From here on the code behave like the first call above after receiving the second 0xAA

So setting XXX to any value greater than 52 but less than 100 allowed you to receive the packet you wanted.

In my opinion the code „vBusRead“ is sub-optimal and brittle. It should not consume a SYNC byte to detect whether it should return a fragment of VBus data. Instead (in my opinion) the code should:

- Wait for the SYNC byte, reseting reception while receiving something else
- Once the SYNC byte is received, store it and all subsequent bytes into the buffer
- After receiving 6 bytes it should check the protocol version in byte 5
    - if it is 0x10 the remainder is a VBus version 1.0 packet
    - if it is 0x20 the remainder is a VBus version 2.0 datagram
    - reset reception in any other case

For the VBus version 1.0 is should:

- Receive four additional bytes (10 in total)
- Check the checksum in byte 9, resetting reception if wrong
- Evaluate the frame count in byte 8
- For each frame
    - Receive six additional bytes
    - Check the frame’s checksum, resetting reception if wrong
- Once the full (10 + FrameCount * 6) bytes were received, exit the function

For the VBus version 2.0 it should:

- Receive ten additional bytes (16 in total)
- Check the checksum in byte 15, resetting reception if wrong

The advantage of this approach is that the SYNC byte of the next VBus fragment is still in the UART RX queue, waiting to be consumed once the function is called again.

I hope that explanation helps you understand the inner workings of the code. If you keep that magic constant at „90“ it should work for your case, but will break on other controllers / configurations.

Shameless self-plug: I have published my own VBus code in C and the behaviour described above is basically what https://github.com/danielwippermann/resol-vbus-c/blob/3b95594b38b4ea35071504f858e206cc0f7551dd/src/ResolVBusLiveDecoder.c#L101 does. But sadly I have no working example for Arduino…

Best regards,
Daniel







Manu rod

unread,
Apr 5, 2023, 4:34:48 PM4/5/23
to Resol Vbus
Greetings Daniel, WOW, I was pleasantly surprised by your explanation, and by the time you have dedicated to it, and the interest you have put into it. I am very grateful to him for his response, it has shed a lot of clarity on the doubts he had. And he has also surprised me how he handles the Code.
Wow! I was right with 90. Anyway, I hadn't seen your code in "C" I agree with you, about the efficiency of the code, or rather the mapping. Someday when I reach knowledge I will debug it.
I only need the encoding according to the table.
What remains is to assign the "VBus Specification
" table with the correct Variables, in the correct "Frame Decode". I don't know how to correlate the byte table and offset, mask etc, with the decoding of the values. Especially if Relay 1, Relay 2, and System Alert Notification is active.

Structure: DFA (0x0010) <= DeltaSol BXL (0x7428), command 0x0100 (00_0010_7428_10_0100)
http://danielwippermann.github.io/resol-vbus/#/vsf/bytes/00_0010_7428_10_0100
I would appreciate it when I can, that information to finish my project.
Kind regards.

Daniel Wippermann

unread,
Apr 6, 2023, 2:54:39 PM4/6/23
to resol...@googlegroups.com
Hi!

I prepared some code but since I do not have a Arduino IDE I was not able to compile it, so it might not be bug-free…


if ((Destination_address == 0x0010) && (Source_address == 0x7428) && (Command == 0x0100) && (Checksum == VBus_CalcCrc(Buffer, 1, 8)) && (Framecnt >= 15)) {
// This code expects 15 frames with 4 bytes each => 60 bytes in total
static uint8_t FrameData [60];

// IsValid might be set to false later if any of the frame checksums are not correct
bool IsValid = true;

// This loop serves multiple purposes:
// - it checks for the checksums of each frame
// - it injects the septett byte back into the 4 frame bytes
// - it copies the 4 bytes into a linear buffer to make accesses easier
for (int FrameIndex = 0; IsValid && (FrameIndex < 15); FrameIndex++) {
size_t SrcIndex = 10 + FrameIndex * 6;

// Check whether the frame's checksum is correct
if (Buffer[SrcIndex + 5] != VBus_CalcCrc(Buffer, SrcIndex, 5)) {
IsValid = false;
}

if (IsValid) {
// If the checksum was correct, inject the septett byte back
Septet = Buffer[SrcIndex + 4];
InjectSeptet(Buffer, SrcIndex, 4);

// Copy this frame over to the linear frame data buffer
size_t DstIndex = FrameIndex * 4;
for (int Index = 0; Index < 4; Index++) {
FrameData [DstIndex + Index] = Buffer [SrcIndex + Index];
}
}
}

// If IsValid is still true, all 15 frames had correct checksums and were copied into the FrameData buffer
if (IsValid) {
// S1: lo-byte at offset 0 and hi-byte at offset 1
sensor1Temp = ReadInt16(FrameData + 0) * 0.1;
// S2: lo-byte at offset 2 and hi-byte at offset 3
sensor2Temp = ReadInt16(FrameData + 2) * 0.1;
// S3: lo-byte at offset 4 and hi-byte at offset 5
sensor3Temp = ReadInt16(FrameData + 4) * 0.1;
// S4: lo-byte at offset 6 and hi-byte at offset 7
sensor4Temp = ReadInt16(FrameData + 6) * 0.1;
// R1: offset 24
Relay1 = FrameData [24];
// R2: offset 25
Relay2 = FrameData [25];
// ErrorMask: lo-byte at offset 44 and hi-byte at offset 45
ErrorMask = ReadUInt16(FrameData + 44);
}
}


In addition to that you need some of those helper functions:

static uint16_t ReadUInt16(const uint8_t *Bytes)
{
return ((uint16_t) Bytes [0]) | (((uint16_t) Bytes [1]) << 8);
}

static int16_t ReadInt16(const uint8_t *Bytes)
{
return ((int16_t) ReadUInt16(Bytes));
}

static uint32_t ReadUInt32(const uint8_t *Bytes)
{
return ((uint32_t) Bytes [0]) | (((uint32_t) Bytes [1]) << 8) | (((uint32_t) Bytes [2]) << 16) | (((uint32_t) Bytes [3]) << 24);
}

static int32_t ReadInt32(const uint8_t *Bytes)
{
return ((int32_t) ReadUInt32(Bytes));
}


As mentioned before: no guarantees :)

Best regards,
Daniel




Daniel Wippermann

unread,
Apr 7, 2023, 12:32:40 AM4/7/23
to resol...@googlegroups.com
Hi!

Since my mail app did not conserve the indentation I have uploaded the code here:


Best regards,
Daniel


Manu rod

unread,
Apr 7, 2023, 2:20:57 PM4/7/23
to Resol Vbus
Hello. Daniel, thank you very much again. I will try to compile your code, but it will take some time.
At the moment I am with the previous version of the code for ARDUINO, I have already found Relay 1 and Relay 2; And I'm already viewing them, their values, and it's the same position that you indicate in your message, 24 and 25. I'm trying to decode the system Time and System Data, the Time and Date, but I don't know how to handle the "factor " in the Packet List (byte table). In other words, when the frame to be decoded is made up of 4 joined bytes. I've done this implementation, but I don't think it's right. I don't know how to interpret the "Factor" Can you give me some clarification? It would work for the whole board. I do not recognize the digits obtained.
But as soon as I can, I'll try to implement your code.
Thanks and greetings again.

VBus Especifiacion Packet List


52 Version 0.01
53 Version 2.56
54 Time 1
55 Time 256
56 Date 1
57 Date 256
58 Date 65536
59 Date 16777216



Código

//*******************  Frame 7  *******************6*4=24
             
              F = FOffset + FLength * 6;
              Septet = Buffer[F + FSeptet];
              InjectSeptet(Buffer, F, 4);
              Relay1= Buffer[F + 0];
              Relay2= Buffer[F + 1];
              //Relay3= Buffer[F + 2];
              //Relay4= Buffer[F + 3];              
             


//*******************  Frame 14   *******************
             
              F = FOffset + FLength * 13;
     
              Septet = Buffer[F + FSeptet];
              InjectSeptet(Buffer, F, 4);
     
             
              Version=Buffer[F+1] << 8| Buffer[F+0];// Display "100"
              SystemTime = Buffer[F + 3] << 8 | Buffer[F + 2];//??????

                     
              //*******************  Frame 15   *******************
             
              F = FOffset + FLength * 14;
     
              Septet = Buffer[F + FSeptet];
              InjectSeptet(Buffer, F, 4);
     
       SystemDate = (Buffer[F + 1] << 8 | Buffer[F + 0]) + (Buffer[F + 3] << 8 | Buffer[F + 2]); //Factor???

greetings again.

Daniel Wippermann

unread,
Apr 12, 2023, 11:58:48 AM4/12/23
to resol...@googlegroups.com
Hi!

> but I don't know how to handle the "factor " in the Packet List (byte table)

Well, the easiest way to use the „factor“ is to multiply each byte with its corresponding factor and add all those products. For example for the version:

              Version=Buffer[F+1] * 2.56 + Buffer[F+0] * 0.01;// Display perhaps „1.00“ or something in that range :)

But since floating-point numbers can be a pain I normally do the floating-point conversion as few and as late as possible. You can write the code above like this:

              Version=(Buffer[F+1] * 256 + Buffer[F+0]) * 0.01;

In which case you do integer math as much as possible and only in the last step convert it to a scaled floating-point number. And „* 256“ is basically your „<< 8“ because shifting something N bits to the left is basically multiplying with 2^N. And 2^8 is 256.

So this would work as well:

              Version=(Buffer[F+1] << 8| Buffer[F+0]) * 0.01;// Display „1.00“ or „0.99999999997“ or „1.00000000003“ or so...

It is the same for the Date:

    Date = (((uint32_t) Buffer [F + 0])) + (((uint32_t) Buffer [F + 1]) * 256) + (((uint32_t) Buffer [F + 2]) * 65536) + (((uint32_t) Buffer [F + 3]) * 16777216);

Or with bit shift logic:

    Date = (((uint32_t) Buffer [F + 0])) | (((uint32_t) Buffer [F + 1]) << 8) | (((uint32_t) Buffer [F + 2]) << 16) | (((uint32_t) Buffer [F + 3]) << 24);


Date is most certainly a number consisting of YYYYMMDD, or ((Year * 10000) + (Month * 100) + Day). Time is the amount of minutes since midnight, ranging from 0 (00:00) to 1439 (23:59).

Best regards,
    Daniel






Reply all
Reply to author
Forward
0 new messages