How To Gateway Messages with CANFDuino

The intention of this tutorial is to provide an example on how to intercept, modify and re-transmit a specific CAN message while “passing through” all other messages untouched using the CANFDuino . This could be used for “spoofing”, new systems integration, or sharing data between 2 buses with differing baud rates.

Step #1: Build and test CANFDuino 

Before we get started, lets make sure everything works. Follow our building and testing your first sketch tutorial here.

Step #2: 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 int the middle acting as a “modifier-repeater”. We are receiving a message on CAN ID 0x64 on CAN 0 modifying it’s 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 bidirectionally 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

Step #3: Program it

Open the IDE and go to File->Examples->CANFduino and select “CANFDuino_PassThruGateway.ino”. Make sure you have selected the proper board and port selected from Tools->Board->CANFDuino and Port->COMxx. Now click upload button, it 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)

Step #4: Modify it

See the example code below (and on github here) to modify for your message types, baud rates etc. 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]);
         }
}