Skip to Content


Tag Archives: LIN

Introduction to LIN in .NET F#

Next edition of  “Get Noticed!” started, and it’s my third attempt to write a blog in scope of one year, you know what they say, third time’s a charm. Little inspired by idea in post by fellow contender, I’m putting X amount for first post a week, and twice X for second in week, to “pleasure budget” that I can spend without remorse. We’ll see where that leads me. The goal of the project is to create “yet undefined” set of tools to make my work with LIN, a little easier and faster. The bread idea is to have tool generating .NET/F# client based on LDF (a little more on that in next post). Let’s start with short introduction to LIN.

What is LIN?

LIN (Local Interconnect Network) is a low-end and low-cost,  single wire Serial Network Protocol that is used in automotive networks to communicate between vehicle components. It consists of 1 master and up to 15 slaves.

LIN message

Each message is identified by ID. Valid IDs are within range <0,63>, where 0 to 56 are used for signal carrying, 60 and 61 for diagnostics, 62 for user defined extensions, and 64 reserved for future enhancements.  on lower 6 bits, while the two upper bits contain parity.

Parity calculation

let calcPID ID =
  let ID0 = ID &&& 1uy
  let ID1 = ID >>> 1 &&& 1uy 
  let ID2 = ID >>> 2 &&& 1uy 
  let ID3 = ID >>> 3 &&& 1uy 
  let ID4 = ID >>> 4 &&& 1uy 
  let ID5 = ID >>> 5 &&& 1uy 
  let P0 = ID0 ^^^ ID1 ^^^ ID2 ^^^ ID4
  let P1 = ~~~(ID1 ^^^ ID3 ^^^ ID4 ^^^ ID5) &&& 1uy
  ID ||| (P0 <<< 6) ||| (P1 <<< 7)


Message data consists from at least 1 byte and up to 8, and checksum. LIN 1.x uses Classic Checksum, while LIN 2.x uses Enhanced Checksum with the exceptions of messages with IDs from 60 to 63 which should be calculated with Classic Checksum.

Classic and Enhanced Checksum

Classic checksum is calculated using only message data, while in Enhanced Checksum we also include Protected ID, In order to calculate checksum we sum all bytes, subtracting  255 each time sum is greater or equal to 256, and then invert resulting value.

let carry255 a b = 
  match a + (b |> uint16) with 
    | s when s > 255us -> s-255us 
    | s -> s
let calcEnhancedChecksum pid = List.fold carry255 (pid |> uint16) >> byte
let calcClassicChecksum = calcEnhancedChecksum 0uy 

Sample Device

Before we continue, let’s describe imaginary example device will be working with further. Let’s say it’s comfort system with following functions:

  • run massage, 12 air cells in 2 rows, 6 cells each. In order to run it we select:
    • one of 3 predefined programs – varying in order of cell inflating/deflating
    • one of 3 intensity levels
    • one of 5 speed levels
  • inflate, deflate:
    • 2 lumbar cells – operating in 4 modes FORWARD (inflate both lumbar cells), BACKWARD (deflate both lumbar cells), UP (inflate lumbar 1 and deflate lumbar 2), DOWN (deflate lumbar 1 and inflate lumbar 2)
    • 2 cushions bolsters – inflate/deflate both at the same time
    • 2 back bolsters – inflate/deflate both at the same time

To give a picture how such a system could look in reality, it could consist of:

  • pump
  • 2 valve blocks, each having 4 bidirectional valves inflate+deflate
  • 1 valve block, having 6 bidirectional valves inflate+deflate

where 6VB would be LIN slave, and master for both 4VB and pump, in other words, we would only communicate with 6VB, while 6VB would then delegate “some work” to two 4VB and pump, on a protocol beyond our concern.

For the convenience of our diagnostics let’s add few more functions to the system:

  • massage status
    • is massage running
    • currently inflating/deflating air cells
  • lumbar and bolster status:
    • is pump running
    • is valve working
  • direct operations on pump and valves (to give example when such would come handy, we could need to test power consumption while operating pump and valves):
    • pump speed 0-100%
    • inflate/deflate singe valve in each valve block


Some time has passed since the last post… actually a long time.

Quick DajSiePoznac summary

Let’s be honest, it was an utter failure. At some point, due to participating in too many projects I faced hard choice regarding my spare time, bloggers fame and glory or sleep, I choose the letter, yet had none of the above. Pure magic. When it comes to visitors, one is sure, bots love my writing. They visit and comment everyday, day and night (if only those comments made any sense). Beside them… well… even saying friends and family is exaggeration.

What’s next?

Since I don’t have enough time to finish library I started to write for DajSiePoznac, I’ll focus on things I use, and will use in following months. Which may be interesting for some (doubt that). By coincidence I will have to learn some new stuff, and learn it fast. Google based crash course you may say, and what’s better way to understand stuff, than explaining it to another?

Real-Time, TwinCAT 3 and LIN

So far I wrote CAN/LIN communication software in C#, and lately in F#. On a horizon, I have project which requires hard RT, and thus .NET is not an option (damn you Garbage Collector!!!).

CLR GC is a poor choice for hard RT

Before you argue, if an actual hard real-time is needed for LIN communication, or it can be worked around for performance, ask yourself, would you’d like to end up with premium car with incorrectly calibrated seat-heater, just because GC kicked-in. I thought so.

I’m kind of excited when I think of it.

  • new programming language and environment (so far I only know how to do pretty basic, PASCAL-like stuff in  TwinCAT 2)
  • new hardware (never worked with Beckhoff EL6001  Serial Interface Terminal before)
  • tight timing for operations

how bad can it get?



So far I considered few alternatives, Haskell EDSLs Ivory and Atom, as funprog is jazzy, but no one I know could confirm it’s actually suited for my application, it would mean writing additional wrappers for manufacturer provided drivers, for Kvaser LIN Leaf or Vector VN1611, plus I already have to failed attempts to learn Haskell.


There seems to be something called RTSJ (Real-Time Specification for Java), which is claimed to be used in South Korean T-50 jet trainer. But it’s more like curiosity for me. I just don’t trust anything that’s named Java, JVM or based on it.


No introduction required, best candidate. But where’s the fun? The journey into unknown?


DajSiePoznac was a failure. Expect “LIN/TwinCAT for dummies by dummy”, unless again I’ll have to pick between sleep and blog.