Arduino Mega 2560 + 2 LinBus Breakout Board

Go To Last Post
2 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hello I have a problem with my project.

I want to connect two LinBus Breakout Board with an Arduino Mega 2560 via Serial1(Slave) and Serial2(Master).

 

For the first I want only that I send the Master a value, this value the Master sends to the slave and then I read via Serial1 from the Slave the value I send before to the Master. And with this value I activate/deactivate the onboard led.

 

I've set the CS/WAKE Pin always to 5V, the FAULT Pin to nothing and the LIN port from Master is connected with them of the slave

 

Here the libary I use to communicate with LinBus:

#include "lin_stack1.h"

/* 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
*/

// CONSTRUCTORS
lin_stack::lin_stack(byte channel){
    sleep_config(channel); // Configurating Sleep pin for transceiver
}

lin_stack::lin_stack(byte channel, byte ident){
    sleep_config(channel); // Configuration of Sleep pin for transceiver
    identByte = ident; // saving idet to private variable
    sleep(1); // Transceiver is always in Normal Mode
}

// PUBLIC METHODS
// WRITE methods
// Creates a LIN packet and then send it via USART(Serial) interface.
int lin_stack::write(byte ident, byte data[], byte data_size){

    // Calculate checksum
  unsigned int checksum =0;
    unsigned int suma = 0;
    for(int i=0;i<data_size;i++){ suma = suma + data[i];
    //suma = suma + 1;
  if(suma>=256)suma-=255;
    }
  suma = 0xFF&(~suma);
  checksum = suma;

    // Start interface
	sleep(1); // Go to Normal mode
    // Synch Break
    serial_pause(13);

    // Send data via Serial interface
    if(ch==1){ // For LIN1 or Serial1
        Serial1.begin(bound_rate); // config Serial
		Serial1.write(0x55); // write Synch Byte to serial
        Serial1.write(ident); // write Identification Byte to serial
        for(int i=0;i<data_size;i++) Serial1.write(data[i]); // write data to serial
        Serial1.write(checksum); // write Checksum Byte to serial
        Serial1.end(); // clear Serial config
    }else if(ch==2){ // For LIN2 or Serial2
        Serial2.begin(bound_rate); // config Serial
        Serial2.write(0x55); // write Synch Byte to serial
        Serial2.write(ident); // write Identification Byte to serialv
        for(int i=0;i<data_size;i++) Serial2.write(data[i]); // write data to serial
        Serial2.write(checksum);// write Checksum Byte to serial
        Serial2.end(); // clear Serial config
    }
    return 1;
}

int lin_stack::writeRequest(byte ident){
    // Create Header
    byte header[2]= {0x55, ident};
    // Start interface
//    sleep(1); // Go to Normal mode
    // Synch Break
    serial_pause(13);
    // Send data via Serial interface
    if(ch==1){ // For LIN1 or Serial1
        Serial1.begin(bound_rate); // config Serial
        Serial1.write(header,2); // write data to serial
        Serial1.end(); // clear Serial config
    }else if(ch==2){ // For LIN2 or Serial2
        Serial2.begin(bound_rate); // config Serial
        Serial2.write(header,2); // write data to serial
        Serial2.end(); // clear Serial config
    }
    return 1;
}

int lin_stack::writeResponse(byte data[], byte data_size){

  // Calculate checksum
  unsigned int checksum =0;
  unsigned int suma = 0;
  for(int i=0;i<data_size;i++){ suma = suma + data[i];

  if(suma>=256)suma-=255;
  }
  suma = 0xFF&(~suma);
  checksum = suma;

    // Start interface
    sleep(1); // Go to Normal mode
    // Send data via Serial interface
    if(ch==1){ // For LIN1 or Serial1
        Serial1.begin(bound_rate); // config Serial
        Serial1.write(data, data_size); // write data to serial
        Serial1.write(checksum); // write data to serial
        Serial1.end(); // clear Serial config
    return 1;
    }else if(ch==2){ // For LIN2 or Serial2
        Serial2.begin(bound_rate); // config Serial
        Serial2.write(data, data_size); // write data to serial
        Serial2.write(checksum); // write data to serial
        Serial2.end(); // clear Serial config
    return 2;
    }
    return -1;
}

// READ methods
// Read LIN traffic and then proces it.
int lin_stack::setSerial(){ // Only needed when receiving signals
    if(ch==1){ // For LIN1 (Channel 1)
        Serial1.begin(bound_rate); // Configure Serial1
    } else if(ch==2){ // For LIN2 (Channel 2)
        Serial2.begin(bound_rate); // Configure Serial1
    }
}

int lin_stack::read(byte data[], byte data_size){
    byte rec[data_size+3];
    if(ch==1){ // For LIN1 or Serial1
        if(Serial1.read() != -1){ // Check if there is an event on LIN bus
            Serial1.readBytes(rec,data_size+3);
            if((validateParity(rec[1]))&(validateChecksum(rec,data_size+3))){
                for(int j=0;j<data_size;j++){
                data[j] = rec[j+2];
                }
                return 1;
            }else{
                return -1;
            }
        }
    }else if(ch==2){ // For LIN2 or Serial2
        if(Serial2.read() != -1){ // Check if there is an event on LIN bus
            Serial2.readBytes(rec,data_size+3);
            if((validateParity(rec[1]))&(validateChecksum(rec,data_size+3))){
                for(int j=0;j<data_size;j++){
                data[j] = rec[j+2];
                }
                return 1;
            }else{
                return -1;
            }
        }
    }
    return 0;
}

int lin_stack::readStream(byte data[],byte data_size){
	byte rec[data_size];
	if(ch==1){ // For LIN1 or Serial1
		if(Serial1.read() != -1){ // Check if there is an event on LIN bus
			Serial1.readBytes(rec,data_size);
			for(int j=0;j<data_size;j++){
				data[j] = rec[j];
			}
			return 1;
		}
	}else if(ch==2){ // For LIN2 or Serial2
		if(Serial2.read() != -1){ // Check if there is an event on LIN bus
			Serial2.readBytes(data,data_size);
			return 1;
		}
	}
	return 0;
}

// PRIVATE METHODS
int lin_stack::serial_pause(int no_bits){
    // Calculate delay needed for 13 bits, depends on bound rate
    unsigned int del = period*no_bits; // delay for number of bits (no-bits) in microseconds, depends on period
    if(ch==1){
    pinMode(18, OUTPUT);
    digitalWrite(18, LOW);
    delayMicroseconds(del); // delay
    digitalWrite(18, HIGH);
    }else if(ch==2){
    pinMode(16, OUTPUT);
    digitalWrite(16, LOW);
    delayMicroseconds(del); // delay
    digitalWrite(16, HIGH);
    }
    return 1;
}

int lin_stack::sleep(byte sleep_state){
    if(sleep_state==1){ // Go to Normal mode
        if(ch==1){
      digitalWrite(A4, HIGH);

        }
        if(ch==2){
      digitalWrite(A5, HIGH);

        }
    }else if(sleep_state==0){ // Go to Sleep mode
        if(ch==1){
      digitalWrite(A4, LOW);

        }
        if(ch==2){
      digitalWrite(A5, LOW);      

        }
    }
    return 1;
}

int lin_stack::sleep_config(byte serial){

    if(serial==1){ // When using LIN1 channel - usign Serial1
      pinMode(A4, OUTPUT);
      digitalWrite(A4, HIGH);
      ch=1; // saved as private variable, used for determening Serial port
    }else if(serial==2){ // When using LIN2 channel - usign Serial2
    pinMode(A5, OUTPUT);
    digitalWrite(A5, HIGH);
    ch=2; // saved as private variable, used for determening Serial port
    }
    return 1;
}

boolean lin_stack::validateParity(byte ident) {
    if(ident == identByte)
        return true;
    else
        return false;
}

boolean lin_stack::validateChecksum(unsigned char data[], byte data_size){
  unsigned int v_checksum = 0;
  unsigned int checksum = data[data_size-1];
  unsigned int suma = 0;
  for(int i=2;i<data_size-1;i++){ suma = suma + data[i];
  if(suma>=256)suma-=255;
  }
  suma = 0xFF&(~suma);
  v_checksum = suma;
  if(checksum==v_checksum)
    return true;
  else
    return false;
}

 

And here is my code:

#include "lin_stack1.h"

const byte ident = 0x11;

lin_stack SLAVE(1,ident);
lin_stack MASTER(2);

const int LED = 13;

byte packageON[] = {255};
byte packageOFF[] = {0};
byte data[1];

bool ON = false;

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);

  Serial.begin(9600);
  SLAVE.setSerial();
}

void loop() {
  //if (ON) {
    //MASTER.write(ident, packageOFF, 1);
    //ON = false;
  //} else {
    MASTER.write(ident, packageON, 1);
    //ON = true;
  //}
  delay(2000);

  byte a = SLAVE.read(data, 1);
  if(a == 1){
    Serial.println("Request Received!");
    Serial.print("Data Byte 1: ");
    Serial.println(data[0]);
    if(data[0] == 255){
      digitalWrite(LED_BUILTIN, LOW);
    }else if(data[0] == 0){
      digitalWrite(LED_BUILTIN, HIGH);
    }
  } else if(a == 0) {
      Serial.println("No Request Received!");
  } else if(a == -1){
      Serial.println("Corrupt Request Received!");
  }
}
Last Edited: Sat. Oct 20, 2018 - 01:54 PM
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Hi Hellfire, welcome to AvrFreaks.

 

This has been sitting around unanswered for almost 2 weeks.

Your fault desciption looks a bit vague, combined much code to work through.

 

Uhm, After re-reading I can not find an actual question in your post.

Apparently something is not working?

 

Do you have anything that works?

Have you confirmed that the master is formatting a valid message on the bus?

Tell us what works, and what does not work.

Do you know that LIN is a single master bus? There can be only one master.

(But no slaves, that word is apparenty out of fashion ???)

 

Recently I looked at a LIN transeiver and was slightly annoyed that RxD was an output and TxD an input ???

So I do not know what labelling is used on the PCB.

Does "TxD" mean: "This is Transmit Data", or does it mean "connect this to Tramsmit data".

Double check your connections.

 

Do you have a logic analyser or an oscilloscope? The "24Mhz 8ch" Logic analysers from Ali / Ebay / China work great with Sigrok and they are too cheap to not buy! Don't be fooled by the low price, the magic is in the Sigrok / Pulseview software.

Paul van der Hoeven.
Bunch of old projects with AVR's:
http://www.hoevendesign.com

Last Edited: Wed. Oct 31, 2018 - 05:49 AM