Customized serial communication driver in Merbon RT

Programming in the ST language (structured text) offers flexibility to application engineers. One of frequently demanded functions is development of 3rd party communication drivers. The following example (download as Merbon IDE project here) shows how a customized driver for Pozyton sEAB energy meters looks like.

These meters communicate over a serial line. The communication protocol is based on the IEC 62056-21 standard, however, it is slightly different, and therefore a special function for data readout had to be written. The complete communication description can be found on the Pozyton web site: www.pozyton.com.pl/polskiepdf/protokoly/ptd_sea-b.pdf.

The communication is state-based, and the list of possible states is in the comments – see the Pozyton_seaB block, line 270 and on:

// Communication states:
// 0 – Initialisation
// 1 – Write ID
// 2 – Communication status
// 3 – Readout
// 4 – Writing HELLO
// 5 – Communication status
// 6 – Reading (ID)
// 7 – Writing command for data
// 8 – Communication status + waiting
// 9 – Closing of the port (obsolete)
// 10 – Waiting (5s)
// 11 – Communication status (obsolete)
// 12 – Data reading
// 13 – Closing of the port
// 14 – Finishing of communication
// 15 – Stand By – waiting for the next communication window

Step 0 initiates and opens the communication port, step 1 writes a request:

/Attt.nnnnnnn[CR][LF]

where ttt.nnnnnnn is the meter serial number. (All meters also respond to serial number of 000.0000000, which can be used if there is only a single meter on the bus.)

Step 2 waits until the request is sent, and step 3 receives the reply. The reply looks similarly to the request:

/gttt.nnnnnnn[CR][LF]

The next step is step 4, which is a standard command according to IEC 62056-21, a
/?![CR][LF] sequence. Step 6 receives the meter response and only checks if it is properly terminated by[CR][LF]. Then the step 7 follows, which asks for data according to the Pozyton documentation, issuing a command for switch-over to the values transmitting mode:

[ACK]054[CR][LF]

In step 8, the program waits until all data are sent, and then waits for 5 seconds in step 10, before it starts parsing the received data in step 12. The data parsing, or disassembling of the string to individual values, is done by the parseData function, which identifies the sequences according to  OBIS codes (as described in the IEC 62056-21 standard) in the string. The sequences have form of:

y.8.0.(eeeeee.ee)[CR][LF]

where y is a parameter which tells what type of energy the value is bringing:

y energy
0 P+ (active consumed)
1 P- (active produced)
2 Q+ (reactive consumed)
3 Q- (reactive produced)

„eeeeee.ee“ is the value which we need to read, and „0“ at the 3rd position means that the value is sum of three energies in the L1 to L3 phases (this is described in the Pozyton communication description).

The parsing of the whole string to individual values is done in the loop starting at line 472 of the code:

while (received > 1) do
received := last_received - parseData(dataLen:=last_received,
a => a, b => b, c => c, d => d, value => val);
// End of communication - parsing was not executed - no data available
if (received = last_received) then
exit;
end_if;
// 0.8.0
if (a = 0 and b = 8 and c = 0 and d < 0) then
actual_energy_p_plus := val;
end_if;
// 1.8.0
if (a = 1 and b = 8 and c = 0 and d < 0) then
actual_energy_p_minus := val;
end_if;
// 2.8.0
if (a = 2 and b = 8 and c = 0 and d < 0) then
actual_energy_q_plus := val;
end_if;
//3.8.0
if (a = 3 and b = 8 and c = 0 and d < 0) then
actual_energy_q_minus := val;
end_if;
last_received := received
end_while;

The variable d would be 0 or higher if the variable identifier would be in a form of y.8.0.x. Such identifier would not fit the values we want to read out, and the read value val would not be assigned to the respective energy variable. Finally, in steps 13 to 15, the port is closed, and the program waits for the next communication cycle.

See the comments in the code for a more detailed description.

pozyton_blok

The function is written as a function block, the inputs of which (communication port, readout interval, meter serial number) are set as constants – they do not change at the program execution time. The outputs of the block show the readout values. Other variables, like comm_error, tout, and write_block, are used to detect communication errors and for mutual blocks interlocking in case of more meters at the same serial line.