SAE J1939 Programming with Arduino - Debugging Code with Macros
This post is part of a series about SAE J1939 ECU Programming & Vehicle Bus Simulation with Arduino.
While one of the Arduino Uno’s strengths is its ease of programming embedded solutions, it can become increasingly frustrating when it comes to debugging the code. The Arduino IDE provides only very limited, if non-existing, debugging capabilities. The only solution to the problem is adding code that converts a variable to a string and display it on the Arduino’s Serial Monitor, a task that can be cumbersome and time-consuming.
Other, professional (and much more costly) programming environments will allow you to set breakpoints and display the value of variables, even arrays. Until the time comes where the Arduino IDE provides such features, let’s debug our code with the help of a few so-called C Preprocessor Macros.
The C preprocessor modifies a source code file before handing it over to the compiler. You’re most likely used to using the preprocessor to include files directly into other files, or #define constants, but the preprocessor can also be used to create “inlined” code using macros expanded at compile time and to prevent code from being compiled twice.
The other major use of the preprocessor is to define macros. The advantage of a macro is that it can be type-neutral (this can also be a disadvantage, of course), and it’s inlined directly into the code, so there isn’t any function call overhead.
Using C Preprocessor Macros, I developed the following instructions to debug my Arduino applications:
- DEBUG_INIT() – Defines a string variable for debugging. This function is mandatory to initiate debugging, and it should be placed at the beginning of the code module (file) that you want to debug.
- DEBUG_PRINTHEX(T, v) – Prints a variable in hexadecimal format with preceding Text.
- DEBUG_PRINTDEC(T, v) - Prints a variable in decimal format with preceding Text.
- DEBUG_PRINTARRAYHEX(T, a, l) – Prints an array of variables with a certain length in hexadecimal format with preceding Text.
- DEBUG_PRINTARRAYDEC(T, a, l) – Prints an array of variables with a certain length in decimal format with preceding Text.
– Stops the program until user submits a keystroke through the Serial Monitor.
Note: The macro is reading one character at a time, i.e. if you submit more than one character, the program will continue until all characters have been read. This can, in certain cases, be a helpful feature.
The variables used for the macros are:
- T – Text to be displayed with the variable (e.g. name of the variable)
- v – The actual variable; can be of any type (e.g. int, byte, float, etc.)
- a – Pointer to an array of variables
- l – Length of the array
The DEBUG instructions, stored in a debug.h file, are part of all Arduino code projects in this book (See the actual code in the appendix).
The result of the debug prints is displayed on the Arduino’s Serial Monitor. The following code represents a program sample that demonstrates the use of the macros:
// Call the J1939 protocol stack
nJ1939Status = j1939Operate(&nMsgID, &lPGN, &pMsg, &nMsgLen, &nDestAddr, &nSrcAddr, &nPriority);
DEBUG_PRINTHEX(“nDestAddr = “, nDestAddr)
DEBUG_PRINTDEC(“nDestAddr = “, nDestAddr)
DEBUG_PRINTARRAYHEX(“pMsg = “, pMsg, nMsgLen)
DEBUG_PRINTARRAYDEC(“pMsg = “, pMsg, nMsgLen)
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.