An Introduction to the CAN Bus: How to Programmatically Control a Car

转自 https://news.voyage.auto/an-introduction-to-the-can-bus-how-to-programmatically-control-a-car-f1b18be4f377


I recently collaborated with my friends at Voyage to enable programmatic control of the A/C systems within a Ford Fusion. Voyage is working to bring about the end-goal of self-driving cars: a world where anyone, anywhere can summon a car directly to their doorstep, travel safely to their destination, all for an extremely low price. For Voyage, it’s imperative that they give their Riders access to control key car functions from the backseat, since there’s a day not too far from now when there won’t be a human driver to do it for them.

An Introduction to the CAN Bus

A modern car has tons of control systems, functioning in many ways like micro-services do in web development. Think of airbags, braking, cruise control, electric power steering, audio systems, power windows, doors, mirror adjustment, battery and recharging systems for electric cars. These systems need to be able to communicate and read state from one another. In 1983, a team at Bosch started development of the CAN (Controller Area Network) Bus to solve this complex problem.

Think of the CAN bus as a simple network where any system in the car can listen and send commands to. It integrates all of these complex components in an elegant way, allowing for many of the modern features we all love in vehicles today.

Self-Driving Cars and the CAN Bus

Since the pace of development of self-driving cars has picked up dramatically, the word CAN bus has become popularized. Why? Most self-driving car companies aren’t building their own vehicles from scratch, and need to find ways to programatically control the car after the fact.

By reverse engineering the CAN bus of a vehicle, it enables an engineer to issue commands to the car via software. The most necessary commands, as you can imagine, are steering (angle) and acceleration and braking.
这里写图片描述

Using sensors like LIDAR (vision), the car is then able to see the world like a superhuman. The PC within the car can then make decisions to fire off commands to the CAN bus to steer, accelerate, brake and more.

Not every car is ready to become self-driving, and there is a reason that Voyage chose the Ford Fusion (drive-by-wire!). You can read more on that topic.

Hacking the CAN Bus of a Ford Fusion

To get started hacking the climate control systems in the Ford Fusion, I opened my favorite book (The Car Hacker’s Handbook) and got to work. Before we dive in, let’s take a look at Chapter 2 of The Car Hacker’s Handbook to describe three important concepts: Bus protocols, the CAN bus, and CAN frames.

The CAN Bus

CAN has been a standard on US cars and light trucks since 1994, but it wasn’t made mandatory until 2008 (2001 for European vehicles). It runs on two wires: CAN high (CANH) and CAN low (CANL). CAN uses differential signalining which means that when a signal comes in, CAN raises the voltage on one line and drops the other line an equal amount. Differential signaling is used in environments that must be fault tolerant to noise, such as in automotive systems and manufacturing.

这里写图片描述

That said, the packets that travel over a CAN bus aren’t standardized. Each CAN bus packet contains four key elements:

  • Arbitration ID The Arbitration ID is a broadcast message that identifies the ID of the device trying to communicate, though any one device can send multiple Arbitration IDs. If two CAN packets are sent along the bus at the same time, the one with the lower Arbitration ID wins.
  • Identifier extension (IDE) This bit is always o for standard CAN.
  • Data length code (DLC) This is the size of the data, which ranges from 0 to 8 bytes.
  • Data This is the data itself. The maximum size of the data carried by a standard CAN bus packet can be up to 8 bytes, but some systems force 8 bytes by padding out the packet.

Format of Standard CAN Packets

这里写图片描述

CAN Frames

In order to turn the A/C on and off we need to find the right CAN bus (a car can have multiple). The Ford Fusion has at least 4 documented buses, 3 of them running at 500kbps (High Speed CAN) and one of them at 125kbps (Medium Speed CAN).

The OBD-II port exposes two of those buses: HS1 and HS2, but they are firewalled on this car and don’t allow you to spoof commands. With help from Alan from Voyage we flipped the problem (and the OBD-II port) inside out and found naked access to HS1, HS2, HS3 and MS. The solution was on the back of the OBD-II port where all those buses arrive to a device called the Gateway Module.

Since the A/C can be modified via the car media interface (SYNC) we went straight for the MS bus.

But how do we get our computer to be able to read and write CAN packets? The answer is SocketCAN, a set of open source CAN drivers and a networking stack contributed by Volkswagen Research to the Linux kernel.

We can connect 3 wires from the car, GND, MSCANH, MSCANL to a Kvaser Leaf Light HSv2 ( 300 o n A m a z o n ) o r t o a C A N a b l e ( 25 on Tindie) and get a computer with a recent Linux kernel to load the CAN bus as a network device.

modprobe can
modprobe kvaser_usb
ip link set can0 type can bitrate 1250000
ifconfig can0 up

After it is loaded, we can use candump can0 and start looking at the traffic:

can0  33A   [8]  00 00 00 00 00 00 00 00                         
can0  415   [8]  00 00 C4 FB 0F FE 0F FE                                                                      
can0  346   [8]  00 00 00 03 03 00 C0 00                                           
can0  348   [8]  00 00 00 00 00 00 00 00                                                                      
can0  167   [8]  72 7F FF 10 00 19 F8 00                                                                      
can0  3E0   [8]  00 00 00 00 80 00 00 00                                                                      
can0  167   [8]  72 7F FF 10 00 19 F7 00                                                                      
can0  34E   [8]  00 00 00 00 00 00 00 00                                                                      
can0  358   [8]  00 00 00 00 00 00 00 00                                                                      
can0  3A4   [8]  00 00 00 00 00 00 00 00                                                                      
can0  216   [8]  00 00 00 00 82 00 00 00                                                                      
can0  3AC   [8]  FF FF FF FF FF FF FF FF                                                                      
can0  415   [8]  00 00 C8 FA 0F FE 0F FE                                                                      
can0  083   [8]  00 00 00 00 00 01 7E F4                                                                      
can0  2FD   [8]  D4 00 E3 C1 08 52 00 00                                                                      
can0  3BC   [8]  0C 00 08 96 01 BB 27 00                                                                      
can0  167   [8]  72 7F FF 10 00 19 F7 00                                                                      
can0  3BE   [8]  00 20 AE EC D2 03 54 00                                                                      
can0  333   [8]  00 00 00 00 00 00 00 00                                                                      
can0  42A   [8]  D6 5B 70 E0 00 00 00 00                                                                      
can0  42C   [8]  05 51 54 00 90 46 A4 00                                                                      
can0  33B   [8]  00 00 00 00 00 00 00 00                                                                      
can0  42E   [8]  93 00 00 E1 78 03 CD 40                                                                      
can0  42F   [8]  7D 04 00 2E 66 04 01 77                                                                      
can0  167   [8]  72 7F FF 10 00 19 F7 00                                                                      
can0  3E7   [8]  00 00 00 00 00 00 00 00                                                                      
can0  216   [8]  00 00 00 00 82 00 00 00                                                                      
can0  415   [8]  00 00 CC F9 0F FE 0F FE                                                                      
can0  3A5   [8]  00 00 00 00 00 00 00 00                                                                      
can0  3AD   [8]  FF FF FF FF FF FF FF FF                                                                      
can0  50B   [8]  1E 12 00 00 00 00 00 00

However, this is equivalent to looking at the amplitude of a sound signal, it is very hard to characterize what’s going on and discover patterns. We need the equivalent of frequency analysis for this problem, and thankfully it exists and is called cansniffer. cansniffer shows a list of IDs and helps focus only on what changes in the data section of the CAN frame. As we figure things out about specific IDs, we can use it to filter out what we don’t need and only enable what we think is related to our problem at hand.

Here is an example of cansniffer on the MS bus. We are filtering out everything and only letting CAN id 355, 356 and 358 show up. Meanwhile, I am pressing the temperature adjust buttons on the car and we can see the 001C00000000 that represents the button push pop up at the very end.

The next step is to connect the A/C functionality to our PC running inside the car. The PC runs the Robot Operating System (ROS), and fortunately there is a module that makes this easy for us since we’re using SocketCAN. socketcan_bridge turns our CAN frame into a message in a ROS topic. Great!

Here is an example of how the decoding is done:

if frame.id == 0x356:
 raw_data = unpack('BBBBBBBB', frame.data)
 fan_speed = raw_data[1] / 4
 driver_temp = parse_temperature(raw_data[2:4])
 passenger_temp = parse_temperature(raw_data[4:6])

The resulting data is stored in a CelsiusReport.msg:

bool auto
bool system_on
bool unit_on
bool dual
bool max_cool
bool max_defrost
bool recirculation
bool head_fan
bool feet_fan
bool front_defrost
bool rear_defrost
string driver_temp
string passenger_temp

After pressing all the relevant buttons in the car we end up with a list:

CONTROL_CODES = {
 'ac_toggle': 0x5C,
 'ac_unit_toggle': 0x14,
 'max_ac_toggle': 0x38,
 'recirculation_toggle': 0x3C,
 'dual_temperature_toggle': 0x18,
 'passenger_temp_up': 0x24,
 'passenger_temp_down': 0x28,
 'driver_temp_up': 0x1C,
 'driver_temp_down': 0x20,
 'auto': 0x34,
 'wheel_heat_toggle': 0x78,
 'defrost_max_toggle': 0x64,
 'defrost_toggle': 0x4C,
 'rear_defrost_toggle': 0x58,
 'body_fan_toggle': 0x04,
 'feet_fan_toggle': 0x0C,
 'fan_up': 0x2C,
 'fan_down': 0x30,
}

And we can then just send strings to the ROS node and have it translate it to the car’s specific codes:

rostopic pub /celsius_control celsius/CelsiusControl ac_toggle

The Result

We are now able to issue the same CAN codes to the CAN bus that pressing the physical temperature up & down buttons would. This gives us the ability to remotely change the temperature of the car, all from an app while sat in the backseat. Success!
这里写图片描述
This is just one small step toward building an amazing Rider experience within the Voyage self-driving taxi.

猜你喜欢

转载自blog.csdn.net/lewif/article/details/79435082
car
今日推荐