Hack Your Vehicle CAN-BUS With Arduino and Seeed CAN-BUS Shield

443,889

211

78

Posted

Introduction: Hack Your Vehicle CAN-BUS With Arduino and Seeed CAN-BUS Shield

Modern Vehicles all come equipped with a CAN-BUS Controller Area Network, Instead of having a million wires running back and forth from various devices in your car to the battery, its making use of a more clever system.

All electronic functions are connected to the TIPM, (Totally integrated Power Module), such as solenoids/relays to lock the doors or mini motors to wind the windows ect ect.

From each node (IE Switch pod that controls your windows or electric door locks) it broadcasts a message across the CAN. When the TIPM detects a valid message it will react accordingly like, lock the doors , switch on lights and so on.

WHY?
Because you can :-)

What you need.
Arduino UNO + Seeed CAN-BUS Shields
You can get the CAN-BUS Shield from SeeedStudio.com

Step 1: Setting Up an Interface for Connecting Your Laptop.

The Seeed CAN-BUS Shield has a header dedicated for the CAN-High (+) and CAN-Low (-)

Obviously all vehicles aren’t the same so the location to tap into the CAN-BUS will differ from vehicle to vehicle.
In this instructable I’m using a Jeep Wrangler (AKA Jeep JK) 2010, Rubicon 2DR , with a manual shifter.

The easiest way into the bus is to connect into the radio, at the back of the radio it has a White/Orange (- CAN-L) and White Grey ( + CAN-H ) wire. From there I routed the cable through to the glove box of the Jeep.

Step 2: Programming the Arduino to Accept Messages From the CAN-BUS

First of all you need the Seeed CAN-BUS Shield’s Library downloadable at GIT-HUB

After downloading the CAN-BUS Library you need to import it into your Arduino Libraries folder.
In the Arduino Editor Select Sketch --> Import Library --> Add Library and then point it to the Zip file you downloaded, (No need to unzip the contents it can be imported as is.

Tip: You might have to rename the zip as the Arduino IDE does not like unusual characters , so maybe try canbus.zip instead of can-bus.zip

Something important to note:

The CAN-BUS Shield library comes with a working example, it does not include getting the CAN-ID which is quite important to know when analysing the data, So i modified it slightly to include the ID also to seperate all values with a comma so that you can use it as a csv file.

Copy and paste the below code into your Arduino Sketch Editor.

#include "mcp_can.h"<br>
INT32U canId = 0x000;
unsigned char len = 0;
unsigned char buf[8];
char str[20];

void setup()
{    
Serial.negin(115200);
START_INIT:
if(CAN_OK == CAN.begin(CAN_125KBPS))
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}
void loop()<br>{
    if(CAN_MSGAVAIL == CAN.checkReceive())
    {
        CAN.readMsgBuf(&len, buf);
        canId = CAN.getCanId();
        
        Serial.print(canId);Serial.print(",");
        for(int i = 0; i<len; i++)
	{
		Serial.print(buff[i]);Serial.print(",");
	}
	Serial.println();
   }
}

Hit the upload button to upload the sketch.

Step 3: Connecting to the Arduino + CAN-BUS Shield to Get CAN Data

Now you need to make sure the CAN-BUS Shield has been connected to the vehicle's CAN-BUS, via the CAN-H & CAN-L Connector.

If you are sure everything has been connected then use putty to connect to the shield via Serial.

Putty is actually a SSH Client but can also handle serial data and it works great for this purpose.

Look at the Image attached to this step for the Serial port configuration.

Once you connect, Your vehicle's CAN-BUS will bombard putty with CAN-BUS Data.

Step 4: Analyze the Data

From here you need to figure out how to detect the messages, such as turning on lightts, open windows ect ect.

When connecting with putty you can log all incomming data to file as explained in the screenshot from the previous step.

Connect and log to a file called file1.csv and let it run with all windows closed, vehicle's key in on position but not started, and let it run for about 5 minutes, Kill the putty session, then restart the Arduino (The Sketch does not clear the buffer), And this time log all data to file2.csv , once putty starts duming data, quickly press a buton (Only one at a time cus you will not know which message goes to which button), once you pressed a button a few times quickly disconnectputty from the can bus.

So theoretically all messages in File2.csv thats also in File1.csv should be ignored/filtered the messages thats left over in File2.scv should be the message button presses.

If you have some programming skills you might find a better way to manage this.
I cretated a basic application in VB6 , you can look for more information about the tool on my Blog
Unfortunatly the application is a bit incomplete, eventhough it has the capability to connect directly to the Arduino Via Serial it doesnt work propperly, so please ignore the Serial Connection part.

It will basically take the fisrt file run which you were dumping data for ~5 Minutes (ignoredatabase.can) and incomming.can as the log file which includes button presses.

I encourage you to find a better way to analyse the data as this can be very stime consuming.

Step 5: Sending a Message Into the CAN-BUS

To send a message into the CAN-BUS is pretty straight forward.

The below will send the "Sway-Bar" disconnect on a Jeep Wrangler.

Note the CAN-ID needs to be converted into HEX format, an easy way to convert it is to use the Windows Calculator, Using "Programmer Mode" for Windows 7 Calculator

From the below code you can see its sending it to CAN-ID 2B0 = 688

#include <mcp_can.h><br>#include <spi.h></spi.h></mcp_can.h>
void setup()
{
    Serial.begin(115200);
  
START_INIT:
    if(CAN_OK == CAN.begin(CAN_125KBPS))                   // init can bus : baudrate = 500k
    {
        Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
        Serial.println("CAN BUS Shield init fail");
        Serial.println("Init CAN BUS Shield again");
        delay(100);
        goto START_INIT;
    }
}
void loop()
{
    unsigned char stmp3[4] = {3, 0, 3, 0};
    CAN.sendMsgBuf(0x2B0, 0, 4, stmp3);  
    delay(10000); 
     
}

Step 6: A Prototype Built Using the Information From This Instructable

Not going into much detail, this is just to show you whats possible.

This Arduino + Seeed CAN-BUS Shield has an added feature, I built a Button & 4 LED Display.
When pressing the red button it will cycle through all posible LED states and each state represents a feature.

Pressing the yellow button will send the message to the bus.

Share

    Recommendations

    • Space Challenge

      Space Challenge
    • Microcontroller Contest

      Microcontroller Contest
    • Spotless Contest

      Spotless Contest
    user

    We have a be nice policy.
    Please be positive and constructive.

    Tips

    Questions

    I have a CANBUS shield and Arduino Uno, I also have an Audi A5 (2012). I want to sniff data on the CANBus network, I've tried connecting via the ODBII socket under the dash, but I see nothing, where can I find information on how to find and connect via CAN-H and CAN-L ?

    Thank you,
    Simon

    69 Comments

    There are too many errors in the code above. First, there is HTML, "<br>" is found in at least two places.

    Also, I get an error:

    "exit status 1

    'CAN' was not declared in this scope"

    for this line:

    "if(CAN_MSGAVAIL == CAN.checkReceive())"

    I think I fixed it by adding code from the original example files, just before setup(), such as:

    "const int SPI_CS_PIN = 9;

    MCP_CAN CAN(SPI_CS_PIN); // Set CS pin"

    But there is also an error with "buff" being undeclared!

    I imagine there are other errors that the compiler didn't catch. Not very usable.

    this complies OK at least on my IDE

    #include <SPI.h>
    #include <mcp_can.h>
    INT32U canId = 0x000;

    unsigned char len = 0;
    unsigned char buff[8];
    char str[20];

    const int SPI_CS_PIN = 10; // select your can shield cs pin

    MCP_CAN CAN(SPI_CS_PIN); // Set CS pin
    void setup()
    {
    Serial.begin(115200);
    START_INIT:
    if(CAN_OK == CAN.begin(CAN_125KBPS))
    {
    Serial.println("CAN BUS Shield init ok!");
    }
    else
    {
    Serial.println("CAN BUS Shield init fail");
    Serial.println("Init CAN BUS Shield again");
    delay(100);
    goto START_INIT;
    }
    }

    void loop(){
    if(CAN_MSGAVAIL == CAN.checkReceive())
    {
    CAN.readMsgBuf(&len, buff);
    canId = CAN.getCanId();

    Serial.print(canId);Serial.print(",");
    for(int i = 0; i<len; i++)
    {
    Serial.print(buff[i]);Serial.print(",");
    }
    Serial.println();
    }
    }

    I take it that, but appears that errors, someone can help me?

    receive_check:33: error: 'canId' was not declared in this scope

    canId = CAN.getCanId();

    ^

    exit status 1

    'INT32U' does not name a type

    How can i get the data if I use this board?

    6988_1_9572.jpg

    I have that board connected to a Dieciemila and downloading CANBus data. Haven't tried sending yet. Still analyzing what the data ID's are that I see (2017 Chev Silverado). Used MCP_CAN library.

    Nice article. Please note that autopi.io has introduced a HW and SW platform to make it easier for everyone interested in hacking vehicles to develop SW for their cars, trucks and other vehicles with e.g. CAN-, K- or L-bus.....

    Can you start the Air Con and Window demister through the Can Bus without the car key?

    Hi Dave. You wont be-able to. The can bus does not run all the time it shuts down after about 3 or so minutes when turning off the ignition. Also it would be draining the battery if it were to run all the time whilst the car is off. Would also be a massive security risk.

    Can I use the ODB2 to DB9 cable or it just only works with CANL/CANR?

    I can confirm what @MoniCris has said: Use the GROUND/GND Luke! Also consider cutting P1 (right above the CAN-H screw)

    I had to do both to finally get my first message from the damned shield in my Ford Mondeo.