feat(adc): 优化 AD7124 数据采集和处理

- 修改数据结构,增加异常值检测和处理功能
- 添加信号丢失检测和芯片状态监控
- 优化滤波算法,提高数据准确性
- 调整采样间隔,提高响应速度
- 修复 TCP 服务器数据传输问题
- 优化 AD7124 驱动接口
This commit is contained in:
qiuxin 2025-06-06 17:18:42 +08:00
parent ce8cadd2bb
commit 90e512ef8c
4 changed files with 339 additions and 92 deletions

View File

@ -168,11 +168,35 @@ DMA_HandleTypeDef hdma_uart6_rx; // UART6接收DMA句柄
DMA_HandleTypeDef hdma_uart6_tx; // UART6发送DMA句柄
// ADC滤波相关定义
#define ADC_FILTER_COUNT 4 // 减少滤波点数从10改为4加快响应速度
#define ADC_FILTER_COUNT 2 // 保持2点滤波
#define ADC_CHANNEL_MAX AD7124_CHANNEL_EN_MAX // 通道数量
#define ADC_STARTUP_SAMPLES 20 // 启动时的快速采样次数
#define ADC_STARTUP_INTERVAL 1 // 启动时的采样间隔(ms)
#define ADC_NORMAL_INTERVAL 5 // 正常采样间隔(ms)
#define ADC_NORMAL_INTERVAL 2 // 正常采样间隔(ms)
#define ADC_NOISE_THRESHOLD 100 // 噪声阈值
#define ADC_CALIBRATION_SAMPLES 20 // 零点校准采样次数
#define ADC_MAX_VALID_VALUE 0x7FFFFF // 最大有效值
#define ADC_MIN_VALID_VALUE -0x7FFFFF // 最小有效值
#define ADC_MAX_DIFF 0x400000 // 最大允许差值
#define ADC_INVALID_COUNT_MAX 10 // 最大连续无效值计数
#define ADC_HIGH_CHANNEL_START 22 // 高值通道起始编号
#define ADC_HIGH_CHANNEL_THRESHOLD 0x00A00000 // 高值通道的预期最小值
#define ADC_HIGH_CHANNEL_MAX_DIFF 0x00200000 // 高值通道的最大允许差值
// 添加通道分组定义
#define ADC_LOW_CHANNEL_MAX_DIFF 0x100000 // 低值通道的最大允许差值
#define ADC_LOW_CHANNEL_THRESHOLD 0x100000 // 低值通道的噪声阈值
// 添加信号检测相关定义
#define ADC_SIGNAL_LOST_THRESHOLD 0x1000 // 信号消失阈值
#define ADC_SIGNAL_LOST_COUNT_MAX 5 // 信号消失计数阈值
#define ADC_ZERO_THRESHOLD 0x1000 // 零点阈值
// 添加信号状态跟踪变量
static uint8_t adc1_signal_lost_count[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的信号消失计数
static uint8_t adc2_signal_lost_count[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的信号消失计数
static uint8_t adc1_signal_valid[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的信号有效标志
static uint8_t adc2_signal_valid[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的信号有效标志
// 为每个ADC设备创建缓冲区
static int32_t adc1_buffer[ADC_CHANNEL_MAX][ADC_FILTER_COUNT]; // 第一个AD7124的缓冲区
@ -181,7 +205,82 @@ static uint8_t adc1_buffer_index[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的
static uint8_t adc2_buffer_index[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的缓冲区索引
static int32_t adc1_filtered_data[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的滤波后数据
static int32_t adc2_filtered_data[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的滤波后数据
static int32_t adc1_zero_offset[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的零点偏移
static int32_t adc2_zero_offset[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的零点偏移
static int32_t adc1_last_valid[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的上次有效值
static int32_t adc2_last_valid[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的上次有效值
static uint8_t adc1_invalid_count[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的连续无效值计数
static uint8_t adc2_invalid_count[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的连续无效值计数
static uint8_t adc_startup_count = 0; // 启动采样计数器
static uint8_t adc_calibration_count = 0; // 校准计数器
static uint8_t adc_calibration_done = 0; // 校准完成标志
// 添加芯片状态检测相关定义
#define ADC_CHIP_ERROR_COUNT_MAX 5 // 芯片错误计数阈值
#define ADC_CHIP_RESET_INTERVAL 1000 // 芯片复位间隔(ms)
#define ADC_CHIP_CHECK_INTERVAL 100 // 芯片状态检查间隔(ms)
#define ADC_ABNORMAL_VALUE_THRESHOLD 0x100000 // 异常值阈值
// 添加芯片状态跟踪变量
static uint8_t adc1_error_count = 0; // 第一个AD7124的错误计数
static uint8_t adc2_error_count = 0; // 第二个AD7124的错误计数
static uint32_t adc1_last_reset_time = 0; // 第一个AD7124的最后复位时间
static uint32_t adc2_last_reset_time = 0; // 第二个AD7124的最后复位时间
static uint8_t adc1_chip_valid = 1; // 第一个AD7124的有效标志
static uint8_t adc2_chip_valid = 1; // 第二个AD7124的有效标志
// 添加异常值检测变量
static int32_t adc1_abnormal_values[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的异常值记录
static int32_t adc2_abnormal_values[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的异常值记录
static uint8_t adc1_abnormal_count[ADC_CHANNEL_MAX] = {0}; // 第一个AD7124的异常值计数
static uint8_t adc2_abnormal_count[ADC_CHANNEL_MAX] = {0}; // 第二个AD7124的异常值计数
// 芯片复位函数
static void reset_adc_chip(uint8_t device_num) {
if (device_num == 1) {
ad7124_setup(1); // 重新初始化第一个AD7124
adc1_error_count = 0;
adc1_last_reset_time = HAL_GetTick();
adc1_chip_valid = 1;
// 清除异常值记录
memset(adc1_abnormal_values, 0, sizeof(adc1_abnormal_values));
memset(adc1_abnormal_count, 0, sizeof(adc1_abnormal_count));
} else if (device_num == 2) {
ad7124_setup(2); // 重新初始化第二个AD7124
adc2_error_count = 0;
adc2_last_reset_time = HAL_GetTick();
adc2_chip_valid = 1;
// 清除异常值记录
memset(adc2_abnormal_values, 0, sizeof(adc2_abnormal_values));
memset(adc2_abnormal_count, 0, sizeof(adc2_abnormal_count));
}
}
// 检查异常值
static int32_t check_abnormal_value(int32_t new_value, int32_t *abnormal_value, uint8_t *abnormal_count, uint8_t channel) {
// 如果新值与记录的异常值相同
if (new_value == *abnormal_value && new_value != 0) {
(*abnormal_count)++;
if (*abnormal_count >= ADC_INVALID_COUNT_MAX) {
// 连续多次出现相同的异常值,认为是有效值
return new_value;
}
return 0; // 返回0表示这是异常值
}
// 如果新值与记录的异常值不同
if (abs(new_value - *abnormal_value) < ADC_ABNORMAL_VALUE_THRESHOLD) {
// 新值接近异常值,更新异常值记录
*abnormal_value = new_value;
*abnormal_count = 1;
return 0; // 返回0表示这是异常值
}
// 新值正常,清除异常值记录
*abnormal_value = 0;
*abnormal_count = 0;
return new_value;
}
/* USER CODE END Variables */
@ -447,66 +546,178 @@ void start_adc_task(void const *argument)
memset(adc2_buffer_index, 0, sizeof(adc2_buffer_index));
memset(adc1_filtered_data, 0, sizeof(adc1_filtered_data));
memset(adc2_filtered_data, 0, sizeof(adc2_filtered_data));
memset(adc1_zero_offset, 0, sizeof(adc1_zero_offset));
memset(adc2_zero_offset, 0, sizeof(adc2_zero_offset));
memset(adc1_last_valid, 0, sizeof(adc1_last_valid));
memset(adc2_last_valid, 0, sizeof(adc2_last_valid));
memset(adc1_invalid_count, 0, sizeof(adc1_invalid_count));
memset(adc2_invalid_count, 0, sizeof(adc2_invalid_count));
adc_startup_count = 0;
adc_calibration_count = 0;
adc_calibration_done = 0;
// 初始化信号状态跟踪变量
memset(adc1_signal_lost_count, 0, sizeof(adc1_signal_lost_count));
memset(adc2_signal_lost_count, 0, sizeof(adc2_signal_lost_count));
memset(adc1_signal_valid, 0, sizeof(adc1_signal_valid));
memset(adc2_signal_valid, 0, sizeof(adc2_signal_valid));
// 初始化芯片状态跟踪变量
adc1_error_count = 0;
adc2_error_count = 0;
adc1_last_reset_time = 0;
adc2_last_reset_time = 0;
adc1_chip_valid = 1;
adc2_chip_valid = 1;
memset(adc1_abnormal_values, 0, sizeof(adc1_abnormal_values));
memset(adc2_abnormal_values, 0, sizeof(adc2_abnormal_values));
memset(adc1_abnormal_count, 0, sizeof(adc1_abnormal_count));
memset(adc2_abnormal_count, 0, sizeof(adc2_abnormal_count));
/* Infinite loop */
for (;;)
{
// 启动时的快速采样模式
if (adc_startup_count < ADC_STARTUP_SAMPLES) {
// 快速采样所有通道
for (uint8_t ch = AD7124_AIN0; ch < AD7124_CHANNEL_EN_MAX; ch++) {
// 第一个AD7124
ad7124_get_analog(ch, 1);
adc1_buffer[ch][adc1_buffer_index[ch]] = ad7124_analog[ch].data;
adc1_buffer_index[ch] = (adc1_buffer_index[ch] + 1) % ADC_FILTER_COUNT;
uint32_t current_time = HAL_GetTick();
// 第二个AD7124
ad7124_get_analog(ch, 2);
adc2_buffer[ch][adc2_buffer_index[ch]] = ad7124_analog2[ch].data;
adc2_buffer_index[ch] = (adc2_buffer_index[ch] + 1) % ADC_FILTER_COUNT;
// 检查芯片状态
if (current_time - adc1_last_reset_time > ADC_CHIP_RESET_INTERVAL) {
if (adc1_error_count >= ADC_CHIP_ERROR_COUNT_MAX) {
reset_adc_chip(1); // 复位第一个AD7124
}
}
if (current_time - adc2_last_reset_time > ADC_CHIP_RESET_INTERVAL) {
if (adc2_error_count >= ADC_CHIP_ERROR_COUNT_MAX) {
reset_adc_chip(2); // 复位第二个AD7124
}
adc_startup_count++;
vTaskDelay(ADC_STARTUP_INTERVAL); // 启动时使用更短的采样间隔
continue;
}
// 正常采样模式
for (uint8_t ch = AD7124_AIN0; ch < AD7124_CHANNEL_EN_MAX; ch++) {
// 第一个AD7124
ad7124_get_analog(ch, 1);
adc1_buffer[ch][adc1_buffer_index[ch]] = ad7124_analog[ch].data;
adc1_buffer_index[ch] = (adc1_buffer_index[ch] + 1) % ADC_FILTER_COUNT;
// 计算平均值
int64_t sum = 0;
for (uint8_t i = 0; i < ADC_FILTER_COUNT; i++) {
sum += adc1_buffer[ch][i];
if (adc1_chip_valid) {
int32_t raw_data = ad7124_get_analog(ch, 1);
if (raw_data < 0) { // 读取失败
adc1_error_count++;
if (adc1_error_count >= ADC_CHIP_ERROR_COUNT_MAX) {
adc1_chip_valid = 0; // 标记芯片无效
ad7124_analog[ch].base.data = 0; // 输出0值
continue;
}
adc1_filtered_data[ch] = (int32_t)(sum / ADC_FILTER_COUNT);
} else {
adc1_error_count = 0; // 重置错误计数
// 更新滤波后的数据
ad7124_analog[ch].data = adc1_filtered_data[ch];
// 检查异常值
int32_t valid_value = check_abnormal_value(raw_data,
&adc1_abnormal_values[ch],
&adc1_abnormal_count[ch],
ch);
if (valid_value != 0) { // 不是异常值
// 检查信号是否消失
if (abs(valid_value - adc1_zero_offset[ch]) < ADC_SIGNAL_LOST_THRESHOLD) {
adc1_signal_lost_count[ch]++;
if (adc1_signal_lost_count[ch] >= ADC_SIGNAL_LOST_COUNT_MAX) {
adc1_signal_valid[ch] = 0;
adc1_filtered_data[ch] = 0;
ad7124_analog[ch].base.data = 0;
continue;
}
} else {
adc1_signal_lost_count[ch] = 0;
adc1_signal_valid[ch] = 1;
}
// 正常数据处理
if (adc1_signal_valid[ch]) {
int32_t max_diff = (ch >= ADC_HIGH_CHANNEL_START) ?
ADC_HIGH_CHANNEL_MAX_DIFF :
ADC_LOW_CHANNEL_MAX_DIFF;
if (abs(valid_value - adc1_last_valid[ch]) > max_diff) {
if (adc1_last_valid[ch] == 0) {
adc1_last_valid[ch] = valid_value;
} else {
valid_value = adc1_last_valid[ch];
}
} else {
adc1_last_valid[ch] = valid_value;
}
adc1_buffer[ch][adc1_buffer_index[ch]] = valid_value;
adc1_buffer_index[ch] = (adc1_buffer_index[ch] + 1) % ADC_FILTER_COUNT;
adc1_filtered_data[ch] = (adc1_buffer[ch][0] + adc1_buffer[ch][1]) / 2;
ad7124_analog[ch].base.data = adc1_filtered_data[ch];
}
} else {
ad7124_analog[ch].base.data = 0; // 异常值输出0
}
}
}
// 第二个AD7124
for (uint8_t ch = AD7124_AIN0; ch < AD7124_CHANNEL_EN_MAX; ch++) {
ad7124_get_analog(ch, 2);
adc2_buffer[ch][adc2_buffer_index[ch]] = ad7124_analog2[ch].data;
if (adc2_chip_valid) {
int32_t raw_data = ad7124_get_analog(ch, 2);
if (raw_data < 0) { // 读取失败
adc2_error_count++;
if (adc2_error_count >= ADC_CHIP_ERROR_COUNT_MAX) {
adc2_chip_valid = 0; // 标记芯片无效
ad7124_analog2[ch].base.data = 0; // 输出0值
continue;
}
} else {
adc2_error_count = 0; // 重置错误计数
// 检查异常值
int32_t valid_value = check_abnormal_value(raw_data,
&adc2_abnormal_values[ch],
&adc2_abnormal_count[ch],
ch);
if (valid_value != 0) { // 不是异常值
// 检查信号是否消失
if (abs(valid_value - adc2_zero_offset[ch]) < ADC_SIGNAL_LOST_THRESHOLD) {
adc2_signal_lost_count[ch]++;
if (adc2_signal_lost_count[ch] >= ADC_SIGNAL_LOST_COUNT_MAX) {
adc2_signal_valid[ch] = 0;
adc2_filtered_data[ch] = 0;
ad7124_analog2[ch].base.data = 0;
continue;
}
} else {
adc2_signal_lost_count[ch] = 0;
adc2_signal_valid[ch] = 1;
}
// 正常数据处理
if (adc2_signal_valid[ch]) {
int32_t max_diff = (ch >= ADC_HIGH_CHANNEL_START) ?
ADC_HIGH_CHANNEL_MAX_DIFF :
ADC_LOW_CHANNEL_MAX_DIFF;
if (abs(valid_value - adc2_last_valid[ch]) > max_diff) {
if (adc2_last_valid[ch] == 0) {
adc2_last_valid[ch] = valid_value;
} else {
valid_value = adc2_last_valid[ch];
}
} else {
adc2_last_valid[ch] = valid_value;
}
adc2_buffer[ch][adc2_buffer_index[ch]] = valid_value;
adc2_buffer_index[ch] = (adc2_buffer_index[ch] + 1) % ADC_FILTER_COUNT;
// 计算平均值
int64_t sum = 0;
for (uint8_t i = 0; i < ADC_FILTER_COUNT; i++) {
sum += adc2_buffer[ch][i];
adc2_filtered_data[ch] = (adc2_buffer[ch][0] + adc2_buffer[ch][1]) / 2;
ad7124_analog2[ch].base.data = adc2_filtered_data[ch];
}
} else {
ad7124_analog2[ch].base.data = 0; // 异常值输出0
}
}
}
adc2_filtered_data[ch] = (int32_t)(sum / ADC_FILTER_COUNT);
// 更新滤波后的数据
ad7124_analog2[ch].data = adc2_filtered_data[ch];
}
vTaskDelay(ADC_NORMAL_INTERVAL); // 使用更短的正常采样间隔
vTaskDelay(ADC_NORMAL_INTERVAL);
}
/* USER CODE END start_adc_task */
}

View File

@ -431,17 +431,17 @@ uint16_t handle_type_87(const uint8_t *body, uint16_t body_len, uint8_t *tx)
// 填充第一个AD7124原始数据到tx[13]~tx[76]每通道4字节MSB格式
extern ad7124_analog_t ad7124_analog[AD7124_CHANNEL_EN_MAX];
for (int ch = 0; ch < AD7124_CHANNEL_EN_MAX; ++ch) {
int32_t data = ad7124_analog[ch].data;
int32_t data = ad7124_analog[ch].base.data; // 使用base.data访问数据
tx[13 + ch * 4 + 0] = (data >> 24) & 0xFF;
tx[13 + ch * 4 + 1] = (data >> 16) & 0xFF;
tx[13 + ch * 4 + 2] = (data >> 8) & 0xFF;
tx[13 + ch * 4 + 3] = (data) & 0xFF;
}
// 填充第二个AD7124原始数据到tx[77]~tx[140]每通道4字节MSB格式
extern ad7124_analog_t ad7124_analog2[AD7124_CHANNEL_EN_MAX];
// 填充第二个AD7124原始数据到tx[77]~tx[140]每通道4字节MSB格式,通道序号反序
extern ad7124_analog2_t ad7124_analog2[AD7124_CHANNEL_EN_MAX];
for (int ch = 0; ch < AD7124_CHANNEL_EN_MAX; ++ch) {
int32_t data = ad7124_analog2[ch].data;
int32_t data = ad7124_analog2[AD7124_CHANNEL_EN_MAX - 1 - ch].base.data; // 使用base.data访问数据
tx[77 + ch * 4 + 0] = (data >> 24) & 0xFF;
tx[77 + ch * 4 + 1] = (data >> 16) & 0xFF;
tx[77 + ch * 4 + 2] = (data >> 8) & 0xFF;

View File

@ -434,28 +434,50 @@ int32_t ad7124_read_data(uint8_t device_num)
return read_data;
}
void ad7124_get_analog(uint8_t channel_nr, uint8_t device_num)
int32_t ad7124_get_analog(uint8_t channel_nr, uint8_t device_num)
{
int32_t read_data;
int32_t read_data = 0;
ad7124_base_t *analog; // 使用基础结构体指针
ad7124_st_reg_t *regs = (device_num == 1) ? ad7124_regs : ad7124_regs2;
ad7124_st_reg_t *channel_regs = (device_num == 1) ? ad7124_channel_regs : ad7124_channel_regs2;
ad7124_analog_t *analog = (device_num == 1) ? ad7124_analog : ad7124_analog2;
// 根据设备号选择正确的数据数组
if (device_num == 1) {
analog = &ad7124_analog[channel_nr].base;
} else if (device_num == 2) {
analog = &ad7124_analog2[channel_nr].base;
} else {
return -1; // 无效的设备号
}
// 配置通道寄存器
regs[AD7124_CHANNEL_0].value = channel_regs[channel_nr].value;
ad7124_write_register(&regs[AD7124_CHANNEL_0], device_num);
if (ad7124_write_register(&regs[AD7124_CHANNEL_0], device_num) < 0) {
return -2; // 写寄存器失败
}
while (ad7124_wait_for_conv_ready(AD7124_RDY, device_num));
analog[channel_nr].channel = channel_nr;
// 等待转换完成
if (ad7124_wait_for_conv_ready(AD7124_RDY, device_num) < 0) {
return -3; // 等待转换超时
}
// 读取数据
read_data = ad7124_read_data(device_num);
analog[channel_nr].data = read_data;
//analog[channel_nr].voltage = (float)(read_data * VREF / GAIN / AD_CODE);
if (read_data < 0) {
return read_data; // 返回错误码
}
// 更新数据结构
analog->channel = channel_nr;
analog->data = read_data;
// 清除通道寄存器
regs[AD7124_CHANNEL_0].value = 0;
ad7124_write_register(&regs[AD7124_CHANNEL_0], device_num);
return read_data;
}
/**
* @brief AD7124设备
*

View File

@ -263,13 +263,27 @@ typedef enum
AD7124_CHANNEL_EN_MAX,
} ad7124_channel_e; // 该项目所使用的通道
typedef struct
{
// 基础采样数据结构
typedef struct {
uint8_t channel;
int32_t data; // 采样数据
} ad7124_base_t;
// 第一个AD7124的完整数据结构
typedef struct {
ad7124_base_t base;
float voltage; // 电压值
float current; // 电流值
} ad7124_analog_t; // 采样数据结构体
// 可以添加第一个芯片特有的属性
} ad7124_analog_t;
// 第二个AD7124的完整数据结构
typedef struct {
ad7124_base_t base;
float voltage; // 电压值
float current; // 电流值
// 可以添加第二个芯片特有的属性
} ad7124_analog2_t;
#define AD7124_CRC8_POLYNOMIAL_REPRESENTATION 0x07 /* x8 + x2 + x + 1 */
#define AD7124_DISABLE_CRC 0 // 默认关闭校验
@ -309,7 +323,7 @@ int32_t ad7124_wait_for_conv_ready(uint32_t timeout, uint8_t device_num); // 等
/*! Reads the conversion result from the device. */
int32_t ad7124_read_data(uint8_t device_num);
void ad7124_get_analog(uint8_t channel_nr, uint8_t device_num);
int32_t ad7124_get_analog(uint8_t channel_nr, uint8_t device_num); // 修改返回类型为int32_t
/*! Initializes the AD7124. */
int32_t ad7124_setup(uint8_t device_num);