LIN Bus an PC

Hallo,

ich möchte mit einem Arduino Uno Rev3 und einem MCP2003B ein Verbdindung zwschen Lenkrad und PC herstellen.
Das Lenkrad (aus einem Audi) soll für einen Simulator dienen bei dem ich die Multifunktionstasten nutzen möchte. Hat einer eine Idee wie das am einfachsten zu lösen wäre?

VG Larry

Hallo,

im Gegensatz zu CAN habe ich für LIN noch nicht wirklich brauchbares gefunden.

Im Prinzip hast du brauchbare Hardware, LIN wird ja in der Regel mit einem UART gemacht, an den man den Transceiver hängt. Allerdings hat der Uno ja nur die eine serielle Schnittstelle, die standardmässig für die USB-Verbindung gebraucht wird.

Da LIN nicht besonders schnell ist, kann man es aber wohl auch ganz in Software realisieren. Eventuell hilft das hier, scheint aber nur zum Mitlesen von LIN gedacht zu sein, du brauchst aber eine LIN Master Implementierung

Für einen Master kenne ich nur diese Lib

die ist aber für ein Board gedacht, das auf dem Arduino Due basiert.

Dann musst du auch noch wissen, was der Master denn tun soll ...

wenn es mit arduino sein soll, dann hilft vllt. das hier:

https://www.mikrocontroller.net/topic/458048

andernfalls nimm den mcp + usb-uart und schreib das programm am pc für den pc.

das ibus resler interface müsste auch funktionieren, wenn du was fertiges für den pc willst.

harryberlin:
andernfalls nimm den mcp + usb-uart und schreib das programm am pc für den pc.

Das ist nicht so einfach. In der Lib für den Due ist der Paketaufbau dokumentiert

/* LIN PACKET:
   It consist of:
    ___________ __________ _______ ____________ _________ 
   |           |          |       |            |         |
   |Synch Break|Synch Byte|ID byte| Data Bytes |Checksum |
   |___________|__________|_______|____________|_________|
   
   Every byte have start bit and stop bit and it is send LSB first.
   Synch Break - 13 bits of dominant state ("0"), followed by 1 bit recesive state ("1")
   Synch Byte - Byte for Bound rate syncronization, always 0x55
   ID Byte - consist of parity, length and address; parity is determined by LIN standard and depends from address and message length
   Data Bytes - user defined; depend on devices on LIN bus
   Checksum - inverted 256 checksum; data bytes are sumed up and then inverted
*/

Für das Break schaltet die oben verlinkte Due Lib den Pin vom Serial TX um zu einem Digitalausgang und schreibt das Break mit direktem Registerzugriff und delayMicroseconds.

dann gibts da noch ein project mit nen ikea tisch, der wohl auch mit lin arbeitet.

Hallo,

ich bringe den Thread noch mal in den Vordergrund, damit er besser als zukünftige Informationsquelle dienen kann. Der Fragesteller hat sich ja nicht mehr gemeldet.

Der obige Link in Beitrag #5 enthält eine LIN Master Implementierung für eine Hardware Serial auf einem Arduino. Ist also für den Uno nur geeignet, wenn man auf die USB-Anbindung verzichten kann.

LIN ist weitgehend normale serielle Kommunikation, bis auf diesen Teil

// Generate a BREAK signal (a low signal for longer than a byte) across the serial line
void Lin::serialBreak(void)
{
  if (serialOn) {
    serial.flush();
    serial.end();
  }

  pinMode(txPin, OUTPUT);
  digitalWrite(txPin, LOW);  // Send BREAK
  const unsigned long int brkend = (1000000UL/((unsigned long int)serialSpd));
  const unsigned long int brkbegin = brkend*LIN_BREAK_DURATION;
  if (brkbegin > 16383) delay(brkbegin/1000);  // delayMicroseconds unreliable above 16383 see arduino man pages
  else delayMicroseconds(brkbegin);
  
  digitalWrite(txPin, HIGH);  // BREAK delimiter

  if (brkend > 16383) delay(brkend/1000);  // delayMicroseconds unreliable above 16383 see arduino man pages
  else delayMicroseconds(brkend);

  serial.begin(serialSpd);
  serialOn = 1;
}

Der muss zu Fuss gemacht werden, weil die AVR UARTs keine LIN Break Unterstützung haben.

Hier alternativ eine Implementierung für den Teensy 3.x (und LC), wo Hardware LIN Unterstützung vorhanden ist:

Da sieht das obige deutlich einfacher aus

  (*PortRegister_C2) |= UART_C2_SBK;
  (*PortRegister_C2) &= ~UART_C2_SBK;

ArduFE:
Hallo,

ich bringe den Thread noch mal in den Vordergrund, damit er besser als zukünftige Informationsquelle dienen kann. Der Fragesteller hat sich ja nicht mehr gemeldet.

Der obige Link in Beitrag #5 enthält eine LIN Master Implementierung für eine Hardware Serial auf einem Arduino. Ist also für den Uno nur geeignet, wenn man auf die USB-Anbindung verzichten kann.

LIN ist weitgehend normale serielle Kommunikation, bis auf diesen Teil

// Generate a BREAK signal (a low signal for longer than a byte) across the serial line

void Lin::serialBreak(void)
{
 if (serialOn) {
   serial.flush();
   serial.end();
 }

pinMode(txPin, OUTPUT);
 digitalWrite(txPin, LOW);  // Send BREAK
 const unsigned long int brkend = (1000000UL/((unsigned long int)serialSpd));
 const unsigned long int brkbegin = brkend*LIN_BREAK_DURATION;
 if (brkbegin > 16383) delay(brkbegin/1000);  // delayMicroseconds unreliable above 16383 see arduino man pages
 else delayMicroseconds(brkbegin);
 
 digitalWrite(txPin, HIGH);  // BREAK delimiter

if (brkend > 16383) delay(brkend/1000);  // delayMicroseconds unreliable above 16383 see arduino man pages
 else delayMicroseconds(brkend);

serial.begin(serialSpd);
 serialOn = 1;
}




Der muss zu Fuss gemacht werden, weil die AVR UARTs keine LIN Break Unterstützung haben.


Hier alternativ eine Implementierung für den Teensy 3.x (und LC), wo Hardware LIN Unterstützung vorhanden ist:
https://github.com/MarkusLange/Teensy_3.x_LIN_Master

Da sieht das obige deutlich einfacher aus


(*PortRegister_C2) |= UART_C2_SBK;
 (*PortRegister_C2) &= ~UART_C2_SBK;

Hi Danke,

ja der auf dem Teensy verwendete Chip macht es sehr einfach, diverse Register setzen und er macht es von alleine.

Für ATMega habe ich auch noch ein recht simples Beispiel, etwas brutaler als das obrige für den Break aber auch das funktioniert.

Link

  Serial1.end();
  pinMode(0,OUTPUT);
  digitalWrite(1, LOW);
  delayMicroseconds(breakfield*Tbit);                 //after Frame Error Tbit to Sync Field
  digitalWrite(1, HIGH);
  delayMicroseconds(breakdelimiter*Tbit);