Details of the Fnirsi DPS-150 power supply control protocol

In the previous article, I began to analyze the control protocol of the Fnirsi DPS-150 power supply. The packet format was analyzed, commands and responses to them were identified, and a draft analysis of the internals of the proprietary control program was made. I promised to show the details of the process later. Well, that time has come. Today we will get command and response tables as complete as required for real work.

Sequence of Analysis

So, we study the program using the .Net Reflector decompiler. When studying the program, it is very desirable to go sequentially. For example, first study the commands, then the responses. Or vice versa, first the responses, then the commands. But the main thing is to go sequentially. Alas! When "digging" with missing debug information, this will not work. We will always come across something incomprehensible. And in such situations, it is very important not to try to break through a brick wall, otherwise you can first lose a lot of time, and then lose interest in the topic altogether.

Can't understand the command? No problem! Let's move on to the next one. Too many incomprehensible commands? Again, no problem, let's look at the responses. In addition to the strings in the program, we also check the logs of the analyzer. Sometimes they help too. For example, we see such a fragment in the log when opening the block with the proprietary program:

Fnirsi DPS-150 power supply connection diagram

...are found only in this context:

Fnirsi DPS-150 control command sequence diagram

The first link is filling its body, the second link just shows that the command is sent during the connection initialization among other commands:

Fnirsi DPS-150 control protocol parameter table

What are UserSelectBox21 and UserSelectBox22? Here they are!

Example code for controlling the Fnirsi DPS-150 power supply

We already know that the juiciest result is given by the InitializeComponent() function. Let's go to it and see which dialog we are in.

Voltage and current change graph in Fnirsi DPS-150

Which translates to "Save current group".

Looking around, where do we have groups in the program... Here they are!

We enter, say, group 5, and see there:

Internal structure diagram of the Fnirsi DPS-150 power supply

We click "Save", and catch such commands in the log:

Description of the Fnirsi DPS-150 control interface

Here is the third command in the sequence — exactly the same COMMAND_3, the code of which in the log is 0xff. What does it do? And what kind of sheet does it return in response? Let's gradually move on to it.

All data from the device at once

So, when the device is opened, the COMMAND_3 command is sent, to which a simply huge response comes:

Example of using the Fnirsi DPS-150 control protocol

0x8c bytes came in the dump. The code that parses this is simply huge. In the new editor, I had trouble hiding it under the cut, so I'll just give the beginning. Those who are really interested will see the full version when they open everything in Reflector themselves.

public static void setAllData(byte[] buffer)
{
buffer = getDataArray(buffer);
Data37 = BitConverter.ToSingle(buffer, 0x6f);
Data38 = BitConverter.ToSingle(buffer, 0x73);
Data1 = BitConverter.ToSingle(buffer, 0);
Data2 = BitConverter.ToSingle(buffer, 4);
Data3 = BitConverter.ToSingle(buffer, 8);
Data4 = BitConverter.ToSingle(buffer, 12);
...
Data41 = BitConverter.ToSingle(buffer, 0x7f);
Data42 = BitConverter.ToSingle(buffer, 0x83);
Data43 = BitConverter.ToSingle(buffer, 0x87);
}

It analyzes just about 0x8c bytes (to be exact, 0x8b, but the dump clearly has an alignment correction). So let's assume that these are the fields.

After minimal comparison, we find that this is indeed the case. In fact, the program uses some of the fields from here as the contents of the EEPROM. We saw above how voltages and currents are saved for groups. And to load them, this command is used. In the operation of its problem-oriented program, it is not particularly needed. But we figured it out. If the purpose of the command is unknown... What if it is vital? Now it is clear that there is no point in digging deeper.

Block addressing

I think this article will be read for two reasons:

1) she was recently published, so the reader just found her in the list;
2) months or years later, someone typed the power supply model into a search engine to find a description of the protocol.

In the first case, the reader will not go into the smallest details. He needs to be shown how the protocol is opened, but not with the accuracy of every nook and cranny of the code. Someone will simply scroll through the general features like a detective, someone may even consolidate the skill by finding the program on the manufacturer's website Fnirsi. The other day she moved to their Software section, for some reason she used to lie around like Firmware. But again, no one will remember and go through all the little things for a block that he does not have and is unlikely to have. General skills are needed. And there is no point in going down to the smallest details.

And whoever came for the data, he is already shaking with indignation: "I will not try all this, give me the command tables!".

So let me show you another interesting thing, and I'll wrap up the parsing process. I'll try to speculate about device addressing.

In general, you can select the block address in the program:

Comparison of control protocols of various power supplies

Just before closing the port, you should send:

Diagram of connecting external devices to the Fnirsi DPS-150

The initialization sequence looks like this:

Example of setting power supply parameters for the Fnirsi DPS-150

Responses

The response table looks like this:

Code

Name

Type

Purpose

0xc0

Data1

float

Input voltage

0xc3

Data4

Data5

Data6

float

float

float

Active voltage

Active current

Active power

0xc4

Data7

float

Temperature

0xd9

Data28

float

A*h (I think the parameter is translated incorrectly)

0xda

Data29

Float

W*h (I think the parameter is translated incorrectly)

0xdb

Data30

uint8

Output state (open or closed)

0xdc

Data31

uint8

LED NORM (no fault)

0xdd

Data32

uint8

Voltage stabilization (01) or current (00)

0xde

Data33

String

Model

0xdf

Data34

String

Usage not found

0xe0

Data35

string

Firmware version

0xe1

Data36

uint8

Some index, it is not yet clear which one. Is it the device address? Until it runs in the air, we do not try to send any commands. If it has not been there for a long time, we disconnect

0xe2

Data37

float

Upper voltage limit that can be requested (input minus drop on the stabilizer)

0xe3

Data38

float

Upper current limit that can be set

0xff

-

-

All data in bulk

Conclusion

We got acquainted with advanced methods of protocol analysis using the example of the Fnirsi DPS-150 power supply. The information provided is sufficient to develop your own program to control the unit.

The program developed by the author is very specific, so it will not be presented in its pure form, but there are plans to make an article explaining an interesting technology using this protocol as an example. There will be real code. Of course, if the topic is of interest to the reader.

Comments