Arduino + CANBUS steering audio buttons decoder.

Hi all.
My name is Tiago, i’m portuguese but currently living in the UK.
I have a background of electronics from 10 years ago in school, TTL logic, transistors, resistors etc. but no programming experience, but i’m a fast learner.
My interest in electronics have recently reapeared and wanting to do some cool projects, after a lot of reading on the current state of things i thought the Arduino would be the best for me.

My project now is:
Mercedes Steering Wheel CANBUS Decoder

Objective: Decode the buttons pressed (VOL+, VOL-, NEXT, PREV, PICKUP, HANG-UP) on the steering wheel of the car to control an aftermarket stereo.

CAR - Mercedes E class (facelift) W210, buttons are sent on the interior CAN (CAN-B) wich runs at 83.3kbs.
Radio - Chinese branded navi unit with resistor dependant button presses.
Hardware - Arduino UNO SMD (DFRDuino) from DFRobot and CANBUS Shield from SKPang.

Phase 1 - read all messages on CANBUS and determine button PID and data (6 buttons), basicaly a CAN SNIFFER and send thru serial to the computer.

Example from Mercedes CLK350 2007 - Source: Howard Honig @ http://www.honeysw.com/canproject.php

Steering Wheel Buttons PID 1A8 - 2 BYTES (BYTE 0 determines button, BYTE 1 not used - always 0)

FUNCTION BYTE0 BYTE1
HANG-UP 80 0
PICKUP 40 0
VOL- 20 0
VOL+ 10 0
NEXT 02 0
PREV 01 0

Phase 2 - set MCP2515 to only accept the PIDs that relate to the buttons.

Phase 3 - Control a digital potentiometer so that each button means a certain resistance.

Phase 4 - Standalone PCB with the ATMega chip from the Arduino and the MCP2515 to install permanently in the car.

THIS IS PHASE 1

This is the code i have so far, i now that there are some libraries out there to control the SKpang shield but I thought about doing it all “by hand” to be able to learn some more.
This code compiles. What i need to know is, is this the correct procedure to initiate the MCP2515? From reading the MCP2515 datasheet and those other libraries (from DaveAK, SKPang, etc.) i think this is correct.
And if so is the next step just to start reading messages from the BUS? Or do i have to do something else before? I’m starting to get a bit lost in the datasheet.

#include <SPI.h>

int CS_PIN = 10;
int INT_PIN = 2;

void setup() 
{
  pinMode(CS_PIN, OUTPUT); //MCP2515 Chip Select PIN on the SKPang shield
  pinMode(INT_PIN, INPUT); //MCP2515 INTERRUPT PIN on the SKPang shield

  Serial.begin(115200); // Start serial comunication to send data to computer.

  // SPI comunication configuration
  SPI.setClockDivider(SPI_CLOCK_DIV2);   // setClockDivider divide by 2 since MCP2515 runs its SPI at 10Mhz.
  SPI.setDataMode(SPI_MODE0);            // DataMode 0 (0,0) or 3 (1,1) are the only ones to use with the MCP2515
  SPI.setBitOrder(MSBFIRST);             // MSB as used by the MCP2515
  SPI.begin();

  // Initiate MCP2515 and set to LISTEN-ONLY mode.
  digitalWrite(CS_PIN, LOW);  
  SPI.transfer(0xC0);    //RESET 
  // Bit timing Data, calculated using "MBTime" from  Intrepid Control Systems for a Oscilator value of 16Mhz used by the MCP2515 and 83.3kbs used by Mercedes for the CANBUS
  SPI.transfer(0x2A);  //CNF1
  SPI.transfer(0x07); // Data
  delay(10);
  SPI.transfer(0x29);  //CNF2
  SPI.transfer(0xA8); // Data
  delay(10);
  SPI.transfer(0x28);  //CNF3
  SPI.transfer(0x03); // Data
  delay(10);
  SPI.transfer(0x2B);
  SPI.transfer(255);  // CANINTE, all interrupts active, used later to tell Arduino that a valid message as been received	   
  delay(10);
  // Set LISTEN-ONLY mode thru BITMODIFY
  SPI.transfer(0x0F);       // CANCTRL
  SPI.transfer(B11100000);  // Send mask
  SPI.transfer(0x60);       // Send mode
  digitalWrite(CS_PIN, HIGH);
}

void loop()
{ 
}

Sorry in advance for the long post and for any gramar errors, english is not my first language.
Hope to learn alot from you guys, Arduino is really a good tool to get started, easy to learn and intuitive.
Best regards
Tiago Amarante

Hi, you can contact chiva from the Spanish forum, he has developed a backpack for CAM bus and has been tapping to several car CAN buses. Perhaps if you also post your query there you will get some guidance from him.

Sorry for the late reply. Thanks. Will contact chiva for some guidance. I'll update this thread with new findings.

Hi all.
I’ve contacted chiva in regards to my query.
In the meantime i’ve made a few changes, i’m now using a library that DaveAK posted in the old forums, http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1289195675 i’ve read thru the datasheets a couple of times and studied this library and (I hope) i’ve got a good understanding of how everything works.

I’ve written this code (most is a copy from DaveAK CANTest.pde), and i’ve got some messages with loads of different IDs (maybe 20 or 30 every second) thru on RXBuffer 1 and only one ID (1C1) on RXBuffer 0 so i’m not reading RXBuffer0 anymore
Now the way this comes thru the Serial Monitor is:

PID - DATA

602 - AF6598FD
20A - AF489CFD
etc…
etc…

This makes it very difficult to find out wich ones are the steering buttons IDs.

Does anyone have any ideia on how to improve my detection method?

Here is my new code. I did change in DaveAk library files all the entrys calling “Wprogram.h” to “Arduino.h” to be able to use them in the Arduino 1.0 so the code compiles OK

#include <SPI.h>
#include <MCP2515.h>

// Pin definitions specific to how the MCP2515 is wired up on the SKPang shield
#define CS_PIN   10
#define INT_PIN  2
byte i=0;

MCP2515 CAN(CS_PIN, INT_PIN); //Start MCP2515 class - "CAN"

void setup() 
{
  Serial.begin(115200);
  SPI.setClockDivider(SPI_CLOCK_DIV2);
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  SPI.begin();

  // Initialise MCP2515 CAN controller at the specified speed and clock frequency
  // *.Init(BAUDRATE, MHZ)
  // In this case 83kbps with a 16MHz oscillator
  CAN.Reset();
  int baudRate=CAN.Init(83,16);
  Serial.print("Baud Rate: ");
  Serial.print(baudRate, DEC);
  Serial.println(" kbps");
  Serial.print("Mode: ");
  CAN.Mode(MODE_LISTEN);
  Serial.println("LISTEN-ONLY");
}

Frame message;

void loop() 
{
  message.id = 0;

  if(CAN.Interrupt()) 
  {
    byte interruptFlags = CAN.Read(CANINTF);

    if(interruptFlags & RX1IF) 
    {
      // read from RX buffer 1
      message = CAN.ReadBuffer(RXB1);
      if(message.id>0)
      {
        // Print message
        Serial.print(message.id,HEX);
        Serial.print(" - ");
        for(i=0;i<message.dlc;i++) 
        {
	  Serial.print(message.data[i],HEX);
        }
      }
      Serial.println();
    }
  }
}

@fm I think you meant IgorR, he is the one that developed the CAN stuff

Whoops, yes I I meant IgorR!

Hi,

Tiago has already contacted me.

Thank you!

;)

Were you able to get some advice on how to sort out which PIDs you were looking for? I want to buy one of the skpang shields but I can't find any info that explains how to listen in on the bus of my vehicle and narrow down the PIDs I want to interact with.

Also, how can you determine the speed of the can bus? I thought I saw a sketch that would cycle through and determine the speed but that was a while ago and I can't seem to find it now.

Thanks!

I'm reviving a very old thread. Wonder if anyone got a CAN-bus shield working for interpreting steering wheel button clicks on a W210 Mercedes (1995-2002 E-Class).

The steering wheel signals on this car are carried on the "CAN-B" bus. The CAN-B bus on this model car has CAN Low voltages of 3.2V active and 4.8V dormant and CAN High voltages of 1.8V active and 0.025V dormant. In other words, CAN High voltages are lower than CAN Low voltages. This doesn't appear to agree with the ISO 11898 CAN bus standard that was originally published in 2003. Anyone know of a CAN bus shield that works with the W210 Mercedes?

Thanks

I am interested in the same for a 2005 Mercedes W209/CLK.

This CAN-BUS Shield adopts MCP2515 CAN Bus controller with SPI interface and MCP2551 CAN transceiver to give your Arduino/Seeeduino CAN-BUS capibility.
http://www.elecfreaks.com/store/canbus-shield-p-746.html

This CAN-BUS Shield adopts MCP2515 CAN Bus controller with SPI interface and MCP2551 CAN transceiver to give your Arduino/Seeeduino CAN-BUS capibility. http://www.elecfreaks.com/store/canbus-shield-p-746.html

Hi Tiagoamarante,

Did you connect the buttons to audio system ?