Hi sorry to bump this thread.
I have joined the forum as am interested in implementing some Lin communication on an ESP to control some ambient light lin devices on my car and I have found this thread to very interesting.
Phatpaul, I was wondering if you are sharing your LIn driver including the headers. It seems to me something very complex for my skills level and it would be a great starting point to have a working driver as an start point.
Will it work as well in an ESP8266?
Thanks a lot in advance
Best regards
UART break at first
Re: UART break at first
Well, a recent update to esp-idf has broken my LIN break method. In 3.3.5 it works, then in 3.3.6, the break is not long enough.
From the release notes:
https://github.com/espressif/esp-idf/re ... tag/v3.3.6
Perhaps something in one of these changes broke my LIN solution:
Freemodbus: Fixed rs485 rts de-assert fail when tx delayed (#6728)
Freemodbus: Added the MB_PORT_TASK_AFFINITY kconfig option for modbus tasks (#6700)
UART: Fixed uart module reset issue (#1202)
UART: Added config to support placing UART ISR in IRAM
UART: Fixed a typo in the error message of invalid rx_thresh_xoff
@Bencium I can share my example project, but I'll need a little time to prepare it. Do you need LIN master or slave for your application? If the lights you want to control are already commanded by a master (i.e. part of your car) then I'm not sure how you can override that.
From the release notes:
https://github.com/espressif/esp-idf/re ... tag/v3.3.6
Perhaps something in one of these changes broke my LIN solution:
Freemodbus: Fixed rs485 rts de-assert fail when tx delayed (#6728)
Freemodbus: Added the MB_PORT_TASK_AFFINITY kconfig option for modbus tasks (#6700)
UART: Fixed uart module reset issue (#1202)
UART: Added config to support placing UART ISR in IRAM
UART: Fixed a typo in the error message of invalid rx_thresh_xoff
@Bencium I can share my example project, but I'll need a little time to prepare it. Do you need LIN master or slave for your application? If the lights you want to control are already commanded by a master (i.e. part of your car) then I'm not sure how you can override that.
Re: UART break at first
Hi I had the same problem and "fixed" it. After lots of trial and error I added a second wait_for_tx_done after the first one. And now it "works" again for some reason. I am not happy with the solution, but after spending two days to understand how to add a brake at-front into the library I gave up. The break-at-end is so complicated embedded that I can not get it to send the break before the data....
Best regards and I hope the quick fix fix helps. I wish I could understand the UART code better and contribute something with more value.
Best regards and I hope the quick fix fix helps. I wish I could understand the UART code better and contribute something with more value.
Re: UART break at first
@FlorianR thanks! You saved me a bunch of time. (I had just reverted to 3.3.5 until I had time to bisect the problem.)
I also don't know why this works, but since this whole break-at-first method is a hack anyway, your solution fits perfectly.
To be clear, here's the modified
I also don't know why this works, but since this whole break-at-first method is a hack anyway, your solution fits perfectly.
To be clear, here's the modified
Code: Select all
void LIN_driver_start_frame(uint8_t pid)
{
uint32_t baudrate;
uint8_t master_tx_buf[2];
master_tx_buf[0] = 0x55; // sync byte
master_tx_buf[1] = pid;
uint8_t dummy = 0;
uart_flush_input(lin_uart_num); // since we are the master, clear out rx buff before starting a frame
xQueueReset(lin_uart_event_queue); // clear the q for slave rx uart breaks
/* Send break character */
// this method sucks b/c it must send a dummy char before the break
// Note: if use this, then +1 to LIN_IN_HEADER_SIZE for dummy byte.
//uart_write_bytes_with_break(lin_uart_num, (char *)&dummy, 1, LIN_BREAK_LEN);
// this method really sucks because of a blocking delay!
//uart_set_line_inverse(param_ptr_config->uart_port_num, UART_INVERSE_TXD);
//ets_delay_us(677);
//uart_set_line_inverse(param_ptr_config->uart_port_num, UART_INVERSE_DISABLE);
//uart_hal_tx_break(&(uart_context[uart_num].hal), 0); - not available in IDF 3x
// Temporarily change baudrate to slightly lower and send a 0 byte
// to get the right baudrate, we want 9 bits (1 start + 8 data) to take the time of 13 bits (one break)
uart_get_baudrate(lin_uart_num, &baudrate);
#define LIN_BREAK_BAUDRATE(BAUD) ((BAUD * 9) / 13)
uart_set_baudrate(lin_uart_num, LIN_BREAK_BAUDRATE(baudrate));
uart_write_bytes(lin_uart_num, (char *)&dummy, 1); // send a zero byte. This call must be blocking.
uart_wait_tx_done(lin_uart_num, 2); // shouldn't be necessary??
uart_wait_tx_done(lin_uart_num, 2); // add 2nd uart_wait_tx_done per https://esp32.com/viewtopic.php?p=98456#p98456
uart_set_baudrate(lin_uart_num, baudrate); // set baudrate back to normal after break is sent
// we have to fake a break detect for the slave, since it doesn't detect it with this method.
uart_event_t event = {.type = UART_BREAK};
xQueueSend(lin_uart_event_queue, (void *)&event, 0);
// Now send the sync and PID bytes
uart_write_bytes(lin_uart_num, (char *)master_tx_buf, sizeof(master_tx_buf));
}
Who is online
Users browsing this forum: Majestic-12 [Bot] and 90 guests