Popularny post H1M4W4R1 Napisano Czerwiec 6, 2021 Popularny post Udostępnij Napisano Czerwiec 6, 2021 Streszczenie W jednym zdaniu: moduł zewnętrzny LIN dla płytek prototypowych (sterowniki dla Pi Pico (C++) są dostępne tutaj). Urządzenie ma na celu umożliwić korzystanie z LIN poprzez port UART. Poglądowy model płytki Opis działania Sercem płytki jest układ TLIN2029 (albo NCV7329). Reszta to opisane w notach katalogowych peryferia. Układ można podłączyć do dowolnej płytki prototypowej (Arduino, Pi Pico, ESP32). Wspiera zarówno logikę 5V jak i 3.3V. Napięcie 5V służy jako zasilanie magistrali LIN (standardowe napięcie), aczkolwiek można wylutować rezystor podłączający ten pin do VSUP i podłączyć zasilanie LIN do header'a LIN. RX podłączamy do RX płytki, TX do TX płytki. (nie zamieniamy RX i TX jak to ma miejsce w przypadku UART). Schemat C1 dla slave powinien wynosić 220pF, dla Master'a 1nF. R1 służy do podłączenia zasilania 5V do magistrali LIN. R7 jest rezystorem podciągającym 5V do pinu EN dla transceivera. D1 i R2 to wymagane przez LIN zabezpieczenie magistrali po stronie Master'a (tylko i wyłącznie) C2 jest kondensatorem stabilizującym zasilanie VSUP. W zależności od płytki powinien wynosić 100nF-10uF. LIN1 to header magistrali - tam podłączamy zasilanie, komunikację oraz masę. LIN2 to header do płytki prototypowej - podłączamy zasilanie 5V oraz GND. LRX podłączamy do RX płytki, LTX do TX płytki. Komunikacja przy użyciu płytki (9600bitps), zrzut pochodzi jeszcze z momentu, gdy algorytm źle wyliczał sumę kontrolną, co zostało już poprawione A tutaj [cenzura] zlutowana płytka Pliki projektu EasyEda - JSON w załączniku EasyEda PCB_LIN Breakout Module_2021-06-06.zip 5
Treker (Damian Szymański) Czerwiec 7, 2021 Udostępnij Czerwiec 7, 2021 @H1M4W4R1 Twój opis został właśnie zaakceptowany, więc jest już widoczny publicznie
PiotrekEl Październik 5, 2021 Udostępnij Październik 5, 2021 Jest tylko jeden problem. Transceivery LIN są dostępne tylko na zamówienie. Czas realizacji około 52 tygodnie Jakbyś wiedział gdzie są dostępne, daj znać. Kupię cały karton
H1M4W4R1 Październik 5, 2021 Autor tematu Udostępnij Październik 5, 2021 (edytowany) 1 godzinę temu, PiotrekEl napisał: Jakbyś wiedział gdzie są dostępne, daj znać. Kupię cały karton Osobiście mam jeszcze ze 20 sztuk Do tego też płytki (chyba, dawno nie grzebałem tak głęboko w szufladzie) Konkretniej ten model: https://pl.mouser.com/ProductDetail/863-NCV7329D10R2G Edytowano Październik 5, 2021 przez H1M4W4R1
arow Styczeń 8, 2024 Udostępnij Styczeń 8, 2024 Cześć. Czy mógłbyś pokazać przykład w ino, który obsługuje tą płytkę z Arduino?
H1M4W4R1 Styczeń 8, 2024 Autor tematu Udostępnij Styczeń 8, 2024 5 godzin temu, arow napisał: Cześć. Czy mógłbyś pokazać przykład w ino, który obsługuje tą płytkę z Arduino? Nie, pisałem w czystym C++ pod RPi Pico. CPP: #include <cstdio> #include "lin.h" #define LIN_BREAK_WIDTH 14 #define LIN_SYNC 0x55 uint baud; uint txPin; uint rxPin; uint8_t lin_sync = LIN_SYNC; uart_inst_t* uart; bool freeHeader = false; alarm_id_t alarmId; uint64_t get_lin_time(){ double micros_d = (double) 1000000 / baud; uint64_t micros = (uint64_t) micros_d; return micros; } void lin_initialize(uart_inst_t *uartInst, uint tx, uint rx, uint baudRate) { // Initialize GPIO gpio_init(tx); gpio_init(rx); gpio_set_dir(tx, true); gpio_set_dir(rx, false); gpio_pull_up(tx); gpio_pull_up(rx); gpio_put(tx, true); // As UART gpio_set_function(tx, GPIO_FUNC_UART); gpio_set_function(rx, GPIO_FUNC_SIO); // Set PIN values txPin = tx; rxPin = rx; // Store BAUD value baud = baudRate; // Init UART uart_init(uartInst, baudRate); uart_set_format(uartInst, 8, 1, UART_PARITY_NONE); uart = uartInst; // READY } uint8_t calculate_checksum(uint8_t id, uint8_t* data, uint8_t len, bool enhanced_checksum){ uint16_t sum = 0; for(int q = 0; q < len; q++){ sum += data[q]; } // IF LIN2, then also consider ID if(enhanced_checksum) { sum += id; } // Subtract sum while(sum >= 256) sum -= 255; // Invert sum uint8_t sum8 = (uint8_t) sum; return ~sum8; } bool get_bit(uint8_t input, uint8_t n){ return (input >> n) & 1; } uint8_t set_bit(uint8_t input, uint8_t n, bool value){ if(value) input |= 1 << n; else input &= ~(1 << n); return input; } uint8_t lin_get_data_size(uint8_t pid){ // Reset parity bits uint8_t id = set_bit(pid, 7, 0); id = set_bit(id, 6, 0); if(id <= 0x1F) return 2; if(id <= 0x2F) return 4; if(id <= 0x3F) return 8; return 0; } uint8_t lin_calculate_parity(uint8_t id){ bool p0 = get_bit(id, 0) xor get_bit(id, 1) xor get_bit(id, 2) xor get_bit(id, 4); bool p1 = not (get_bit(id, 1) xor get_bit(id, 3) xor get_bit(id, 4) xor get_bit(id, 5)); id = set_bit(id, 6, p0); id = set_bit(id, 7, p1); return id; } void lin_send_frame(lin_frame* frame) { // Calculate settings uint64_t lin_delay = get_lin_time(); uint8_t id = lin_calculate_parity(frame->id); // Break gpio_set_function(txPin, GPIO_FUNC_SIO); gpio_put(txPin, false); // Send 0 for 14 TLIN sleep_us(LIN_BREAK_WIDTH * lin_delay); gpio_put(txPin, true); sleep_us(lin_delay); uint8_t checksum = calculate_checksum(id, frame->data, frame->length, frame->enhanced_checksum); gpio_set_function(txPin, GPIO_FUNC_UART); // Prepare data array uint8_t data[12]; data[0] = lin_sync; data[1] = id; for(int q = 2; q < 2 + frame->length; q++){ data[q] = frame->data[q - 2]; } data[2 + frame->length] = checksum; // Send uart_write_blocking(uart, data, frame->length + 3); } int64_t lin_not_received(alarm_id_t id, void *user_data) { if(alarmId == id) { // Free header freeHeader = true; return 0x0; } else{ return 0x1; } } void lin_send_header(lin_frame* frame) { freeHeader = false; uint64_t lin_delay = get_lin_time(); uint8_t id = lin_calculate_parity(frame->id); // Break gpio_set_function(txPin, GPIO_FUNC_SIO); gpio_put(txPin, false); // Send 0 for 14 TLIN sleep_us(LIN_BREAK_WIDTH * lin_delay); gpio_put(txPin, true); sleep_us(lin_delay); // Frame gpio_set_function(txPin, GPIO_FUNC_UART); // Prepare data uint8_t data[2] = {lin_sync, id}; // Send uart_write_blocking(uart, data,2); // Check if is readable alarmId = add_alarm_in_us(get_lin_time() * 512, lin_not_received, nullptr, false); // Try to read frame if(!lin_read_frame_blocking(frame)) { for(uint8_t q = 0; q < lin_get_data_size(id); q++) frame->data[q] = 0x0; } // Cancel alarm cancel_alarm(alarmId); } void lin_send_response(lin_frame* frame) { // Calculate PID uint8_t id = lin_calculate_parity(frame->id); // Update settings gpio_set_function(txPin, GPIO_FUNC_UART); uint8_t checksum = calculate_checksum(id, frame->data, frame->length, frame->enhanced_checksum); uint8_t data_size = lin_get_data_size(id); // Build uint8_t data[9]; for(int q = 0; q < data_size; q++) data[q] = frame->data[q]; data[data_size] = checksum; // Send response uart_write_blocking(uart, data, frame->length + 1); } bool lin_read_frame_blocking(lin_frame *frame) { // Get timing uint64_t lin_delay = get_lin_time(); gpio_set_function(rxPin, GPIO_FUNC_UART); uint8_t sync; uint8_t id; // Check if can be freed while(!uart_is_readable(uart)){ if(freeHeader) return false; } // Break catcher uart_read_blocking(uart, &sync, 1); if(sync == 0x55){ goto skip_sync; } if(sync != 0x0){ gpio_set_function(rxPin, GPIO_FUNC_SIO); return false; } // Check if can be freed while(!uart_is_readable(uart)){ if(freeHeader) return false; } // Invalid SYNC uart_read_blocking(uart, &sync, 1); if (sync != 0x55){ gpio_set_function(rxPin, GPIO_FUNC_SIO); return false; } skip_sync: // Check if can be freed while(!uart_is_readable(uart)){ if(freeHeader) return false; } uart_read_blocking(uart, &id, 1); frame->id = id; // Read data (if sent proper frame) if(uart_is_readable_within_us(uart, 16 * lin_delay)) { uart_read_blocking(uart, frame->data, lin_get_data_size(id)); uart_read_blocking(uart, &frame->checksum, 1); } gpio_set_function(rxPin, GPIO_FUNC_SIO); return true; } H: #ifndef PICOUARTLIN_LIN_H #define PICOUARTLIN_LIN_H #include "pico/stdlib.h" #include <hardware/uart.h> struct lin_frame{ uint8_t id; uint8_t* data; uint8_t length; bool enhanced_checksum; // Checksum only in received frames uint8_t checksum; }; void lin_initialize(uart_inst_t* uartInst, uint tx, uint rx, uint baudRate); void lin_send_frame(lin_frame* frame); void lin_send_response(lin_frame* response); bool lin_read_frame_blocking(lin_frame* frame); void lin_send_header(lin_frame* frame); uint8_t lin_get_data_size(uint8_t pid); uint8_t lin_calculate_parity(uint8_t id); #endif //PICOUARTLIN_LIN_H
arow Styczeń 8, 2024 Udostępnij Styczeń 8, 2024 Szkoda Walczę z tym LIN BUS od 5 miesięcy i żadnego postępu :(. Cały czas odczytuje ale nic nie jestem w stanie wysłać. 1
H1M4W4R1 Styczeń 8, 2024 Autor tematu Udostępnij Styczeń 8, 2024 1 godzinę temu, arow napisał: Szkoda Walczę z tym LIN BUS od 5 miesięcy i żadnego postępu :(. Cały czas odczytuje ale nic nie jestem w stanie wysłać. Możesz przejrzeć wcześniej podesłany kod. Wysyłanie działało bardzo dobrze, gorzej z odbiorem, bo czasem potrafił się przywiesić. Przepisanie tego na Arduino nie powinno być dużym problemem.
Pomocna odpowiedź
Bądź aktywny - zaloguj się lub utwórz konto!
Tylko zarejestrowani użytkownicy mogą komentować zawartość tej strony
Utwórz konto w ~20 sekund!
Zarejestruj nowe konto, to proste!
Zarejestruj się »Zaloguj się
Posiadasz własne konto? Użyj go!
Zaloguj się »