LIN Bus Communication

Support forum for users of the M1 Build

LIN Bus Communication

Postby MalcolmG on Mon Nov 04, 2019 10:17 am

Hi there

I'm looking for some guidance on implementing LIN in Build. From what I've gathered so far, I think I need:

To send data:
1 - initialise the port using a Serial Port class object (LIN port, LIN protocol)
2 - open a handle (Serial.GetHandle)
3 - set a LIN header (Serial.SetLinHeader)
4 - write some data (Serial.SetUnsignedInteger)
5 - checksum - calculated using Serial.XOR8 - just reading through the LIN spec I don't think this is correct, and that it should be the (inverted) 8-bit sum, which I guess I can achieve using Serial.Sum8 and a bitwise NOT operation
6 - transmit data (Serial.Transmit)

So what I have so far is this:
Code: Select all
local h1 = Serial.GetHandle(true);
local offset = 0; // this will keep running tally of offset position
local dataOffset = 0; // stores where the data begins for XOR operation

dataOffset = Serial.SetLinHeader(h1, 0, 4, Tx Address, true, false);
offset = Serial.SetUnsignedInteger(h1, dataOffset, 1, data); // send data byte
offset = Serial.SetUnsignedInteger(h1, offset, 1, Serial.XOR8(h1, dataOffset, 4)); // calculate and send checksum
Serial.Transmit(h1, 1, offset);


I don't have an ECU spare to test this at the moment - but does it look roughly correct? Is there anything I'm missing?

Receiving seems a bit trickier, since the ECU will initiate the communication but then needs to listen for the response within the packet. The way I think it should be done is:
1 - open a handle (Serial.GetHandle)
2 - set a LIN header (Serial.SetLinHeader)
3 - transmit header (Serial.Transmit)
4 - receive data (Serial.GetUnsignedInteger)

But I'm not sure if that would be correct or not.

So any guidance, especially example code for sending and receiving, would be greatly appreciated.
MalcolmG
Pro User
 
Posts: 76
Joined: Fri Dec 18, 2015 1:34 pm
Location: Auckland, NZ

Re: LIN Bus Communication

Postby MalcolmG on Wed Nov 06, 2019 7:49 pm

I guess I have to answer my own questions then...

Well for the sake of anyone who comes to this thread searching for answers, I pulled an ECU out of a vehicle today to do some testing and I believe I have it mostly working now. I did this testing on a bench with a Picoscope reading the bus traffic to verify everything:

Sending data:
- In the code posted I didn't adjust the offset for the missing bytes, so the checksum occurs too soon
- For LIN 1.3, the ~Serial.Sum8 works fine, for LIN 2.1 with the Enhanced Checksum, you need to do as posted below - subtract 1 from the data offset position to get the protected ID and add 1 to the data length.
Code: Select all
local dataOffset = Serial.SetLinHeader(h1, 0, 4, Tx Address, true, true);
local offset = Serial.SetUnsignedInteger(h1, dataOffset, 1, data1);
offset =       Serial.SetUnsignedInteger(h1, offset, 1, data2);
offset =       Serial.SetUnsignedInteger(h1, offset, 1, data3);
offset =       Serial.SetUnsignedInteger(h1, offset, 1, data4);
offset =       Serial.SetUnsignedInteger(h1, offset, 1, ~Serial.Sum8(h1, dataOffset-1, 5));
Serial.Transmit(h1, 1, offset);

- It seems you need a decent time spacing between messages; I'm not sure if this is particular to the device I'm working with but you can't send consecutive messages in the same scheduled function, and the execution rate has to be slow - like 1Hz. To get my device working I sent a message on the first execution, received a message on the second, then received another message on the third. If I executed it at 5Hz the device no longer responded to the message requests. I noticed that the Bosch Wiper in GPR is executed at 50Hz, but maybe if you're not trying to receive messages too you can go a lot faster?

Receiving messages:
- If you try to receive a message as I outlined in my first post, it doesn't work; it takes some time for the received message to be read so you have to read it on the next execution of the function. It seems that the received message is automatically read into a receive buffer, so if you call Serial.Receive on the next execution the message should be waiting (assuming execution rate isn't too fast I suppose)
- The Serial Port class object deals with reading and checking the checksum, so you don't need to do anything about that.
- The data stored in the receive buffer has the address at byte 0 and the data begins at byte 2.

If anyone with more information wants to add to this that would be great.
MalcolmG
Pro User
 
Posts: 76
Joined: Fri Dec 18, 2015 1:34 pm
Location: Auckland, NZ


Return to M1 Build

Who is online

Users browsing this forum: Google [Bot] and 27 guests