Hello everyone ! I have read various projects regarding this in the forum, but all where closed so i had to make a new topic.
I am trying to use an Arduino to just sniff, the LIN bus of my vehicle's ( opel insignia) HVAC system
As many people have suggested, i have made a simple voltage divider to downscale the 12 to 5v , and just use the software serial to receive and dump the bytes received.
currently i am facing two issues:
The LIN frame consists of a break (14+bits) , and a sync field (fixed value of 0x55)
i cant seem to understand how to detect this break on the serial line. most people argue that it dosent even show up in the serial buffer since it dosnet have start and end characters , so you just have to look for a zero.
-no matter if i try 9600 or 19200 baud, i cant seem to be able to receive a byte 0x55 ...
i do receive repeating patterns , and i have managed to correlate some changes in this patterns, to changes on my HVAC controls.
Anyone has any previous experience with this ?
i am not posting any code because i am looking for a more generic guidance..
all the libraries i have found are based on a transceiver IC which is a road i would be happy to go with, but i dont have access to any such chips currently here , and i would like to have an idea of what i am doing before ordering .
Do you see 0x55 in the data that you receive? I would start by checking that.
It will indeed not show up in the serial buffer. You can detect a falling edge on the receive pin, next detect the rising edge and measure the time between them. At 9600 baud, it should be longer than 14 * 1000000 / 9600 microseconds.
Once you know that the break is finished, you can do the detection of 0x55.
char ch = Serial1.read();
if(ch == 0x55)
{
possible start of LIN packet
read the rest of the LIN packet
}
Above for a board with a secondary UART; else you will have to use software serial.
thanks for the reply !
yes, i have done allot of research in googling prior to posting !
Sadly no, i never see the 0x55 value. i see many others , but never this one . even if i just leave it there to receive, and look for a 0x55, it will never show up !
but if the break dosent show in the serial, and since the protocol says that the first byte after the break, is always 0x55, shouldent i be seeing this value, even without specifically looking for the break ??
i will try your suggestion though ! i have also tried different baudrates (All of them actually) , but to no avail
After that, I would write a simple loop() that just reads the LINBus (no break detection).
```cpp
if(LINBusSerial.available()!=0)
{
byte b = LINBusSerial.read();
Serial.println(b, HEX);
}
Set the Serial (not LINBusSerial) baudrate to e.g. 115200 (and adjust serial monitor).
Maybe you already tried it, but are there any 0x55 in there?
// Edit
You did try it; so what are the results (show them in code tags). Any chance that the bus is inverted?
// end edit
This is useless for a receiver; it flushes the output buffer, not the input buffer. Try below instead of the flush().
well , that was my initial attempt figuring that since no one mentions anything more special, that would be it. but unfortunately i never see this 0x55 character...
hey so today i tried this:
modified the arduino to work a bit like logic analyzer with the following code
int LinPin = 2;
void setup() {
Serial.begin(115200);
pinMode(LinPin,INPUT);
}
unsigned long micro_fall;
unsigned long micro_rise;
unsigned long pulse_dur ;
#define tsize 1024
bool val[tsize];
void loop() {
while (digitalRead(LinPin) == 1){} //detect a falling edge
micro_fall = micros();
while (digitalRead(LinPin) == 0){} //detect a rising edge
micro_rise = micros();
pulse_dur = micro_rise - micro_fall;
if (pulse_dur>700){
for (int i = 0 ; i <tsize ; i++){
val[i] = digitalRead(LinPin);
}
for (int i = 0 ; i <tsize ; i++){
Serial.println(val[i]);
}
while(1){}
}
}
I worked with the assumption that each digitalRead costs ~5 microseconds.
saddly arduino dosent have that much space so i was limited to just ~1500 measurments, and this is why i tried to measure what happens after the "pause".
it definetly shows a 10101010 pattern , (0x55) , as LIN is supposed to... so why my serial read does not read that but instead something else? >_>
this pattern is irelevant of my , assuming 5micros delay.
measuring the bit duration, i get ~100microsec per bit , which is in track for the 9600baud rate...
but my pause is ~800micros , which is in track for the 19200 Baud rate... but maybe my assumption for the 5micros is wrong.
Sorry - I just deleted my post before I noticed you had replied ( as I re read and saw you were just sniffing the bus on an active system ) , so my message was irrelevant .
so , in whatever logic analyzer i look, i see ~9600 baud, and i also see this 0x55 value.
but not on serial of arduino..
So i am starting to think that maybe i got an electrical issue ?
i have used a voltage divider, with rather high values (R1 10K and R2 6K) to scale down the car voltage to 5v . Issue is , car voltage is not stable, so i cant be presciese with this values.. my osciloscope shows ~3.5 - 4 V on the arduino side.
I couldent use lower values , becouse then the cars LIN would turn-off, propably becouse of overcurrent ??
maybe these high values effect high times, and/or slopes ?? any ideas on that ? unfortunately on this wiring part i have no clue
hey !
so some progress, in case someone bumps here in the future :
my main issue, was that the Baud rate that my car used , was not a standarized one..
for instance baud of 9600 requires bittime of 104uS.
but following LIN protocol to the letter, and using the SYNC byte to calculate the baudrate, at least in my car , resulted in bittime of 95uS !!
apart from that, i still havent figured out how could the software library deal with the syncbreak
(13ccs of LOW in line). i ended up writing some polling based serial library .
after that i started seeing some stuff that made sense!
do you guys know if i can set a completely custom baud rate for the software serial library ?