Car Hacking | Stop installing aftermarket switches! | How to add extra functionality to buttons that already exist in your car.

TJ Bruno
TJ Bruno
Jul 19 · 5 min read

The goal of this article is to provide the reader a seamless way to add new functions to buttons in their vehicle — all through the magic of CAN bus!

The Influence

Since cars were invented, people have been customizing them. It’s in our DNA. For the better part of a decade, I’ve worked as a 12v installer integrating all different sorts of electronics into modern cars.

The problem with adding most aftermarket electronics is that typically no ideal way to activate or deactivate them exists. Most people will just add a momentary button somewhere on their dashboard — either with adhesive or by drilling a permanent hole. Others that want to preserve a factory look will purchase OEM buttons specifically designed for their year, make, and model. However, the cost of these can add up fast and soon you’re spending a considerable amount on simply switches alone.

In my experience, customers that purchase high end vehicles often times want little to no aesthetic modification at all. Using an Arduino and CAN receiver, we are able to accomplish exactly this.

If you are brand new to Arduino or CAN, it may be beneficial to skim through my last article before continuing.

How It’s Done

Let’s take a look at the sketch I used to complete this on my first project , along with a breakdown of what’s happening starting from the top and working down.

digitalRead(2) is connected to the interrupt on our mcp2515 module. If this pin is low, new CAN messages have been received by the Ardino so we then call on the function CAN0.readMsgBuf(&rxId, &len, rxBuf) to read the data.

With (rxId == buttonId) && (rxBuf == buttonData)buttonId is the CAN ID that corresponds with the button we want to add functionality to and buttonData is the data we observe when the button is pressed. buttonPress is the variable we’ll use to keep count of how many times the button’s been pressed. At this point all we are saying is if the button in the car is pressed, increase the count by 1.

To understand the next part, you need to be somewhat familiar with the millis() function. Essentially, it’s just keeping a running log of the milliseconds that have passed since the program started running and by calling on it you are able to get a snapshot of that time.

So with if (buttonPress == 1) { startMillis = millis(); what we are saying is if the button has been pressed once, record the current time. The same applies for if (buttonPress == 2) { endMillis = millis();. If it’s pressed again, record the current time, but in a different variable.

Then we need to compare the time values to eachother. By using the statement if (endMillis — startMillis <= 1000) //Do something! what we are saying is that if the button is double pressed (pressed 2x within 1 second) then do something.

If the interval between presses is longer than 1 second, else {buttonPress — ; decreases the the counter back to 1. And if the second press just never comes, if ((buttonPress == 1) && (millis() — startMillis > 1000)) { buttonPress — ; resets the counter to zero.

DoublePress Demo

As you can see, by utilizing this sketch we can easily add a second function to any button we have bus access to. Also, we can customize by increasing the length of time needed between presses, or make it so a long press and hold is needed instead, or even require more than one button is pressed at a single time in order to activate.

Keep in mind that because we are only listening to the bus, every time the button is pressed whatever the default action of that button is will still occur. For instance, you likely wouldn’t want to program something like this to a volume up button for the radio. In my car, I used the ‘cancel cruise control’ button since majority of the time it’s not being used. Now, if we were to use a pair of Arduino’s and CAN receivers then we could firewall the bus and avoid the default action from taking place entirely, but that is another story…

Lastly, this was developed using the GMLAN bus on a late model Chevrolet and there is always a possibility that your CAN data behaves differently.

Taking It One Step Further

To test myself, I started thinking what if someone wanted to implement this but had no experience?

Expanding on the ideas I outlined, I was able to develop a sketch that automatically identifies, programs, and permanently saves the desired button selected by the user.

Automatic Button Programming

And then built my own shield for the nano to use with the sketch, integrating both a CAN receiver and single 10a relay module onto one pcb identical in size.

Nano CAN/Relay Shield

By building these tools, I’ve created close to a plug and play solution anyone can use to turn a button in their car into a double press on/off switch for a device. It could be used to activate custom lights, sound systems, or anything else that one can imagine.

The coolest part is this does not require any prior programming or wiring knowledge from the end user!

If you’re interested in the code you can find it here —

Coming Up

In my next article I will be delving deeper into this topic by explaining how to firewall bus data, giving us full control over the physical buttons.

If there’s a related topic you would like me to cover, don’t hesitate to ask!

Contact Me!

Questions? Feedback? Or simply interested in knowing more?

Reach out to me directly at

TJ Bruno

Written by

TJ Bruno

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade