Work ID test

This commit is contained in:
Valentin Dabstep 2025-06-11 22:00:51 +03:00
parent e80f04d857
commit 207b889fef
4 changed files with 164 additions and 89 deletions

View file

@ -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);

View file

@ -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);
}

View file

@ -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 <typename T>
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',&current_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:

View file

@ -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()