PGN Requests

Introduction

The following article will describe the correct execution of the PGN Request/Response J1939 protocol with examples of common scenarios. For simplicity, we will assume that our controller application will only respond to requests for PGN 0xFEEB.

The J1939 protocol allows one CA (controller application) to request information from another CA on the network or from all CAs on the network. This is done using the PGN request. The PGN request is unique in that it only has 3 bytes of data. All other PGNs have 8 bytes of data and fill the unused or unavailable SPNs with 1's or 0xFF's but the request PGN has a DLC of 3 and only transmits 3 bytes of data.

Here is an example of what a PGN request message looks like in practice. In this example, the ECM at address 0x00 is requesting PGN 0xFEEB from our CA at address 0x31. The PGN is represented by D0-D2. Notice that the order of the bytes are reversed. We are are requesting PGN 0xFEEB, but the data field reads 'EB FE 00'. That is because the bit order is reversed so that the least significant bit (LSB) is sent first. This is referred to as endianness and can express binary data with the least significant bit (LSB) first or most significant bit (MSB) first.

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7
1 1CEA3100 3 EC FE 00

There are three possible ways our CA can respond to a request for a PGN that our CA supports (reference SAE J1939-21-5.3.1/5.3.2).

  1. If our response is 8 bytes or less, then the response should always be to the global address, even if the request was specifically directed to our address.
  2. If our response is greater than 8 bytes and the request was addressed to the global address, our response should use the BAM transport protocol.
  3. If our response is greater than 8 bytes and the request was addressed to our source address, our response should use the RTS/CTS transport protocol.

There is a 4th scenario, that our CA responds with a NACK if we do not support an address-specific PGN request to our address. For example, if we see a request for a PGN that our CA does not support to our address 0x31, then our CA should send a NACK message. In this case, the destination address will be the global address 0xFF and the source is our CAs address which is 0x31 in this example. That makes the message ID 0x18E8FF31.

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7
1 1CEA3100 3 DC FE 00
2 18E8FF31 8 01 FF FF FF 31 DC FE 00

The data field is specified by J1939-21 5.4.4 for a NACK, or negative acknowledgment.

We do not need to respond to global PGN requests (addressed to 0xFF) that our CA does not support.

Responding to A Request

Each of the responding test scenarios will begin with a PGN request message sent from the Peak Viewer or CANKing software. The PGN request message will have a source address of 0x00 and will be addressed to either the global address or our CAs address (0x31) depending on the scenario being tested.

Responding With 8 Bytes Or Less

This is the simplest case, where our CA simply needs to broadcast a CAN message to the global address containing the requested PGN. We will need to test two scenarios, one where the request is to the global address and one where the request is to our source address (0x31). Our CAs response should be the same for both of those requests.

Here is an excerpt from a global request for 0xFEEB:

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7 Time (ms)
1 1CEAFFFF 3 EB FE 00 1021.9
2 18FEEB31 8 43 4D 4D 4E 53 2A 2A 2A 1031.3

We can see the initial request with message ID 0x1CEAFFFF and our CAs immediate response with 0x18FEEB31, using our source address. The data field translated from ASCII is "CMMNS***" The asterisks (* or 0x2A hex) are delimiters that need to go between MAKE, MODEL, and SERIAL NUMBER. In this example, we are only transmitting MAKE to keep our response under 8 bytes. The MAKE is always a 5 character code defined by the American Trucking Association Vehicle Maintenance Reporting Standard (ATA/VMRS). In this example, we are borrowing the code for Cummins, but if you do not have a code this field would be blank.

The response should be identical if the PGN request is addressed to our address. Here is an excerpt from a address-specific request for 0xFEEB from the ECM at address 0x00:

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7 Time (ms)
1 1CEA3100 3 EB FE 00 1074.9
2 18FEEB31 8 43 4D 4D 4E 53 2A 2A 2A 1078.1

Responding With Greater Than 8 Bytes Using BAM (Global)

If the response to the PGN request is greater than 8 bytes, a transport protocol must be used. In this scenario, the request is sent to the global address 0xFF. Because the request was global and not address-specific, our response should use the BAM (Broadcast Announce Message) transport protocol.

The BAM protocol does not require initialization with the requestor like RTS/CTS does. Instead, we just expect to see the request followed by a connection protocol message indicating that a BAM will be transmitted. Immediately after the connection protocol message, our packetized PGN can be transmitted. Note the D0 field is reserved for the packet number, and D1-D7 are used to transmit the actual data.

Here is an excerpt from a BAM response to a global request for PGN 0xFEEB that is greater than 8 bytes:

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7 Time (ms)
1 1CEAFFFF 3 EB FE 00 998.1
2 18FEEB31 8 20 2C 00 07 FF EB FE 00 1004.1
3 1CEBFF31 8 01 43 4D 4D 4E 53 2A 36 1063.7
4 1CEBFF31 8 02 42 20 75 32 31 44 30 1123.8
5 1CEBFF31 8 03 36 37 30 30 30 30 30 1184.0
6 1CEBFF31 8 04 30 30 2A 33 30 30 33 1244.1
7 1CEBFF31 8 05 30 39 31 36 2A 2A 2A 1304.2
8 1CEBFF31 8 06 2A 2A 2A 2A 2A 2A 2A 1364.4
9 1CEBFF31 8 07 2A 2A FF FF FF FF FF 1424.3

Row 2 with message ID 0x18FEEB31 is the BAM header to indicate to the network that a BAM is about to be sent with a total length of 44 (0x2C) bytes in 8 packets, or 8 separate messages.

Responding With Greater Than 8 Bytes Using RTS/CTS (Address-Specific)

If the response is greater than 8 bytes and the request was addressed specifically to our CA, then our CA must use the RTS/CTS protocol to respond. RTS/CTS is similar to BAM, except there is a 'handshake' between the requestor and the sender to ensure the connection is managed and the data is received in its entirety.

With this transaction, we should expect to see the initial request from the ECM 0x00 to our CA 0x31. After the request, our CA responds with an RTS, or Request to Send, message to make sure the requestor knows how much data we will be sending. If the requestor is ready to receive our PGN, it will send a CTS, or Clear to Send message to our address.

Once our CA receives the CTS message, packet transmission begins. When the requestor receives the last packet, it must close the connection with an EndOfMsgACK message. The EndOfMsgACK confirms the number of packets received, the total number of bytes received, and the PGN received.

Here is an excerpt from an RTS/CTS exchange between 0x00 and 0x31 to satisfy a request for PGN 0xFEEB:

Msg # Msg ID DLC D0 D1 D2 D3 D4 D5 D6 D7 Time (ms)
1 1CEA3100 3 EB FE 00 1018.4
2 1CEC0031 8 10 2C 00 07 FF EB FE 00 1020.3
3 1CEC3100 8 11 07 01 FF FF EB FE 00 1022.6
4 1CEBFF31 8 01 43 4D 4D 4E 53 2A 36 1030.2
5 1CEBFF31 8 02 42 20 75 32 31 44 30 1040.2
6 1CEBFF31 8 03 36 37 30 30 30 30 30 1050.1
7 1CEBFF31 8 04 30 30 2A 33 30 30 33 1061.1
8 1CEBFF31 8 05 30 39 31 36 2A 2A 2A 1070.6
9 1CEBFF31 8 06 2A 2A 2A 2A 2A 2A 2A 1080.5
10 1CEBFF31 8 07 2A 2A FF FF FF FF FF 1090.5
12 1CEC3100 8 13 2C 00 07 FF EB FE 00 2274.2

Rows 2 & 3 are the RTS and CTS messages respectively. With the RTS message, bytes D1 and D3 represent the total message size in bytes and total number of packets respectively. You can also see the PGN in the last three bytes, D5-D7. The CTS message follows, confirming the total number of packets (D1), which packet to send (D2), and the PGN (D5-D7).

After the data has finished transmitting, the requestor must send an EndOfMsgACK which we can see here with message ID 0x1CEC3100. The EndOfMsgACK confirms the total number of bytes received (D1), the total number of packets (D3), and the PGN (D5-D7). After the EndOfMsgACK is sent, the connection is considered closed and must be re-initiated if more or new data needs to be sent.