Stimulate/main/ecg_generator.c

158 lines
5.7 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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;
}