Pre- CAN/OBD-II Lotus Elise/Exige – you CAN data!

A few days ago a customer asked if we could integrate with the OBD-II interface on pre-2008 ECUs on the Lotus Elise or Exige. Normally we’d say ‘sorry, not out of the box’, as 2008 was the year CAN was mandated on OBD-II. As it turns out from this post on LotusTalk, even the pre-OBDII/CAN Lotus Elise ECUs emit some useful CAN bus data on the OBD-II port, even though they won’t respond to regular OBD-II queries.

Electronic Gauge Cluster

Turns out, the ECU regularly transmits a CAN bus message to the instrument cluster packed full of interesting information. Available in this message is:

  • Vehicle Speed
  • RPM
  • Engine temperature
  • Fuel Level
  • Shift light status

The data is constantly broadcast to the instrument cluster, so it should actually be super easy to pick up and transform into virtual channels inside of RaceCapture/Pro.  So this weekend, I asked around if I could borrow a Lotus Elise for some CAN bus hacking. My friend David de Regt replied and on Sunday, he and his race-prepped 2006 Elise made their way to our Lab. Excellent!


Yes, that’s a long cable running to the OBD-II port

Lotus Elise CAN bus instrument cluster format

The data to the instrument cluster is broadcast on CAN id 0x400 (1024 decimal) with the following format:

byte   - info
01     - adjusted speed (A - 11)
02     - unused (always 0)
03, 04 - RPM (A * 256 + B)
05     - Fuel Level (0xFF = full, 0x00 = empty)
06     - Engine Temperature (A - 14)
07     - MIL (06 = on, 04 = cranking, 00 = running, 01 = shift light)
08     - unused (always 0)

The OBD-II to RJ45 cable plugs right into RaceCapture/Pro, supplying data and power. In this case, we extended it using a very long network cable extension. We were a bit worried about the cable length, but as it turns out, CAN bus supports 40 meter cable length at the 1 megabit transmission rate used in the Lotus network.  Yes, 40 meters – another reason why CAN is so kickass-robust!


RaceCapture/Pro MK2 on bench, Hacking CAN data from the Lotus!

Once we hooked it up to the OBD-II port we opened up a Lua scripting console right on the RaceCapture/Pro unit. A quick command immediately yielded a message:

> id, e, d = rxCAN(0, 100) --receive a message from CAN1; 100ms timeout
> println(id)

ID 1024 represented the CAN bus ID of the instrument cluster- Excellent!

So we probed further:

> println(d[1])

OK, Speed is zero, that makes sense since the car is stationary. what about RPM?

> println(d[3])
> println(d[4])

Now we’re getting somewhere!  So the formula for RPM is A*256 + B, so:

> println(d[3] * 256 + d[4])

855 RPM sounds about right!

So a full script to map all messages to virtual channels would look something like this:

--set the rate of onTick() to 10Hz

--create the virtual channels
speedId = addChannel("GndSpd", 10) --Ground Speed @ 10Hz
rpmId = addChannel("RPM",10) --RPM @ 10Hz logging rate
fuelId = addChannel("Fuel", 1) -- Fuel % @ 1Hz
tempId = addChannel("EngineTemp", 1) --Engine Temp @ 1Hz

function onTick()
 id, e, d = rxCAN(0, 100) --call with 100ms timeout
 if id == 1024 --did we get a valid CAN message from the cluster?
 speed = d[1] - 11 --ground speed
 rpm = d[3] * 256 + d[4] --RPM
 fuel = d[5] / 256 * 100 -- fuel %
 temp = d[6] - 14 --engine temperature

 -- set the virtual channels
 setChannel(speedId, speed)
 setChannel(rpmId, rpm)
 setChannel(fuelId, fuel)
 setChannel(tempId, temp)

A library of mappings (It’s open source, baby!)

Sounds hard? Don’t worry – we’ll add this script and scripts for other systems like Hydra, Megasquirt and more – ready for you to copy and paste into your RaceCapture/Pro configuration. As users contribute scripts you’ll be able to take advantage, tweak and re-submit updated versions for others to use. It’s freedom, baby!