This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino.
void j1939.Init(int nSystemTime);
Initializes the ARD1939’s memory, baud rate settings, etc.
nSystemTime - This is the loop time of your application in milliseconds. This information will provide the ARD1939 protocol stack a time base to manage all timers required for various protocol tasks.
Ideally, the system time should be 1 millisecond for best performance, however, up to 10 milliseconds should be sufficient for regular network traffic. Any higher values can be used but may jeopardize performance.
void j1939.SetPreferredAddress(byte nAddr);
Sets the preferred node address. Default setting is 128 (see ARD1939.h file). This function call is mandatory for initializing the protocol stack; otherwise the stack will not be able to send messages into the vehicle network. The preferred address is independent of the negotiable address range, i.e. it can be set anywhere within or outside that range.
nAddr – This is the preferred node (source) address. It should be in a range between 128 and 252. Addresses lower than 128 are allowed, but are regulated by the SAE J1939 Standard.
void j1939.SetAddressRange(byte nAddrBottom, byte nAddrTop);
Sets the negotiable address range. The default range (per ARD1939.h file) is 129 to 247. This function call is optional, meaning the protocol stack will work only with the preferred address.
nAddrBottom defines the bottom of the negotiable address range.
nAddrTop defines the top of the negotiable address range.
void j1939.SetNAME(long lIdentityNumber, int nManufacturerCode, byte nFunctionInstance, byte nECUInstance, byte nFunction, byte nVehicleSystem, byte nVehicleSystemInstance, byte nIndustryGroup, byte nArbitraryAddressCapable);
Sets the ECU’s NAME by using individual parameters.
The following shows the default settings for the device’s NAME as found in the ARD1939.h file:
#define NAME_IDENTITY_NUMBER 0xFFFFFF
#define NAME_MANUFACTURER_CODE 0xFFF
#define NAME_FUNCTION_INSTANCE 0
#define NAME_ECU_INSTANCE 0x00
#define NAME_FUNCTION 0xFF
#define NAME_RESERVED 0
#define NAME_VEHICLE_SYSTEM 0x7F
#define NAME_VEHICLE_SYSTEM_INSTANCE 0
#define NAME_INDUSTRY_GROUP 0x00
#define NAME_ARBITRARY_ADDRESS_CAPABLE 0x01
nArbitraryAddressCapable should be set to zero when your application does not support a negotiable address range (see function j1939SetAddressRange).
The NAME fields have been assigned in a way that they will not interfere when used within an existing vehicle network. This has been done by setting the Identity Number and Manufacturer Code to the maximum value, which will result in a more passive role during the address claim process. An ECU with a NAME of higher value is more likely to lose the competition with another node using the same address.
Note: All settings as shown are used for demonstration purposes only. In all consequence, you must follow the SAE's recommendations. Also, you alone (and not the author or publisher) are responsible for the final implementation and the results thereof.
byte j1939.SetMessageFilter(long lPGN);
Sets the PGNs to be processed in your application. ARD1939 supports up to 10 (UNO) or 100 (Mega 2560) message filters.
lPGN – This is the PGN you allow to be passed to your application.
Function returns OK or ERROR (as defined in ARD1939.h) where EROR means that no more message filters are available.
Special case – Request Message:
As defined in the SAE J1939 Standard, the Request message is 0xEA00, where the LSB is used as the destination address, i.e. the address of the ECU that is supposed to provide the requested information (e.g. 0xEA80, where 0x80 is the destination address).
The ARD1939 protocol stack’s message filter, however, will allow every message in the 0xEAxx range to pass when you set any filter PGN in the 0xEAxx range.
This behavior is necessary to allow the global address (255), meaning there are scenarios where one ECU requests the information from all nodes in the network.
As a consequence, it is mandatory that the application, in addition to the Request message, also verifies the destination address with its own address.
byte j1939.Operate(byte* nMsgId, long* lPGN, byte* pMsg, int* nMsgLen, byte* nDestAddr, byte* nSrcAddr, byte* nPriority);
Handles the address claim process, reads PGNs from the vehicle network, and delivers the current protocol status (Address Claim in progress, Address Claim successful, Address Claim failed).
The function returns ADDRESSCLAIM_INPROGRESS, NORMALDATATRAFFIC (Address claim successful), or ADDRESSCLAIM_FAILED.
The parameters passed to the function are pointers to:
nMsgId = J1939_MSG_NONE – No message received or J1939_MSG_MSG_APP – Message was received.
lPGN = PGN of received message
pMsg = Message data array
nMsgLen = Size of message data array
nDestAddr = The message’s destination address (usually the source address of your application but could also be the global address 255 – message broadcasting)
nSrcAddr = The source address, i.e. the address of the node who sent the message.
nPriority = Message priority.
byte j1939.Transmit(byte nPriority, long lPGN, byte nSourceAddress, byte nDestAddress, byte* pData, int nDataLen);
Transmits data to the vehicle network and handles the Transport Protocol (TP), meaning it handles data messages between 0 and 1785 bytes long (For the Arduino Uno, this number is limited to 256). The function automatically invokes the Transport Protocol (TP) when the message is longer than 8 bytes.
The parameters passed to the function are:
lPGN = PGN of the
pMsg = Message data array
nMsgLen = Size of
message data array
nDestAddr = The message’s destination address (could also be the global address 255 for message broadcasting)
nSrcAddr = The source address, i.e. the address of your ECU.
nPriority = Message priority.
Resets the protocol stack settings.
Delivers the negotiated node address; will be NULLADDRESS (254) in case the address claim process failed.
void j1939.DeleteMessageFilter(long lPGN);
Deletes a message filter.
lPGN = PGN to be deleted. Any attempts to delete a PGN that has not been set previously, will be ignored.
SAE J1939 has become the accepted industry standard and the vehicle network technology of choice for off-highway machines in applications such as construction, material handling, and forestry machines. J1939 is a higher-layer protocol based on Controller Area Network (CAN). It provides serial data communications between microprocessor systems (also called Electronic Control Units - ECU) in any kind of heavy duty vehicles. The messages exchanged between these units can be data such as vehicle road speed, torque control message from the transmission to the engine, oil temperature, and many more.
A Comprehensible Guide to J1939 is the first work on J1939 besides the SAE J1939 standards collection. It provides profound information on the J1939 message format and network management combined with a high level of readability.
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. As with every Arduino application, the initialization of data and the J1939 protocol takes place during the setup() function, while the actual application resides in loop(). setup() - The j1939.Init function is mandatory to operate ARD1939. [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. The functions available to the SAE J1939 application layer (i.e your program) are:Initialization j1939.Init – Initializes the protocol stack settings j1939.SetPreferredAddress – Sets the preferred node (source) address j1939.SetAddressRange– Sets the negotiable [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. Please be aware that the following macros are one-liners. Due to the limited page space, some macros appear as wrapped into more than one line and the line breaks are indicated with “\”. SAE J1939 has become the accepted industry standard and [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. Just for kicks, I extended the previously used Arduino sketch to simulate a fully functional RTS/CTS session (yet again, the code is highly tailored to the previous RTS/CTS session). Based on that sketch, I could simulate all error scenarios on the receiver’s side.This [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. With all previous programming examples installed and explained, you should now have a pretty good grip on programming your own SAE J1939 application with the Arduino Uno and/or the Mega 2560.Yet, there are still numerous, possible scenarios for J1939 applications and all [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. The typical SAE J1939 ECU application not only involves the protocol stack but also a good amount of input and/or output processing. This could involve reading sensors and sending the result in form of a PGN or reading a PGN and setting [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. In order to test all timeouts during an RTS/CTS session, I used a dedicated Arduino sketch to simulate all the “nasty” features that would trigger a communication breakdown. This method was easier to implement rather than using a full SAE J1939 stack. [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. The simplest test for a Clear to Send timeout is accomplished by running the Mega 2560 ECU as the only node in the network.To test this scenario, I run the Mega 2560 at an address of 0x80 (128) and attempt to initiate [...]
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino. Note the time stamps from line 3 through line 5 of the screen shot (look at the last four numbers indicating the time in tenth of milliseconds; for instance 352.4 milliseconds in line 3). SAE J1939/21 requires a packet frequency between 50 [...]