CANFDuino

The best platform for open source, CAN-bus Arduino projects

Mar 14, 2022

Project update 7 of 14

How to Gateway Messages with CANFDuino

by daniel k

Hi everyone,

today we have for you a really easy, but very powerful, example use-case of the CANFDuino. Finding an open-source stand-alone solution with two CAN/CANFD ports isn’t easy, and many of the backers out there who have been drawn to the project are looking for this specific feature. Why? primarily because they need a "middle man". One such case is you have two CAN devices that need to share information, but they are not "looking" for the right messages or even the right byte order (e.g., you have a CAN based tachometer looking for a given RPM in message 0x100, but you have an ECU sending it in 0x7DF). A similar use-case is you need to intercept a specific message from an upstream device, modify its contents, and then send it to the downstream device while letting all other messages through, a.k.a. "spoofing".

This tutorial will provide an example of using the CANFDuino to intercept, modify, and re-transmit a specific CAN message while "passing through" all other messages untouched. This could be used for "spoofing", new systems integration, or sharing data between two buses with differing baud rates.

Step One: Build and test the CANFDuino

Before we get started, let’s make sure everything works by taking our building and testing your first sketch tutorial.

Step Two: Wire up the two CAN ports

In this example, we will be intercepting the CAN lines from one "black box" to another with the CANFDuino in the middle acting as a "modifier-repeater". We are receiving a message on CAN ID 0x64 on CAN 0, modifying its contents, and re-transmitting it on CAN 1, and doing the same for message 0x200 on CAN 1 re-transmitting on CAN 0. We will also "pass-thru" all other messages bi-directionally between CAN 0 and CAN 1 as "untouched".

The CAN bus should be physically broken (not spliced), with the upstream device wired to CAN H and CAN L signals on the CANFDuino shield port 0, and the downstream devices wired to CAN H and CAN L on CAN 1.

CAN gateway diagram
CAN gateway diagram

Step Three: Program It

Open the IDE, go to File->Examples->CANFduino, and select CANFDuino\_PassThruGateway.ino. Make sure you have the proper board and port selected from Tools->Board->CANFDuino and Port->COMxx. Now click the upload button, which will verify and upload the code to the CANFDuino. The board should be communicating as a gateway at this point.

You could add print statements as you like for debug messages to the serial terminal. If you happen to be the proud owner of another CANFDuino unit, you can flash the CANTerm sniffing program to monitor your gateway code in action as shown below.

CANTerm output of our new intercept, modify and transmit gateway example (modifications in yellow)
CANTerm output of our new intercept, modify, and transmit gateway example (modifications in yellow)

Step Four: Now Modify It!

See the example below (and on GitHub) to see how to modify the code for your particular message types, baud rates, etc.

As always, thank you to all of our backers, we wish you success!

void loop() 
{
         //note this code is just a polling example, not optimized for interrupt driven performance
         //poll for messages on ports
         CanPort0.RxMsgs();
         CanPort1.RxMsgs();

         //retransmit port 0 rx Messages on Port 1
         for (i=0;i<CanPort0.numRxMsgs;i++)
         {
             //intercept message 0x64 and modify byte 0 if it equals 55 before re-transmitting on port 1
             if(CanPort0.rxMsgs[i].rxMsgInfo.id == 0x64)
             {
                 if(CanPort0.rxMsgs[i].rxMsgInfo.data[0] == 0x55)
                 {
                    CanPort0.rxMsgs[i].rxMsgInfo.data[0] = 0x88;
                 }
             }
             //send all messages RX on CAN 0, and including moodified message
             CanPort1.TxMsg(&CanPort0.rxMsgs[i]);
         }

         //retransmit port 1 rx Messages on Port 0
         for (i=0;i<CanPort1.numRxMsgs;i++)
         {
             //intercept message 0x200 and modify byte 0 if it equals 55 before re-transmitting on port 1
             if(CanPort1.rxMsgs[i].rxMsgInfo.id == 0x200)
             {
                    CanPort1.rxMsgs[i].rxMsgInfo.data[0] = 0xFF;
             }

             //send all messages RX on CAN 1, and including moodified message
             CanPort0.TxMsg(&CanPort1.rxMsgs[i]);
         }
}

Sign up to receive future updates for CANFDuino.

Subscribe to the Crowd Supply newsletter, highlighting the latest creators and projects