Help Needed in Analyzing LIN Bus Data Using Arduino and TJA1021

Hello everyone,

I've been working on a project where I'm trying to read data from a LIN bus using an Arduino Leonardo and a TJA1021 transceiver. I have written two programs to read the data: one using SoftwareSerial and the other using Serial1 (the hardware serial port).

Here's a simplified version of the two programs I used:

**Program using SoftwareSerial:

#include <Arduino.h>
#include <SoftwareSerial.h>

#define LIN_SERIAL_RX_PIN 14
#define LIN_SERIAL_TX_PIN 15
#define LIN_BAUD_RATE 9600
#define TJA_WAKEUP_PIN 7

SoftwareSerial linSerial(LIN_SERIAL_RX_PIN, LIN_SERIAL_TX_PIN);

void setup() {
  Serial.begin(115200);
  linSerial.begin(LIN_BAUD_RATE);
  pinMode(TJA_WAKEUP_PIN, OUTPUT);
  digitalWrite(TJA_WAKEUP_PIN, HIGH);
}

void loop() {
  if (linSerial.available()) {
    byte receivedByte = linSerial.read();
    Serial.println(receivedByte, HEX);
  }
}

**Program using Serial1:

#include <Arduino.h>

#define LIN_SERIAL_RX_PIN 0
#define LIN_SERIAL_TX_PIN 1
#define LIN_BAUD_RATE 9600
#define TJA_WAKEUP_PIN 7

void setup() {
  Serial.begin(115200);
  Serial1.begin(LIN_BAUD_RATE);
  pinMode(TJA_WAKEUP_PIN, OUTPUT);
  digitalWrite(TJA_WAKEUP_PIN, HIGH);
}

void loop() {
  if (Serial1.available()) {
    byte receivedByte = Serial1.read();
    Serial.println(receivedByte, HEX);
  }
}

I've noticed that the data I'm getting from the two programs seem to be different. I'm not sure why this is happening, as I believe the physical connections and the LIN signal are correct.

Data from first code:

80
80
0
2
0
80
80
80
21
68
60
0
80
80
0
2
0
80
80
10
0
10
0
E0
80
80
0
2
0
80
80
10
FE
80
80
0
2
0
80
80
10
0
10
0
E0
80
81
0
2
0
80
80
80
D0
79
18
7A
FE
80
81
0
2
0
80
80
7
0
10
0
E0
80
80
0
2
0
80
80
10
FE
80
80
0
2
0
80
80
11
84
10
0
E0
80
83
0
2
0
80
80
80
21
68
60
0
80
80
0
2
0
80
80

Data frome secound code:

FE
80
6
8
8
8
FB
80
FC
80
6
8
8
8
FB
80
D
8
8
8
58
80
6
4E
8
8
FF
80
FC
80
6
4E
8
0
FF
80
F0
80
6
4E
8
8
FF
80
FC
80
86
4E
8
8
FF
80
42
8
8
E8
FA
80
86
4E
8
5
FF
80
2C
8
84
8
FE
0
4
E
8
85
FF
80
F8
80
86
4E
8
5
FF
80
2C
8
4
8
F8
0
6
4E
8
85
FF
80
wpisz lub wklej tutaj kod

I'm having difficulty interpreting these data. I don't have a clear mapping of the identifier field to slave devices, and I'm not sure if the data are being correctly and fully received.

Could anyone provide some insight into why the data might be different between the two programs, and how I might interpret these data? Any help would be greatly appreciated.

Thank you in advance!

It is the blue thing that is not working. Without knowing what you are working with the blue thing is about the best I can do. What is the source of the signal. Post a schematic showing how it is connected. Post links to technical information on all the hardware parts. What is the protocol, has it been defined or are you guessing?

1 Like

yes, baud rate too high for software serial and it's not needed use serial1..
error, i see it's 9600?? should work, so idk..

no idea, too vague..

sorry.. ~q

Serial1 is hardware serial and is by far more reliable than software serial (aka bit banging). that is probably why LIN communication fails for the latter.

btw if you check out my github, I have a LIN library already created for AVR platform which make used of hardware serial. would love to here some fb for it! :slight_smile:

happy coding!

2 Likes

Thx, for your reply.
Currently Im testing ardino and TJA 1021 for beater understand car LIN communication. I have only basic knowledge about LIN communication from this [source](http://www.volkspage.net/technik/ssp/ssp/SSP_286_d1.pdf). For my project Im using signal LIN communication between front and rear door module in Audi C6, I choose this because the master - driver door unit is only link to Slave - rear door via LIN. So in this case the signal is only between two devices.

1 Like

Thx, for your reply, I will try to change this to 9600.

Thx for this information I will try to include this library to my project. I worked a little with LINBus_stack however with out success.

I wanted to take a moment to express my gratitude to @sherzaad for his invaluable guidance and resources for working with the LIN protocol on Arduino.

Your library for the LIN protocol has been incredibly useful in my project. It has provided a solid foundation for me to understand and implement communication over the LIN bus with Arduino. The functions in the library are well thought out and the code is structured in a way that is easy to understand and use.

Additionally, the sample code you provided for monitoring the LIN bus was a great starting point for me. With a few minor modifications, I was able to get it working seamlessly on my Arduino Leonardo. This has saved me a significant amount of time and effort, and has allowed me to move forward in my project more quickly than I had anticipated.

Your work has truly made a difference in my project and I am deeply grateful for your contributions. I am sure there are many others in the community who have benefited from your work as well.

Once again, thank you @sherzaad for your wonderful work on the LIN protocol with Arduino. Your expertise and willingness to share your knowledge with the community is greatly appreciated.

this date I received from LIN Bus:

New Frame: F0, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 41, 0, 0, 0, 0, FC, 
Sync: 55, PID: 42, ID: 2, Data: 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 41, 0, 0, 0, 0, FC, 
Sync: 55, PID: C4, ID: 4, Data: 20, 0, 0, 0, 1B, 0, 1B, 0, E4, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 0, 0, EA, 
Sync: 55, PID: 42, ID: 2, Data: 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 0, 0, EA, 
Sync: 55, PID: 3, ID: 3, Data: FE, FD, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 0, 0, EA, 
Sync: 55, PID: 42, ID: 2, Data: 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 0, 0, EA, 
Sync: 55, PID: 85, ID: 5, Data: 6E, E2, 74, 1, 17, 35, 8D, 96, 43, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 94, 0, 56, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 1, 0, 0, 0, 0, 72, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 94, 0, 56, 
Sync: 55, PID: 3, ID: 3, Data: FE, FD, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 41, 0, 0, 94, 0, 56, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 8, A, 42, 0, 0, 94, 0, 55, 
Sync: 55, PID: C4, ID: 4, Data: 20, 0, 0, 0, 1B, 0, 1B, 0, E4, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, A, 42, 0, 0, 94, 0, 5D, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 43, 0, 0, 94, 0, 66, 
Sync: 55, PID: 3, ID: 3, Data: FE, FD, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 43, 0, 0, 94, 0, 66, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 43, 0, 0, 94, 0, 66, 
Sync: 55, PID: 85, ID: 5, Data: 0, 0, 0, 0, 0, 0, 0, BF, BA, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 43, 0, 0, 94, 0, 66, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 43, 0, 0, 94, 0, 66, 
Sync: 55, PID: 3, ID: 3, Data: FE, FD, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 44, 0, 0, 0, 0, F9, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 44, 0, 0, 0, 0, F9, 
Sync: 55, PID: C4, ID: 4, Data: 20, 0, 0, 0, 1B, 0, 1B, 0, E4, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 44, 0, 0, 0, 0, F9, 
Sync: 55, PID: 42, ID: 2, Data: 6, 0, 44, 9, 40, 0, 0, 0, 2A, 
Sync: 55, PID: C1, ID: 1, Data: 0, 0, 0, 44, 0, 0, 0, 0, F9, 
wpisz lub wklej tutaj kod

Interesting from this data is that the LIN communication is only from master to one slave however we can see 10 ID - '1', '2', '3', '3C', '4', '42', '5', '85', 'C1', 'C4'.

Does anyone know why there is 10xIDs?

1 Like

Glad to hear it was of good use to you! :slight_smile:

the PID contains the ID. so you have only 4 or 5 distinct LIN frames according to your trace! you can find material online explaning what is the PID is.

one of 2 thing IMHO;

either your LIN networks has more that one node

or

it is perfectly acceptable for a LIN slave to respond to more than one LIN ID(PID)! :wink:

hope that helps....

1 Like

Thank you very much for your response. Your insights have been really helpful in understanding the function of the PID and the possibility of multiple nodes in the LIN network or multiple PIDs for a single LIN slave. I've found some material online regarding the PID and I'm going to delve into it.

To further my understanding, I have an additional question. Would you be able to indicate which part of the LIN frame is the response from the Slave to the data previously sent? It's not immediately clear to me and your expertise on this would be very much appreciated.

Thank you once again for your help.

that I cannot answer unfortunately.

However what I can answer is that a LIN frame consists of 2 parts a header(aka the PID) and the 'data' part.

the PID is always transmitted by the MASTER as a means to ping the slave ECUs and if said slave is assigned the PID, it will respond with the 'data' part.

note that the MASTER too can have its own PID in which case it would transmit the 'data' part as well.

hope that helps...

Thank you for the information. I've partially solved this problem by analyzing the LIN signal from the slave only. In addition, I disconnected all slave units to see what signal would be sent from the master. It's worth noting that the master is the climatronic from an Audi Q7, and the CAN bus was disconnected. I investigated the signal from the seat heating. Below are the results:

Sync: 55, PID: E7, ID: 27, Data: 80, FC, 3, 97, - Heating off
Sync: 55, PID: E7, ID: 27, Data: 81, FC, 3, 96, - Heating Level 1
Sync: 55, PID: E7, ID: 27, Data: 82, FC, 3, 95, - Heating Level 2
Sync: 55, PID: E7, ID: 27, Data: 83, FC, 3, 94, - Heating Level 3
Sync: 55, PID: E7, ID: 27, Data: 84, FC, 3, 93, - Heating Level 4
Sync: 55, PID: E7, ID: 27, Data: 85, FC, 3, 92, - Heating Level 5
Sync: 55, PID: E7, ID: 27, Data: 86, FC, 3, 91,  - Heating Level 6 

It's worth noting that the first byte after the data changes from 80, which represents 'OFF', to 86, which represents level 6. 'FC' and '3' appear to be constants for all these messages. The last byte might represent a checksum or information about the response from the slave, in this case, there was no response."

While monitoring the LIN communication, I've observed something peculiar. For certain frames, the PID is showing as 6 while the ID is also 6. As far as I understand, the PID is derived from the ID with added parity bits. This makes such an occurrence seem impossible in standard LIN communication.

Here's a snippet of the code I use to read and interpret the frames:

if (LIN.FieldType(val) == PID) {
  Serial.print("PID: ");
  Serial.print(val & 0xFF, HEX);
  Serial.print(", ID: ");
  Serial.print((val & 0xFF) & 0x3F, HEX);
  Serial.print(", Data: ");
}

The output I get is: "PID: 6, ID: 6", which seems inconsistent with how I understand the LIN protocol.

Could anyone explain why I might be observing this behavior? Is this an error in my code, an issue with the library I'm using, or could the master device (sending these frames) be operating non-standardly? Any insights or pointers would be highly appreciated.

Raw data from from LIN:

Sync: 55, PID: 85, ID: 5, Data: 6, 0, F9, 
Sync: 55, PID: 6, ID: 6, Data: 1, 0, FE, 
Sync: 55, PID: 85, ID: 5, Data: 6, 0, F9, 
Sync: 55, PID: F0, ID: 30, Data: 
Sync: 55, PID: 6, ID: 6, Data: 1, 0, FE, 
Sync: 55, PID: 85, ID: 5, Data: 6, 0, F9, 
Sync: 55, PID: 6, ID: 6, Data: 1, 0, FE, 

you can use this website to check:
https://linchecksumcalculator.machsystems.cz/

and according to it, the PID is correct and your system is using "classic" checksum calculation (the checksum byte is the last 'data' byte btw).

if you are using the "GetPID" routine to calculate back the PID and not getting the same as what your are reading, it may be a bug... will check that out when I have sometime.

thank you for your input

there was a bug in that routine... now fixed on git.

1 Like

ok, thx for that :slight_smile:

Hey @sherzaad! :red_car::wrench:

I'm diving deep :man_detective: into the LIN bus data and came across some interesting observations on an AUDI model. Specifically, I found the following for PID 85 - Driver's side ventilation:

Sync: 55, PID: 85, ID: 5, Data: 0, 6, F9 - Ventilation speed 0 -OFF
Sync: 55, PID: 85, ID: 5, Data: 0, 5, FA - Ventilation speed 1
Sync: 55, PID: 85, ID: 5, Data: 0, 4, FB - Ventilation speed 2
Sync: 55, PID: 85, ID: 5, Data: 0, 3, FC - Ventilation speed 3
Sync: 55, PID: 85, ID: 5, Data: 0, 2, FD - Ventilation speed 4
Sync: 55, PID: 85, ID: 5, Data: 0, 1, FE - Ventilation speed 5
Sync: 55, PID: 85, ID: 5, Data: 0, 0, FF - Ventilation speed 6

The first BYTE is always 0x00.
The second BYTE indicates the fan speed level, from 6 (which means the ventilation is off) to 0 (which is level 6).
As mentioned above, this is not a mistake; the ventilation level arrangement is reversed here.
The third BYTE is the checksum, calculated as "255 minus the sum of bytes modulo 256."

From this, I deduced :thinking: that the checksum calculation might be using the "255 minus the sum of bytes modulo 256" method. Are you using this approach in your LIN library? :books:

Would love your insights on this! :pray:

yes.

if you have checked the LIN.h file you would have found a routine called "GetChecksum" in there! :wink:

Oops, my bad! :see_no_evil: I indeed missed that detail on my initial review. You're right, the library defaults to using the checksum calculation method for LIN 2.0. For my project, I needed it for version 1.0, hence the modification. Thanks for pointing it out! :+1::blush:

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.