With the arrival of the chips required to build a CAN Bus interface (The Microchip MCP2515 and MCP 2551) and a CAN Bus shield for testing purposes I was able to get the Tachometer and Temperature gauge working on the instrument cluster. Thaniel has done a lot of work in documenting the various messages which has come in very useful. I don’t own a BMW on which to perform the logging required to decipher the protocol (I’m more of a Citroën fan ;)). With some further experimentation I was able to figure out the individual bits that control various warning lights on the cluster, such as the engine management, cruise control and oil level lights.

I have documented the messages in greater detail here but for my purposes the messages which were important to me were:

  • 0x316: RPM
  • 0x545: Various warning indicators
  • 0x329: Coolant Temperature
  • 0x153: Unknown but seems to clear the red (!) warning LED

Indicators and light status indication LEDs are controlled over a separate bus called the KBus which requires its own driving circuitry.

Sending RPM with the Arduino

To map the game’s RPM to the gauge I am using the Arduino’s built in map function. In my implementation the gauge is not absolute, instead the maximum RPM of the game’s vehicle is mapped to the maximum RPM of the gauge so even if I am playing Euro Truck Simulator with big low revving Diesel engines, the full scale is used.

MaxRPM = 7000;
RPM = 4500;
RPMMaxVal = 175; // 175 = 25 * 7 (25 per 1000)

// Clamp the RPM to the defined maximum
if(RPM > MaxRPM) { RPM = MaxRPM; }
// Map the RPM to a value for the cluster
RPMSendVal = map(RPM, 0, MaxRPM, 0, RPMMaxVal);

// Send the RPM CAN message
unsigned char rpm_message[8] = {0x05, 0x62, 0xFF, RPMSendVal, 0x65, 0x12, 0, 62};
CAN.sendMsgBuf(0x316, 0, 8, rpm_message);

Source and schematics for driver circuitry I am using can be found at my GitHub repository.


Leave a Reply

Your email address will not be published. Required fields are marked *