From 58a051b217f8dd6d11169a00c6fe9cffdc1e37f8 Mon Sep 17 00:00:00 2001 From: Valentin Dabstep Date: Fri, 6 Jun 2025 18:37:48 +0300 Subject: [PATCH 1/4] Add new process msg --- controller/fw/embed/include/process_can.h | 7 +- controller/fw/embed/include/reg_cah.h | 10 +-- controller/fw/embed/platformio.ini | 4 +- controller/fw/embed/src/main.cpp | 5 ++ controller/fw/embed/src/process_can.cpp | 87 ++++++++++++++--------- 5 files changed, 71 insertions(+), 42 deletions(-) diff --git a/controller/fw/embed/include/process_can.h b/controller/fw/embed/include/process_can.h index 90e4c66..f5d4f2a 100644 --- a/controller/fw/embed/include/process_can.h +++ b/controller/fw/embed/include/process_can.h @@ -19,9 +19,10 @@ void send_motor_enabled(); void send_id(); void firmware_update(); void send_pid_angle(uint8_t param_pid); -// void send_motor_torque(); +void send_torque(); void send_pid(uint8_t param_pid); void setup_id(uint8_t my_id); void setup_angle(float target_angle); -void setup_pid_angle(uint8_t param_pid, float data); -void listen_can(const CAN_message_t &msg); \ No newline at end of file +void setup_velocity(float target_velocity); + +void listen_can(const CAN_message_t &msg); diff --git a/controller/fw/embed/include/reg_cah.h b/controller/fw/embed/include/reg_cah.h index 68f2405..a168e19 100644 --- a/controller/fw/embed/include/reg_cah.h +++ b/controller/fw/embed/include/reg_cah.h @@ -1,5 +1,4 @@ -#ifndef REG_CAH_H_ -#define REG_CAH_H_ +#pragma once #define APP_ADDR 0x0800400 // 16KB - Application #define ADDR_VAR 0x8040000 @@ -16,6 +15,10 @@ #define REG_ID 0x01 #define REG_BAUDRATE 0x02 +#define DATA_TYPE_ANGLE 0x03 +#define DATA_TYPE_VELOCITY 0x04 +#define DATA_TYPE_TORQUE 0x05 + #define REG_MOTOR_POSPID_Kp 0x30 #define REG_MOTOR_POSPID_Ki 0x31 #define REG_MOTOR_POSPID_Kd 0x32 @@ -43,6 +46,3 @@ #define CAN_MSG_MAX_LEN 7 #define CRC_SIZE 2 #define ID_SIZE sizeof(uint8_t) - - -#endif // REG_CAH_H_ diff --git a/controller/fw/embed/platformio.ini b/controller/fw/embed/platformio.ini index a15e7c9..f7f813d 100644 --- a/controller/fw/embed/platformio.ini +++ b/controller/fw/embed/platformio.ini @@ -14,10 +14,10 @@ build_flags = -D STM32F446xx -D HAL_CAN_MODULE_ENABLED -D SIMPLEFOC_PWM_LOWSIDE_ACTIVE_HIGH - + lib_deps = askuric/Simple FOC@^2.3.4 - pazi88/STM32_CAN@^1.1.2 + pazi88/STM32_CAN@^1.1.2 extra_scripts = pre:gen_compile_commands.py diff --git a/controller/fw/embed/src/main.cpp b/controller/fw/embed/src/main.cpp index 79eede0..322b07d 100644 --- a/controller/fw/embed/src/main.cpp +++ b/controller/fw/embed/src/main.cpp @@ -18,6 +18,7 @@ #include "config.h" #include "process_can.h" + void SysTick_Handler(void) { HAL_IncTick(); } @@ -98,9 +99,13 @@ MotorControlInputs motor_control_inputs; void loop() { __enable_irq(); + send_angle(); + send_velocity(); foc_step(&motor); CAN_message_t msg; + + // Process incoming CAN messages while (Can.read(msg)) { listen_can(msg); diff --git a/controller/fw/embed/src/process_can.cpp b/controller/fw/embed/src/process_can.cpp index 08ad180..5cf46ff 100644 --- a/controller/fw/embed/src/process_can.cpp +++ b/controller/fw/embed/src/process_can.cpp @@ -40,9 +40,9 @@ void send_velocity() { // Error handling: logging, alerts, etc. return; } - float value = flash_rec[vel].value; + // float value = flash_rec[vel].value; uint8_t id = flash_rec[addr_id].value; - send_can_with_id_crc(id,'V',&value); + send_can_with_id_crc(id,'V',¤t_velocity); } void send_angle() { @@ -67,6 +67,15 @@ void send_motor_enabled() { send_can_with_id_crc(id,'M',&value); } + +void send_torque() { + float i_q = motor.current.q; // Q-axis current (A) + float torque = 100 * i_q; // Torque calculation + if (flash_rec == nullptr) return; + uint8_t id = flash_rec[addr_id].value; + send_can_with_id_crc(id, 'T', &torque); +} + void send_id() { /* Firmware data reading */ if (flash_rec == nullptr) { // Null check @@ -78,17 +87,6 @@ void send_id() { send_can_with_id_crc(id,'I',&id); } -// void send_motor_torque() { -// float i_q = motor.current.q; // Q-axis current (A) -// float torque = kt * i_q; // Torque calculation -// torque *= 100; -// CAN_TX_msg.id = flash_rec->value; -// CAN_TX_msg.buf[0] = 'T'; -// CAN_TX_msg.len = 5; -// memcpy(&CAN_TX_msg.buf[1], &torque, sizeof(torque)); -// Can.write(CAN_TX_msg); -// } - void send_pid_angle(uint8_t param_pid){ if (flash_rec == nullptr) { // Null check return; @@ -129,26 +127,26 @@ void setup_angle(float target_angle) { // motor.move(target_angle); } -// void setup_pid_angle(uint8_t param_pid, uint32_t data){ -// conv_float_to_int.f = data; -// switch (param_pid) { -// case pid_p: -// motor.P_angle.P = conv_float_to_int.f; -// break; -// case pid_i: -// motor.P_angle.I = conv_float_to_int.f; -// break; -// case pid_d: -// motor.P_angle.D = conv_float_to_int.f; -// break; -// default: -// break; -// } - -// write_param(param_pid,data); -// } - +/** + * @brief Set the up velocity object + * + * @param target_velocity + */ +void setup_velocity(float target_velocity) { + motor.enable(); + motor_control_inputs.target_velocity = target_velocity; +} +/** + * @brief Function for process data from CAN + * @details Function check your ID deviceю. Compare receive and calculated CRC. + * If ID && CRC == TRUE, then process message or dont send data. + * If if and crc = true: + * Check CAN_REG + * Gives your data type + * Write with data or send data + * @param msg + */ void listen_can(const CAN_message_t &msg) { msg_id = msg.id; msg_ch = msg_id & 0xF; // Extract message channel @@ -171,6 +169,7 @@ void listen_can(const CAN_message_t &msg) { return; // Ignore message on CRC mismatch } flash_rec = load_params(); + /* Message Structure: 0x691 69 - Device address 1 - Action code */ @@ -241,5 +240,29 @@ void listen_can(const CAN_message_t &msg) { default: break; } } + + /* If msg_ch != REG_WRITE or REG_READ, then SimpleFOC*/ + else{ + switch(msg.buf[0]) { + /* Read after write*/ + case DATA_TYPE_ANGLE: + send_angle(); + memcpy(&motor_control_inputs.target_angle, &msg.buf[1], sizeof(float)); + setup_angle(motor_control_inputs.target_angle); + break; + + case DATA_TYPE_VELOCITY:{ + send_velocity(); + float vel = 0.0f; + memcpy(&vel, &msg.buf[1], sizeof(float)); + setup_velocity(vel); + break; + } + + case DATA_TYPE_TORQUE: + send_torque(); + break; + } + } } } From 28ce1bb5564c44c605417cb2a116219e99af8de0 Mon Sep 17 00:00:00 2001 From: Valentin Dabstep Date: Fri, 6 Jun 2025 18:37:48 +0300 Subject: [PATCH 2/4] Add save data_type CAN --- controller/fw/embed/include/flash.h | 3 ++- controller/fw/embed/include/reg_cah.h | 7 +++++ controller/fw/embed/src/process_can.cpp | 34 +++++++++++++++++++++++-- 3 files changed, 41 insertions(+), 3 deletions(-) diff --git a/controller/fw/embed/include/flash.h b/controller/fw/embed/include/flash.h index 01ec21b..6b9b3c3 100644 --- a/controller/fw/embed/include/flash.h +++ b/controller/fw/embed/include/flash.h @@ -22,7 +22,8 @@ enum { firmw, foc_id, angl, - vel + vel, + torq }; /* for saved in FLASH float data*/ diff --git a/controller/fw/embed/include/reg_cah.h b/controller/fw/embed/include/reg_cah.h index a168e19..7fced2a 100644 --- a/controller/fw/embed/include/reg_cah.h +++ b/controller/fw/embed/include/reg_cah.h @@ -1,5 +1,12 @@ #pragma once + +enum{ + error_foc = 0, + error_canRX, + error_canTX +}; + #define APP_ADDR 0x0800400 // 16KB - Application #define ADDR_VAR 0x8040000 diff --git a/controller/fw/embed/src/process_can.cpp b/controller/fw/embed/src/process_can.cpp index 5cf46ff..2cb350d 100644 --- a/controller/fw/embed/src/process_can.cpp +++ b/controller/fw/embed/src/process_can.cpp @@ -87,6 +87,11 @@ void send_id() { send_can_with_id_crc(id,'I',&id); } +void send_error(uint8_t error_code){ + uint8_t id = flash_rec[addr_id].value; + send_can_with_id_crc(id,'P',&error_code); +} + void send_pid_angle(uint8_t param_pid){ if (flash_rec == nullptr) { // Null check return; @@ -137,6 +142,11 @@ void setup_velocity(float target_velocity) { motor_control_inputs.target_velocity = target_velocity; } +void send_data_type(uint8_t type_d){ + uint8_t id = flash_rec[addr_id].value; + send_can_with_id_crc(id,'D',&type_d); +} + /** * @brief Function for process data from CAN * @details Function check your ID deviceю. Compare receive and calculated CRC. @@ -151,7 +161,7 @@ void listen_can(const CAN_message_t &msg) { msg_id = msg.id; msg_ch = msg_id & 0xF; // Extract message channel uint16_t id_x = (msg_id >> 4) & 0x7FF; // Extract device address - + uint8_t data_type = 1; //type for work with foc /* CRC Calculation */ uint16_t received_crc = (msg.buf[msg.len - 2]) | (msg.buf[msg.len - 1] << 8); uint8_t data[10] = {0}; // Message buffer for CRC verification @@ -210,6 +220,18 @@ void listen_can(const CAN_message_t &msg) { write_param(pid_d,conv_float_to_int.i); break; + case DATA_TYPE_ANGLE: + data_type = DATA_TYPE_ANGLE; + break; + + case DATA_TYPE_VELOCITY: + data_type = DATA_TYPE_VELOCITY; + break; + + case DATA_TYPE_TORQUE: + data_type = DATA_TYPE_TORQUE; + break; + case FIRMWARE_UPDATE: firmware_update(); break; @@ -232,6 +254,9 @@ void listen_can(const CAN_message_t &msg) { case MOTOR_VELOCITY: send_velocity(); break; case MOTOR_ANGLE: send_angle(); break; case MOTOR_ENABLED: send_motor_enabled(); break; + case DATA_TYPE_ANGLE: send_data_type(uint8_t(DATA_TYPE_ANGLE)); break; + case DATA_TYPE_VELOCITY: send_data_type(uint8_t(DATA_TYPE_VELOCITY)); break; + case DATA_TYPE_TORQUE: send_data_type(uint8_t(DATA_TYPE_TORQUE)); break; // case MOTOR_TORQUE: send_motor_torque(); break; // case FOC_STATE: send_foc_state(); break; case REG_MOTOR_POSPID_Kp: send_pid_angle(pid_p); break; @@ -243,7 +268,7 @@ void listen_can(const CAN_message_t &msg) { /* If msg_ch != REG_WRITE or REG_READ, then SimpleFOC*/ else{ - switch(msg.buf[0]) { + switch(data_type) { /* Read after write*/ case DATA_TYPE_ANGLE: send_angle(); @@ -262,6 +287,11 @@ void listen_can(const CAN_message_t &msg) { case DATA_TYPE_TORQUE: send_torque(); break; + + default: + send_error(error_foc); + break; + } } } From e80f04d857448279014560d3ca379c842e748f82 Mon Sep 17 00:00:00 2001 From: Valentin Dabstep Date: Sun, 8 Jun 2025 12:29:55 +0300 Subject: [PATCH 3/4] Add test SimpleFOC --- controller/fw/embed/test/test_simpleFOC.py | 96 ++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 controller/fw/embed/test/test_simpleFOC.py diff --git a/controller/fw/embed/test/test_simpleFOC.py b/controller/fw/embed/test/test_simpleFOC.py new file mode 100644 index 0000000..d87a6e8 --- /dev/null +++ b/controller/fw/embed/test/test_simpleFOC.py @@ -0,0 +1,96 @@ +import can +import time +import sys +import struct + +# Конфигурация +CAN_INTERFACE = 'can0' +DEVICE_ID = 0x69 # Текущий ID устройства +REG_READ = 0x7 +REG_WRITE = 0x8 +DATA_TYPE_ANGLE = 0x03 +DATA_TYPE_VELOCITY = 0x04 +DATA_TYPE_TORQUE = 0x05 + +# CRC функция (аналогичная устройству) +def validate_crc16(data): + crc = 0xFFFF + for byte in data: + crc ^= byte + for _ in range(8): + if crc & 0x0001: + crc = (crc >> 1) ^ 0xA001 + else: + crc >>= 1 + return crc + +def send_can_message(bus, can_id, data): + try: + msg = can.Message( + arbitration_id=can_id, + data=data, + is_extended_id=False + ) + bus.send(msg) + print(f"[Отправка] CAN ID: 0x{can_id:03X}, Данные: {list(data)}") + return True + except can.CanError as e: + print(f"Ошибка CAN: {e}") + return False + +def receive_response(bus, timeout=1.0): + start_time = time.time() + while time.time() - start_time < timeout: + msg = bus.recv(timeout=0.1) + if msg: + print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}") + return msg + print("[Ошибка] Таймаут") + return None + +def test_simplefoc_else_block(): + bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan') + + # 1. Установка типа данных (DATA_TYPE_ANGLE) + can_id_write = (DEVICE_ID << 4) | REG_WRITE + data_set_type = [DATA_TYPE_ANGLE, 0x00] + full_data = list(can_id_write.to_bytes(2, 'little')) + data_set_type + crc = validate_crc16(full_data) + crc_bytes = list(crc.to_bytes(2, 'little')) + packet = data_set_type + crc_bytes + send_can_message(bus, can_id_write, packet) + time.sleep(0.1) # Ожидание обработки + + # 2. Отправка SimpleFOC сообщения (угол) + target_angle = 45.0 + angle_bytes = struct.pack(' Date: Wed, 11 Jun 2025 22:00:51 +0300 Subject: [PATCH 4/4] Work ID test --- controller/fw/embed/include/process_can.h | 10 +- controller/fw/embed/src/main.cpp | 40 +++--- controller/fw/embed/src/process_can.cpp | 61 +++++++--- controller/fw/embed/test/read_id.py | 142 ++++++++++++++-------- 4 files changed, 164 insertions(+), 89 deletions(-) diff --git a/controller/fw/embed/include/process_can.h b/controller/fw/embed/include/process_can.h index f5d4f2a..9fa5e2b 100644 --- a/controller/fw/embed/include/process_can.h +++ b/controller/fw/embed/include/process_can.h @@ -4,13 +4,19 @@ #include "flash.h" #include "reg_cah.h" +#define CAN_TIMEOUT 50 +#define CAN_SILENCE_TIMEOUT 500 +#define MAX_CAN_READS 2 extern FLASH_RECORD *flash_rec; extern volatile uint16_t msg_id; extern volatile uint16_t id_x; extern volatile uint8_t msg_ch; extern volatile uint8_t crc_h; extern volatile uint8_t crc_l; +extern volatile bool send_blocked; +static volatile bool need_send_angle = false; +static volatile bool need_send_velocity = false; void send_velocity(); void send_angle(); @@ -19,10 +25,12 @@ void send_motor_enabled(); void send_id(); void firmware_update(); void send_pid_angle(uint8_t param_pid); -void send_torque(); +void send_with_confirmation(void (*send_func)(void)); +// void send_torque(); void send_pid(uint8_t param_pid); void setup_id(uint8_t my_id); void setup_angle(float target_angle); void setup_velocity(float target_velocity); +void process_can_messages(); void listen_can(const CAN_message_t &msg); diff --git a/controller/fw/embed/src/main.cpp b/controller/fw/embed/src/main.cpp index 322b07d..ced6c34 100644 --- a/controller/fw/embed/src/main.cpp +++ b/controller/fw/embed/src/main.cpp @@ -30,7 +30,7 @@ uint8_t flag_can = 0; uint32_t flash_error; FLASH_EraseInitTypeDef pEraseInit; uint32_t SectorError; - +uint32_t timeout; /* bool for test CAN */ volatile bool CAN_GET = false; @@ -95,26 +95,22 @@ MotorControlInputs motor_control_inputs; } - - -void loop() { - __enable_irq(); - send_angle(); - send_velocity(); - foc_step(&motor); - CAN_message_t msg; - - - - // Process incoming CAN messages - while (Can.read(msg)) { - listen_can(msg); - CAN_GET = true; - } - /* If receive data from CAN */ - if(CAN_GET) { - - CAN_GET = false; - } +bool is_can_busy() { + return (CAN2->TSR & (CAN_TSR_TME0 | CAN_TSR_TME1 | CAN_TSR_TME2)) != 0x07; } +void loop() { + process_can_messages(); + + static uint32_t last_send = 0; + if(!send_blocked && !is_can_busy() && (HAL_GetTick() - last_send >= 50)) { + send_angle(); + send_velocity(); + last_send = HAL_GetTick(); + } + + foc_step(&motor); + HAL_Delay(1); +} + + diff --git a/controller/fw/embed/src/process_can.cpp b/controller/fw/embed/src/process_can.cpp index 2cb350d..42e9c5f 100644 --- a/controller/fw/embed/src/process_can.cpp +++ b/controller/fw/embed/src/process_can.cpp @@ -3,8 +3,8 @@ static CAN_message_t CAN_TX_msg; static CAN_message_t CAN_inMsg; - - +static uint8_t data_type = DATA_TYPE_ANGLE; +volatile bool send_blocked = false; template void send_can_with_id_crc(uint8_t id, uint8_t message_type, T* data) { // Create CAN message @@ -44,7 +44,7 @@ void send_velocity() { uint8_t id = flash_rec[addr_id].value; send_can_with_id_crc(id,'V',¤t_velocity); } - + void send_angle() { float current_angle = motor.shaftAngle(); if (flash_rec == nullptr) { // Null check @@ -68,13 +68,13 @@ void send_motor_enabled() { } -void send_torque() { - float i_q = motor.current.q; // Q-axis current (A) - float torque = 100 * i_q; // Torque calculation - if (flash_rec == nullptr) return; - uint8_t id = flash_rec[addr_id].value; - send_can_with_id_crc(id, 'T', &torque); -} +// void send_torque() { +// float i_q = motor.current.q; // Q-axis current (A) +// float torque = 100 * i_q; // Torque calculation +// if (flash_rec == nullptr) return; +// uint8_t id = flash_rec[addr_id].value; +// send_can_with_id_crc(id, 'T', &torque); +// } void send_id() { /* Firmware data reading */ @@ -147,6 +147,39 @@ void send_data_type(uint8_t type_d){ send_can_with_id_crc(id,'D',&type_d); } +// Вспомогательные функции +void send_with_confirmation(void (*send_func)(void)) { + uint32_t t_start = HAL_GetTick(); + send_func(); + + // Ожидание подтверждения отправки + while (!(CAN2->TSR & (CAN_TSR_RQCP0 | CAN_TSR_RQCP1 | CAN_TSR_RQCP2))) { + if (HAL_GetTick() - t_start > CAN_TIMEOUT) break; + } +} + +void process_can_messages() { + static uint32_t last_received = HAL_GetTick(); + CAN_message_t msg; + uint8_t count = 0; + + // block send while data cant + send_blocked = true; + + // Чтение сообщений с ограничением + while(count < MAX_CAN_READS && Can.read(msg)) { + listen_can(msg); + last_received = HAL_GetTick(); + count++; + } + + // Проверка таймаута молчания + if(HAL_GetTick() - last_received > CAN_SILENCE_TIMEOUT) { + // Разблокируем отправку при отсутствии сообщений + send_blocked = false; + } +} + /** * @brief Function for process data from CAN * @details Function check your ID deviceю. Compare receive and calculated CRC. @@ -160,8 +193,7 @@ void send_data_type(uint8_t type_d){ void listen_can(const CAN_message_t &msg) { msg_id = msg.id; msg_ch = msg_id & 0xF; // Extract message channel - uint16_t id_x = (msg_id >> 4) & 0x7FF; // Extract device address - uint8_t data_type = 1; //type for work with foc + uint16_t id_x = (msg_id >> 4) & 0x7FF; // Extract device address /* CRC Calculation */ uint16_t received_crc = (msg.buf[msg.len - 2]) | (msg.buf[msg.len - 1] << 8); uint8_t data[10] = {0}; // Message buffer for CRC verification @@ -271,7 +303,8 @@ void listen_can(const CAN_message_t &msg) { switch(data_type) { /* Read after write*/ case DATA_TYPE_ANGLE: - send_angle(); + send_angle(); + delay(200); memcpy(&motor_control_inputs.target_angle, &msg.buf[1], sizeof(float)); setup_angle(motor_control_inputs.target_angle); break; @@ -285,7 +318,7 @@ void listen_can(const CAN_message_t &msg) { } case DATA_TYPE_TORQUE: - send_torque(); + // send_torque(); break; default: diff --git a/controller/fw/embed/test/read_id.py b/controller/fw/embed/test/read_id.py index 17ec647..e3331f8 100644 --- a/controller/fw/embed/test/read_id.py +++ b/controller/fw/embed/test/read_id.py @@ -1,12 +1,23 @@ import can import time import sys + # Конфигурация CAN_INTERFACE = 'can0' -OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства (по умолчанию) +OLD_DEVICE_ID = int(sys.argv[1]) # Текущий ID устройства REG_READ = 0x7 # Код команды чтения REG_ID = 0x01 # Адрес регистра с ID устройства +def flush_can_buffer(bus, duration=0.3): + """Очистка входного буфера CAN""" + start_time = time.time() + flushed_count = 0 + while time.time() - start_time < duration: + msg = bus.recv(timeout=0) + if msg: + flushed_count += 1 + print(f"Очищено сообщений из буфера: {flushed_count}") + def send_can_message(bus, can_id, data): """Отправка CAN-сообщения""" try: @@ -23,14 +34,14 @@ def send_can_message(bus, can_id, data): return False def receive_response(bus, timeout=1.0): - """Ожидание ответа от устройства""" + """Ожидание ответа от устройства (сохраняем вашу оригинальную логику)""" start_time = time.time() while time.time() - start_time < timeout: msg = bus.recv(timeout=0.1) if msg: print(f"[Прием] CAN ID: 0x{msg.arbitration_id:03X}, Данные: {list(msg.data)}") return msg - print("[Ошибка] Таймаут") + print("[Ошибка] Таймаут приема") return None def validate_crc16(data): @@ -45,64 +56,91 @@ def validate_crc16(data): crc >>= 1 return crc -# Инициализация CAN-интерфейса -bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan') +def main(): + # Инициализация CAN-интерфейса + try: + bus = can.interface.Bus( + channel=CAN_INTERFACE, + bustype='socketcan', + bitrate=1000000 # Совпадает с устройством + ) + except Exception as e: + print(f"Ошибка инициализации CAN: {e}") + sys.exit(1) -# ======= 1. Запрос текущего ID устройства ======= + # ======= 1. Подготовка запроса ======= + can_id_read = (OLD_DEVICE_ID << 4) | REG_READ + data_read = [REG_ID, 0x00] + + # Формируем полные данные для расчета CRC: + full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read + + # Рассчитываем CRC + crc = validate_crc16(full_data_for_crc) + crc_bytes = list(crc.to_bytes(2, 'little')) + + # Собираем итоговый пакет + packet_read = data_read + crc_bytes -# Формируем CAN ID для чтения: (OLD_DEVICE_ID << 4) | REG_READ -can_id_read = (OLD_DEVICE_ID << 4) | REG_READ - -# Данные для запроса: [регистр, резервный байт] -data_read = [REG_ID, 0x00] - -# Формируем полные данные для расчета CRC: -# - CAN ID разбивается на 2 байта (little-endian) -# - Добавляем данные запроса -full_data_for_crc = list(can_id_read.to_bytes(2, 'little')) + data_read - -# Рассчитываем CRC и разбиваем на байты (little-endian) -crc = validate_crc16(full_data_for_crc) -crc_bytes = list(crc.to_bytes(2, 'little')) - -# Собираем итоговый пакет: данные + CRC -packet_read = data_read + crc_bytes - -print("Запрос на чтение ID:", packet_read) -send_can_message(bus, can_id_read, packet_read) - -# ======= 2. Получение и проверка ответа ======= -response = receive_response(bus) -if response: + # ======= 2. Отправка запроса с повторами ======= + max_retries = 3 + response = None + + for attempt in range(max_retries): + print(f"\nПопытка {attempt+1}/{max_retries}") + + # Очистка буфера перед отправкой + flush_can_buffer(bus, 0.3) + + # Отправка запроса + print(f"Отправка запроса на чтение ID: {packet_read}") + if not send_can_message(bus, can_id_read, packet_read): + print("Ошибка отправки, повтор...") + time.sleep(0.2) + continue + + # Ожидание ответа + response = receive_response(bus, timeout=0.5) + if response: + break + + print("Ответ не получен, повтор...") + time.sleep(0.2) + + # ======= 3. Обработка ответа ======= + if not response: + print("Устройство не ответило после всех попыток") + bus.shutdown() + sys.exit(1) + data = response.data - if len(data) < 4: print("Слишком короткий ответ") + bus.shutdown() + sys.exit(1) # Проверяем минимальную длину ответа (данные + CRC) + id_bytes = response.arbitration_id.to_bytes(1, byteorder='little') + full_data = list(id_bytes) + list(data[:-2]) + print(f"Полные данные для CRC: {full_data}") + + received_crc = int.from_bytes(data[-2:], byteorder='little') + calc_crc = validate_crc16(full_data) + + print(f"Расчитанный CRC: 0x{calc_crc:04X}, Полученный CRC: 0x{received_crc:04X}") + + if received_crc == calc_crc: + print(f"Текущий ID устройства: 0x{data[1]:02X}") else: - id_bytes = response.arbitration_id.to_bytes(1,byteorder='little') - #buff with id and data without CRC - full_data = list(id_bytes) + list(data[:-2]) - print(f"Received full_data: {list(full_data)}") - received_crc = int.from_bytes(data[-2:], byteorder='little') - #calc CRC - calc_crc = validate_crc16(full_data) - - print(f"Расчитанный CRC PYTHON : 0x{calc_crc:02X}") - if received_crc == calc_crc: - # Если CRC совпадает, проверяем структуру ответа: - print(f"Текущий ID устройства: 0x{data[1]:02X}") - else: - print("Ошибка: CRC не совпадает") -else: - print("Устройство не ответило") - -# Завершаем работу с шиной -bus.shutdown() + print("Ошибка: CRC не совпадает") + + # Завершаем работу с шиной + bus.shutdown() if __name__ == "__main__": - import sys if len(sys.argv) != 2: - print("Использование: python3 can_flasher.py address") + print("Использование: python3 can_flasher.py <адрес_устройства>") + print("Пример: python3 can_flasher.py 1") sys.exit(1) + + main() \ No newline at end of file