Audi steering wheel lin bus reading

Hey! I am writing to you from Ukraine through a translator. Tell me, did you manage to connect a new steering wheel using LIN2, or rather read the buttons and make an emulator for a new steering wheel? I have Mega256 and Lin transiver TJA1020. Audi a7 2012 car and new steering wheel from Audi a5 2017 LIN2

Hi,

i am trying this code with my Audi and i am using UNO board at this time. When i compile this code i get the below error log

*VehicleSimulator = (HardwareSerial *)&Serial2,
^~~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:27:44: note: suggested alternative: 'Serial'
*VehicleSimulator = (HardwareSerial *)&Serial2,
^~~~~~~
Serial
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void setup()':
volvo_linbus:48:5: error: 'SerialConsole' was not declared in this scope
SerialConsole->begin(115200);
^~~~~~~~~~~~~
volvo_linbus:60:5: error: 'UCSR1C' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:5: note: suggested alternative: 'UCSR0C'
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^~~~~~
UCSR0C
In file included from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:99:0,
from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
from C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:28,
from C:\Users\RAHUL~1.CHA\AppData\Local\Temp\arduino_build_351419\sketch\volvo_linbus.ino.cpp:1:
volvo_linbus:60:18: error: 'UCSZ11' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:18: note: suggested alternative: 'UCSZ01'
volvo_linbus:60:32: error: 'UCSZ10' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:32: note: suggested alternative: 'UCSZ00'
volvo_linbus:61:5: error: 'UBRR1' was not declared in this scope
UBRR1 = 51; //19.2kbaud UBRR = (16MHz / 16 x 19200) - 1
^~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:61:5: note: suggested alternative: 'UBRR0'
UBRR1 = 51; //19.2kbaud UBRR = (16MHz / 16 x 19200) - 1
^~~~~
UBRR0
volvo_linbus:62:5: error: 'UCSR1B' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:5: note: suggested alternative: 'UCSR0B'
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^~~~~~
UCSR0B
In file included from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:99:0,
from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
from C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:28,
from C:\Users\RAHUL~1.CHA\AppData\Local\Temp\arduino_build_351419\sketch\volvo_linbus.ino.cpp:1:
volvo_linbus:62:18: error: 'RXCIE1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:18: note: suggested alternative: 'RXCIE0'
volvo_linbus:62:32: error: 'RXEN1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:32: note: suggested alternative: 'RXEN0'
volvo_linbus:62:45: error: 'TXEN1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:45: note: suggested alternative: 'TXEN0'
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void linRXStateMachine()':
volvo_linbus:136:34: error: 'FE1' was not declared in this scope
if( (s & _BV(FE1)) && (b == FRAME_BYTE) )
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:136:34: note: suggested alternative: 'FE0'
volvo_linbus:155:35: error: 'FE1' was not declared in this scope
if( !(s & _BV(FE1) ) )
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:155:35: note: suggested alternative: 'FE0'
volvo_linbus:178:33: error: 'SerialConsole' was not declared in this scope
SerialConsole->println( "Message invalid" );
^~~~~~~~~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void USART1_RX_vect()':
volvo_linbus:217:9: error: 'UCSR1A' was not declared in this scope
s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:217:9: note: suggested alternative: 'UCSR0A'
s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
^~~~~~
UCSR0A
volvo_linbus:218:10: error: 'UDR1' was not declared in this scope
ch = UDR1;
^~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:218:10: note: suggested alternative: 'UDR0'
ch = UDR1;
^~~~
UDR0
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void DumpFrame()':
volvo_linbus:239:13: error: 'SerialConsole' was not declared in this scope
SerialConsole->write( '0' );
^~~~~~~~~~~~~
volvo_linbus:240:9: error: 'SerialConsole' was not declared in this scope
SerialConsole->print( b, HEX );
^~~~~~~~~~~~~
volvo_linbus:244:5: error: 'SerialConsole' was not declared in this scope
SerialConsole->println();
^~~~~~~~~~~~~
Using library SoftwareSerial at version 1.0 in folder: C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\SoftwareSerial
exit status 1
'Serial2' was not declared in this scope

Hi

when i run this code on my UNO board, i get the following compilation error

*VehicleSimulator = (HardwareSerial *)&Serial2,
^~~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:27:44: note: suggested alternative: 'Serial'
*VehicleSimulator = (HardwareSerial *)&Serial2,
^~~~~~~
Serial
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void setup()':
volvo_linbus:48:5: error: 'SerialConsole' was not declared in this scope
SerialConsole->begin(115200);
^~~~~~~~~~~~~
volvo_linbus:60:5: error: 'UCSR1C' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:5: note: suggested alternative: 'UCSR0C'
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^~~~~~
UCSR0C
In file included from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:99:0,
from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
from C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:28,
from C:\Users\RAHUL~1.CHA\AppData\Local\Temp\arduino_build_351419\sketch\volvo_linbus.ino.cpp:1:
volvo_linbus:60:18: error: 'UCSZ11' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:18: note: suggested alternative: 'UCSZ01'
volvo_linbus:60:32: error: 'UCSZ10' was not declared in this scope
UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:60:32: note: suggested alternative: 'UCSZ00'
volvo_linbus:61:5: error: 'UBRR1' was not declared in this scope
UBRR1 = 51; //19.2kbaud UBRR = (16MHz / 16 x 19200) - 1
^~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:61:5: note: suggested alternative: 'UBRR0'
UBRR1 = 51; //19.2kbaud UBRR = (16MHz / 16 x 19200) - 1
^~~~~
UBRR0
volvo_linbus:62:5: error: 'UCSR1B' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:5: note: suggested alternative: 'UCSR0B'
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^~~~~~
UCSR0B
In file included from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\io.h:99:0,
from c:\users\rahul.chandrashekar\appdata\local\arduino15\packages\arduino\tools\avr-gcc\7.3.0-atmel3.6.1-arduino7\avr\include\avr\pgmspace.h:90,
from C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\cores\arduino/Arduino.h:28,
from C:\Users\RAHUL~1.CHA\AppData\Local\Temp\arduino_build_351419\sketch\volvo_linbus.ino.cpp:1:
volvo_linbus:62:18: error: 'RXCIE1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:18: note: suggested alternative: 'RXCIE0'
volvo_linbus:62:32: error: 'RXEN1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:32: note: suggested alternative: 'RXEN0'
volvo_linbus:62:45: error: 'TXEN1' was not declared in this scope
UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1); //enable the UART1 receiver & transmitter and UART1 RX interrupt
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:62:45: note: suggested alternative: 'TXEN0'
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void linRXStateMachine()':
volvo_linbus:136:34: error: 'FE1' was not declared in this scope
if( (s & _BV(FE1)) && (b == FRAME_BYTE) )
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:136:34: note: suggested alternative: 'FE0'
volvo_linbus:155:35: error: 'FE1' was not declared in this scope
if( !(s & _BV(FE1) ) )
^
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:155:35: note: suggested alternative: 'FE0'
volvo_linbus:178:33: error: 'SerialConsole' was not declared in this scope
SerialConsole->println( "Message invalid" );
^~~~~~~~~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void USART1_RX_vect()':
volvo_linbus:217:9: error: 'UCSR1A' was not declared in this scope
s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
^~~~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:217:9: note: suggested alternative: 'UCSR0A'
s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
^~~~~~
UCSR0A
volvo_linbus:218:10: error: 'UDR1' was not declared in this scope
ch = UDR1;
^~~~
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino:218:10: note: suggested alternative: 'UDR0'
ch = UDR1;
^~~~
UDR0
C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void DumpFrame()':
volvo_linbus:239:13: error: 'SerialConsole' was not declared in this scope
SerialConsole->write( '0' );
^~~~~~~~~~~~~
volvo_linbus:240:9: error: 'SerialConsole' was not declared in this scope
SerialConsole->print( b, HEX );
^~~~~~~~~~~~~
volvo_linbus:244:5: error: 'SerialConsole' was not declared in this scope
SerialConsole->println();
^~~~~~~~~~~~~
Using library SoftwareSerial at version 1.0 in folder: C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\arduino\hardware\avr\1.8.5\libraries\SoftwareSerial
exit status 1
'Serial2' was not declared in this scope

That's because that code was written for a Mega2560 Arduino, not an Uno.

1 Like

Thanks -> the write command worked fine. But i have issues reading the frame from my Transreciever.

i see that the below function is been called, but when i debug the frames and messages. it is always "0". The transreciever is sending me the following message

"0x01 0xFF 0x08 0x57 0x44 0xFF 0x03 0x90 0xB2"

    //process LIN messages
    linRXStateMachine();




void linRXStateMachine( void )
{

    static uint8_t
        stateLIN = SEEK_FRAME_START;        //LIN state variable
    uint16_t
        rx;                                 //combo of status and received byte
    uint8_t
        b,                                  //rx'd byte
        s,                                  //status
        tempHead;                           //temporary receive buffer head pointer value

    //read the head pointer
    noInterrupts();             
    tempHead = rxHeadPtr;
    interrupts();

    //if not the same as the tail pointer there are bytes to process
    if( tempHead != rxTailPtr )
    {
      
        do
        {
            //read the combination status and rx'd byte from the buffer
            rx = gruRxBuffer[rxTailPtr];            
            //split into the byte and status
            b = (uint8_t)(rx & 0xff);                        
            s = (uint8_t)((rx >> 8) & 0xff); 
                       
            switch( stateLIN )
            {
                case    SEEK_FRAME_START:
                    //waiting for a break indication (framing error; FE1 bit in status register)
                    //start of frame ==  framing error and rx'd a 0x00                    
                    if( (s & _BV(FE1)) && (b == FRAME_BYTE) )
                        stateLIN = SEEK_SYNC_BYTE;
                break;

                case    SEEK_SYNC_BYTE:
                    //byte immediately following the start condition should be a SYNC byte
                    if( b == SYNC_BYTE )
                    {
                        //got it; reset the LIN frame
                        frame.reset();
                        //and go get the frame
                        stateLIN = RECEIVE_FRAME_DATA;                                                
                        
                    }//if
                    
                break;

                case    RECEIVE_FRAME_DATA:
                    //if we don't see a framing error
                    if( !(s & _BV(FE1) ) )
                    {
                        //just append the received byte to the frame
                        frame.append_byte( b );
                        
                    }//if
                    else
                    {
                        //we see a break here; if we rx'd a 0x00 we
                        //are looking at the start of the next frame so we can process
                        //the one sitting in the buffer                        
                        if( b == 0x00 )
                        {
                            //if the frame is valid... frame.isValid()
                            if(true )
                            {
                                //show it
                                DumpFrame();
                               
                            }//if
                            else
                            {
                                //frame check failed
                                SerialConsole->println( "Message invalid" );
                                
                            }//else

                            //got back and wait for the sync byte
                            stateLIN = SEEK_SYNC_BYTE;
                            
                        }//if
                        else
                        {
                            //got a framing error but not an accompanying 0x00
                            //go to seek a frame start state
                            stateLIN = SEEK_FRAME_START;
                            
                        }//else
                        
                    }//else
                    
                break;
                
            }//switch

            //after each pass, advance the tail pointer...
            rxTailPtr = (rxTailPtr + 1) & (BUFF_SIZE - 1);

            //until we match the head pointer when we started this
        }while( rxTailPtr != tempHead );
        
    }//if

}//linRXStateMachine

ISR( USART1_RX_vect )
{
    uint8_t
        ch,
        s;

    //read the character and the status register
    s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
    ch = UDR1;    

    //put the status byte in the most-sig. byte and the character in the least-sig byte of the word in the buffer
    gruRxBuffer[rxHeadPtr] = (uint16_t)((s << 8) | ch);
    //bump the head pointer
    rxHeadPtr = (rxHeadPtr + 1) & (BUFF_SIZE - 1);
    
}//RX interrupt


void DumpFrame( void )
{        
    if (frame.get_byte(0) != WHEEL_SLAVE2)
    {
      SerialConsole->println(frame.get_byte(0));
      return;
    }
   
    for (uint8_t idx = 0; idx<frame.num_bytes(); idx++) 
    {
        uint8_t b = frame.get_byte(idx);
        if( b <= 0xf )
            SerialConsole->write( '0' );
        SerialConsole->print( b, HEX );
        SerialConsole->write( ' ' );
        
    }//for    
   
    
}//DumpFrame

Scope signal when i insert the probe in the Rx1 (pin number 17)

yes, it works with MCP2003/4

Are you seeing the state machine walking through the SEEK_FRAME_START (first pass) and/or the SEEK_SYNC_BYTE states?

Do you see the break/0x00 (FRAME_START) followed by the 0x55 (SYNC) bytes before you see the 0x01 0xFF 0x08 0x57... data?

Do you ever see it append a byte to the LIN buffer (e.g. a call to frame.append_byte( b ) )?

I noticed you changed:

                            if( frame.isValid() )
                            {
                                //show it
                                DumpFrame();
                               
                            }//if

to

                            if(true )
                            {
                                //show it
                                DumpFrame();
                               
                            }//if

You might place any received characters in a global byte within the ISR and just print those in loop. Maybe like:

volatile uint8_t prByte;            // <-- add global variable
volatile bool bPrByte = false;      // <-- add global variable

.
.
.

ISR( USART1_RX_vect )
{
    uint8_t
        ch,
        s;

    //read the character and the status register
    s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
    ch = UDR1; 

    prByte = ch;        // <-- add
    bPrByte = true;     // <-- add

    //put the status byte in the most-sig. byte and the character in the least-sig byte of the word in the buffer
    gruRxBuffer[rxHeadPtr] = (uint16_t)((s << 8) | ch);
    //bump the head pointer
    rxHeadPtr = (rxHeadPtr + 1) & (BUFF_SIZE - 1);
    
}//RX interrupt

.
.
.
void loop( void )
{
    //process LIN messages
    linRXStateMachine();

    //add this to print bytes as they are received in the ISR
    if( bPrByte )
    {
        bPrByte = false;
        SerialConsole->println( prByte, HEX );

    }//if

}//loop
1 Like

thanks -> the code works fine ;).

I have an another question -> i am using ESP32 with Atmega 2560 were i want to relay messages between these two boards. My objective is to pass the read LIN messages from Atmega to ESP32.

do you recommend me to use Serial3? or are their any other stratergy.

If I'm not mistaken the ESP32 has three HW serial ports; do you need the Mega2560 at all? Is it doing other stuff for your project?

You can use Serial3 of the Mega for this task but keep in mind that the ESP32 has 3.3V I/O so you'll need a level translator between the two.

1 Like

Thanks for your inputs. I have Atmega2560 with ESP8266 and DIP switches.

Can I use only ESP8266 to read and write LIN? If yes this would be a super clean approach for me. Pls let me know on your comments and the tweak I will have to do to execute this

i am unable to compile the Atmega code in ESP board. I would be happy to use ESP32 board as it serves connectivity + HW read. Pls let me know if there are any tweaks to be done to support the write and read functionality in ESP board.

i get compilation errors for the ESP board in the following locations. possibly they are more Atmega libraries

ISR(USART1_RX_vect)
{
    uint8_t
        ch,
        s;

    //read the character and the status register
    s = UCSR1A; //need to be in this order (read status then received data) to get the right status value
    ch = UDR1;    

    //put the status byte in the most-sig. byte and the character in the least-sig byte of the word in the buffer
    gruRxBuffer[rxHeadPtr] = (uint16_t)((s << 8) | ch);
    //bump the head pointer
    rxHeadPtr = (rxHeadPtr + 1) & (BUFF_SIZE - 1);
    
}//RX interrupt

 //send a break on UART0 by disabling TX, setting the pin
        //low and waiting >10 bit times at 19200
        UCSR2B &= ~(_BV(TXEN2));        //disable transmitter to access pin

error message

Arduino: 1.8.19 (Windows 10), Board: "LOLIN(WEMOS) D1 R2 & mini, 80 MHz, Flash, Disabled (new aborts on oom), Disabled, All SSL ciphers (most compatible), 32KB cache + 32KB IRAM (balanced), Use pgm_read macros for IRAM/PROGMEM, 4MB (FS:2MB OTA:~1019KB), v2 Lower Memory, Disabled, None, Only Sketch, 921600"

volvo_linbus:217:5: error: expected constructor, destructor, or type conversion before '(' token

  217 | ISR(USART1_RX_vect)

      |     ^

C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void setup()':

volvo_linbus:60:5: error: 'UCSR1C' was not declared in this scope; did you mean 'USRXC'?

   60 |     UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1

      |     ^~~~~~

      |     USRXC

In file included from sketch\volvo_linbus.ino.cpp:1:

volvo_linbus:60:18: error: 'UCSZ11' was not declared in this scope

   60 |     UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1

      |                  ^~~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

volvo_linbus:60:32: error: 'UCSZ10' was not declared in this scope

   60 |     UCSR1C = _BV(UCSZ11) | _BV(UCSZ10); //async operation, 8N1

      |                                ^~~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

volvo_linbus:61:5: error: 'UBRR1' was not declared in this scope

   61 |     UBRR1 = 51;                         //19.2kbaud UBRR = (16MHz / 16 x 19200) - 1

      |     ^~~~~

volvo_linbus:62:5: error: 'UCSR1B' was not declared in this scope

   62 |     UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);  //enable the UART1 receiver & transmitter and UART1 RX interrupt

      |     ^~~~~~

In file included from sketch\volvo_linbus.ino.cpp:1:

volvo_linbus:62:18: error: 'RXCIE1' was not declared in this scope; did you mean 'RTCIE'?

   62 |     UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);  //enable the UART1 receiver & transmitter and UART1 RX interrupt

      |                  ^~~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

volvo_linbus:62:32: error: 'RXEN1' was not declared in this scope

   62 |     UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);  //enable the UART1 receiver & transmitter and UART1 RX interrupt

      |                                ^~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

volvo_linbus:62:45: error: 'TXEN1' was not declared in this scope

   62 |     UCSR1B = _BV(RXCIE1) | _BV(RXEN1) | _BV(TXEN1);  //enable the UART1 receiver & transmitter and UART1 RX interrupt

      |                                             ^~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void loop()':

volvo_linbus:90:9: error: 'UCSR2B' was not declared in this scope

   90 |         UCSR2B &= ~(_BV(TXEN2));        //disable transmitter to access pin

      |         ^~~~~~

In file included from sketch\volvo_linbus.ino.cpp:1:

volvo_linbus:90:25: error: 'TXEN2' was not declared in this scope

   90 |         UCSR2B &= ~(_BV(TXEN2));        //disable transmitter to access pin

      |                         ^~~~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: In function 'void linRXStateMachine()':

volvo_linbus:143:34: error: 'FE1' was not declared in this scope

  143 |                     if( (s & _BV(FE1)) && (b == FRAME_BYTE) )

      |                                  ^~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

volvo_linbus:162:35: error: 'FE1' was not declared in this scope

  162 |                     if( !(s & _BV(FE1) ) )

      |                                   ^~~

C:\Users\rahul.chandrashekar\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\3.0.2\cores\esp8266/Arduino.h:157:25: note: in definition of macro '_BV'

  157 | #define _BV(b) (1UL << (b))

      |                         ^

C:\Users\rahul.chandrashekar\Downloads\volvo_linbus-master\volvo_linbus\volvo_linbus.ino: At global scope:

volvo_linbus:217:4: error: expected constructor, destructor, or type conversion before '(' token

  217 | ISR(USART1_RX_vect)

      |    ^

exit status 1

expected constructor, destructor, or type conversion before '(' token



This report would have more information with
"Show verbose output during compilation"
option enabled in File -> Preferences.

The Mega code won't compile for the ESP32. For the Mega I used direct register access to set up the serial port and to access status registers etc by name. I've not done low-level ESP32 programming so I really can't help there. It can be done; you can get some pointers, say, here.

The logic can be the same as you have now, you just need to modify how the UART is set up and how break events are detected and handled.

It'd probably be easier to stick with the Mega to do the LIN interface with a quick and short serial interface to the ESP32 (level translation included) if you don't want to get into low-level ESP programming.

1 Like

Thanks -> even i believe to stick with hybrid approach of Mega with ESP.

Based on what i understand i just need to use Serial3 to tramsit data to ESP and Serial to transmit data to Mega.

I hope this would be the approach. Should i do this within the loop? do you have some examples.

Because you're working in an automotive environment, I would wrap the LIN frame data in a packet for transmission to the ESP.

In this example for the Mega that you can integrate into your main program, I use a simple message structure with a preamble byte, a byte indicating the number of data bytes in the message, the LIN frame data and a simple checksum.

I use Serial3 and use TX interrupts to send the message so as not to block on sending it. You can use whatever you like.

On the ESP32 side, you'll set up a receive state machine to look for the preamble byte (0xA5), followed by the number-of-data byte. You can then receive that data and the checksum. The sum is the 8-bit addition of all bytes of the message except the checksum byte. If they match, you have a good message.

If you need more reliability you can change the checksum to a CRC (e.g.)

Code:


#define BUFF_SIZE       64

#define LIN_BUFF_SIZE   16
#define MSG_PREAMBLE    0xa5


const uint8_t
    grLINPacket[] = { 0x50, 0x00, 0x80, 0xFF, 0x7F };           //test msg

//give the serial ports names to make things more human-readable
HardwareSerial 
    *SerialConsole = (HardwareSerial *)&Serial,
    *ESPComm = (HardwareSerial *)&Serial3;
    
typedef struct structTXMsg
{
    uint8_t     msgPointer;
    uint8_t     msgChecksum;
    uint8_t     msgNumBytes;
    uint8_t     gruTxBuffer[BUFF_SIZE];
    
}sTXMsg_t;

//I create this structure only to emulate the LINFrame object
//this doesn't need to be copied into you code...
typedef struct structLinFrame
{
    uint8_t     grBuff[LIN_BUFF_SIZE];
    uint8_t     num_bytes;

    uint8_t get_byte( uint8_t idx )
    {
        return grBuff[idx];
        
    }//get_byte
    
}sLINFrame_t;

sTXMsg_t TXMsg;
sLINFrame_t frame;

void setup( void ) 
{
    //set up mock LIN frame
    frame.num_bytes = 5;
    for( uint8_t i=0; i<5; i++ )
        frame.grBuff[i] = grLINPacket[i];
    
    //UART0 (default) serial console
    SerialConsole->begin(115200);
    //UART3 for comms to the ESP
    ESPComm->begin(115200);             //Serial3

}//setup

void loop( void ) 
{
    //when you get a good frame, call DumpFrameToESP...
    DumpFrameToESP();
    
    delay(1000);    //for demo purposes only; send test msg once a second
    
}//loop


//
//  Send LIN frame to the ESP32
//  Message structure is:
//      0xA5        message preamble
//      0xNN        num data bytes
//      0xaa..0xnn  data packet (LIN frame)
//      0xcc        checksum
//
void DumpFrameToESP( void )
{
    uint8_t
        i;
        
    //set up the message to send    
    TXMsg.gruTxBuffer[0] = MSG_PREAMBLE;        //preamble
    TXMsg.gruTxBuffer[1] = frame.num_bytes;     //num data bytes in packet
    for( i=0; i<frame.num_bytes; i++ )          //frame data
        TXMsg.gruTxBuffer[2+i] = frame.get_byte(i);
        
    TXMsg.msgNumBytes = 2 + frame.num_bytes;    //preamble + num bytes + checksum + frame data
    TXMsg.msgPointer = 1;                       //preamble has already gone so we point to next byte
    TXMsg.msgChecksum = MSG_PREAMBLE;           //checksum init to preamble (first byte sent)
    
    //send the preamble and get the ball rolling
    UCSR3A |= _BV(TXC3);            //clear the TX flag
    UDR3 = TXMsg.gruTxBuffer[0];    //send the preamble
    UCSR3B |= _BV(TXCIE3);          //enable the TX complete interrupt    
    
}//DumpFrame

ISR( USART3_TX_vect )
{
    uint8_t
        bVal;

    //last byte of message?
    if( TXMsg.msgNumBytes == 1 )
    {
        //yes; send the checksum
        bVal = TXMsg.msgChecksum;
        
    }//if
    else
    {
        //no; send the next msg byte and add it to the checksum
        bVal = TXMsg.gruTxBuffer[TXMsg.msgPointer++];    
        TXMsg.msgChecksum = TXMsg.msgChecksum + bVal;
        
    }//if

    //transmit the byte
    UDR3 = bVal;
    //decrement the number of bytes left in the message
    TXMsg.msgNumBytes--;
    //if it's now zero, we've sent the last byte so...
    if( TXMsg.msgNumBytes == 0 )
    {
        //...disable further TX interrupts
        UCSR3B &= ~(_BV(TXCIE3));
        
    }//if
    
}//UART3 TX interrupt

Logic analyzer:

1 Like

appreciate this, can we have a call (15 mins) at your free time tomorrow? I am in EST and can work flexible based on your convenience.

i am able to transfer the LIN packet from ESP to Mega but the issue is sending the packet from Mega to LIN (via ESP8266 webpage).

for instance the earlier code in the forum had dumpframe() where the frame information was iterated. All i would need is to update the values to the ESP8266server running at (80) port.

if i implement DumpframeESP() -> what would be the hook to get that information to ESP (implementation at ESP to understand that it has recieved LIN packet.

for example - tried below implementation in ESP but did not yield consistent results.

void serialEvent() {
while(Serial1.available()) {
    Serial.write( Serial1.read());
  }
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.