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.
/* 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(", ");
}
}
}
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
"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
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.