Tesla steering wheel control buttons - DECODED
Some background... Tesla Model S steering column is a Mercedes Benz unit. The control buttons in the steering wheel pad talk LIN (via the clock spring) on three wires back to the circuit on the main column. The main column then talks CAN to the rest of the car.
To start with I tried (without success) to wake up the steering column (with CAN messages) and get it to send CAN frames when the steering pad or control stalks were used. The only buttons that sent CAN were the steering column position adjuster and the P'ark button. Even so, activating any of these sent out a stream of CAN messages, but for every CAN frame containing useful data, there were 100s of frames with nothing useful (3 second long stream of crap frames).
I decided to interface directly with the (19200 baud) LIN messages coming from the steering pad controls. LIN is not as easily approachable as CAN, but I eventually got it to work. The steering wheel pad and control buttons can be removed and disconnected from the clock spring.
I used...
1) LIN-BUS (from skpang, via CopperHill Technologies in the US (
http://copperhilltech.com/lin-bus-breakout-board/)
- Essentially just protects the Arduino from the 12v LIN bus. You supply it with 12v, it powers up the LIN connection, and then it outputs a TX/RX 5v connection for the Arduino. Finally got it going after figuring out that CS (chip select) needed to be 12v to activate the chip.
2) Modified code from Andrew Stone on Github
(
https://github.com/gandrewstone/LIN)
- Andrews LIN code was very helpful, but I did need to back out his demo code specifically designed to talk to two LIN-enabled multicolored LEDs. My new main code prompts LIN-slave chips on the steering pad buttons for a response. LIN is a prompt and response network, so the Arduino stands in for the Master node. (Note: I tried using the LIN-BUS code by zapta on github, but I was unable to get it to be reliable for this application. It attempts, by using interrupts and clever timing, to make a digital pin on the Arduino act like a serial RX pin.)
3) I also used an Arduino Mega (with additional hardware serial ports - other than the one used to talk back to the PC via the USB port). The LIN-BUS is connected to the Serial1 pins 18,19 on the Arduino.
The Arduino code acts as a Master node in the 'steering pad' LIN network. It sends out a request with the ID 0X3D, and gets 8 bytes (1 ID byte and 7 data bytes) in response back from the LIN slaves in the steering pad. Depending on which buttons are pressed / wheels rolled, the bytes of the response are modified.
My TesLorean goal in all this is to replace the stock DeLorean steering wheel with the Tesla wheel. I will also be using the Tesla stalks for PNDR and indicators/beams/wipers. The LIN messages from the steering pad will be combined with the stalk control signals to produce TesLorean CAN messages for the main computer (which will link to the motor controller, battery BMS, charger, etc).
=============================
LIN Network Responses
ID + 7 bytes
Baseline
=======
Prompt 0x12 Receive ID 0x00 and 00 00 00 00 00 00 00
(while the steering pad responds to prompt id 0x12, returned data is always 00,...,00
Prompt 0X3D Receive ID 0x00 and 00 00 82 80 00 00 00
Horn ::
Prompt 0X3D Receive ID 0x00 and 00 01 82 80 00 00 00
Voice & Right Up ::
Prompt 0X3D Receive ID 0x08 and 00 00 82 80 00 00 00
Menu Back & Right Down ::
Prompt 0X3D Receive ID 0x20 and 00 00 82 80 00 00 00
Scroll Wheel Right Press ::
Prompt 0X3D Receive ID 0x10 and 00 00 82 80 00 00 00
Scroll Wheel Right Down ::
Prompt 0X3D Receive ID 0x00 and 3C 00 82 80 00 00 00 (down 1 click)
Prompt 0X3D Receive ID 0x00 and 38 00 82 80 00 00 00 (down 2 clicks)
Prompt 0X3D Receive ID 0x00 and 34 00 82 80 00 00 00 (down 3 clicks)
...
Prompt 0X3D Receive ID 0x00 and 20 00 82 80 00 00 00 (down N clicks)
Scroll Wheel Right Up ::
Prompt 0X3D Receive ID 0x00 and 04 00 82 80 00 00 00 (up 1 click)
Prompt 0X3D Receive ID 0x00 and 08 00 82 80 00 00 00 (up 2 clicks)
...
Forward & Left + ::
Prompt 0X3D Receive ID 0x01 and 00 00 82 80 00 00 00
Back & Left - ::
Prompt 0X3D Receive ID 0x04 and 00 00 82 80 00 00 00
Scroll Wheel Left Press ::
Prompt 0X3D Receive ID 0x02 and 00 00 82 80 00 00 00
Scroll Wheel Left Down ::
Prompt 0X3D Receive ID 0xC0 and 03 00 82 80 00 00 00 (down 1 click)
Prompt 0X3D Receive ID 0x80 and 03 00 82 80 00 00 00 (down 2 clicks)
Prompt 0X3D Receive ID 0x40 and 03 00 82 80 00 00 00 (down 3 clicks)
...
Prompt 0X3D Receive ID 0xC0 and 02 00 82 80 00 00 00 (down N click)
Prompt 0X3D Receive ID 0x80 and 02 00 82 80 00 00 00 (down N+ clicks)
Prompt 0X3D Receive ID 0x40 and 02 00 82 80 00 00 00 (down N++ clicks)
Scroll Wheel Left Up ::
Prompt 0X3D Receive ID 0x40 and 00 00 82 80 00 00 00 (up 1 click)
Prompt 0X3D Receive ID 0x80 and 00 00 82 80 00 00 00 (up 2 clicks)
Prompt 0X3D Receive ID 0xC0 and 00 00 82 80 00 00 00 (up 3 clicks)
...
Prompt 0X3D Receive ID 0x40 and 01 00 82 80 00 00 00 (up N clicks)
Prompt 0X3D Receive ID 0x80 and 01 00 82 80 00 00 00 (up N+ clicks)
Prompt 0X3D Receive ID 0xC0 and 01 00 82 80 00 00 00 (up N++ clicks)