Struggling with my BMW IBUS projects. Serial.read related issues.

Hey guys,

I'm also working with the code from Curious Ninjas website, but can't get the code to work.
I can see messages are being received by the arduino, but for some reason the packethandler never gets called. Maybe bad packets as well?

Does any of you have a working sketch that is able to actually read and send messages?
I've been struggling with this for a while now. Don't understand why it won't work.

Any help would be greatly appreciated!!

If you can show/attach the code and library files, I can take a look. I also need to know what Arduino board and iBus interface chip you're using.

The packethandler will only get called if a valid message is received.

Ian.

Thanks Ian!

I currently use the code from George @Curious Ninja.

Here is the main code:

// v0.1.0 - Beta branch

#include <avr/interrupt.h>
#include <IbusGlobals.h>
#include <IbusSerial.h>
#include <RingBuffer.h>

IbusSerial ibus; // Create an instance of the Ibus library called ibus.

// If using processor board with more than one HardwareSerial port, you don't need to use SoftwareSerial, or AltSoftSerial for
// DEBUG, so just define which HardwareSerial port you plan to use.
//#define debugSerial Serial2

// If using Arduino with only one hardware serial port (Uno, Nano etc) AND using MCP interface chip, use AltSoftSerial instead
// of SoftwareSerial for DEBUG messages. SoftwareSerial uses pin change interrrupts that clash with the Ibus library. Also note
// that AltSoftSerial only works on pins 8(Rx) & 9(Tx).
//#include <AltSoftSerial.h>
//AltSoftSerial debugSerial;

// Software serial can be used with Melexis interface chip, but not with Microchip MCP Lin bus transceiver chips.
#include <SoftwareSerial.h>
SoftwareSerial debugSerial(7, 8); // 7 is Rx, 8 is Tx

// Setting up our variables
boolean goodPacket; //boolean value set true if good IBUS message detected
byte source;
byte length;
byte *pDebugByte;
byte databytes[36]; // Byte array to store message data bytes. ibusByte array of 40 - 4 for (Source, length, destination, checksumByte) = 36
byte outgoingMsg[32];
int outgoingSize;
unsigned long currentTime;


void setup()
{
  ibus.setIbusSerial(Serial); // Tell library which serial port is used for IBUS. Must be HardwareSerial port.
  ibus.setScrollSpeed(1500, 1000, 200, 2); // Start delay, End delay, scroll speed & number of repeats. Defaults to 2000, 1000, 200, 2 if no alternatives specified
  ibus.setIbusPacketHandler(packetHandler); // Define callback function. This is the function that is called by the library when it has a complete IBUS packet/message.
  ibus.sleepEnable(60); // Enable sleep timer, and set sleep time in seconds. Comment out/delete line to disable timer.
  debugSerial.begin(9600); // Set debug Baud rate
  ibus.setIbusDebug(debugSerial); // Tell library which serial port is used for DEBUG. Comment out line if debug disabled in IbusGlobals.h
  debugSerial.println(F("--IBUS reader V2--"));
  attachInterrupt(digitalPinToInterrupt(3), startTimer, CHANGE);
  pinMode(ledPin, OUTPUT);
  Serial.begin(9600);
  Serial.println("Serial Start!");
}
void loop()
{
  ibus.run(); // This keeps the IbusSerial library running.
  digitalWrite(12, LOW);
  ibus.write(CLOWN_FLASH, sizeof(CLOWN_FLASH));
}

// This is where we compare the received message with all the message bytes
// in IbusGlobals.h, or to known source/destination, and respond accordingly.
// 2. Implement timer to remove written text from radio display after X seconds

void packetHandler(byte *packet) // callback function
{
  Serial.println("Handling packet!");
  
  source = packet[0];
  length = packet[1];
  byte destination = packet[2];
  pDebugByte = packet;

  // Identify message databytes - populate our databytes array
  for (int i = 0, s = 3; i <= length - 3; i++, s++) {
    databytes[i] = packet[s];
  }



  // Message from MFL_RT
  if (memcmp_P(packet, MFL_RT_PRESS, 6) == 0 ) {
    // This is how to send a known i-Bus message, from list in IbusGlobals.h.
    // It's sending the CD_STOP message whenever you press the
    // R/T button on the steering wheel. This is just an example, and probably
    // not something you would ever want to do.
    //ibus.write(CD_STOP, sizeof(CD_STOP));
  }




  // Message from MFL_VOL_UP
  if (memcmp_P(packet, MFL_VOL_UP, 6) == 0 ) {
    // This is how to send text message to the Business CD/Radio display
    //ibus.radioWrite("Vol UP Vol UP Vol UP ");


  }




  // Message from MFL_VOL_DOWN
  if (memcmp_P(packet, MFL_VOL_DOWN, 6) == 0 ) {
    ibus.radioWrite("Vol DOWN");
  }
  // Message from RLS to LCM
  if ((source == 0xE8) && (destination == 0xD0)) {
    if (databytes[1] == 0x11) {
      //debugSerial.println(F("It's dark out, lights commanded on"));
      // TODO:
      // Blinking alert LED wire will come into arduino as a digital input (Radar detector alert LED).
      // Implement dimming feature here. If this I-Bus message is present, find a method to dim this LED
      // Arduino output to actual LED == Increase resistance to ground? PWM? Or activate a relay that includes resistor?
    }
  }
}

void startTimer()
{
  ibus.startTimer();
}

Here are the libraries (straight from Curious Ninja's website):

I only added a serial.print "Handling packet" inside the packet handler to check if the function is triggered.
I am using an Arduino Uno just like George does on his website, together with an TH3122.4.
The chip works as I can successfully receive and send message with Navcoder.

I greatly appreciate your help!

Luck

Hi Luck,

Can you show me what you can see in the serial monitor ?

Ian.

You mean the Serial monitor in the Arduino programm? Or via putty?

Either. I just need to see what debug output you are seeing from the Arduino.

Ian.

Finally found the time to check with the debugger. Got it working after some time.

I started adding printlines and this is where it "stops"

case FIND_SOURCE:
//printDebugMessage("IbusSerial::readIbus - case FIND_SOURCE"); // WORKS(Looping. Not sure if it loops when/between receiving messages)
   if (ibusReceiveBuffer.available() >= 1) 
   {
 printDebugMessage("IbusSerial::readIbus - case FIND_SOURCE - if (ibusReceiveBuffer.available() >= 1)  ");
     source = ibusReceiveBuffer.peek(0);
     ibusState = FIND_LENGTH;
   }
   break;

It does reach the FIND_SOURCE case, but nothing happens after that...

This is the Debugger output:

--IBUS reader V2--
IbusSerial::readIbus - case FIND_SOURCE00 00

Not sure what those 4 zero's mean.

I hope you have any thoughts about what the issue might be.
Thanks for your help.

Luck

Hi Luck,

You're doing that all wrong.

Delete all the "printDebugMessage" lines you've added. Than go and look at the top of IbusGlobals.h, and make sure "#define IBUS_DEBUG" is not commented out. While you're there, make sure "#define MELEXIS" is also active (not commented). As long as you have everything connected correctly, you should see plenty of debug text in the serial monitor.

It would make life much easier if you just posted all your code (attach all files, including the library files), and I can see if everything looks good.

If you can also show how you have the Melexis TH3122 connected to the Arduino, it would also help. If you're not working in the car, do you have the iBus line pulled up to 12v through a 1K resistor ? You won't see anything at all unless the iBus line is pulled high.

Ian.

Hi Ian,

I've done precisely what you said, but no luck.
#define IBUS_DEBUG is not commented out, neither is #define MELEXIS.

I'm using the The TH3211.4 chip, which is MELEXIS correct?

I know the chip works, as I can use Navcoder perfectly fine with it.
Only when I connect it to the arduino, things won't work.
I can see a LED which is connected to pin 13 light up every time a message is received, so the connection to the arduino itself should be fine.

I use this setup (just like George, aka Curious Ninja describes):

The only difference is the brand of the TTL converter. But since I see the setup message "--IBUS reader V2--" in Putty and since I can use Navcoder perfectly, it has to be the software. (right?)

Here's a .rar of all my code. (Which I downloaded straight from Curious Ninja's website http://curious.ninja/)

I was wondering if you ever got any positive results receiving and sending messages to a bmw?

Best regards and many thanks,
Luck Hermsen

Hi Luck,

You need to swap the Tx & Rx connections between the Melexis TH3122 and the Arduino. You have them crossed on your diagram, but they need to go Tx to Tx and Rx to Rx. That would certainly stop things working.

I've used this code connected to my E46 3 Series BMW, and can send and receive messages without any problems.

Ian.

Wow....
That would be awkward.

I'll test it later today and let you know!

You were right, unbelievable. I've spent so many hours trying to figure out what was wrong. Never doubted the schematics.

Do you have an easy example of a function that checks for a specific message and sends a message back as a reply?
For some reason that doesn't seem to work.

For example the Volume up function, it always replies. No matter if the button is actually pressed or not.

void packetHandler(byte *packet) // callback function
{
  
  source = packet[0];
  length = packet[1];
  byte destination = packet[2];
  pDebugByte = packet;

  Serial.println("New message received!");

  // Identify message databytes - populate our databytes array
  for (int i = 0, s = 3; i <= length - 3; i++, s++) {
    databytes[i] = packet[s];
  }
  // Message from MFL_RT
  if (memcmp_P(packet, MFL_RT_PRESS, 6) == 0 ) {
    // This is how to send a known i-Bus message, from list in IbusGlobals.h.
    // It's sending the CD_STOP message whenever you press the
    // R/T button on the steering wheel. This is just an example, and probably
    // not something you would ever want to do.
    Serial.println("MFL RT!");
    //ibus.write(CD_STOP, sizeof(CD_STOP));
  }
  // Message from MFL_VOL_UP
  if (memcmp_P(packet, MFL_VOL_UP, 6) == 0 ) {
    // This is how to send text message to the Business CD/Radio display
    //ibus.radioWrite("Vol UP Vol UP Vol UP ");
    //ibus.write(CLOWN_FLASH, sizeof(CLOWN_FLASH));
    Serial.println("MFL Up!");
  }
  // Message from MFL_VOL_DOWN
  if (memcmp_P(packet, MFL_VOL_DOWN, 6) == 0 ) {
    //ibus.radioWrite("Vol DOWN");
        Serial.println("MFL Down!");
  }
  // Message from RLS to LCM
  if ((source == 0xE8) && (destination == 0xD0)) {
    if (databytes[1] == 0x11) {
      //debugSerial.println(F("It's dark out, lights commanded on"));
      // TODO:
      // Blinking alert LED wire will come into arduino as a digital input (Radar detector alert LED).
      // Implement dimming feature here. If this I-Bus message is present, find a method to dim this LED
      // Arduino output to actual LED == Increase resistance to ground? PWM? Or activate a relay that includes resistor?
    }
  }
}

It just keeps printing MFL Up! every time a message is received...

Hi Luck,

Try this to start with. Just replace the existing function.

void packetHandler(byte *packet) // callback function
{
	if (memcmp_P(packet, MFL_VOL_UP, 6) == 0 )
	{
		Serial.println("MFL Up pressed");
	}
	
	if (memcmp_P(packet, MFL_VOL_DOWN, 6) == 0 )
	{
		Serial.println("MFL Down pressed");
	}
}

This won't reply to anything yet, but should print the correct message to the serial monitor, each time you press the volume up/down buttons on the steering wheel. There's no point trying to reply until we have the basics working correctly.

Whenever the iBus library detects a good message, it will call the packetHandler function, and pass it a pointer to this message. This function just compares the new message with the known messages defined in IbusGlobals.h. If you get a match, it will perform the appropriate action. In this case, just printing to the serial monitor.

You should also see the incoming messages shown on the serial monitor. George added a lot of unnecessary code to the example program which can make it a little harder to see what's going on. If it still doesn't work, I'll post my current library code, and the original example sketch.

Let me know if this works, and we can then look at sending messages.

Ian.

Hello guys,

I'm trying to read a BMW F33 Lin bus, so far it seems no one has done it for the F series or at least there is no info on the net, wich is a bit scary.

Anyways I used the hardware and code provided here --> Arduino & BMW I/K Bus Interface – Schematic Descriptions » Curious-Ninja – IT, Cars, and Aviation
Only diference is Im using an Arduino Mega and no USB to TTL as i can use the multiple hardware serials.

I made a connection to the climate control/radio LIN Bus, set the code in debug mode and it seems i am getting messages every few seconds, some chatter is going on the line, but when i press buttons on the control panel i dont see any specific messages being sent. Just the chatter on the line continues as if nothing happened.

So far I tried with a MCP2004 chip and a TH3122, to see if it made a difference but its the same.

Any idea what could be happening please?

thanks.

Edit: After reading a little I think BMW E series use LIN 1.3 and F series use the newer LIN 2.0, so the code is not compatible.

This is my simple Solution for IBus Communication

cederron:
After reading a little I think BMW E series use LIN 1.3 and F series use the newer LIN 2.0, so the code is not compatible.

I'm not sure what BMW did on the F series cars. Even on the later E series cars (E9x onwards), they mostly moved over to CAN bus. I think they did still use the iBus for some modules, but not the infotainment systems.

Even on the E series, BMW didn't really use a traditional LIN bus with master and slaves. They used the LIN standard for the voltage levels etc, but the iBus protocol was considerably different to the LIN protocol. Any module could take control of the bus (assuming the bus was idle), and send data to another module. I believe a proper LIN bus is controlled by the master, and the slaves only send data when asked to do so.

What are you trying to achieve ?

Ian.

ian332isport:
I'm not sure what BMW did on the F series cars. Even on the later E series cars (E9x onwards), they mostly moved over to CAN bus. I think they did still use the iBus for some modules, but not the infotainment systems.

Even on the E series, BMW didn't really use a traditional LIN bus with master and slaves. They used the LIN standard for the voltage levels etc, but the iBus protocol was considerably different to the LIN protocol. Any module could take control of the bus (assuming the bus was idle), and send data to another module. I believe a proper LIN bus is controlled by the master, and the slaves only send data when asked to do so.

What are you trying to achieve ?

Ian.

Im trying to control the air con/heating from a tablet already installed in the car.
I started monitoring the can bus at first but i noticed some of the buttons in the air con panel didnt post a message to the bus. So i started looking at insta and the control panel sends the commands to the heating control box via LIN bus.

The heating and air conditioning system is operated via the operating elements in the heating and air conditioning system control box. The request signals from the control box are transmitted via the LIN bus to the control unit for the heating and air conditioning system.

I understand the only way to control it is via LIN bus.
Thanks for the info about the non-standard lin bus implementation didnt know that.

I will try to read lin 2.0 frames and see what happens.

This is probably the best description of what BMW did prior to the E9x series. It was called the BMW iBus.

http://web.comhem.se/mulle2/IBUSInsideDRAFTREV5.pdf

It's possible that BMW still uses the same system, but the device address may be different. Do you have an example of what a message looks like ?

Ian.

ian332isport:
This is probably the best description of what BMW did prior to the E9x series. It was called the BMW iBus.

http://web.comhem.se/mulle2/IBUSInsideDRAFTREV5.pdf

It's possible that BMW still uses the same system, but the device address may be different. Do you have an example of what a message looks like ?

Ian.

Thanks for your interest Ian.
I'm receiving messages like these:

Good message:00 1A FE 00 3F 00 50 00 00 B9 1C F9 00 84 08 00 1A FE 00 3F 00 0A 00 F8 FE 00 84 08 
Good message:84 08 CF 1A FE 00 1E 00 00 B9 
Good message:00 1A FE 00 3F 00 0A 00 B9 1C F9 9F 00 84 08 CF 00 1A FE 00 3F 00 00 F8 FE 00 84 08 
Good message:00 1A FE 00 0A 00 39 1C F9 00 84 08 00 1A FE 00 3F C0 C3 FE 00 84 08 EF 00 1A 1F FE 
Good message:B9 1C F9 00 84 08 00 39 1A FE 00 3F 00 0A 00 8C F8 FE 00 84 08 EF 00 1A FE 00 3F 00 0A 00 
Good message:00 1A FE 00 FA 00 0A 00 8F F8 FE 00 84 08 EF 00 1A E3 FE 00 1E FA 00 05 00 1C F9 FD 
Good message:00 1A FE 00 3F 00 0A C3 FE 00 84 08 EF 1A 00 00 0A 00 1C F9 FD 00 84 08 EF 00 1A FE 
Good message:00 1C F9 FD 00 84 08 00 1A FE 00 3F 00 0A 00 F8 FE 84 08 EF 00 1A E3 FE 00 3F 00 1C F9 FD 
Good message:00 1A FE 00 3F 00 0A 00 1C F8 FE 00 84 08 CF 00 1A FE 00 3F 00 0A 00 2C F9 00 84 08 
Good message:00 0A 00 B9 2C F9 F8 FD 00 84 08 EF 
Good message:00 0A 0C C0 1C 99 F8 F8 00 84 08 CF 
Good message:00 1A FE 00 3F 00 2C F9 00 84 08 EF 00 1A FE 00 3F 00 0A 00 F8 FE 00 84 08 CF 1A E3 
Good message:00 0A F9 8C 99 FB 00 84 1A FE 00 7D

They come between 1-4 seconds each, but when i press buttons i dont see corresponding messages at the same time or different messages reacting to the presses.
I dont know i think the code interprets random data as messages because the checksums are validated

I would tend to agree that those are not valid messages. Based on the known iBus protocol (which is what my code is designed to read), you have device 00 trying to communicate with itself on one of the messages above.

You may need to use a logic analyser to decode the messages on the LIN bus. Assuming it's standard LIN, and not some BMW variant. I know the Saleae software con decode LIN frames, but I don't have an F series BMW to test on.

Ian.