Serial data from controller

strantor

Joined Oct 3, 2010
6,782
how close was this screenshot:
1676435592865.png
to this data:
Code:
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x03\x00\x00\x04\x00\x00\xf8\x14\x00\x00\x00\x00\x04\x00\x00\xb8\x03\x00\x00\x00\x00\x99d\x04m'
was 'motor rev' jumping around perhaps? By how much? what about 'bat charge watts' and other new parameters?
 

Ya’akov

Joined Jan 27, 2019
9,069
Neither was I. You can thank whatever undiagnosed disorder I have. Sometimes my mind and an idea get stuck together like two dogs humping, and the only way to get unstuck is to let it run its course. I would have done all this even if I knew you had died last night and would never see it.
My entirely scientific and reliable diagnosis which cannot be inaccurate in any way without the laws of physics needing revision is ADHD... at a guess.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
how close was this screenshot:
View attachment 287587
to this data:
Code:
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x03\x00\x00\x04\x00\x00\xf8\x14\x00\x00\x00\x00\x04\x00\x00\xb8\x03\x00\x00\x00\x00\x99d\x04m'
was 'motor rev' jumping around perhaps? By how much? what about 'bat charge watts' and other new parameters?
It could have been jumping around. The data on the screenshot looks to update about every second. It could also be that the software takes a average of a couple readings. I’ll keep messing around with it later today to see if I can come up with anything. I was hoping it wouldn’t come down to unhooking everything to try and simulate a 3phase generator input to keep the values at a constant rpm but it’s hard to be exact when the numbers could fluctuate. Thanks again for your time.
 

strantor

Joined Oct 3, 2010
6,782
It could have been jumping around. The data on the screenshot looks to update about every second. It could also be that the software takes a average of a couple readings. I’ll keep messing around with it later today to see if I can come up with anything. I was hoping it wouldn’t come down to unhooking everything to try and simulate a 3phase generator input to keep the values at a constant rpm but it’s hard to be exact when the numbers could fluctuate. Thanks again for your time.
If you could just record a video of your screen or something while taking samples that should do it. Sniffed bytes printing onscreen beside software display. Then a log file from the time of the video can be used to correlate the controllerData bytearray to the exact value that was displayed at that time.
 

strantor

Joined Oct 3, 2010
6,782
Just realized I didn't address a few things...
I did notice today I had one log from the sniffer that was 198 bytes for some reason. I’m not sure if it was a fluke or not because it seems to always work otherwise with 50.
That would indicate a good reason to go to a time-based trigger for end of message. Was this 198 byte message sent in response to the Chinese software or your python script? If it was the Chinese software, was the command different as well? Did it happen only once? In what time span? Can you post the 198 byte message?

Do you think the data would fall inline like we see the battery voltage data and kWh spaced just like the software gui?
It would be logical but by no means guaranteed.

rpm was recording around 370rpms but the index location for signed and unsigned int was 1024. It is a 18pole 3 phase generator so I’m not sure if that’s possible to get the math to come out right.
Is there an RPM sensor (encoder, inductive prox, hall sensor, or similar)? If so, please provide details (type, pulses per rev). If not then it may be using generator output frequency.



I also have a feeling that the Watt output fields are calculated by the software from the voltage and current being sent from the controller.
You may be correct.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
There may be some kind of data error I am running into. I have changed my python script like you suggested to read for a set amount of time (based on the response lengths of 200ms, I set it to read for 500ms to be sure it would catch longer data responses) and it is still getting 50 bytes of data with or without the turbine spinning. However, when the turbine is spinning, running the sniffer and software I am getting 200 bytes. This is one of the responses with 200 bytes:
Code:
\0x55\0x2E\0xFF\0x01\0x11\0x00\0x00\0x25\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x1D\0x15\0x3D\0x01\0xB1\0x06\0x06\0x00\0x00\0xBC\0x14\0x20\0x00\0xAE\0x00\0x06\0x00\0x00\0x72\0x01\0x00\0x00\0x00\0x00\0x89\0x64\0x05\0x95
After running it through a couple of the structs, this is the output which doesn't look correct:
Code:
Polling Controller...
len(controllerData) =  200 and screenshot shows 24 values on the screen
could it be unsigned INTs? : (30768, 17990, 30720, 16705, 30720, 13621, 30720, 17714, 30720, 17990, 30720, 12592, 30720, 12593, 30720, 12336, 30720, 12336, 30720, 13618, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 17457, 30720, 13617, 30720, 17459, 30720, 12592, 30720, 12610, 30720, 13872, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 17218, 30720, 13361, 30720, 12338, 30720, 12336, 30720, 17729, 30720, 12336, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 12855, 30720, 12592, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 14648, 30720, 13366, 30720, 13616, 30720, 13625)
could it be signed INTs? :  (30768, 17990, 30720, 16705, 30720, 13621, 30720, 17714, 30720, 17990, 30720, 12592, 30720, 12593, 30720, 12336, 30720, 12336, 30720, 13618, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 17457, 30720, 13617, 30720, 17459, 30720, 12592, 30720, 12610, 30720, 13872, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 17218, 30720, 13361, 30720, 12338, 30720, 12336, 30720, 17729, 30720, 12336, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 12855, 30720, 12592, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 14648, 30720, 13366, 30720, 13616, 30720, 13625)
Formatting data...
could it be unsigned INTs? : (18040, 70, 16760, 65, 13688, 53, 12920, 69, 18040, 70, 12408, 49, 12664, 49, 12408, 48, 12408, 48, 12920, 53, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12664, 68, 12664, 53, 13176, 68, 12408, 49, 17016, 49, 12408, 54, 12408, 54, 12408, 48, 12408, 48, 17016, 67, 12664, 52, 12920, 48, 12408, 48, 16760, 69, 12408, 48, 12408, 54, 12408, 48, 12408, 48, 14200, 50, 12408, 49, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 14456, 57, 13944, 52, 12408, 53, 14712, 12341)
could it be signed INTs? :  (18040, 70, 16760, 65, 13688, 53, 12920, 69, 18040, 70, 12408, 49, 12664, 49, 12408, 48, 12408, 48, 12920, 53, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12664, 68, 12664, 53, 13176, 68, 12408, 49, 17016, 49, 12408, 54, 12408, 54, 12408, 48, 12408, 48, 17016, 67, 12664, 52, 12920, 48, 12408, 48, 16760, 69, 12408, 48, 12408, 54, 12408, 48, 12408, 48, 14200, 50, 12408, 49, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 14456, 57, 13944, 52, 12408, 53, 14712, 12341)
 

strantor

Joined Oct 3, 2010
6,782
There may be some kind of data error I am running into. I have changed my python script like you suggested to read for a set amount of time (based on the response lengths of 200ms, I set it to read for 500ms to be sure it would catch longer data responses) and it is still getting 50 bytes of data with or without the turbine spinning. However, when the turbine is spinning, running the sniffer and software I am getting 200 bytes. This is one of the responses with 200 bytes:
Code:
\0x55\0x2E\0xFF\0x01\0x11\0x00\0x00\0x25\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x1D\0x15\0x3D\0x01\0xB1\0x06\0x06\0x00\0x00\0xBC\0x14\0x20\0x00\0xAE\0x00\0x06\0x00\0x00\0x72\0x01\0x00\0x00\0x00\0x00\0x89\0x64\0x05\0x95
After running it through a couple of the structs, this is the output which doesn't look correct:
Code:
Polling Controller...
len(controllerData) =  200 and screenshot shows 24 values on the screen
could it be unsigned INTs? : (30768, 17990, 30720, 16705, 30720, 13621, 30720, 17714, 30720, 17990, 30720, 12592, 30720, 12593, 30720, 12336, 30720, 12336, 30720, 13618, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 17457, 30720, 13617, 30720, 17459, 30720, 12592, 30720, 12610, 30720, 13872, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 17218, 30720, 13361, 30720, 12338, 30720, 12336, 30720, 17729, 30720, 12336, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 12855, 30720, 12592, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 14648, 30720, 13366, 30720, 13616, 30720, 13625)
could it be signed INTs? :  (30768, 17990, 30720, 16705, 30720, 13621, 30720, 17714, 30720, 17990, 30720, 12592, 30720, 12593, 30720, 12336, 30720, 12336, 30720, 13618, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 17457, 30720, 13617, 30720, 17459, 30720, 12592, 30720, 12610, 30720, 13872, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 17218, 30720, 13361, 30720, 12338, 30720, 12336, 30720, 17729, 30720, 12336, 30720, 13872, 30720, 12336, 30720, 12336, 30720, 12855, 30720, 12592, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 12336, 30720, 14648, 30720, 13366, 30720, 13616, 30720, 13625)
Formatting data...
could it be unsigned INTs? : (18040, 70, 16760, 65, 13688, 53, 12920, 69, 18040, 70, 12408, 49, 12664, 49, 12408, 48, 12408, 48, 12920, 53, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12664, 68, 12664, 53, 13176, 68, 12408, 49, 17016, 49, 12408, 54, 12408, 54, 12408, 48, 12408, 48, 17016, 67, 12664, 52, 12920, 48, 12408, 48, 16760, 69, 12408, 48, 12408, 54, 12408, 48, 12408, 48, 14200, 50, 12408, 49, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 14456, 57, 13944, 52, 12408, 53, 14712, 12341)
could it be signed INTs? :  (18040, 70, 16760, 65, 13688, 53, 12920, 69, 18040, 70, 12408, 49, 12664, 49, 12408, 48, 12408, 48, 12920, 53, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 12664, 68, 12664, 53, 13176, 68, 12408, 49, 17016, 49, 12408, 54, 12408, 54, 12408, 48, 12408, 48, 17016, 67, 12664, 52, 12920, 48, 12408, 48, 16760, 69, 12408, 48, 12408, 54, 12408, 48, 12408, 48, 14200, 50, 12408, 49, 12408, 48, 12408, 48, 12408, 48, 12408, 48, 14456, 57, 13944, 52, 12408, 53, 14712, 12341)
Ok that is weird. I'm pretty sure those are 32 bit numbers since there is a 4-byte pattern there. but I have no idea whether float, signed/unsigned int, whatever. And a lot of the data is repeated. Here's something you can use to play with the data more easily:
Python:
longData =    bytearray(b'\0x55\0x2E\0xFF\0x01\0x11\0x00\0x00\0x25\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x00\0x1D\0x15\0x3D\0x01\0xB1\0x06\0x06\0x00\0x00\0xBC\0x14\0x20\0x00\0xAE\0x00\0x06\0x00\0x00\0x72\0x01\0x00\0x00\0x00\0x00\0x89\0x64\0x05\0x95')

def decodeByteArray(letter,length,data,note):
    ret = []
    for i in range(0,len(data)-3):
        end = i+length
        unknown1 = data[i:end]
        a = struct.unpack(letter * ((len(unknown1)) // length), unknown1)[0]
        ret.append(a)
        print(note,"first Byte:",str(i)+", last Byte:",str(end-1)+", data:",a)
    return ret

# uncomment to see other formats
# numbers = decodeByteArray("i",4,longData,"32 bit Signed Int...")
# numbers = decodeByteArray("I",4,longData,"32 bit Unsigned Int...")
# numbers = decodeByteArray("h",2,longData,"16 bit Signed Int...")
# numbers = decodeByteArray("H",2,longData,"16 bit Unsigned Int...")
# numbers = decodeByteArray("s",1,longData,"8 bit char...")
numbers = decodeByteArray("f",4,longData,"Float...")
for i in range(0,len(numbers)):
    if i%4 == 0:
        print(i,numbers[i])
Here's what it looks like as floats. Any of these numbers look familiar?
Code:
0 6.760237738490105e-07
4 2855.5
8 12702.0
12 2.567958290455863e-09
16 2.5825102056842297e-09
20 6.419895726139657e-10
24 6.419895726139657e-10
28 6.648479029536247e-07
32 6.419895726139657e-10
36 6.419895726139657e-10
40 6.419895726139657e-10
44 6.419895726139657e-10
48 6.419895726139657e-10
52 6.419895726139657e-10
56 6.419895726139657e-10
60 6.419895726139657e-10
64 6.419895726139657e-10
68 6.419895726139657e-10
72 6.419895726139657e-10
76 6.419895726139657e-10
80 709.875
84 6.611226126551628e-07
88 717.875
92 2.567958290455863e-09
96 2.8298927645664662e-09
100 2.6295892894268036e-06
104 2.6295892894268036e-06
108 6.419895726139657e-10
112 6.419895726139657e-10
116 194.46875
120 1.652806531637907e-07
124 6.492655302281491e-10
128 6.419895726139657e-10
132 3095.5
136 6.419895726139657e-10
140 2.6295892894268036e-06
144 6.419895726139657e-10
148 6.419895726139657e-10
152 1.0679286788217723e-08
156 2.567958290455863e-09
160 6.419895726139657e-10
164 6.419895726139657e-10
168 6.419895726139657e-10
172 6.419895726139657e-10
176 0.00017592310905456543
180 1.699372660368681e-07
184 6.573973223567009e-07
188 6.909249350428581e-07



Process finished with exit code 0
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
Nothing stands out with that. I find it hard to believe 2 values would work perfectly using the int filter you provided but no other ones do. You would think it would be easier to program it to use all the same type. Another thing about the RPM format. It may be displaying as frequency and the GUI does the freq*120/poles conversion or since only the controller only knows the number of poles, it may be displaying freq/poles and the software * 120.
 

strantor

Joined Oct 3, 2010
6,782
Nothing stands out with that. I find it hard to believe 2 values would work perfectly using the int filter you provided but no other ones do. You would think it would be easier to program it to use all the same type. Another thing about the RPM format. It may be displaying as frequency and the GUI does the freq*120/poles conversion or since only the controller only knows the number of poles, it may be displaying freq/poles and the software * 120.
It would be quite normal in my experience that different values are formatted differently. As what most people would call a "Systems Integrator" I work with data exchange between industrial equipment on a daily basis. I don't normally have to do this forensic investigation of exchanges; I am normally the one programming the devices on either end, so I know exactly what is being sent. It is more often than not, a buffet of different data types. I might construct a message containing (12) 16-bit integers, (5) 32-bit integers, (7) 32-bit floats, and string represented by an array of (50) 8-bit ASCII Characters, and a two 32-bit integers that represent the status of 64 digital signals, and the raw bytes wouldn't look any different that what we are seeing here (just a lot longer). These values might be sent as scaled values or they might require some scaling at the other end.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
That makes sense how you know so much about this. I am trying to find the best way to simulate rpm without taking my turbine down and apart and coupled to a known rpm motor. I do have some ESCs from rc brushless motors but when I hooked the output to my oscilloscope it was not close to a sine wave so I didn’t want to take the chance on messing up my controller.
 

strantor

Joined Oct 3, 2010
6,782
I am trying to find the best way to simulate rpm without taking my turbine down and apart and coupled to a known rpm motor. I do have some ESCs from rc brushless motors but when I hooked the output to my oscilloscope it was not close to a sine wave so I didn’t want to take the chance on messing up my controller.
It should be sufficient to make a video recording of the software display at same time as the serial data is printing beside it (with corresponding log file). Then frame-by-frame we can see how for example 1 RPM or 10 RPM of the turbine changes the message.

This issue is that we have only one bytearray from one day and another bytearray from another day, and several values changed during that time, and we can't tell which bytes correspond to which changed value. And it isn't clear if the screenshot coincides precisely with the data in the bytearray. We might be looking for certain values in the data that aren't the right values we should be looking for, because that's what we see in the screenshot.

A video should clear all this up.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
I have tried that yesterday, the issue is when using the software and the logic sniffer, it doesn’t display it in real time, it does the sampling and then you can view it after the sample interval. I tried recording the screen for 1 response and that is what I used when I sent the last screenshot. It did seem funky , like the info on the software values were more fluid than the one response received. This is with the logic view software that came with it, I have not tried pulse view yet to see if that’s different. If I use the python program to gather the data, the software can’t be used at the same time. So it would still be a guess. Also the sample rate the software polls the controller is in 2 second intervals if that means anything.
 

strantor

Joined Oct 3, 2010
6,782
I have tried that yesterday, the issue is when using the software and the logic sniffer, it doesn’t display it in real time, it does the sampling and then you can view it after the sample interval. I tried recording the screen for 1 response and that is what I used when I sent the last screenshot. It did seem funky , like the info on the software values were more fluid than the one response received. This is with the logic view software that came with it, I have not tried pulse view yet to see if that’s different. If I use the python program to gather the data, the software can’t be used at the same time. So it would still be a guess. Also the sample rate the software polls the controller is in 2 second intervals if that means anything.
I see. Is it possible to use either sniffer (hardware or software) as a 2nd com port? So that the python program can be printing out the message in the background? What if you just jumper the TX wire from the inverter to the RX terminal a second serial port on you computer?
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
I see. Is it possible to use either sniffer (hardware or software) as a 2nd com port? So that the python program can be printing out the message in the background? What if you just jumper the TX wire from the inverter to the RX terminal a second serial port on you computer?
I will have to try that and find out.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
I see. Is it possible to use either sniffer (hardware or software) as a 2nd com port? So that the python program can be printing out the message in the background? What if you just jumper the TX wire from the inverter to the RX terminal a second serial port on you computer?
I used a 2nd usb to serial like you suggested, wrote a python script to run in loop to print out the serial data and it is working. I will have to wait until we get some wind later today to do the screen recording.
 

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
Here is a video. You will have to change the extention to .mov. It is only 480p due to the file size. In the video, only 2 values are changing, RPM and Wind Average DC. Here is also the shell print out from the video some of the bits get cut off due to polling it for a set # of seconds. If this way doesn't work for you I can have it try to read 50bits instead of for the set time:
Code:
Polling Controller...
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00'
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x02\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x1e\x00\x00\x00\x00\x00\x89d\x03\x96'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x14\x00\x00\x00\x00\x00\x89d\x03\xbb'
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x14\x00\x00\x00\x00\x00\x89d\x03\xbb'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xf0'
Response from controller: b'\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x1a\x00\x00\x00\x00\x00\x89d\x048'
Response from controller: b'\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x1a\x00\x00\x00\x00\x00\x89d\x048'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd2\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x18\x00\x00\x00\x00\x00\x89d\x04\x18'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00'
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x07\x00\x00\x00\x00\x00\x89d\x034'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x02\x00\x00\x00\x00\x00\x89d\x03/'
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x02\x00\x00\x00\x00\x00\x89d\x03/'
Response from controller: b''
Response from controller: b''
Response from controller: b''
Response from controller: b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x00'
Response from controller: b'\x00\x00\x00\x00\x00\x89d\x03-'
Response from controller: b'\x00\x00\x00\x00\x00\x89d\x03-'
 

Attachments

Thread Starter

Slvrsky07

Joined Jan 29, 2023
51
I do see the rpm may be the 5th to the last bit of the non shifted pattern. I will have to keep testing with different RPMs.
It does seem to fit so far that 40:42 not bit-shifted INTs seem to be RPM. I am hoping your idea works for the others and they are all just INTs. I will keep you posted.
 

strantor

Joined Oct 3, 2010
6,782
It does seem to fit so far that 40:42 not bit-shifted INTs seem to be RPM. I am hoping your idea works for the others and they are all just INTs. I will keep you posted.
agreed. And wind DCV is [22:24]. It fits very well with observations from the video. But not with screenshots from before. I suspect screenshots from before are not trustworthy. Only video is trustworthy going forward. If you can record in higher resolution it will be very helpful. I realize you won't be able to upload larger videos here but if you have google drive or something you can upload elsewhere and post a link.
Here's what I got (see notes at end)
Python:
import struct
import pprint

# from the 7 complete 50-byte messages in the video:
log = [bytearray(b'')]*7
log[0] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00I\x02\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x1e\x00\x00\x00\x00\x00\x89d\x03\x96')
log[1] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x14\x00\x00\x00\x00\x00\x89d\x03\xbb')
log[2] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00y\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x14\x00\x00\x00\x00\x00\x89d\x03\xbb')
log[3] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xd2\x01\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x18\x00\x00\x00\x00\x00\x89d\x04\x18')
log[4] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x06\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x07\x00\x00\x00\x00\x00\x89d\x034')
log[5] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x02\x00\x00\x00\x00\x00\x89d\x03/')
log[6] = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x80\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00&\x00\x00\xbc\x14\x00\x00\x00\x00\x06\x00\x00\x02\x00\x00\x00\x00\x00\x89d\x03/')
# data from previous tests
oldResponse = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x04\x00\x00\xc8\x14\x00\x00\x00\x00\x04\x00\x00\x00\x00\x00\x00\x00\x00\x89d\x035')
newResponse = bytearray(b'\xff\xaaU.\xff\x01\x11\x00\x00%\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00:\x03\x00\x00\x04\x00\x00\xf8\x14\x00\x00\x00\x00\x04\x00\x00\xb8\x03\x00\x00\x00\x00\x99d\x04m')

# observations from the video, displayed in the software, values corresponding to the messages above
windRPM = [0]*7
windRPM[0] = 30
windRPM[1] = 20
windRPM[2] = 25 #26?
windRPM[3] = 24
windRPM[4] = 7
windRPM[5] = 2
windRPM[6] = 0
windDCV = [0]*7
windDCV[0] = 5.8
windDCV[1] = 3.7
windDCV[2] = 4.9
windDCV[3] = 4.6
windDCV[4] = 0.0
windDCV[5] = 0.0
windDCV[6] = 0.0

# Show what bytes changed between the (7) 50-byte messages:
for i in range(0,6):
    for a in range(0,50):
        if log[i][a]!=log[i+1][a]:
            print("log["+str(i)+"], byte #"+str(a)+" = "+str(log[i][a])+", log["+str(i+1)+"], byte #"+str(a)+" = "+str(log[i+1][a]))

def calcKnownVals(data):
    ret = {}
    batV = data[31:33]
    ret["batV_decoded"] = struct.unpack("h" * ((len(batV)) // 2), batV)[0]/100
    windAvgDCV = data[22:24]
    ret["windDCV_decoded"] = struct.unpack("h" * ((len(windAvgDCV)) // 2), windAvgDCV)[0]/100
    MotorRev = data[40:42]
    ret['motorRev_decoded'] = struct.unpack("h" * ((len(MotorRev)) // 2), MotorRev)[0]
    ret['inexplicableBytes']={}
    ret['inexplicableBytes'][12]=data[12]
    ret['inexplicableBytes'][28]=data[28]
    ret['inexplicableBytes'][48]=data[48]
    ret['inexplicableBytes'][49]=data[49]
    return ret
valuesDict = {}
for i in range(0,7):
    valuesDict["log[" + str(i) + "]     "] = calcKnownVals(log[i])
    valuesDict["log[" + str(i) + "]     "]['windDCV_observed']=windDCV[i]
    valuesDict["log[" + str(i) + "]     "]['motorRev_observed']=windRPM[i]

valuesDict["oldResponse"] = calcKnownVals(oldResponse)
valuesDict["oldResponse"]['windDCV_observed'] = 0.0 # per screenshot
valuesDict["oldResponse"]['motorRev_observed'] = 0 # per screenshot
valuesDict["newResponse"] = calcKnownVals(newResponse)
valuesDict["newResponse"]['windDCV_observed'] = 54.6 # per screenshot
valuesDict["newResponse"]['motorRev_observed'] = 370 # per screenshot
pprint.pprint(valuesDict)

# Bytes that changed during this experiment:                      12,22,23,28,40,  48,49
# Byte changes accounted for in this experiment:                     22,23,  ,40,41
# Inexplicable byte changes with no corresponding display change: 12,      28,      48,49
# - Byte # 12 is observed at either 0 or 128, which is toggling of bit # 7 of a byte, so this most likely corresponds
#     to a digital signal. Digital input maybe? could be anything
# - Byte # 49 is most likely a checksum and can be ignored.
# - Byte # 48 maybe part of checksum, not sure. Changes between 3 and 4
# - Byte # 28...? Mystery for now. Could be a digital signal but probably not
Code:
Z:\G\solarData\venv\Scripts\python.exe Z:/G/solarData/decodeFromMov2.py
log[0], byte #22 = 73, log[1], byte #22 = 121
log[0], byte #23 = 2, log[1], byte #23 = 1
log[0], byte #40 = 30, log[1], byte #40 = 20
log[0], byte #49 = 150, log[1], byte #49 = 187
log[2], byte #22 = 121, log[3], byte #22 = 210
log[2], byte #40 = 20, log[3], byte #40 = 24
log[2], byte #48 = 3, log[3], byte #48 = 4
log[2], byte #49 = 187, log[3], byte #49 = 24
log[3], byte #22 = 210, log[4], byte #22 = 0
log[3], byte #23 = 1, log[4], byte #23 = 0
log[3], byte #40 = 24, log[4], byte #40 = 7
log[3], byte #48 = 4, log[4], byte #48 = 3
log[3], byte #49 = 24, log[4], byte #49 = 52
log[4], byte #12 = 0, log[5], byte #12 = 128
log[4], byte #28 = 6, log[5], byte #28 = 38
log[4], byte #40 = 7, log[5], byte #40 = 2
log[4], byte #49 = 52, log[5], byte #49 = 47
{'log[0]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 0, 28: 6, 48: 3, 49: 150},
                 'motorRev_decoded': 30,
                 'motorRev_observed': 30,
                 'windDCV_decoded': 5.85,
                 'windDCV_observed': 5.8},
'log[1]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 0, 28: 6, 48: 3, 49: 187},
                 'motorRev_decoded': 20,
                 'motorRev_observed': 20,
                 'windDCV_decoded': 3.77,
                 'windDCV_observed': 3.7},
'log[2]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 0, 28: 6, 48: 3, 49: 187},
                 'motorRev_decoded': 20,
                 'motorRev_observed': 25,
                 'windDCV_decoded': 3.77,
                 'windDCV_observed': 4.9},
'log[3]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 0, 28: 6, 48: 4, 49: 24},
                 'motorRev_decoded': 24,
                 'motorRev_observed': 24,
                 'windDCV_decoded': 4.66,
                 'windDCV_observed': 4.6},
'log[4]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 0, 28: 6, 48: 3, 49: 52},
                 'motorRev_decoded': 7,
                 'motorRev_observed': 7,
                 'windDCV_decoded': 0.0,
                 'windDCV_observed': 0.0},
'log[5]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 128, 28: 38, 48: 3, 49: 47},
                 'motorRev_decoded': 2,
                 'motorRev_observed': 2,
                 'windDCV_decoded': 0.0,
                 'windDCV_observed': 0.0},
'log[6]     ': {'batV_decoded': 53.08,
                 'inexplicableBytes': {12: 128, 28: 38, 48: 3, 49: 47},
                 'motorRev_decoded': 2,
                 'motorRev_observed': 0,
                 'windDCV_decoded': 0.0,
                 'windDCV_observed': 0.0},
'newResponse': {'batV_decoded': 53.68,
                 'inexplicableBytes': {12: 0, 28: 4, 48: 4, 49: 109},
                 'motorRev_decoded': 952,
                 'motorRev_observed': 370,
                 'windDCV_decoded': 0.0,
                 'windDCV_observed': 54.6},
'oldResponse': {'batV_decoded': 53.2,
                 'inexplicableBytes': {12: 0, 28: 4, 48: 3, 49: 53},
                 'motorRev_decoded': 0,
                 'motorRev_observed': 0,
                 'windDCV_decoded': 0.0,
                 'windDCV_observed': 0.0}}

Process finished with exit code 0
Note lines 63-66 (data from your most recent screenshot, prior to the video).
 
Last edited:
Top