Add py test and fix work with float in FLASH

This commit is contained in:
Valentin Dabstep 2025-05-15 23:13:07 +03:00
parent a0800410e0
commit 0980243848
4 changed files with 136 additions and 16 deletions

View file

@ -9,14 +9,14 @@
/* no padding for this struct, beacuse storing 8 bytes*/ /* no padding for this struct, beacuse storing 8 bytes*/
typedef struct{ typedef struct{
uint8_t data_id; // data_id = id register of can uint8_t data_id; // data_id = id register of can
uint8_t data_type; //float or uint8_t if 4 - float 1 - uint8_t uint8_t data_type;
uint16_t crc; uint16_t crc;
uint32_t value; uint32_t value;
// uint32_t write_ptr_now; // uint32_t write_ptr_now;
}FLASH_RECORD; }FLASH_RECORD;
enum { enum {
addr_id = 0, addr_id = 0,
pid_p, pid_p = 1,
pid_i, pid_i,
pid_d, pid_d,
foc_id, foc_id,
@ -24,6 +24,12 @@ enum {
vel vel
}; };
/* for saved in FLASH float data*/
union{
uint32_t i;
float f;
}conv_float_to_int;
#define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct #define FLASH_RECORD_SIZE sizeof(FLASH_RECORD) //size flash struct
#define PARAM_COUNT 4 // count data in flash #define PARAM_COUNT 4 // count data in flash

View file

@ -242,3 +242,5 @@ FLASH_RECORD* load_params(){
__enable_irq(); __enable_irq();
return latest; return latest;
} }

View file

@ -42,7 +42,6 @@ volatile bool CAN_GET = false;
volatile float kt = 0.1; // Torque calculation constant volatile float kt = 0.1; // Torque calculation constant
static FLASH_RECORD* flash_rec; static FLASH_RECORD* flash_rec;
static FLASH_RECORD flash_buf[PARAM_COUNT];
static CAN_message_t CAN_TX_msg; static CAN_message_t CAN_TX_msg;
static CAN_message_t CAN_inMsg; static CAN_message_t CAN_inMsg;
@ -134,7 +133,8 @@ void send_can_with_id_crc(uint8_t id, uint8_t message_type, const T* data) {
memcpy(crc_data, (uint8_t*)&msg_l.id, sizeof(T)); memcpy(crc_data, (uint8_t*)&msg_l.id, sizeof(T));
// Copy all data bytes // Copy all data bytes
memcpy(crc_data + 1, msg_l.buf, 6); memcpy(crc_data + 1, msg_l.buf, 6);
// Calculate CRC
// Calculate CRC
uint16_t crc_value = validate_crc16(crc_data, CAN_MSG_MAX_LEN); uint16_t crc_value = validate_crc16(crc_data, CAN_MSG_MAX_LEN);
// Insert CRC into buffer // Insert CRC into buffer
@ -215,7 +215,8 @@ void send_pid(uint8_t param_pid){
return; return;
} }
uint8_t id = flash_rec[addr_id].value; uint8_t id = flash_rec[addr_id].value;
float data = flash_rec[param_pid].value; conv_float_to_int.i = flash_rec[param_pid].value;
uint32_t data = conv_float_to_int.i;
switch(param_pid){ switch(param_pid){
case pid_p: case pid_p:
param_pid = REG_MOTOR_POSPID_Kp; param_pid = REG_MOTOR_POSPID_Kp;
@ -298,20 +299,31 @@ void listen_can(const CAN_message_t &msg) {
delay(100); delay(100);
} }
break; break;
case MOTOR_ANGLE: case MOTOR_ANGLE:
memcpy(&motor_control_inputs.target_angle, &msg.buf[1], memcpy(&motor_control_inputs.target_angle, &msg.buf[1],
sizeof(motor_control_inputs.target_angle)); sizeof(motor_control_inputs.target_angle));
setup_angle(motor_control_inputs.target_angle); setup_angle(motor_control_inputs.target_angle);
break; break;
case REG_MOTOR_POSPID_Kp: case REG_MOTOR_POSPID_Kp:
setup_pid_angle(pid_p,msg.buf[1]); memcpy(&motor.P_angle.P, &msg.buf[1], sizeof(float));
conv_float_to_int.f = motor.P_angle.P;
write_param(pid_p,conv_float_to_int.i);
break; break;
case REG_MOTOR_POSPID_Ki: case REG_MOTOR_POSPID_Ki:
setup_pid_angle(pid_i,msg.buf[1]); memcpy(&motor.P_angle.I, &msg.buf[1], sizeof(float));
conv_float_to_int.f = motor.P_angle.I;
write_param(pid_i,conv_float_to_int.i);
break; break;
case REG_MOTOR_POSPID_Kd: case REG_MOTOR_POSPID_Kd:
setup_pid_angle(pid_d,msg.buf[1]); memcpy(&motor.P_angle.D, &msg.buf[1], sizeof(float));
conv_float_to_int.f = motor.P_angle.D;
write_param(pid_d,conv_float_to_int.i);
break; break;
case MOTOR_ENABLED: case MOTOR_ENABLED:
if (msg.buf[1] == 1) { if (msg.buf[1] == 1) {
motor.enable(); motor.enable();
@ -382,15 +394,13 @@ void foc_step(BLDCMotor *motor, Commander *commander) {
// Настройка прерываний CAN // Настройка прерываний CAN
CAN2->IER |= CAN_IER_FMPIE0; CAN2->IER |= CAN_IER_FMPIE0;
// flash_rec = load_params();
// /* For test */
// float value = 3.46; //addr
// write_param(pid_p,value); //for update address in firmware
// // Load parameters from flash
flash_rec = load_params(); flash_rec = load_params();
/* For test */
for(int i = 0;i < PARAM_COUNT;i++) // float value = 3.46; //addr
flash_buf[i] = flash_rec[i]; // conv_float_to_int.f = value;
// write_param(pid_p,conv_float_to_int.i); //for update address in firmware
// // Load parameters from flash
// flash_rec = load_params();
// Initialize FOC system // Initialize FOC system
setup_foc(&encoder, &motor, &driver, &current_sense, &command, doMotor); setup_foc(&encoder, &motor, &driver, &current_sense, &command, doMotor);

View file

@ -0,0 +1,102 @@
import can
import time
import struct
# Конфигурация (замените значения на актуальные для вашей системы)
CAN_INTERFACE = 'can0'
DEVICE_ID = 0x00 # ID устройства по умолчанию
REG_READ = 0x7 # Код команды чтения
REG_MOTOR_POSPID_Kp = 0x30 # Адрес регистра Kp (пример, уточните в коде устройства)
def send_can_message(bus, can_id, data):
"""Отправка CAN-сообщения"""
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 validate_crc16(data):
"""Расчет CRC16 (MODBUS)"""
crc = 0xFFFF
for byte in data:
crc ^= byte
for _ in range(8):
if crc & 0x0001:
crc = (crc >> 1) ^ 0xA001
else:
crc >>= 1
return crc
# Инициализация CAN-интерфейса
bus = can.interface.Bus(channel=CAN_INTERFACE, bustype='socketcan')
# ======= 1. Запрос значения PID_P =======
# Формируем CAN ID для чтения: (DEVICE_ID << 4) | REG_READ
can_id = (DEVICE_ID << 4) | REG_READ
# Данные для запроса: [регистр Kp, резервный байт]
data_read = [REG_MOTOR_POSPID_Kp, 0x00]
# Формируем данные для CRC: CAN ID (2 байта) + данные запроса
full_data_for_crc = list(can_id.to_bytes(2, 'little')) + data_read
# Расчет CRC и сборка пакета
crc = validate_crc16(full_data_for_crc)
packet = data_read + list(crc.to_bytes(2, 'little'))
# Отправка запроса
print("\nЗапрос параметра PID_P...")
send_can_message(bus, can_id, packet)
# ======= 2. Обработка ответа =======
response = receive_response(bus)
if response:
data = response.data
if len(data) < 7:
print(f"Ошибка: получено {len(data)} байт, ожидалось 7")
else:
# Извлекаем CRC из ответа
received_crc = int.from_bytes(data[-2:], byteorder='little')
# Формируем данные для проверки CRC
arb_id_bytes = response.arbitration_id.to_bytes(2, 'little')
full_data = list(arb_id_bytes) + list(data[:-2])
# Проверка CRC
calculated_crc = validate_crc16(full_data)
if calculated_crc != received_crc:
print(f"Ошибка CRC: рассчитанный 0x{calculated_crc:04X}, полученный 0x{received_crc:04X}")
else:
# Проверяем адрес регистра в ответе
if data[0] != REG_MOTOR_POSPID_Kp:
print(f"Ошибка: получен регистр 0x{data[0]:02X}, ожидался 0x{REG_MOTOR_POSPID_Kp:02X}")
else:
# Декодируем значение float (little-endian)
kp_value = struct.unpack('<f', bytes(data[1:5]))[0]
print(f"Успешно! Текущее значение PID_P: {kp_value}")
else:
print("Устройство не ответило")
# Завершение работы
bus.shutdown()