mcneil
Veteran Member
There's probably a million ways to do this but this is probably one of the easiest if you're like me and not a software programmer. This thread contains all the Arduino code and other resources I used to make it happen.
Here's my example: a 2000 Jeep TJ instrument cluster displaying RPM from the ALH ECM.
https://picasaweb.google.com/lh/photo/L9JY-zJcovIxaHFt7rLKndMTjNZETYmyPJy0liipFm0?feat=directlink
So there's the ECM, full of all sorts of data that we'd love to have looking up at us from the instrument cluster. Tach, water temp, boost, etc, it's all there as a digital value in the cluster.
There's three ways to get data out of the ECM:
1. OBD II over K-line
Standard, but slow. You have to ask for each piece of data using a standard set of OBD II codes.
2. VAG-com over K-line
How the VCDS tool talks to the ECM. I don't know the structure of these messages, but the speed over here is similar to logging with a VCDS.
3. CAN bus
Fastest, 500kbps. No lag. This is how the RPM signal gets from the ECM to the Instrument cluster in a factory ALH.
Connecting to the CAN bus you need a CAN transciever to read the messages from the bus and a microprocessor to get the message off the transciever and do something useful with them. I used the SeeedStudio CANshield and an Arduino Uno.
Also remember that the CAN bus at the OBD port doesn't offer the same features as the CAN bus between the ECM and Instrument cluster. Mk4s with the EDC15 had a gateway in the instrument cluster for the OBD port. So the gateway will filter messages coming to and from your transciever. By being a "bus", CAN networks aren't point to point but can be tapped in the middle. In my case, with no cluster, I just connected to the orange/black and orange/brown twisted pair coming off T121.
On the can bus, a typical message looks like this (but in binary)
640 65 42 28 14 42 0 35 41
The above string of numbers is one message recorded on the bus while idling. Going through each one of those numbers, we first have the CAN ID (640). My code looks for all messages with CAN ID = 640. I saw about half a dozen other CAN ID's on the bus, but I don't know what they do yet.
Next is the data - 8 bytes worth. It's described byte by byte, starting at zero because computer programmers start at zero. It took a frustated hour to remember that. Byte 0 in the above example message has a value of 65
Byte What it is
0 Don't know
1 Don't know, but suspect IQ or something like that
2 Don't know
3 RPM (1 byte = 64 RPM)
4 Don't know
5 TPS (0-255 where 255=floored)
6 Don't know
7 Don't know
This graph is how I figured out the bytes. This is the values of bytes 1, 3, and 5 as I did the little run in the above video.
So when a CAN ID 640 message appears on the bus, the Arduino applies a conversion factor and saves it to a variable named rpm_int.
Now the RPM is in the Arduino, we can display the value a couple ways.
1. Serial Monitor
This is also how I log data. Serial connections send it over USB to the laptop, and I log the data by pasting it to a text file. Good for science, not very useful when driving.
2. Display on an LCD screen
There's a ton of LCD screens on Sparkfun with Arduino libraries which you can display anything you want on. Going for an OEM look in my conversion, I wasn't interested in this option
3. Take control of you exisiting dash.
If your swap vehicle had CAN bus, you can use a second CAN shield to make your arduino a man-in-the-middle gateway. But CAN was only standard after 2008, up to that point it may or may not be there. Also, most of us are swapping the TDIs into older chassis anyway so let's assume you don't have a CAN dash.
Most gauges are air core. I used a Melexis 10407 air core gauge driver. This is a chip which makes the signals to move the needles on the gauges. You talk to it over a protocol called "SPI". Coincidently, SPI is the same way you talk to the CAN shield. Arduino has several good examples for SPI so I won't get into it deeply here.
Hooking up to the cluster is a lot of wiring because each big gauge is 4 wires, plus 2 wires for oil press, temp, etc. Eventually I'm going to print a PCB to do this with the Melexis 10407 on it. But for now it's a cardboard box with too many wires. It looks like this:
The function in the code which is probably most helpful to someone using the Melexis is the tachWrite. You give this function a value for RPM, and it does the calculations and communications to write it to the Melexis. Note that these values for quadrant and bytes per RPM are only valid for the TJ tachometer. You'll need to calibrate it for your own gauges.
I'll post the latest version of the code below, if you can make improvements and updates please feel free to do so and I'll include them in the latest.
Next steps for the code:
1. Fix the calibration issue with tachWrite (the blip at 2300 rpm)
2. Write the "speedoWrite" function which can take speed in MPH and send a needle position command to the Melexis
3. Write a function to control the 1-quadrant gauges
4. Decode the rest of the CAN ID's and Bytes, see if there's any juicy information there
Resources:
SeeedStudio CAN shield wiki
http://www.seeedstudio.com/wiki/CAN-BUS_Shield
Using a Mk6 cluster as a video game dashboard
http://www.seeedstudio.com/recipe/291-volkswagen-can-bus-gaming.html
Instructable on Jeep CAN bus hacking
http://www.instructables.com/id/Hack-your-vehicle-CAN-BUS-with-Arduino-and-Seeed-C/?ALLSTEPS
My pin configurations for the Arduino
Pin State Function To
0 Digital PD0
1 Digital PD1
2 Digital PD2 OUTPUT INT - CANBUS CAN Shield
3 Digital PD3
4 Digital PD4 OUTPUT RSTB Melexis - 15
5 Digital PD5
6 Digital PD6
7 Digital PD7 INPUT ERR Melexis 16
8 Digital PB0
9 Digital PB1 OUTPUT CS Melexis -11
10 Digital PB2 OUTPUT CS CAN Shield
11 Digital PB3 OUTPUT MOSI SPI Bus
12 Digital PB4 INPUT MISO SPI Bus
13 Digital PB5 OUTPUT SCLK SPI Bus/mlx 12
14 GND
Here's my example: a 2000 Jeep TJ instrument cluster displaying RPM from the ALH ECM.
https://picasaweb.google.com/lh/photo/L9JY-zJcovIxaHFt7rLKndMTjNZETYmyPJy0liipFm0?feat=directlink
So there's the ECM, full of all sorts of data that we'd love to have looking up at us from the instrument cluster. Tach, water temp, boost, etc, it's all there as a digital value in the cluster.
There's three ways to get data out of the ECM:
1. OBD II over K-line
Standard, but slow. You have to ask for each piece of data using a standard set of OBD II codes.
2. VAG-com over K-line
How the VCDS tool talks to the ECM. I don't know the structure of these messages, but the speed over here is similar to logging with a VCDS.
3. CAN bus
Fastest, 500kbps. No lag. This is how the RPM signal gets from the ECM to the Instrument cluster in a factory ALH.
Connecting to the CAN bus you need a CAN transciever to read the messages from the bus and a microprocessor to get the message off the transciever and do something useful with them. I used the SeeedStudio CANshield and an Arduino Uno.
Also remember that the CAN bus at the OBD port doesn't offer the same features as the CAN bus between the ECM and Instrument cluster. Mk4s with the EDC15 had a gateway in the instrument cluster for the OBD port. So the gateway will filter messages coming to and from your transciever. By being a "bus", CAN networks aren't point to point but can be tapped in the middle. In my case, with no cluster, I just connected to the orange/black and orange/brown twisted pair coming off T121.
On the can bus, a typical message looks like this (but in binary)
640 65 42 28 14 42 0 35 41
The above string of numbers is one message recorded on the bus while idling. Going through each one of those numbers, we first have the CAN ID (640). My code looks for all messages with CAN ID = 640. I saw about half a dozen other CAN ID's on the bus, but I don't know what they do yet.
Next is the data - 8 bytes worth. It's described byte by byte, starting at zero because computer programmers start at zero. It took a frustated hour to remember that. Byte 0 in the above example message has a value of 65
Byte What it is
0 Don't know
1 Don't know, but suspect IQ or something like that
2 Don't know
3 RPM (1 byte = 64 RPM)
4 Don't know
5 TPS (0-255 where 255=floored)
6 Don't know
7 Don't know
This graph is how I figured out the bytes. This is the values of bytes 1, 3, and 5 as I did the little run in the above video.
So when a CAN ID 640 message appears on the bus, the Arduino applies a conversion factor and saves it to a variable named rpm_int.
Now the RPM is in the Arduino, we can display the value a couple ways.
1. Serial Monitor
This is also how I log data. Serial connections send it over USB to the laptop, and I log the data by pasting it to a text file. Good for science, not very useful when driving.
2. Display on an LCD screen
There's a ton of LCD screens on Sparkfun with Arduino libraries which you can display anything you want on. Going for an OEM look in my conversion, I wasn't interested in this option
3. Take control of you exisiting dash.
If your swap vehicle had CAN bus, you can use a second CAN shield to make your arduino a man-in-the-middle gateway. But CAN was only standard after 2008, up to that point it may or may not be there. Also, most of us are swapping the TDIs into older chassis anyway so let's assume you don't have a CAN dash.
Most gauges are air core. I used a Melexis 10407 air core gauge driver. This is a chip which makes the signals to move the needles on the gauges. You talk to it over a protocol called "SPI". Coincidently, SPI is the same way you talk to the CAN shield. Arduino has several good examples for SPI so I won't get into it deeply here.
Hooking up to the cluster is a lot of wiring because each big gauge is 4 wires, plus 2 wires for oil press, temp, etc. Eventually I'm going to print a PCB to do this with the Melexis 10407 on it. But for now it's a cardboard box with too many wires. It looks like this:
The function in the code which is probably most helpful to someone using the Melexis is the tachWrite. You give this function a value for RPM, and it does the calculations and communications to write it to the Melexis. Note that these values for quadrant and bytes per RPM are only valid for the TJ tachometer. You'll need to calibrate it for your own gauges.
I'll post the latest version of the code below, if you can make improvements and updates please feel free to do so and I'll include them in the latest.
Next steps for the code:
1. Fix the calibration issue with tachWrite (the blip at 2300 rpm)
2. Write the "speedoWrite" function which can take speed in MPH and send a needle position command to the Melexis
3. Write a function to control the 1-quadrant gauges
4. Decode the rest of the CAN ID's and Bytes, see if there's any juicy information there
Resources:
SeeedStudio CAN shield wiki
http://www.seeedstudio.com/wiki/CAN-BUS_Shield
Using a Mk6 cluster as a video game dashboard
http://www.seeedstudio.com/recipe/291-volkswagen-can-bus-gaming.html
Instructable on Jeep CAN bus hacking
http://www.instructables.com/id/Hack-your-vehicle-CAN-BUS-with-Arduino-and-Seeed-C/?ALLSTEPS
My pin configurations for the Arduino
Pin State Function To
0 Digital PD0
1 Digital PD1
2 Digital PD2 OUTPUT INT - CANBUS CAN Shield
3 Digital PD3
4 Digital PD4 OUTPUT RSTB Melexis - 15
5 Digital PD5
6 Digital PD6
7 Digital PD7 INPUT ERR Melexis 16
8 Digital PB0
9 Digital PB1 OUTPUT CS Melexis -11
10 Digital PB2 OUTPUT CS CAN Shield
11 Digital PB3 OUTPUT MOSI SPI Bus
12 Digital PB4 INPUT MISO SPI Bus
13 Digital PB5 OUTPUT SCLK SPI Bus/mlx 12
14 GND