Stimulate/main/ecg_generator.c

158 lines
5.7 KiB
C
Raw Normal View History

2025-09-25 18:50:48 +08:00
#include "ecg_generator.h"
#include <math.h>
#include <string.h>
#include "esp_log.h"
// 初始化ECG生成器
void ecg_generator_init(ecg_generator_t *generator, float sample_rate) {
if (generator == NULL) return;
memset(generator, 0, sizeof(ecg_generator_t));
// 设置默认参数
generator->heart_rate = 75.0f; // 心率75次/分
generator->amplitude = 1.0f; // 幅值1.0V
generator->sample_rate = sample_rate;
generator->is_running = false;
// 固定波形参数 (保持正常ECG比例)
generator->p_amp_ratio = 0.2f; // P波幅度比例
generator->q_amp_ratio = 0.3f; // Q波幅度比例
generator->r_amp_ratio = 1.0f; // R波幅度比例
generator->s_amp_ratio = 0.4f; // S波幅度比例
generator->t_amp_ratio = 0.4f; // T波幅度比例
// 固定时间参数 (保持正常ECG时序)
generator->p_width = 0.03f; // P波宽度
generator->qrs_width = 0.01f; // QRS波群宽度
generator->t_width = 0.05f; // T波宽度
}
// 设置心率
void ecg_generator_set_heart_rate(ecg_generator_t *generator, float heart_rate) {
if (generator == NULL) return;
// 限制心率范围
if (heart_rate < 30.0f) heart_rate = 30.0f;
if (heart_rate > 200.0f) heart_rate = 200.0f;
generator->heart_rate = heart_rate;
}
// 设置幅值直接输入mV值内部自动转换为DAC输出值
void ecg_generator_set_amplitude(ecg_generator_t *generator, float amplitude_mv) {
if (generator == NULL) return;
// 硬件衰减系数约38倍 (根据实际测量0.132V → 5mV)
// 对应关系amplitude(V) × 38 ≈ 示波器显示值(mV)
const float attenuation_factor = 38.0f;
// 将mV除以衰减系数得到DAC输出值
float dac_amplitude = amplitude_mv / attenuation_factor;
generator->amplitude = dac_amplitude;
}
// 开始生成
void ecg_generator_start(ecg_generator_t *generator) {
if (generator == NULL) return;
generator->is_running = true;
generator->sample_count = 0;
}
// 停止生成
void ecg_generator_stop(ecg_generator_t *generator) {
if (generator == NULL) return;
generator->is_running = false;
}
// 重置生成器
void ecg_generator_reset(ecg_generator_t *generator) {
if (generator == NULL) return;
generator->sample_count = 0;
}
// 获取下一个样本 - 修正时间参数为相对比例
float ecg_generator_get_next_sample(ecg_generator_t *generator) {
if (generator == NULL || !generator->is_running) {
return 0.0f;
}
// 计算RR间期 (秒)
float rr_interval = 60.0f / generator->heart_rate;
// 计算当前时间
float t = (float)generator->sample_count / generator->sample_rate;
// 周期内时间
float t_mod = fmodf(t, rr_interval);
// 归一化时间到0-1范围相对于RR间期的比例
float t_norm = t_mod / rr_interval;
// 计算各波幅度
float p_amp = generator->amplitude * generator->p_amp_ratio;
float q_amp = generator->amplitude * generator->q_amp_ratio;
float r_amp = generator->amplitude * generator->r_amp_ratio;
float s_amp = generator->amplitude * generator->s_amp_ratio;
float t_amp = generator->amplitude * generator->t_amp_ratio;
// 时间参数相对于RR间期的比例 - 根据Python代码修正
float p_time_ratio = 0.125f; // P波位置12.5%
float q_time_ratio = 0.3125f; // Q波位置31.25%
float r_time_ratio = 0.3375f; // R波位置33.75%
float s_time_ratio = 0.3625f; // S波位置36.25%
float t_time_ratio = 0.625f; // T波位置62.5%
// 宽度参数相对于RR间期的比例 - 修正QRS宽度使其充分重叠
float p_width_ratio = 0.0375f; // P波宽度0.03/0.8 = 3.75%
float qrs_width_ratio = 0.0125f; // QRS宽度增加到2.5%确保Q、R、S充分重叠
float t_width_ratio = 0.0625f; // T波宽度0.05/0.8 = 6.25%
// P波 - 修正后的计算
float p = p_amp * expf(-(t_norm - p_time_ratio) * (t_norm - p_time_ratio) / (2.0f * p_width_ratio * p_width_ratio));
// QRS波群 - 修正后的计算
float q = -q_amp * expf(-(t_norm - q_time_ratio) * (t_norm - q_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
float r = r_amp * expf(-(t_norm - r_time_ratio) * (t_norm - r_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
float s = -s_amp * expf(-(t_norm - s_time_ratio) * (t_norm - s_time_ratio) / (2.0f * qrs_width_ratio * qrs_width_ratio));
float qrs = q + r + s;
// T波 - 修正后的计算
float t_wave = t_amp * expf(-(t_norm - t_time_ratio) * (t_norm - t_time_ratio) / (2.0f * t_width_ratio * t_width_ratio));
// 组合波形
float ecg_value = p + qrs + t_wave;
// 调试信息每1000个样本输出一次最大值
static float max_ecg_value = 0.0f;
static uint32_t debug_counter = 0;
debug_counter++;
if (fabsf(ecg_value) > max_ecg_value) {
max_ecg_value = fabsf(ecg_value);
}
if (debug_counter >= 1000) {
ESP_LOGI("ECG_DEBUG", "Max ECG value before offset: %.3fV", max_ecg_value);
debug_counter = 0;
max_ecg_value = 0.0f;
}
// 添加偏置电压将ECG波形平移到DAC有效范围
// ECG波形范围约为 -amplitude 到 +amplitude
// 需要平移到 0 到 2*amplitude然后限制在DAC范围内
float offset = generator->amplitude; // 偏置电压
ecg_value = ecg_value + offset;
// 限制在DAC有效范围内 (0V 到 2.048V)
if (ecg_value < 0.0f) ecg_value = 0.0f;
if (ecg_value > 2.048f) ecg_value = 2.048f;
generator->sample_count++;
return ecg_value;
}