Reliable BMW IBUS interface schematic?

I've built a project using a RPi and one of Resler's USB IBUS interfaces which works nicely in essence, but the boot times of the RPi are making it unusable for some of the functions I had planned for it.

To that end, I've started to look towards using an Arduino.

I'm great a programming, but no so much when it comes to designing/building circuits.
I've spend the best part of a week googling around, hunting for a reliable schematic, or pre-built BMW IBUS interface that will work well with an Arduino, to no avail.

I've read that the chip to go for is the Melexis TH3122, but I've hit two problems with that idea:

  • I can't find this for sale anywhere in the UK?
  • I can't find a schematic on how to hook this up to an arduino

I'd be very appreciative if someone could point me on the right track, as I'm feeling like I'm going very unproductive circles here :frowning:

I can't find this for sale anywhere in the UK?

The manufacturer is in Belgium. Have you tried contacting them?

I can't find a schematic on how to hook this up to an arduino

Same response. There is no one better than the manufacturer to answer questions about a product.

Sk93:
I've read that the chip to go for is the Melexis TH3122, but I've hit two problems with that idea:

  • I can't find this for sale anywhere in the UK?
  • I can't find a schematic on how to hook this up to an arduino

It's actually an obsolete chip now, but they are still available from here:

Not cheap at €5 each, and shipping is €6.90 to the UK from Germany. I was about to order some more myself, and I'm happy to split the shipping cost if you like. How many are you looking for ?

I've attached my TH3122 schematic below.

Pin 2 (EN) goes to a digital output pin on the Arduino. Drive it high to enable the chip, and drive it low to put the chip to sleep. If you power the Arduino from the built in 5v regulator, you can use this to shut everything down to save power. The TH3122 will wake up as soon as it sees any traffic on the IBUS. As soon as this happens, the Arduino will also power back up. My entire system shuts down after 60 seconds of IBUS inactivity. Boot up is pretty much instantly. As soon as you hit the unlock button, it all fires up, and is running before you get the door open :slight_smile:

Tx & Rx are self explanatory. It is Tx to Tx and Rx to Rx though. Don't cross them over as you would normally. Remember to set the serial port to SERIAL_8E1 for the IBUS.

I feed pin 9 (SEN/STA) to one of the Arduino interrupt pins (2 or 3 on the Uno/Nano). This is used to tell if it's clear to send on the IBUS.

Let me know if you need any more info.

Cheers,

Ian.

Hi Ian,

That's awesome - thanks for the reply!

In regards to ordering some, I'd be interested in that, but can't do so until the end of the month.
If you can wait that long, I'd happily split the cost?

Quantity-wise, I'm probably looking at obtaining 20 units.

Cheers,
Ian (also)

Sk93:
Hi Ian,

That's awesome - thanks for the reply!

In regards to ordering some, I'd be interested in that, but can't do so until the end of the month.
If you can wait that long, I'd happily split the cost?

Quantity-wise, I'm probably looking at obtaining 20 units.

Cheers,
Ian (also)

Hi Ian,

No problem waiting until the end of the month. Just let me know when you're ready.

I don't know which Arduino you had in mind, but I found the Nano was very good, but recently moved over to the Teensy. It's about the same size as the Nano, but runs at 96MHz, and has much more memory and features.

Cheers,

Ian.

Hello Guys,

What are your experiences with the MCP2025? I am not able to receive/send any message to my Arduino Mega with this microchip. I would like to use it because I can find it for 1.5usd in a dealer near where I live.

Thanks.

mbt28:
Hello Guys,

What are your experiences with the MCP2025? I am not able to receive/send any message to my Arduino Mega with this microchip. I would like to use it because I can find it for 1.5usd in a dealer near where I live.

Thanks.

I've used it before without any real problems. Sending needs a bit of extra coding to avoid data collisions on the ibus, but it does the job, and the built in 5v regulator is handy.

Ian.

Thank you Ian. I am going to put my schematic and code here when I go to home. Probably, I am making a mistake somewhere but I cannot figure it out.

Edit: I made some more changes yesterday to understand today I will try one more time and write paste my code here.

First I would like talk about my setup. My head unit is removed from the car and I powered it with an 12V adapter on my desk. Currently it is disabled as there is no ibus message on the line.

I cannot create the schematics due to issues with KiCAD on win10. But basicly I connected 12V+ to VBB, both arduino's and power supply ground to VSS, connected linbus to LIN line, CS to Arduino pin 8 and RX-RX and TX-TX and pin 2 to ibus line.

I was trying to write my code just to receive but than I swithced on your code that you shared on "Struggling with my BMW IBUS projects. Serial.read related issues.". I just modified for my needs, I am using a mega and serial0 to communicate to PC and Serial1 to communicate with MCP2025. But I dont get any message beside "-- IBUS Gap Detect version --" and then a legth to zero.

I am not even sure if the Linbus tranceiver wakes up or not.

// http://forum.arduino.cc/index.php?topic=234125.75

// this version is the one I posted on Forum modified to use an interrupt.
// 07Jun2014
// this version is modified to use a Timer2 interrupt to detect gaps to avoid the need
//   to wait for a new message when there is a long delay between messages.
// The Timer2 code is in gapDetect.ino
//
// Having detected the gap Timer2 will be inactive during a long gap.
//   It will only be restarted when the first bit of the next message is detected
// This means that detecting a gap signals the end of a message
// Previous versions of this code were based on detecting a new message.

const int CS_LWAKE = 8; // HIGH enables MCP2025 Tx

volatile boolean endOfMessage = false;

byte ibusData[37];  // assumes max message is 37 bytes
byte ibusCol = 0;
byte length;
byte checksumByte;


void setup() {
  pinMode (CS_LWAKE, OUTPUT); // initialize pin.
  digitalWrite (CS_LWAKE, HIGH); // write pin HIGH - enables MCP2025 Tx
  Serial.begin(9600);
  Serial.println("-- IBUS Gap Detect version --");

  Serial1.begin(9600, SERIAL_8E1);

  beginGapDetection(); // function in gapDetect.ino
}


void loop() {

  getIbusStuff();

}

void getIbusStuff() {

  if (endOfMessage) {
    startNewIbusMessage();
    saveIbusBytes(); // all of them
    endOfMessage = false;
    processData();
  }

}

void processData()
{
  length = ibusData[1];
  if (length == 0) {
    Serial.println("Length Zero");
    return;
  }
  byte checksumByte = 0;
  for (int i = 0; i <= length; i++){
    checksumByte ^= ibusData[i];
  }
  if (ibusData[length + 1] == checksumByte){
    for(int i = 0; i <= length + 1; i++)
    {
      Serial.print(ibusData[i], HEX);
      Serial.print(" ");
    }
    Serial.println();



  }
  else {
    Serial.println("Checksum Bad");

  }
}

void startNewIbusMessage() {
  ibusCol = 0;
}

void saveIbusBytes() {

  while (Serial1.available() > 0) {
    ibusData[ibusCol] = Serial1.read();
    ibusCol ++;
    if (ibusCol > 37) {
      ibusCol = 37;
    }
  }

}
//    Getting Timer2A to work requires these steps

//    Registers
//    TCCR2A   - compare match and waveform WGM                = B0000 0000  normal WGM
//    TCCR2B   - WGM and prescaler also used to stop the count = B0000 0110   256 prescaler
//    TCNT2    - the current count value
//    OCR2A    - value to count up to                          = TCNT2 + interval
//    OCR2B    -    NA
//    TIMSK2   - interrupt enables                             = B0000 0010   compare matchA interrupt
//    TIFR2    - flags                                        |= B0000 0010   clear matchA flag
//    ASSR     -    NA  async status - for external clocking
//    GTCCR    -    NA  resets prescaler - shared with all timers




byte gapTimerCount = 94; // gives a test interval of 94 * 16 = 1504 usecs

void beginGapDetection() {
  // this sets the appropriate timer mode and then attaches an interrupt to Pin 2
   
  TCCR2A = B00000000; // set normal mode (not fast PWM)
                       // with fast PWM the clock resets when it matches
                       // and gives the wrong timing
                       
  TCCR2B = B00000110;  // this is new - it sets the prescaler to 256
 
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, startTimer, RISING);
}


//========================

void startTimer() {
  // when a rising pulse is detected on pin2 the clock is started to trigger another
  //  interrupt after NN microseconds (determined by the value on gapTimerCount)

  OCR2A = TCNT2 + gapTimerCount; // sets up Timer2A to run for the sample period
  TIMSK2 = B00000010;  // Enable Timer2 Compare Match A Interrupt
                       
  TIFR2  = B00000010;   // Clear  Timer2 Compare Match A Flag
}

//========================


ISR(TIMER2_COMPA_vect) {
    // this is modified from the dcc code

    // this function runs when the Timer2A compare expires

  TIMSK2 &= B11111101;  // Disable Timer2 Compare Match A Interrupt
                        // the 1 bits will be unchanged, the zero will change that bit to zero
                       
  endOfMessage = true;  // I think all that is needed is to signal when a gap has been detected
}

Hi,

On the hardware side, you'll need to add a 1k pull-up resistor to the bus line. The bus idles high, and is pulled up by the instrument cluster in the car. On the bench, you need to do it yourself.

I never managed to get the gap timing code to work in the end. I posted some code at the top of page 6 of the same thread that actually works very well. It's come along a bit since then, but the basic theory is sound, and should get you going.

Cheers,

Ian.

Hi,

Here I attached my circuit. I dont see any pull-up resistor in the datasheet, I think mcp2025 has its own internal pull-up resistor. I still dont have any communication with this one as well.

I have another question as well about just a simple serial receiver but I dont know if it is better to open a new thread or not. I modified a bit two way serial communication example of arduino mega for Serial communication with pc. Do you think if we put aside the collision is it possible to communicate in that way without modifying the raw data? Can I see the hex codes separately on serial terminal or will it look like a mess?

If I manage to communicate I would like to create a github account for a library and schematics to communicate with ibus. I think there are quite a lot people who are playing with this and unfortunately in most cases they have to discover it from scratch.

I asked a bit too much, hope you dont mind. :confused:

Thanks.

mbt28:
I dont see any pull-up resistor in the datasheet

Page 12 - Fig 1-9. On the right hand side, it's shown under where it says 'Master Node Only'. When you're not in the car, the MCP2025 is the master node. Just connect the resistor between pins 1 & 4 (VBB & LBUS).

What's with the connection between the LIN bus line and Arduino pin 2 ? The LIN bus line is going to swing from GND to 12v, and won't be doing the Arduino any favours. Assuming you haven't already damaged something, I would disconnect it. The MCP2025 is what converts the 12v LIN bus levels down to TTL 5v levels, you don't want any direct connection from the LIN bus to the Arduino.

I have another question as well about just a simple serial receiver but I dont know if it is better to open a new thread or not. I modified a bit two way serial communication example of arduino mega for Serial communication with pc. Do you think if we put aside the collision is it possible to communicate in that way without modifying the raw data? Can I see the hex codes separately on serial terminal or will it look like a mess?

I'm not quite following you here.

If I manage to communicate I would like to create a github account for a library and schematics to communicate with ibus. I think there are quite a lot people who are playing with this and unfortunately in most cases they have to discover it from scratch.

I keep meaning to make an iBus library :slight_smile:

Ian.

Hello Ian,

I placed the pullup resistor as you said. I also used another simple code to just to make things simple for the beginning, and removed the pin 2.

I dont receive anything and I am not able to send anything.
I think something wrong with my hardware scheme, I did everything like in the datasheet. I also checked arduino it functions normal. All the serial ports are working.

Should I do anything with the head unit to start to communicate? It connected to 12V, Ignition, GND and Ibus line connected to MCP2025. Stays in DISABLED mode currently.

Regards

const int cspin = 8;  //CS

void setup() {
  pinMode(cspin, OUTPUT);
  digitalWrite(cspin,HIGH); // Force MCP2025 wake up
  // initialize both serial ports:
  Serial.begin(9600);
  Serial1.begin(9600, SERIAL_8E1);
  Serial.print("Print to serial monitor works!");
}

void loop() {
  // read from port 1, send to port 0:
  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.print("Parsing messages to serial monitor:");
    Serial.write(inByte); // Is it a right way to parse them?
  }

  // read from port 0, send to port 1:
  if (Serial.available()) {
    int inByte = Serial.read();
    
    Serial1.write(inByte);
  }
}

mbt28:
I also used another simple code to just to make things simple for the beginning.

It may be simple, but it's not going to do anything useful.

I dont receive anything and I am not able to send anything.
I think something wrong with my hardware scheme, I did everything like in the datasheet. I also checked arduino it functions normal. All the serial ports are working.

I don't see anything obviously wrong with the hardware setup. It would be nice to see some decoupling capacitors though. Your main problem is the code. Have you tried the code I suggested previously ?

Should I do anything with the head unit to start to communicate? It connected to 12V, Ignition, GND and Ibus line connected to MCP2025. Stays in DISABLED mode currently.

It will stay disabled until it sees traffic on the ibus. Something like this should kick it into life.

const int cspin = 8;  //CS
const byte IGNITION_POS1 [6] = { 0x80 , 0x04 , 0xBF , 0x11 , 0x01 , 0x2B }; // Ignition Acc position - POS1

void setup() {

pinMode(cspin, OUTPUT);
digitalWrite(cspin,HIGH); // Force MCP2025 wake up
Serial1.begin(9600, SERIAL_8E1);
Serial1.write(IGNITION_POS1, sizeof (IGNITION_POS1));
}

void loop() {

}

Ian.

Hi Ian,

I will go crazy, finally it works however I crossed the txd and rxd then it worked. I mean I connected rxd to txd and txd to rxd but in the datasheet it says the opposite maybe something wrong with my Chinese Arduino.

Thanks again, I will update later now I need a good sleep.

Regards.

mbt28:
I crossed the txd and rxd then it worked. I mean I connected rxd to txd and txd to rxd but in the datasheet it says the opposite

That is unusual. I've used the MCP2025 with lots of different models of Arduino (Uno, Nano, Mega and even Teensy 3.1), and always had them uncrossed. Apart from the Teensy, all my boards are clones. I think the Uno is from Sainsmart, and the Nano and Mega are branded Funduino I think.

Glad to hear you finally made some progress.

Ian.

Hi Ian,

I was already using your code which you used on page 7, you mentioned that it works. I couldn’t receive anything with that code. Where did you pinned the gap detector pin? On the RX side?

Why my simple code that I shared previously doesn’t work? Cant I receive simply with this ones? Thanks.

  if (Serial1.available()) {
    int inByte = Serial1.read();
    Serial.write(inByte, HEX);
  }

Regards.

mbt28:
I was already using your code which you used on page 7, you mentioned that it works. I couldn’t receive anything with that code. Where did you pinned the gap detector pin? On the RX side?

You probably didn't receive anything, because there was nothing sending messages. If you only have the radio, and the Arduino, there will be little or no traffic on the IBUS. There is no gap detector pin on the MCP2025. To send without collisions, you need to check the bus has been idle for more than 10ms before you send anything

Why my simple code that I shared previously doesn’t work? Cant I receive simply with this ones? Thanks.

  if (Serial1.available()) {

int inByte = Serial1.read();
   Serial.write(inByte, HEX);
 }

I guess that would show all the bytes on the IBUS, but it would just be a long sequence of bytes, that don't show individual messages. Without extra code, you wouldn't be able to do anything with the data you received.

Ian.

ian332isport:
I've attached my TH3122 schematic below.

Pin 2 (EN) goes to a digital output pin on the Arduino. Drive it high to enable the chip, and drive it low to put the chip to sleep. If you power the Arduino from the built in 5v regulator, you can use this to shut everything down to save power. The TH3122 will wake up as soon as it sees any traffic on the IBUS. As soon as this happens, the Arduino will also power back up. My entire system shuts down after 60 seconds of IBUS inactivity. Boot up is pretty much instantly. As soon as you hit the unlock button, it all fires up, and is running before you get the door open :slight_smile:

Tx & Rx are self explanatory. It is Tx to Tx and Rx to Rx though. Don't cross them over as you would normally. Remember to set the serial port to SERIAL_8E1 for the IBUS.

I feed pin 9 (SEN/STA) to one of the Arduino interrupt pins (2 or 3 on the Uno/Nano). This is used to tell if it's clear to send on the IBUS.

Let me know if you need any more info.

Cheers,

Ian.

Hi Ian,

I realise this an old post so apologise for awakening it! I've recently been trying to suss out some iBus stuff myself. I've acquired a handful of TH3122.4 chips and came across your schematic. I also came across a schematic on Curious Ninja's website - who credits you with assisting them.

I have a question though - his numerous schematics all state 47uF capacitor (C6 on your schematic) - you've put nF - so did he get it wrong, or have you updated yours since?

Your schematic shows a 47nF aka 0.047uF, but Curious Ninjas's is 47uF aka 47000nF.

Also, just out of curiosity what voltage are the caps rated?