SAE J1939 ECU Simulator And Data Monitor for Raspberry Pi
The jCOM.J1939.USB gateway board is a high-performance, low-latency vehicle network adapter for SAE J1939 applications. It allows any host device with a USB COM port to monitor SAE J1939 data traffic and communicate with a SAE J1939 vehicle network.
The board supports the full SAE J1939 protocol according to J1939/81 Network Management (Address Claiming) and J1939/21 Transport Protocol (TP). It is also supported by an extensive programming interface for the Raspberry Pi, including full C source code for short time-to-market developments.
The strength of the board lies in the fact that the entire SAE J1939 protocol, including all timing requirements, is stored on-chip, thus taking the burden off the Raspberry Pi CPU. The board uses a USB COM port to communicate with the RPi, i.e. all data transfer is handled through standard COM port access (/dev/ttyUSB0). The communication protocol between the board and the main system is well documented, which allows a portation to any computer system with a USB connection. A working source code library exists for the Raspberry Pi (C using the standard gcc compiler).
With all its features, the jCOM.J1939.USB allows the simulation of an SAE J1939 ECU (Electronic Control Unit) using embedded solutions such as the Raspberry Pi.
Why Not Implement a Linux SAE J1939 Protocol Stack?
There are a few choices in the market for buying an SAE J1939 protocol stack, but their pricing is prohibitive in comparison to the RPi's low-cost approach. We're talking several thousands of dollars, including the limitations of use due to license agreements.
I have toyed with the thought of implementing an SAE J1939 protocol stack for Linux (for instance on the Raspberry Pi in combination with our PiCAN boards) several times during the past years, and I always come to the same conclusion: The actual implementation is easy, while the real problem is warranting reliable operation, specifically satisfying the numerous J1939 timing requirements.
I am not saying that it is impossible, but the efforts would be enormous. Add to this the ever-changing operating system updates and the efforts to prove that the current protocol stack will still work with each new Linux version (not even talking about backward-compatibility).
In contrast, communication with our jCOM.J1939.USB board is entirely operating-system-independent and thus resistant to frequent Linux updates. The SAE J1939 functionality remains constant, and the protocol stack's performance is not influenced by the operating system.
Connecting the jCOM.J1939.USB Board
Connect the jCOM.J1939.USB board to any free USB port on your Raspberry Pi. The Raspbian operating system will recognize the new USB connection automatically, meaning there is no driver installation required.
For the CAN/J1939 connection, the jCOM.J1939.USB board uses a 5-pin terminal connector. The board also features an internal termination resistor of 120 Ohm, which is activated by inserting a wire jumper in the terminal block (the jumper is installed per default).
The connections (from top to bottom) are:
- CAN Termination Wire Jumper
- CAN Termination Wire Jumper
It may sound obvious, but it is, nevertheless, overseen frequently: You will need a second SAE J1939 node (or an entire network) to check the board's full functionality. The board comes with a "heartbeat" function (i.e., a heartbeat message sent per USB every one second), which indicates that the board is "awake" and working, but that doesn't prove any SAE J1939 functionality.
The jCOM.J1939.USB board comes with three LEDs:
- PWR - Directly connected to power.
- LED2 - Indicates USB port activity (including heartbeat message)
- LED1 - CAN / SAE J1939 activity
Upon powering up the board you will see the power LED plus the USB LED blinking with a one second frequency (heartbeat).
Programming the jCOM.J1939.USB Using C
The jCOM.J1939.USB C source code contains of the following files:
The config.h file is important, because it allows some user/application settings such as:
- Preferred Node Address (for Address Claim Process)
- Negotiable Node Address Range (also for Address Claim Process)
- ECU NAME
The COM1939 and CANInterface modules manage the communication between the Raspberry Pi and the jCOM.J1939.USB board. These modules need no further detailed attention, unless you want to spend the time to understand and extend them.
The most important module, when it comes to mere application programming, is main.c.
To initialize the board, use the following lines:
In order to call the SAE J1939 protocol stack, you need only one line:
int nStatus = COM1939_Receive(&lPGN, &nPriority, &nSourceAddress, &nDestAddress, &nData, &nDataLen);
This function call receives messages from the J1939 network. However, before you can receive any messages, you will need to set message filters for the PGNs you need:
PGN_SAMPLE_RX is defined in config.h and it can be replaced with any PGN. And, of course, you can add more PGNs using the same function call (up to 80 PGNs).
To negotiate an address, use this line:
COM1939_SetProtocolParameters(msgNAME, SA_PREFERRED, ADDRESSRANGEBOTTOM, ADDRESSRANGETOP, OPMODE_EVENT, true);
Again, all parameters are set in config.h.
Please, be aware that you need a valid J1939 node address before you can transmit data into the network. To transmit data, use the following line:
COM1939_Transmit(6, PGN_SAMPLE_TX, nSA, DEST_ADDR_SAMPLE, &SampleTxData, 8);
For further details, have a closer look at the main.c file. The code explains all functionality is an easy-to-comprehend form.
Compile and Run the C Program
In order to compile the program, run the following command in terminal mode:
gcc main.c COM1939.c CANInterface.c -o jCOM1939
Naturally, you can use any other name than jCOM1939 for the executable file.
To run the program, type:
Download the C Source Code
Some Screen Shots
To edit or view any of the program modules use the internal editor, for instance:
After executing the jCOM1939 program, the screen will show the COM port status, either successful (as shown here) or with an error message:
Type 'h' for help:
Type 'b' to check the reception of the heartbeat message:
Type 'f' to apply the message filter, type 'd' to delete the message filter:
Type 'c' to initiate the address claim process:
Type 't' to transmit a J1939 data frame:
Supplement August 13, 2020:
We have updated the code to address the sending of multiple PGN filter messages. The sample code demonstrated the setting of one filter, while for real-world applications it will be necessary to assign multiple filters. To demonstrate the entire startup sequence, we have added a command ('1') into the main.c file:
The sample PGNs (PGN_RX1...PGN_RX4) are defined within the config.h file.
We also modified the CANINterface.c file to address some timing issues during the serial communication between the Raspberry Pi and the USB gateway.