Catch me if you CAN
This past weekend, my friends and I won HackIllinois by hacking a car to work as a Mario Kart 64 controller. For the impatient, you can go watch a video of that right below.
We arrived at HackIllinois with a plan for the weekend entirely consisting of “hack cars.” To enable this, we brought with us an ODB2 cable, along with a Raspberry Pi with a PiCAN2 attached to read the car’s CAN bus data. Since 2005, all new cars must have an ODB port somewhere, usually under the steering wheel, which transmits a legally mandated minimal amount of information about what’s going on with the car, along with whatever else the manufacturer feels would be useful. It was relatively simple to use can-utils to simply view that diagnostic data as a hex dump, and via trial and error, we were even able to discern which parts of the hex corresponded to a few events with the car (windshield wipers, headlights, brakes, etc.) As a quick point of reference, below is a screenshot of the CAN bus dumps for a 2011 Crown Victoria (owned by our teammate Dan).
The main two tools we used were cansniffer and candump. Cansniffer enabled us to get a live view of the data while removing duplicate lines and stale data. Cansniffer helps humans read CAN bus traffic and look at relevent traffic. The above two screenshots are using cansniffer. Candump, when paired with filters, allowed us to get the relevent data in a machine friendly format that can be processed easily.
We actually took some time to decide on what to build. Some of our initial plans included tag, but with cars (the actual tagging mechanism would probably have been proximity, but we were open to ideas), some kind of machine learning, and pretty LED readouts, but over lunch Saturday, one of our team members jokingly suggested Mario Kart, but controlled by an actual car, and after a minute of laughter and a minute of concerned thought, it was generally realized that that was in fact a viable idea, and even kind of a cool one. The CR-V had slightly more available data, and as a result, we elected to use that as the controller itself.
The main flow of the data goes from the car though the CAN bus to the raspberry pi. This data is then sent over UDP using nc to the laptop that is hosting the emulator. On board the laptop, a python script processes the raw CAN data into useful information. This script is open source on github. This information is then used to emulate the keyboard which is used to control the emulator.
While there are actually slightly more than five controls on the real Nintendo 64 controller, we decided that most of those were probably unnecessary, although it should be less than challenging to modify our code to use those. This left us with the seemingly simple problem of translating that data into fake keypresses, at which point we’d simply have to edit the emulator control settings, and we’d be off.
Of course, like anything “seemingly simple” done at a hackathon, it was in reality anything but. Identifying the portions of the CAN bus data corresponding to our input was actually remarkably quick, but turning that into actual keypresses required some clever hacking.
The most stright forward thing to translate from physical controls to keypresses were the brakes and windshield wipers. It was a simple matter of finding a binary setting and looking for changes in it. The accelerator was also fairly stright forward but we had to find the data that corresponded to engine RPM rather than speed the car was moving at. The first odd one was the light’s control, which was supposed to activate the jump in Mario Kart. We found the value and hooked it up during the night time, however between that and when we went to test it next morning the value had changed. This prompted minor panic until we found the new values. We suspect that the value may change based on if the car believes the lights should be on, but we haven’t tested to confirm that yet.
The hardest control to change from the phyiscal car to the emulator was the steering wheel. The emulator only supported two button presses, one to go right and the other to go left. When the steering wheel however reported how far way from center it was. The first attempt was say if the wheel was left, the button for left would be held down and the same for the right side. This caused significant problems for the person driving becasue they would turn the wheel further but the charcter wouldn’t turn any faster.
We ended up solving the problem by not continously pushing the button down when turning. The further the wheel is turned to the left or right, the greater amount of time the button stays down and the further the car turns. This results in a very intuitive experience for the driver that results in control similar to driving an actual car.
Overall we had a lot of fun building this hack and more fun playing with it afterwards. Thanks for all the people who we met during the weekend who stopped by to check out the strange car in the parking lot. Thanks to the hackIllinois team who threw an excellent hackathon and we hope to see you next year. Now for an image of the laptop when it’s running.