Skip to content
Start free evaluation

The 19 function codes and diagnostics

In this tutorial you run every function code in one headless simulator. It’s configured as an RTU server but never connected, so you need no serial port. RTU lets you run the serial-line-only functions (07, 08, 11, 12 and 17); in a TCP configuration they return exception 01.

Every result is a local result of execute. To send the same PDUs to a real device, use request on a client.

  • Prepare a model with the four tables, file records, a FIFO queue and device identification objects.
  • Check the request and response bytes of all 19 function codes.
  • See the diagnostics counters, listen-only mode and recovery, broadcasts and requests for other units.
  • Tell apart requests that cause exceptions 01, 02 and 03.
  • The PDComm Modbus SDK and the MODBUS_SDK variable (see the quickstart)
  • One terminal

Start the headless simulator:

터미널 창
"$MODBUS_SDK/bin/pdcomm-modbus-headless"

Configure an RTU server and replace the whole model. Enter each command on one line:

{"action":"configure","config":{"transport":"rtu","role":"server","address":"127.0.0.1:0","port":"","unit":1,"baud":19200,"parity":"even","stop_bits":1,"timeout_ms":1000}}
{"action":"model_set","model":{"coils":{"start":0,"values":[0,0,0,0,0,0,0,0]},"discrete_inputs":{"start":0,"values":[1,0,1,0,0,0,0,0]},"holding_registers":{"start":0,"values":[42,4660,0,0]},"input_registers":{"start":0,"values":[123,0,0,0]},"files":{"1":[0,0,0,0]},"fifos":{"0":[18,52]},"objects":{"0":[80,68,67],"1":[77,66],"2":[49]},"server_id":[1,255],"exception_status":5,"individual_access":true}}

model_set returns {"ok":true,"result":{"updated":true}}. The model contains:

Item Value
Coils 0–7 All 0
Discrete inputs 0–7 1, 0, 1, 0, 0, 0, 0, 0
Holding registers 0–3 42, 4660 (0x1234), 0, 0
Input registers 0–3 123, 0, 0, 0
File 1 Records 0–3, all 0
FIFO 0 18, 52
Device identification objects 0 = PDC, 1 = MB, 2 = 1
Server ID 01 FF (ID 1, running)
Exception status 5
  • model_set needs every member; a missing one fails with an error such as missing field `discrete_inputs` .
  • A value such as 2 in a bit table fails with Bit table values must be zero or one.
  • Device identification objects 0, 1 and 2 are mandatory, and the reserved range 7–127 isn’t allowed. Violations fail with Invalid file, FIFO or device identification model.
  • A failed model_set leaves the existing model unchanged.

Run the requests in this table from top to bottom, each as {"action":"execute","pdu":"<request PDU>"}. Responses are arrays of decimal bytes; run them in order to get the same values.

Step Function Request PDU response Notes
1 01 Read Coils 0100000001 [1,1,0] Coil 0 is off.
2 02 Read Discrete Inputs 0200000003 [2,1,5] 1, 0, 1 packed as 0b101.
3 03 Read Holding Registers 0300000001 [3,2,0,42]
4 04 Read Input Registers 0400000001 [4,2,0,123]
5 05 Write Single Coil 050000FF00 [5,0,0,255,0] Echoes the request.
6 01 Read Coils 0100000001 [1,1,1] Coil 0 is on now.
7 06 Write Single Register 0600000009 [6,0,0,0,9]
8 03 Read Holding Registers 0300000001 [3,2,0,9]
9 07 Read Exception Status 07 [7,5] The model’s exception_status
10 08 Diagnostics, sub-function 0 0800001234 [8,0,0,18,52] Echoes the data.
11 11 Get Comm Event Counter 0B [11,0,0,0,9] Status 0000 (not busy), event count 9
12 12 Get Comm Event Log 0C [12,29,0,0,0,9,0,12,128,64,...] Byte count, status, event count, message count, recent events
13 15 Write Multiple Coils 0F000000010100 [15,0,0,0,1] Writes 0 to coil 0.
14 16 Write Multiple Registers 100000000102000A [16,0,0,0,1] Writes 10 to holding register 0.
15 17 Report Server ID 11 [17,2,1,255] Byte count 2, the model’s server_id
16 20 Read File Record 140706000100000001 [20,4,3,6,0,0] File 1, record 0, one word
17 21 Write File Record 1509060001000000010009 Same as the request Writes 9 to file 1, record 0.
18 20 Read File Record 140706000100000001 [20,4,3,6,0,9] The written value
19 22 Mask Write Register 160000FF000055 Same as the request (10 AND FF00) OR (0055 AND NOT FF00) = 85
20 03 Read Holding Registers 0300000001 [3,2,0,85]
21 23 Read/Write Multiple Registers 170000000200000001020009 [23,4,0,9,18,52] Writes 9 to register 0, then reads 0–1.
22 24 Read FIFO Queue 180000 [24,0,6,0,2,0,18,0,52] Byte count 6, count 2, values 18 and 52. Reading leaves the queue intact.
23 43/14 Read Device Identification 2B0E0100 [43,14,1,129,0,0,3,0,3,80,68,67,1,2,77,66,2,1,49] Basic objects 0–2
24 43/14, individual access 2B0E0401 [43,14,4,129,0,0,1,1,2,77,66] Object 1 only

Two responses decoded:

  • 11 Get Comm Event Counter: the event count is the number of successfully processed messages other than the diagnostics management functions (08, 11, 12): the nine earlier requests other than 08.
  • 43/14: 14 01 is MEI 14, read code 1. 129 (0x81) is the conformity level: basic level 1 plus the individual-access bit 0x80. 0 0 means no further page and the next object ID, and 3 is the number of objects. Each object follows as ID, length and value.

Put the test value 0x1234 into the diagnostic register, then run the sub-functions:

{"action":"diagnostics_set","register":4660,"busy":false}
Request PDU Response Notes
0800020000 [8,0,2,18,52] Diagnostic register 0x1234
08000B0000 [8,0,11,0,27] Bus message count; depends on the requests in this session
08000E0000 [8,0,14,0,28] Messages addressed to this server
08000D0000 [8,0,13,0,1] Exception responses sent
08000A0000 [8,0,10,0,0] Clears the counters and the diagnostic register.
08000B0000 [8,0,11,0,1] Only this request has been counted since the clear.
0800030A00 [8,0,3,10,0] Sets the ASCII end character to LF (0x0A). The response still uses the previous one.
0800140000 [8,0,20,0,0] Clears the overrun counter and flag.

The counters are 16 bits wide and wrap from 65535 to 0. Their values depend on the requests processed, so check increments and resets rather than fixed numbers. {"action":"diagnostics"} returns all counters and the event log.

{"action":"execute","pdu":"0800040000"}
{"action":"execute","pdu":"060000002A"}
{"action":"diagnostics"}
{"ok":true,"result":{"response":null,"source":"local","status":"no_response"}}
{"ok":true,"result":{"response":null,"source":"local","status":"no_response"}}
{"ok":true,"result":{"counters":{...,"no_responses":2,...},...,"listen_only":true,"register":0}}
  • The request that enters listen-only mode gets no response (no_response).
  • The following write also gets no response and isn’t applied.

Recover with a restart request, which gets no response either:

{"action":"execute","pdu":"0800010000"}
{"action":"diagnostics"}
{"action":"execute","pdu":"0300000001"}
{"ok":true,"result":{"response":null,"source":"local","status":"no_response"}}
{"ok":true,"result":{"counters":{"bus_messages":0,...},...,"listen_only":false,"register":0}}
{"ok":true,"result":{"response":[3,2,0,9],"source":"local","status":"success"}}

listen_only is false again and the counters are cleared. The 42 sent during listen-only mode wasn’t applied, so the value is 9. On a real serial line the recovery request gets no response either, so don’t treat its timeout as a failed recovery: confirm with a read.

5. Send a broadcast and a request for another unit

Section titled “5. Send a broadcast and a request for another unit”
{"action":"execute","unit":0,"pdu":"060000002A"}
{"action":"execute","pdu":"0300000001"}
{"action":"execute","unit":5,"pdu":"0300000001"}
{"ok":true,"result":{"response":null,"source":"local","status":"no_response"}}
{"ok":true,"result":{"response":[3,2,0,42],"source":"local","status":"success"}}
{"ok":true,"result":{"response":null,"source":"local","status":"no_response"}}
  • A write to unit 0 is a broadcast: no response, but the value changed.
  • Unit 5 isn’t this server’s address (unit 1), so it doesn’t answer, just as it ignores requests for other servers on a serial bus.
  • A broadcast read can’t return a value; broadcasts are for writes only. An RTU or ASCII client refuses to send a read to unit 0 and returns the InvalidConfig error.
Request PDU Response Exception Reason
0300000000 [131,3] 03 Quantity 0 is outside 1–125.
0F0000000101 [143,3] 03 The byte count says 1, but the data byte is missing.
03FFFF0001 [131,2] 02 Address 65535 isn’t in the model.
1800FF [152,2] 02 FIFO 255 isn’t in the model.
2B0D00 [171,1] 01 The default server doesn’t handle MEI 13.
5A [218,1] 01 Function code 90 isn’t supported.

Finally, run a diagnostics request in a TCP configuration:

{"action":"disconnect"}
{"action":"configure","config":{"transport":"tcp","role":"server","address":"127.0.0.1:0","port":"","unit":1,"baud":19200,"parity":"even","stop_bits":1,"timeout_ms":1000}}
{"action":"execute","pdu":"0800001234"}
{"ok":true,"result":{"response":[136,1],"source":"local","status":"exception"}}

A TCP server answers serial-line-only functions with exception 01. To test them, go back to an RTU or ASCII configuration.

Enter {"action":"shutdown"}. None of these commands caused a service error, so the exit code is 0. To start again with the same model, enter the two commands of step 1 in a new session, or save them as a project file.