Arduino Lin example errors

Hi, Im trying to get an arduino nano setup to read an automotive LIN bus.

From searching the forms, led me to
https://github.com/sherzaad/LIN

I get a error:

exit status 1
'LIN1' was not declared in this scope

anyone know what to try and do to eliminate the error?

Im using this board:

Thanks,
Clint

You will need to show your sketch. Your error indicates you have used the variable LIN1... but did not define it... it looks like you were trying to add a class.

here is the sketch from the example

/* This example was tested on a Mega2560. Serial1 was connected via a suitable LIN transceiver such as a MCP2003 to sniff LIN bus*/

#include "LIN.h"

#define LIN_BAUD1 9600
#define LIN_BAUD2 19200UL

void setup() {
  /*IMPORTANT BEFORE START*/
  /*
   * if you are using ANY of the Hw Serial Ports for other that LIN, 
   * you MUST move the corresponding HardwareSerialLINx.cpp file to the 'OtherThanLIN' folder.
   * Else you may have 'multiple definition' compile error 
   */
  Serial.begin(115200); //HardwareSerialLIN0.cpp moved to 'OtherThanLIN' folder since using Serial0 port for Serial Monitor
  LIN1.begin(LIN_BAUD2);

  Serial.println("READY");

}

void loop() {
  if (LIN1.available()) {
    uint16_t val = LIN1.read();

    if (LIN.FieldType(val) == BREAKFIELD) {
      Serial.println("");
    }
    else if (LIN.FieldType(val) == NEW_FRAME) {
      Serial.println("");
      Serial.print("New Frame: ");
      Serial.print(val & 0xFF, HEX);
      Serial.print(", ");
    }
    else if (LIN.FieldType(val) == SYNC) {
      Serial.print("Sync: ");
      Serial.print(val & 0xFF, HEX);
      Serial.print(", ");
    }
    else 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: ");
    }
    else if (LIN.FieldType(val) == DATA) {
      Serial.print(val & 0xFF, HEX); //data/checksum bytes. 
                                     //Last received DATA byte of a given LIN frame would normally be the Checksum Byte
      Serial.print(", ");
    }
  }

}

thanks,
Clint

Verify you have the full library, and not just LIN.h. GitHub - sherzaad/LIN: Arduino Library to enable LIN communication using Hardware UART port

This is difficult for me to read, but it seems that Serial.begin() is using HWSERIAL0, so the LIN library needs HardwareSerialLIN0.cpp move to "OtherThanLIN" folder... to hide it from use. I do not know if this has caused the error.

all files from the github are installed. I tried a few things and still no joy.

I also found a different lin program:
LINBus_stack - Arduino Reference
This one has its own errors.. I think I found one and maybe fixed? and got another :frowning:

"sniffer sketch from Example folder"

/*  LIN Sniffer - Monitor traffic on LIN Bus
 *
 *  Written in September 2016 by Blaž Pongrac B.S., RoboSap, Institute of Technology, Ptuj (www.robosap-institut.eu) for Macchina LLC
 *
 *  To the extent possible under law, the author(s) have dedicated all copyright and related and neighboring rights to this software to the public domain worldwide. This software is distributed without any warranty.
 *
 *  You should have received a copy of the CC0 Public Domain Dedication along with this software. If not, see <http://creativecommons.org/publicdomain/zero/1.0/>. 
 *  
 *  Using LIN Stack v2.0 Library (https://github.com/macchina/LIN)
 *  
 *  Developed against Arduino IDE 1.6.9
 */

// Including LIN Stack library
**#include <lin_stack.h>**   // does not match the .h file name in the folder

// Variables
const byte ident = 0; // Identification Byte
byte data_size=8; // length of byte array
byte data[8]; // byte array for received data

// Creating LIN Object
lin_stack LIN1(1,ident); // 1 - channel, ident - Identification Byte

void setup() {
  SerialUSB.begin(9600); // Configure Serial for Serial Monitor
  LIN1.setSerial(); // Configure Serial for receiving
}

void loop() {
  // Checking LIN Bus periodicly
  byte a = LIN1.readStream(data, data_size);
  if(a == 1){ // If there was an event on LIN Bus, Traffic was detected. Print data to serial monitor
     SerialUSB.println("Traffic detected!");
     SerialUSB.print("Synch Byte: ");
     SerialUSB.println(data[0]);
     SerialUSB.print("Ident Byte: ");
     SerialUSB.println(data[1]);
     SerialUSB.print("Data Byte1: ");
     SerialUSB.println(data[2]);
     SerialUSB.print("Data Byte2: ");
     SerialUSB.println(data[3]);
     SerialUSB.print("Data Byte3: ");
     SerialUSB.println(data[4]);
     SerialUSB.print("Data Byte4: ");
     SerialUSB.println(data[5]);
     SerialUSB.print("Data Byte5: ");
     SerialUSB.println(data[6]);
     SerialUSB.print("Check Byte: ");
     SerialUSB.println(data[7]);
     SerialUSB.print("\n");
  } 
}

LINBus_stack.h file

/*  Copyright (c) 2016 Macchina
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 *  LIN STACK for TJA1021
 *  v2.0
 *
 *  Short description:
 *  Comunication stack for LIN and TJA1021 LIN transceiver.
 *  Can be modified for any Arduino board with UART available and any LIN slave.
 *
 *  Author: Blaž Pongrac B.S., RoboSap, Institute of Technology, Ptuj (www.robosap-institut.eu)
 *  Author: Laszlo Hegedüs
 *
 *  Arduino IDE 1.6.9
 *  RoboSap, Institute of Technology, September 2016
 *
 * Changes in 3.0 are Copyright (c) 2023 Gavin Hurlbut
 *  - reworked for better slave use
 *  - reworked sleep/wake modes
 *  - refactored/renamed class
 *  - added support for AVR (particularly in break detection)
 *  - made available via the Arduino Library Manager
 */

#ifndef __LINBus_stack_h_
#define __LINBus_stack_h_

#include <Arduino.h>
#include <HardwareSerial.h>
#include <stdint.h>

typedef enum {
    STATE_NORMAL,
    STATE_STANDBY,
    STATE_SLEEP,
} linbus_state_t;

#ifndef OWERRIDE_GPIO_FUNCS
#define pinModeFunc pinMode
#define digitalWriteFunc digitalWrite
#endif

class LINBus_stack {
public:
    // Constructors
    LINBus_stack(HardwareSerial &_channel = Serial, uint16_t _baud = 19200);

#ifdef OVERRIDE_GPIO_FUNCS
    void setPinMode(void (*pinModeFunc_)(uint8_t, uint8_t))
    {
      pinModeFunc = pinModeFunc_;
    };

    void setDigitalWrite(void (*digitalWriteFunc_)(uint8_t, uint8_t))
    {
      digitalWriteFunc = digitalWriteFunc_;
    };
#endif

    void begin(int8_t _wakeup_pin = -1, int8_t _sleep_pin = -1,
               uint8_t _ident = 0); // Constructor for Master and Slave Node

    // Methods

    // write whole package
    void write(const uint8_t ident, const void *data, size_t len);

    // Write header only (used to request data from a slave)
    void writeRequest(const uint8_t ident);

    // Write response only (used by a slave to respond to a request)
    void writeResponse(const void *data, size_t len);

    // Writing user data to LIN bus as is.
    void writeStream(const void *data, size_t len);

    // read data from LIN bus, checksum and ident validation (no checksum check if only header received)
    bool read(uint8_t *data, const size_t len, size_t *read);

    // send wakeup frame for waking up all bus participants
    void busWakeUp(void);

    // method for controlling transceiver modes (0 - sleep, 1 - standby, 2 - normal)
    void sleep(linbus_state_t sleep_state);

    // set up Serial communication for receiving data.
    void setupSerial(void);

    bool waitBreak(uint32_t maxTimeout);

    // read data from LIN bus as is.
    int readStream(uint8_t *data, size_t len);

    uint8_t generateIdent(const uint8_t addr) const;

    uint8_t calcIdentParity(const uint8_t ident) const;

    // for validating Checksum Byte
    bool validateChecksum(const void *data, size_t len);

    static constexpr uint32_t MAX_DELAY = UINT32_MAX;

private:
    // 10417 is best for LIN Interface, most device should work
    const uint16_t baud;

    // which channel should be used
    HardwareSerial &channel;

    // user defined Identification Byte
    uint8_t ident;

    int8_t wake_pin;
    int8_t sleep_pin;
    linbus_state_t current_sleep_state;

#ifdef OVERRIDE_GPIO_FUNCS
    void (*pinModeFunc)(uint8_t, uint8_t);
    void (*digitalWriteFunc)(uint8_t, uint8_t);
#endif

    // configuration of sleep pins
    void sleep_config(void);

    // is break detected?
    bool breakDetected(void);

    // for generating Synch Break
    void lin_break(void);

    // for validating Identification Byte, can be modified for validating parity
    bool validateParity(uint8_t ident);

    uint8_t calcChecksum(const void *data, size_t len);
};

#endif

"LINBus_stack.cpp"

/*  Copyright (c) 2016 Macchina
 *
 *  Permission is hereby granted, free of charge, to any person obtaining
 *  a copy of this software and associated documentation files (the
 *  "Software"), to deal in the Software without restriction, including
 *  without limitation the rights to use, copy, modify, merge, publish,
 *  distribute, sublicense, and/or sell copies of the Software, and to
 *  permit persons to whom the Software is furnished to do so, subject to
 *  the following conditions:
 *
 *  The above copyright notice and this permission notice shall be included
 *  in all copies or substantial portions of the Software.
 *
 *  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 *  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 *  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 *  IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
 *  CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
 *  TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
 *  SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 *
 *  LIN STACK for TJA1021
 *  v2.0
 *
 *  Short description:
 *  Comunication stack for LIN and TJA1021 LIN transceiver.
 *  Can be modified for any Arduino board with UART available and any LIN slave.
 *
 *  Author: Blaž Pongrac B.S., RoboSap, Institute of Technology, Ptuj (www.robosap-institut.eu)
 *
 *  Arduino IDE 1.6.9
 *  RoboSap, Institute of Technology, September 2016
 *
 * Changes in 3.0 are Copyright (c) 2023 Gavin Hurlbut
 *  - reworked for better slave use
 *  - reworked sleep/wake modes
 *  - refactored/renamed class
 *  - added support for AVR (particularly in break detection)
 *  - made available via the Arduino Library Manager
 */

#include <Arduino.h>
#include <LINBus_stack.h>
#ifndef STM32F0xx
#include <avr/sfr_defs.h>
#endif


/* 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 - min 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 summed up and then inverted
*/

// CONSTRUCTORS
LINBus_stack::LINBus_stack(HardwareSerial &_channel, uint16_t _baud) :
  baud(_baud), channel(_channel)
{
#ifdef OVERRIDE_GPIO_FUNCS
  setPinMode(pinMode);
  setDigitalWrite(digitalWrite);
#endif
}

void LINBus_stack::begin(int8_t _wake_pin, int8_t _sleep_pin, uint8_t _ident)
{
  ident = _ident;
  wake_pin = _wake_pin;
  sleep_pin = _sleep_pin;

  if(wake_pin >= 0 || sleep_pin >= 0) {
    sleep_config();
  }
}

// PUBLIC METHODS
// WRITE methods
// Creates a LIN packet and then send it via USART(Serial) interface. (master-side write)
void LINBus_stack::write(const uint8_t ident, const void *data, size_t len) {
    // Synch Break
    lin_break();
    // Send data via Serial interface
    channel.begin(baud);
    channel.write(0x55);
    channel.write(ident);
    channel.write((const char *)(data), len);
    channel.write(calcChecksum(data, len));
    channel.flush();
}

// Setup a master-side read.
void LINBus_stack::writeRequest(const uint8_t ident) {
    // Synch Break
    lin_break();
    // Send data via Serial interface
    channel.begin(baud);
    channel.write(0x55);
    channel.write(ident);
    channel.flush();
}

// Send the slave-side response to a master-side read
void LINBus_stack::writeResponse(const void *data, size_t len) {
    channel.begin(baud);
    channel.write((const char *)(data), len);
    channel.write(calcChecksum(data, len));
    channel.flush();
}

void LINBus_stack::writeStream(const void *data, size_t len) {
    // Synch Break
    lin_break();
    // Send data via Serial interface
    channel.begin(baud);
    channel.write(0x55);
    channel.write(ident);
    channel.write((const char *)(data), len);
    channel.flush();
}

// slave-side receive from master
bool LINBus_stack::read(uint8_t *data, const size_t len, size_t *read_) {
    size_t loc;
    uint8_t header[2];
    bool retval;

    if(!read_)
        read_ = &loc;
    *read_ = channel.readBytes(header, 2);

    if (*read_ != 2) {
      retval = false;
    } else if (header[0] != 0x55) {
      retval = false;
    } else if (!validateParity(header[1])) {
      retval = false;
    }

    if (!retval) {
      channel.flush();
      return false;
    }

    if (!channel.available()) {
      // Header only.  This is a read
      *read_ = 0;
      return true;
    }

    // This was a write
    *read_ = channel.readBytes(data, len);
    channel.flush();
    return validateChecksum(data, *read_);
}

void LINBus_stack::setupSerial(void) {
    channel.begin(baud);
}

bool LINBus_stack::breakDetected(void) {
#ifdef __AVR_ATtinyxy4__
  return bit_is_set(USART0.STATUS, USART_BDF_bm);
#else
 #ifdef ARDUINO_ARCH_RP2040
  return channel.getBreakReceived();
 #else
  #ifdef STM32F0xx
  // bit FE in USART_ISR - just return true for now
  return true;
  #else
  return bit_is_set(UCSR0A, FE0);
  #endif
 #endif
#endif
}

bool LINBus_stack::waitBreak(uint32_t maxTimeout) {
    const auto enterTime = millis();
    while(!breakDetected()) {
        const auto now = millis();
        if(maxTimeout < UINT32_MAX &&  now - enterTime > maxTimeout) {
            // we timed out
            return false;
        }
    }
    return true;
}

int LINBus_stack::readStream(uint8_t *data, size_t len)
{
    return channel.readBytes(data, len);
}

// PRIVATE METHODS
void LINBus_stack::lin_break(void) {
    // send the break field. Since LIN only specifies min 13bit, we'll send 0x00 at half baud
    channel.flush();
    channel.begin(baud / 2);

    // send the break field
    channel.write(0x00);
    channel.flush();
}

void LINBus_stack::sleep(linbus_state_t sleep_state) {
    const static uint8_t wake_value[3][3] = {
        { HIGH, LOW, HIGH },
        { LOW, HIGH, HIGH },
        { HIGH, HIGH, HIGH },
    };

    const static uint8_t sleep_value[3][3] = {
        { HIGH, HIGH, LOW },
        { HIGH, HIGH, LOW },
        { HIGH, HIGH, LOW },
    };

    current_sleep_state = min(max(current_sleep_state, STATE_NORMAL), STATE_SLEEP);
    sleep_state = min(max(sleep_state, STATE_NORMAL), STATE_SLEEP);

    digitalWriteFunc(wake_pin, wake_value[current_sleep_state][sleep_state]);
    digitalWriteFunc(sleep_pin, sleep_value[current_sleep_state][sleep_state]);

    // According to TJA1021 datasheet this is needed for proper working
    delayMicroseconds(20);

    current_sleep_state = sleep_state;
}

void LINBus_stack::sleep_config(void) {
    pinModeFunc(wake_pin, OUTPUT);
    pinModeFunc(sleep_pin, OUTPUT);
    digitalWriteFunc(wake_pin, HIGH);
    digitalWriteFunc(sleep_pin, LOW);
    current_sleep_state = STATE_SLEEP;
}

bool LINBus_stack::validateParity(uint8_t _ident) {
    return (_ident == ident);
}

uint8_t LINBus_stack::calcChecksum(const void *data, size_t len) {
    const uint8_t *p = static_cast<const uint8_t *>(data);
    uint8_t ret = 0;
    for(size_t i = 0; i < len; i++) {
        ret += p[i];
    }
    return ~ret;
}

bool LINBus_stack::validateChecksum(const void *data, size_t len) {
    uint8_t crc = calcChecksum(data, len - 1);
    return (crc == ((const uint8_t *)(data))[len]);
}

void LINBus_stack::busWakeUp(void) {
    // generate a wakeup pattern by sending 9 zero bits, we use 19200 baud to generate a 480us pulse
    channel.flush();
    channel.begin(19200);
    channel.write(0x00);
    channel.flush();
    channel.begin(baud);
}

uint8_t LINBus_stack::generateIdent(const uint8_t addr) const {
    return (addr & 0x3f) | calcIdentParity(addr);
}

/* Create the Lin ID parity */
#define BIT(data, shift) ((ident & (1 << shift)) >> shift)
uint8_t LINBus_stack::calcIdentParity(const uint8_t ident) const {
    uint8_t p0 = BIT(ident, 0) ^ BIT(ident, 1) ^ BIT(ident, 2) ^ BIT(ident, 4);
    uint8_t p1 = ~(BIT(ident, 1) ^ BIT(ident, 3) ^ BIT(ident, 4) ^ BIT(ident, 5));
    return (p0 | (p1 << 1)) << 6;
}

#include <lin_stack.h> from Sniffer example does not match the .h file name in the SCR folder
I get error

exit status 1
**lin**_stack.h: No such file or directory

I change to match thinking that whats wrong

#include <**LINBus**_stack.h>

Compile, I get error

lin_stack' does not name a type

So I change all lin_stack to LINBus_stack .. i get further maybe, and error out with

exit status 1
no matching function for call to 'LINBus_stack::LINBus_stack(int, const byte&)'

and found

that doesnt have a solution, only references the 1st Lin project in post 1

any insite on this one?

after more searching, i wound up on the github page

and had notes of what i just was guessing on

LINBus_stack LIN1(Serial, 19200)

vs original

lin_stack LIN1(1)

new error lol...

'SerialUSB' was not declared in this scope

doing more searching now :wink:
update, changed SerialUSB to Serial....
new error,

changed
LIN1.setSerial(); // Configure Serial for receiving
to
arduino recommendation

'class LINBus_stack' has no member named 'setSerial'; did you mean 'setupSerial'?

and complied... now to see if if the nano and lin board i have can read the lin bus

What kind of arduino was the library designed for?

Mega2560? The library references many serial ports (0, 1, 2, 3) and expects files configuring ports not used for LIN devices (like the Serial Monitor) be moved to another directory so only the files for LIN ports are compiled.

the nano has only ONE hardware serial port!
As the is no 'Serial1' for this board, it would not be possible to use 'LIN1' on this board

the library I created is intended for ATmega boards