LIN-BUS MCP2025 Arduino Uno

Hello looking for assistance in connection through an Arduino Uno -> MCP2025 to the line K / I-Bus in the car.

That's what I already have added in the Annex, in the Sketch as well as a diagram of how I got connected to Uno, which does not send / receive data.

Sketch works does not send data to the already Cars

Please help with writing a new, or modify this to impossible to send, unless the fault of the MCP connection to the Arduino.

ibus.zip (9.69 KB)

bmwV2.ino (5.13 KB)

I'm not sure where to start...

On the hardware side:

  1. You don't have any power supply decoupling capacitors on the 5v regulator pin.
  2. You have Tx and Rx crossed. You need Tx to Tx & Rx to Rx with the MCP2025.

On the software side:

  1. You need to have the iBus on Hardware serial with 9600 8E1, and debug serial on Software serial.
  2. Your first bit of code in loop is reading from Hardware/Debug serial. You won't have any iBus data there.
// Check Serial (PC) to see if we need to send something. 
    if (Serial.available()){
        Serial.println("Got Input");
        handleMessage(Serial.read()); <<THIS LINE
    }

Assuming this was a typo, it still won't work. You read it in, and pass it to function 'handleMessage'. Once it's gone, you can't get it back. You need to save it somewhere if you still want to do something with it. You may get lucky and catch the odd byte if one comes in at just the right time, but the chance of getting a complete message is slim.

I also noticed that your 'sendMessage' function is calculating the checksum. This isn't necessary, as you already have the checksum on the end of the messages in the 'handleMessage' function. That said, these messages are out of scope inside the 'sendMessage' function, as they only have local scope in the 'handleMessage' function. You need to give these global scope to be able to use them like that.

You probably want to re-think how you read the iBus. Try something like this:

  1. Read in 2 bytes and store them.

  2. Check if the 2nd byte is in the limits of a valid length byte (3 to 36 decimal).

  3. If it is, read in the rest of the message (based on the length byte).

  4. If it isn't, discard the 1st byte and try again.

  5. When you have a potential message, calculate the theoretical checksum and compare it with the last byte of the message.

  6. If they match, you have a good message. If not, discard the first byte and try again from the beginning. You'll eventually synchronise with the iBus

I use a circular buffer to store the incoming bytes. This makes it easy to discard the first byte and move on. I actually wrote a library for the circular/ring buffer. See here:

http://forum.arduino.cc/index.php?topic=332419.msg2295389#msg2295389

I really should try and write a library to read the BMW iBus, but it would be difficult to cover all the different interface chip options.

Ian.

Please help:
Just sketched the idea for my motorcycle LINBUS (a BMW R1200GS LC 2014).

DLR (Dayllight running light) SIGNAL READINGS (LIN BUS)
*DLR (ON/OFF) (getLINcode)
*FTP (FLASH-TO-PASS SWITCH) (getLINcode)
*HIGH BEAM SWITCH (getLINcode)
*HORN SWITCH (getLINcode)

MAIN SWITCH ON (on the handlebar)
IF DLR=ON THEN
AUX LED LIGHTS ALLWAYS ON 50%
WHEN LINcode = FTP >> PWM 50%->100%
WHEN LINcode = HORN >> PWM 50%->100%
WHEN LINcode = HIGHBEAM >> PWM 50%->100%
THEN 50%

IF DLR=OFF (LOW BEAM=NIGHT) THEN
AUX LED LIGHTS ALLWAYS ON 30%
WHEN LIN = FTP >> PWM 30%->100%
WHEN LIN = HORN >> PWM 30%->100%
WHEN LIN = HIGHBEAM >>> PWM 30%->100%
THEN 30%

MAIN SWITCH OFF
AUX LED LIGHTS ALWAYS OFF
WHEN LIN = FTP >> PWM 100%
WHEN LIN = HIGHBEAM >> PWM 100%

AUX LED LIGHTS
2X 12Volt 20Watts 1.6Amps


Have Arduino Uno R3 to use.

Probably using a MCP2025 (LIN transciever Microchip).
For the PWM i´d probably should use a MOSFET, like a RFP30N06LE, right?
Please help.
Very little experience in coding / hardware (but i believe it is a simple project)..
Thank you all!

The problem lies in the fact that I can receive messages from the I-bus every Possible pressing a button which shows me the Serial Monitor, and how it wants to send a message but fortunately not send me any messages sciaszania volume up nothing.

zaba141:
The problem lies in the fact that I can receive messages from the I-bus every Possible pressing a button which shows me the Serial Monitor, and how it wants to send a message but fortunately not send me any messages sciaszania volume up nothing.

What changes have you made to the arduino code ?

Please include the current code.

Ian.

#include <SoftwareSerial.h>

SoftwareSerial IBusSerial(11,10); // RX, TX for IBus

//Lbus = Ibus from Car
//Vss = Ground
//Vbb = +12V do Pin LWAKE - Rezystor 220ohm

// Pins we use for MCP2025
const int cspin = 8;  //CS

boolean read_byte = false;
byte readbuffer[64];

int i;
int buffer_index = 0;
int buffer_max = 64; // 64 default
int cksum;
long lastrx;
long lasttx;
char *Buffer = new char[buffer_max];

boolean byteSTATE = false;
int EventID = 0; // Event number (for case select)

    byte volup[6] = {0x50,0x4,0x68,0x32,0x11,0x1F}; // Steering wheel Volume Up
    //char volume_up[]="\x50\x04\x68\x32\x11\x1F";
    byte voldown[6] = { 0x50 , 0x4 , 0x68 , 0x32, 0x10 , 0x1E }; // Steering wheel Volume Down
    //50 4 68 32 11 1F
    //50 4 68 32 10 1E 
    byte pressmode[6] = { 0xF0, 0x4, 0x68, 0x48, 0x23, 0xF7 };
    byte pressmenu[6] = {0x68,0x4,0x3B,0x46,0x1,0x10}; //Menu Klikniecie
    byte showmenu[6] = {0x68,0x4,0x3B,0x46,0xC,0x1D};  //Menu Pokazanie
    byte releasemode[6] = { 0xF0, 0x4, 0x68, 0x48, 0xA3, 0x77 };
    //MENU  68 4 3B 46 1 10 
    ////68 4 3B 46 C 1D
    byte ibussucks[22] = {
        0x68, 0x12, 0x3B, 0x23, 0x62, 0x10, 0x49, 0x42, 0x55,
        0x53, 0x53, 0x55, 0x43, 0x4b, 0x53, 0x20, 0x20, 0x20,
        0x20, 0x20, 0x20, 0x40
    };
int messagelen;

void setup(){
    // initialize buffer array to 0's
    memset(readbuffer, 0, sizeof(readbuffer));
    
    // Debug to PC serial
    Serial.begin(9600, SERIAL_8E1);
    Serial.println("IBus Debugging begins");
    
    // set the data rate for the SoftwareSerial port
    IBusSerial.begin(9600);
    
    // Set high to enable TX on MCP2025
    pinMode(cspin, OUTPUT);
    digitalWrite(cspin, HIGH); //High To CS/LWAKE MCP

    pinMode(13, OUTPUT);
    digitalWrite(13, LOW); // Disable L diode
    
    lastrx = millis();
    lasttx = millis();
}

void loop(){
    delayMicroseconds(3000);
    
    if (Serial.available()){
        Serial.println("Got Input");
        handleMessage(Serial.read());
    }
    lasttx = millis();

    if ((millis() - lastrx) > 15) {
        memset(readbuffer, 0, sizeof(readbuffer));
        buffer_index = 0;
        read_byte = false;
        buffer_max = 64;
        lastrx = millis();
        return;
    }

    if (IBusSerial.available()) {
        readbuffer[buffer_index] = IBusSerial.read();
        read_byte = true;
    }

    if (read_byte){
        if (buffer_index == 1){
            buffer_max = readbuffer[buffer_index] + 2;
            cksum = readbuffer[0] ^ readbuffer[1];
        } else if ((buffer_index > 1 ) && (buffer_index < buffer_max)){
            cksum = cksum ^ readbuffer[buffer_index];
        }
    }

    // Reset buffer_index when it is buffer_max - 1.
    if (buffer_index == (buffer_max - 1)) {
     //  if ((readbuffer[0] == 0x68) || (readbuffer[2] == 0x68)) { //Disable to read all data I-Bus
            if (cksum == 0) {
                for (i = 0; i < buffer_max; i++){
                   Serial.print(readbuffer[i],HEX);        
                }
                if(memcmp(readbuffer, volup, 6) == 0 ){ Serial.println("Wcisniety guzik z głośnosci"); }  //Get Info is a push button + on Managers
            }else {
                Serial.print("Invalid message. cksum: ");
                Serial.println(cksum, HEX);
                for (i = 0; i < buffer_max; i++){
                    Serial.print(readbuffer[i], HEX);
                    Serial.print(" ");
                }
            }
            Serial.println();
//      }

        // Empty the buffer
        memset(readbuffer, 0, sizeof(readbuffer));
        buffer_index = 0;
        read_byte = false;
        lastrx = millis();
    }
    
    // Increment index if we put something into the buffer
    if (read_byte == true){
        read_byte = false;
        buffer_index++;
        lastrx = millis();
    }
}

void handleMessage(byte messageType){
    switch (messageType){
        case 0x70: // p for vol up
            Serial.println("Sending vol up.");
            sendMessage(volup);
            break;
        case 0x6E: // n for vol down
            Serial.println("Sending vol down.");
            sendMessage(voldown);
            break;
        case 0x42: // B for IBus Sucks
            Serial.println("Sending IBus Sucks.");
            sendMessage(ibussucks);
            break;
        case 0x6D: // m for mode
            Serial.println(" Mode.");
            sendMessage(pressmode);
            delay(150);
            sendMessage(releasemode);
            break;
    }
}

void sendMessage(byte message_data[]){
    for (int i=0; i <= sizeof(message_data); i++){
      IBusSerial.write(message_data[i]);
   }
}

You still have serial 8E1 on the debug serial. It must be on the ibus serial.

Ian

 It must be on the ibus serial.

At softwareserial not going to set SERIAL_8E1

zaba141:

 It must be on the ibus serial.

At softwareserial not going to set SERIAL_8E1

That's why you need to move the ibus to the hardware serial port, and use software serial for debug.

Ian.