xidipower test

This commit is contained in:
2026-03-09 01:57:43 +08:00
parent 5145d60794
commit 9c58a09eab
4 changed files with 92 additions and 72 deletions

View File

@@ -7,11 +7,11 @@
#include "daemon.h"
static PowerMeterInstance *power_meter_instance = NULL;
static XidiPowerMeterInstance *power_meter_instance = NULL;
/**
* @brief 功率计数据解码函数
* @param instance FDCAN实例指针
* @param _instance FDCAN实例指针
*
* @note 数据格式:
* DATA[0]: 电流数值低8位
@@ -22,13 +22,13 @@ static PowerMeterInstance *power_meter_instance = NULL;
*
* 电压电流数值均为放大100倍后的整数需要除以100.0得到实际值
*/
void PowerMeterDecode(FDCANInstance *instance)
void XidiPowerMeterDecode(FDCANInstance *_instance)
{
if (power_meter_instance == NULL)
return;
uint8_t *rxbuff = instance->rx_buff;
PowerMeter_Measure_s *measure = &power_meter_instance->measure;
uint8_t *rxbuff = _instance->rx_buff;
XidiPowerMeter_Msg_s *measure = &power_meter_instance->powermeter_msg;
// 重载守护进程
// if (power_meter_instance->daemon != NULL)
@@ -60,57 +60,51 @@ void PowerMeterDecode(FDCANInstance *instance)
* @brief 功率计丢失回调函数
* @param power_meter_ptr 功率计实例指针
*/
void PowerMeterLostCallback(void *power_meter_ptr)
void XidiPowerMeterLostCallback(void *power_meter_ptr)
{
PowerMeterInstance *power_meter = (PowerMeterInstance *) power_meter_ptr;
XidiPowerMeterInstance *power_meter = (XidiPowerMeterInstance *) power_meter_ptr;
}
/**
* @brief 功率计初始化
* @param can_handle FDCAN句柄指针
* @return PowerMeterInstance* 功率计实例指针
* @param XidiPowerMeter_config 功率计初始化配置结构体指针 (必须确保其生命周期是全局或静态的)
* @return XidiPowerMeterInstance* 功率计实例指针
*/
PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle)
XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config)
{
// 检查是否已经初始化
// 1. 检查是否已经初始化
if (power_meter_instance != NULL)
{
return power_meter_instance;
}
// 分配内存
power_meter_instance = (PowerMeterInstance *) malloc(sizeof(PowerMeterInstance));
// 2. 分配内存并清零
power_meter_instance = (XidiPowerMeterInstance *)malloc(sizeof(XidiPowerMeterInstance));
if (power_meter_instance == NULL)
{
return NULL;
}
memset(power_meter_instance, 0, sizeof(PowerMeterInstance));
memset(power_meter_instance, 0, sizeof(XidiPowerMeterInstance));
// 配置功率计初始化参数
FDCAN_Init_Config_s can_config = {
.can_handle = can_handle,
.rx_id = 0x213, // 功率计反馈标识符
.tx_id = 0x000, // 不需要发送设为0
.can_module_callback = PowerMeterDecode,
.id = power_meter_instance, // 将实例指针作为ID传递
};
// 3. 配置并注册 FDCAN 实例
// (rx_id, tx_id, can_handle 等参数由外部 config 提供,这里只绑定回调和私有指针)
XidiPowerMeter_config->can_config.can_module_callback = XidiPowerMeterDecode;
XidiPowerMeter_config->can_config.id = power_meter_instance;
// 注册FDCAN实例
power_meter_instance->can_instance = CANRegister(&can_config);
if (power_meter_instance->can_instance == NULL)
power_meter_instance->fdcan_ins = CANRegister(&XidiPowerMeter_config->can_config);
if (power_meter_instance->fdcan_ins == NULL)
{
free(power_meter_instance);
power_meter_instance = NULL;
return NULL;
}
//注册守护进程
Daemon_Init_Config_s daemon_config = {
.callback = PowerMeterLostCallback,
.owner_id = power_meter_instance,
.reload_count = 5, // 50ms未收到数据则认为丢失 (1000Hz发送5个周期)
};
power_meter_instance->daemon = DaemonRegister(&daemon_config);
// 4. 配置并注册 守护进程
// (reload_count 等参数由外部 config 提供,这里只绑定回调和私有指针)
XidiPowerMeter_config->daemon_config.callback = XidiPowerMeterLostCallback;
XidiPowerMeter_config->daemon_config.owner_id = power_meter_instance;
power_meter_instance->daemon = DaemonRegister(&XidiPowerMeter_config->daemon_config);
return power_meter_instance;
}
@@ -120,11 +114,11 @@ PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle)
* @param power_meter 功率计实例指针
* @return float 电压值 (V)
*/
float PowerMeterGetVoltage(PowerMeterInstance *power_meter)
float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.voltage;
return power_meter->powermeter_msg.voltage;
}
/**
@@ -132,11 +126,11 @@ float PowerMeterGetVoltage(PowerMeterInstance *power_meter)
* @param power_meter 功率计实例指针
* @return float 电流值 (A)
*/
float PowerMeterGetCurrent(PowerMeterInstance *power_meter)
float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.current;
return power_meter->powermeter_msg.current;
}
/**
@@ -144,11 +138,11 @@ float PowerMeterGetCurrent(PowerMeterInstance *power_meter)
* @param power_meter 功率计实例指针
* @return float 功率值 (W)
*/
float PowerMeterGetPower(PowerMeterInstance *power_meter)
float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.power;
return power_meter->powermeter_msg.power;
}
/**
@@ -156,22 +150,22 @@ float PowerMeterGetPower(PowerMeterInstance *power_meter)
* @param power_meter 功率计实例指针
* @return float 累计能量 (J)
*/
float PowerMeterGetEnergy(PowerMeterInstance *power_meter)
float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter)
{
if (power_meter == NULL)
return 0.0f;
return power_meter->measure.energy;
return power_meter->powermeter_msg.energy;
}
/**
* @brief 重置累计能量
* @param power_meter 功率计实例指针
*/
void PowerMeterResetEnergy(PowerMeterInstance *power_meter)
void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter)
{
if (power_meter != NULL)
{
power_meter->measure.energy = 0.0f;
power_meter->powermeter_msg.energy = 0.0f;
}
}
@@ -179,7 +173,7 @@ void PowerMeterResetEnergy(PowerMeterInstance *power_meter)
* @brief 获取功率计实例(用于外部访问)
* @return PowerMeterInstance* 功率计实例指针
*/
PowerMeterInstance *GetPowerMeterInstance(void)
XidiPowerMeterInstance *GetXidiPowerMeterInstance(void)
{
return power_meter_instance;
}

View File

@@ -19,34 +19,40 @@ typedef struct
float energy; // 累计能量 (J)
uint32_t update_cnt; // 更新计数器
float dt; // 更新时间间隔
} PowerMeter_Measure_s;
} XidiPowerMeter_Msg_s;
/* 功率计实例结构 */
typedef struct
{
FDCANInstance *can_instance; // FDCAN实例指针
PowerMeter_Measure_s measure; // 测量数据
FDCANInstance *fdcan_ins; // FDCAN实例指针
XidiPowerMeter_Msg_s powermeter_msg; // 测量数据
Daemon_Instance *daemon; // 守护进程
uint32_t feed_cnt; // 喂狗计数器
} PowerMeterInstance;
} XidiPowerMeterInstance;
/* 功率计初始化配置 */
typedef struct {
FDCAN_Init_Config_s can_config;
Daemon_Init_Config_s daemon_config;
} XidiPowerMeter_Init_Config_s;
/* 函数声明 */
PowerMeterInstance *PowerMeterInit(FDCAN_HandleTypeDef *can_handle);
XidiPowerMeterInstance *XidiPowerMeterInit(XidiPowerMeter_Init_Config_s *XidiPowerMeter_config);
void PowerMeterDecode(FDCANInstance *instance);
void XidiPowerMeterDecode(FDCANInstance *_instance);
void PowerMeterLostCallback(void *power_meter_ptr);
void XidiPowerMeterLostCallback(void *power_meter_ptr);
float PowerMeterGetVoltage(PowerMeterInstance *power_meter);
float XidiPowerMeterGetVoltage(XidiPowerMeterInstance *power_meter);
float PowerMeterGetCurrent(PowerMeterInstance *power_meter);
float XidiPowerMeterGetCurrent(XidiPowerMeterInstance *power_meter);
float PowerMeterGetPower(PowerMeterInstance *power_meter);
float XidiPowerMeterGetPower(XidiPowerMeterInstance *power_meter);
float PowerMeterGetEnergy(PowerMeterInstance *power_meter);
float XidiPowerMeterGetEnergy(XidiPowerMeterInstance *power_meter);
void PowerMeterResetEnergy(PowerMeterInstance *power_meter);
void XidiPowerMeterResetEnergy(XidiPowerMeterInstance *power_meter);
PowerMeterInstance *GetPowerMeterInstance(void);
XidiPowerMeterInstance *GetPowerMeterInstance(void);
#endif //TRONONEH7_SCAFFOLD_XIDIPWMETER_H

View File

@@ -8,7 +8,7 @@
// ==================== 2. 定义局部指针 ====================
static PowerMeterInstance *chassis_power_meter; // 功率计实例指针
static XidiPowerMeterInstance *chassis_power_meter; // 功率计实例指针
// 存放读取到的功率数据(也可以直接放进发给底盘的结构体里)
static float current_power_w = 0.0f;
@@ -16,15 +16,34 @@ static float current_voltage_v = 0.0f;
static float current_energy_j = 0.0f;
// ==================== 3. 在初始化函数中注册 ====================
// 1. 定义为静态变量static确保它的内存空间常驻防止底层指针悬垂
static XidiPowerMeter_Init_Config_s xidi_pm_config = {
.can_config = {
.can_handle = &hfdcan1, // 原来直接传的句柄,现在放进结构体里
.rx_id = 0x213, // 接收 ID
.tx_id = 0x000, // 发送 ID (不发送填0)
},
.daemon_config = {
.reload_count = 5, // 守护进程超时周期 (例如5次没收到算离线)
}
};
// 2. 初始化任务
void RobotCMDInit()
{
chassis_power_meter = PowerMeterInit(&hfdcan1);
// 传入配置结构体的地址,而不是直接传 hfdcan1
chassis_power_meter = XidiPowerMeterInit(&xidi_pm_config);
if (chassis_power_meter == NULL)
{
LOGERROR("[CMD] Power Meter Init Failed!");
}
else
{
// 建议加一句成功日志,方便上机调试时确认
LOGINFO("[CMD] Power Meter Init Success!");
}
}
// ==================== 4. 在控制任务中读取使用 ====================
void CmdTask()
{
@@ -33,9 +52,9 @@ void CmdTask()
{
if (chassis_power_meter != NULL)
{
current_power_w = PowerMeterGetPower(chassis_power_meter);
current_voltage_v = PowerMeterGetVoltage(chassis_power_meter);
current_energy_j = PowerMeterGetEnergy(chassis_power_meter);
current_power_w = XidiPowerMeterGetPower(chassis_power_meter);
current_voltage_v = XidiPowerMeterGetVoltage(chassis_power_meter);
current_energy_j = XidiPowerMeterGetEnergy(chassis_power_meter);
// 你可以将获取到的功率写入要发送给底盘的 cmd 中,例如限制最大速度
// chassis_cmd_send.real_power = current_power_w;

View File

@@ -3,25 +3,26 @@
OpenDocument="main.c", FilePath="/home/tuxmonkey/CLionProjects/tronone-h7-scaffold/Core/Src/main.c", Line=0
OpenToolbar="Debug", Floating=0, x=0, y=0
OpenWindow="Registers 1", DockArea=BOTTOM, x=5, y=0, w=492, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, FilteredItems=[], RefreshRate=1
OpenWindow="Source Files", DockArea=LEFT, x=0, y=0, w=539, h=202, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Source Files", DockArea=LEFT, x=0, y=0, w=539, h=203, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Disassembly", DockArea=BOTTOM, x=0, y=0, w=453, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Break & Tracepoints", DockArea=LEFT, x=0, y=1, w=539, h=293, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VectorCatchIndexMask=254
OpenWindow="Break & Tracepoints", DockArea=LEFT, x=0, y=1, w=539, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VectorCatchIndexMask=254
OpenWindow="Memory 1", DockArea=BOTTOM, x=4, y=0, w=438, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, EditorAddress=0x200003D8
OpenWindow="Global Data", DockArea=RIGHT, x=0, y=1, w=561, h=330, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Watched Data 1", DockArea=LEFT, x=0, y=2, w=539, h=146, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Global Data", DockArea=RIGHT, x=0, y=1, w=561, h=329, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Watched Data 1", DockArea=LEFT, x=0, y=2, w=539, h=153, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Functions", DockArea=BOTTOM, x=3, y=0, w=411, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
OpenWindow="Data Sampling", DockArea=BOTTOM, x=1, y=0, w=355, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0, VisibleTab=0, UniformSampleSpacing=0
OpenWindow="Timeline", DockArea=RIGHT, x=0, y=0, w=561, h=312, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=1, CodePaneShown=1, PinCursor="Cursor Movable", TimePerDiv="1 ns / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="355;0", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=1, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="360;-67", CodeGraphLegendShown=1, CodeGraphLegendPosition="369;0"
OpenWindow="Timeline", DockArea=RIGHT, x=0, y=0, w=561, h=313, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=1, DataPaneShown=1, PowerPaneShown=1, CodePaneShown=1, PinCursor="Cursor Movable", TimePerDiv="1 ns / Div", TimeStampFormat="Time", DataGraphDrawAsPoints=0, DataGraphLegendShown=1, DataGraphUniformSampleSpacing=0, DataGraphLegendPosition="355;-67", DataGraphShowNamesAtCursor=0, PowerGraphDrawAsPoints=0, PowerGraphLegendShown=1, PowerGraphAvgFilterTime=Off, PowerGraphAvgFilterLen=Off, PowerGraphUniformSampleSpacing=0, PowerGraphLegendPosition="360;-67", CodeGraphLegendShown=1, CodeGraphLegendPosition="309;0"
OpenWindow="Console", DockArea=BOTTOM, x=2, y=0, w=406, h=285, FilterBarShown=0, TotalValueBarShown=0, ToolBarShown=0
SmartViewPlugin="", Page="", Toolbar="Hidden", Window="SmartView 1"
TableHeader="Global Data", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Location";"Size";"Type";"Scope"], ColWidths=[100;100;100;100;100;364]
TableHeader="Global Data", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Location";"Size";"Type";"Scope"], ColWidths=[100;100;100;100;100;100]
TableHeader="Vector Catches", SortCol="", SortOrder="ASCENDING", VisibleCols=["";"Vector Catch";"Description"], ColWidths=[50;300;500]
TableHeader="Break & Tracepoints", SortCol="None", SortOrder="ASCENDING", VisibleCols=["";"Type";"Location";"Extras"], ColWidths=[100;100;100;239]
TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1435;100;100;100;231]
TableHeader="Source Files", SortCol="File", SortOrder="ASCENDING", VisibleCols=["File";"Status";"Size";"#Insts";"Path"], ColWidths=[225;100;100;100;875]
TableHeader="Functions", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Address";"Size";"#Insts";"Source"], ColWidths=[1435;100;100;100;100]
TableHeader="Source Files", SortCol="File", SortOrder="ASCENDING", VisibleCols=["File";"Status";"Size";"#Insts";"Path"], ColWidths=[225;100;100;100;100]
TableHeader="Data Sampling Table", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time"], ColWidths=[100;100]
TableHeader="Data Sampling Setup", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Type";"Value";"Min";"Max";"Average";"# Changes";"Min. Change";"Max. Change"], ColWidths=[126;100;100;100;100;100;100;100;100]
TableHeader="Power Sampling", SortCol="None", SortOrder="ASCENDING", VisibleCols=["Index";"Time";"Ch 0"], ColWidths=[100;100;100]
TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[100;105;287]
TableHeader="Registers 1", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Description"], ColWidths=[100;105;271]
TableHeader="Watched Data 1", SortCol="Expression", SortOrder="ASCENDING", VisibleCols=["Expression";"Value";"Location";"Refresh"], ColWidths=[170;100;100;169]
TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[]
TableHeader="RegisterSelectionDialog", SortCol="None", SortOrder="ASCENDING", VisibleCols=[], ColWidths=[]
TableHeader="TargetExceptionDialog", SortCol="Name", SortOrder="ASCENDING", VisibleCols=["Name";"Value";"Address";"Description"], ColWidths=[26;26;26;26]