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

View File

@@ -19,34 +19,40 @@ typedef struct
float energy; // 累计能量 (J) float energy; // 累计能量 (J)
uint32_t update_cnt; // 更新计数器 uint32_t update_cnt; // 更新计数器
float dt; // 更新时间间隔 float dt; // 更新时间间隔
} PowerMeter_Measure_s; } XidiPowerMeter_Msg_s;
/* 功率计实例结构 */ /* 功率计实例结构 */
typedef struct typedef struct
{ {
FDCANInstance *can_instance; // FDCAN实例指针 FDCANInstance *fdcan_ins; // FDCAN实例指针
PowerMeter_Measure_s measure; // 测量数据 XidiPowerMeter_Msg_s powermeter_msg; // 测量数据
Daemon_Instance *daemon; // 守护进程 Daemon_Instance *daemon; // 守护进程
uint32_t feed_cnt; // 喂狗计数器 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 #endif //TRONONEH7_SCAFFOLD_XIDIPWMETER_H

View File

@@ -8,7 +8,7 @@
// ==================== 2. 定义局部指针 ==================== // ==================== 2. 定义局部指针 ====================
static PowerMeterInstance *chassis_power_meter; // 功率计实例指针 static XidiPowerMeterInstance *chassis_power_meter; // 功率计实例指针
// 存放读取到的功率数据(也可以直接放进发给底盘的结构体里) // 存放读取到的功率数据(也可以直接放进发给底盘的结构体里)
static float current_power_w = 0.0f; 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; static float current_energy_j = 0.0f;
// ==================== 3. 在初始化函数中注册 ==================== // ==================== 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() void RobotCMDInit()
{ {
chassis_power_meter = PowerMeterInit(&hfdcan1); // 传入配置结构体的地址,而不是直接传 hfdcan1
chassis_power_meter = XidiPowerMeterInit(&xidi_pm_config);
if (chassis_power_meter == NULL) if (chassis_power_meter == NULL)
{ {
LOGERROR("[CMD] Power Meter Init Failed!"); LOGERROR("[CMD] Power Meter Init Failed!");
} }
else
{
// 建议加一句成功日志,方便上机调试时确认
LOGINFO("[CMD] Power Meter Init Success!");
}
} }
// ==================== 4. 在控制任务中读取使用 ==================== // ==================== 4. 在控制任务中读取使用 ====================
void CmdTask() void CmdTask()
{ {
@@ -33,9 +52,9 @@ void CmdTask()
{ {
if (chassis_power_meter != NULL) if (chassis_power_meter != NULL)
{ {
current_power_w = PowerMeterGetPower(chassis_power_meter); current_power_w = XidiPowerMeterGetPower(chassis_power_meter);
current_voltage_v = PowerMeterGetVoltage(chassis_power_meter); current_voltage_v = XidiPowerMeterGetVoltage(chassis_power_meter);
current_energy_j = PowerMeterGetEnergy(chassis_power_meter); current_energy_j = XidiPowerMeterGetEnergy(chassis_power_meter);
// 你可以将获取到的功率写入要发送给底盘的 cmd 中,例如限制最大速度 // 你可以将获取到的功率写入要发送给底盘的 cmd 中,例如限制最大速度
// chassis_cmd_send.real_power = current_power_w; // 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 OpenDocument="main.c", FilePath="/home/tuxmonkey/CLionProjects/tronone-h7-scaffold/Core/Src/main.c", Line=0
OpenToolbar="Debug", Floating=0, x=0, y=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="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="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="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="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=146, 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="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="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 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" 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="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="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="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;875] 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 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="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="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="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]