How I did it:
First, let's take a look at what we're trying to accomplish here. CAN bus is a specialized data network that allows all kind of components in your car to talk to each other. Your car's components are constantly talking, sending out all kinds of data across the network. At the same time, they're also listening for messages that are relevant to them. If a component has no use for a message, it just ignores it. The CAN network is terminated on each end by a 120 ohm resistor. There are several different CAN networks in our cars, but the one we're worried about for this purpose is "C-CAN" (chassis CAN).
If we look at the network diagrams from Hyundai, you can see that the instrument cluster is one of the endpoints of the C-CAN network.
So our goal here is to place the Canny device just before the cluster so that it intercepts the data. If the data contains vehicle speed information, it will adjust the value before sending it on to the cluster. If it doesn't, it will just forward it along the network unchanged.
Now that we know the big picture, let's get into the details. How do we tell the device what data to look for and how to modify it? Fortunately, some people who are much smarter than me have done some of that work. The comma.ai team makes an open-source product called openpilot, and in their github repo they have a bunch of dbc files that describe the CAN bus data for various makes and models including Hyundai: opendbc/hyundai_kia_generic.dbc at master · commaai/opendbc
CAN bus data is sent in chunks of hexadecimal data, which then must be converted to binary, and then the individual bits of binary have to be interpreted. I won't get into the technical details of how to extract and modify the speed data (although I'll be happy to answer any questions). But for our purposes, I'm looking at this section of the dbc file:
BO_ 902 WHL_SPD11: 8 ABS
SG_ WHL_SPD_FL : 0|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_FR : 16|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_RL : 32|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_RR : 48|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
Essentially, the speed of each wheel is represented by 14 bits. The value must be scaled by 0.03125 to get the value in km/h, and the speed represented can range from 0 to 511.96875.
So as an example: if the number 2560 came across the CAN bus, it would represent a speed of 80 km/h: 2560 x 0.03125 = 80.
The Canny products are programmed with a graphical interface, which makes it relatively easy to program. I put together a quick proof-of-concept that would just simply double the speed value, just to see if it could be done. I sent a CAN data with a speed of 10 mph to the cluster, and success! The speedometer read 20 mph!
It took a bit more work (and some very much appreciated help from Konstantin) to actually implement the multiplier that I wanted.
First, let's take a look at what we're trying to accomplish here. CAN bus is a specialized data network that allows all kind of components in your car to talk to each other. Your car's components are constantly talking, sending out all kinds of data across the network. At the same time, they're also listening for messages that are relevant to them. If a component has no use for a message, it just ignores it. The CAN network is terminated on each end by a 120 ohm resistor. There are several different CAN networks in our cars, but the one we're worried about for this purpose is "C-CAN" (chassis CAN).
If we look at the network diagrams from Hyundai, you can see that the instrument cluster is one of the endpoints of the C-CAN network.
So our goal here is to place the Canny device just before the cluster so that it intercepts the data. If the data contains vehicle speed information, it will adjust the value before sending it on to the cluster. If it doesn't, it will just forward it along the network unchanged.
Now that we know the big picture, let's get into the details. How do we tell the device what data to look for and how to modify it? Fortunately, some people who are much smarter than me have done some of that work. The comma.ai team makes an open-source product called openpilot, and in their github repo they have a bunch of dbc files that describe the CAN bus data for various makes and models including Hyundai: opendbc/hyundai_kia_generic.dbc at master · commaai/opendbc
CAN bus data is sent in chunks of hexadecimal data, which then must be converted to binary, and then the individual bits of binary have to be interpreted. I won't get into the technical details of how to extract and modify the speed data (although I'll be happy to answer any questions). But for our purposes, I'm looking at this section of the dbc file:
BO_ 902 WHL_SPD11: 8 ABS
SG_ WHL_SPD_FL : 0|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_FR : 16|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_RL : 32|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
SG_ WHL_SPD_RR : 48|[email protected]+ (0.03125,0.0) [0.0|511.96875] "km/h"
Essentially, the speed of each wheel is represented by 14 bits. The value must be scaled by 0.03125 to get the value in km/h, and the speed represented can range from 0 to 511.96875.
So as an example: if the number 2560 came across the CAN bus, it would represent a speed of 80 km/h: 2560 x 0.03125 = 80.
The Canny products are programmed with a graphical interface, which makes it relatively easy to program. I put together a quick proof-of-concept that would just simply double the speed value, just to see if it could be done. I sent a CAN data with a speed of 10 mph to the cluster, and success! The speedometer read 20 mph!
It took a bit more work (and some very much appreciated help from Konstantin) to actually implement the multiplier that I wanted.