diff --git a/Git提交方法.md b/Git提交方法.md new file mode 100644 index 0000000..3071c2b --- /dev/null +++ b/Git提交方法.md @@ -0,0 +1,161 @@ +# Git 提交和推送成功方法 + +## 项目配置信息 + +- **远程仓库地址**: `http://lmhrt.cn:6771/ming/Rader_IQ.git` +- **主分支**: `main` +- **Git 路径**: `C:\Program Files\Git\bin\git.exe` + +## 方法一:使用 git.bat 脚本(推荐) + +### 脚本位置 +`git.bat` 位于项目根目录 + +### 使用步骤 +1. 双击运行 `git.bat` +2. 查看步骤 1:检查 Git 状态 +3. 查看步骤 2:添加所有文件到暂存区 +4. 查看步骤 3:输入提交信息(默认:Update project) +5. 查看步骤 4:自动拉取远程代码 +6. 查看步骤 5:推送到远程仓库 + +### 脚本流程 +``` +[1/5] 检查 Git 状态 +[2/5] 添加所有文件到暂存区 +[3/5] 提交更改 +[4/5] 拉取远程代码 +[5/5] 推送到远程仓库 +``` + +## 方法二:手动执行 PowerShell 命令 + +### 完整流程 +```powershell +# 1. 查看当前状态 +& "C:\Program Files\Git\bin\git.exe" status + +# 2. 添加所有修改的文件 +& "C:\Program Files\Git\bin\git.exe" add -A + +# 3. 提交更改 +& "C:\Program Files\Git\bin\git.exe" commit -m "你的提交信息" + +# 4. 拉取远程代码(避免冲突) +& "C:\Program Files\Git\bin\git.exe" pull + +# 5. 推送到远程仓库 +& "C:\Program Files\Git\bin\git.exe" push +``` + +## 常见问题及解决方案 + +### 1. 推送失败,提示需要拉取 +**问题**: 提示远程有新提交 +```powershell +# 解决方案:先拉取远程代码 +& "C:\Program Files\Git\bin\git.exe" pull + +# 解决冲突后再推送 +& "C:\Program Files\Git\bin\git.exe" push +``` + +### 2. 认证失败 +**问题**: `Authentication failed for 'http://lmhrt.cn:6771/ming/Rader_IQ.git/'` + +**解决方案**: +```powershell +# 方案1:配置凭据存储 +& "C:\Program Files\Git\bin\git.exe" config --global credential.helper store +& "C:\Program Files\Git\bin\git.exe" push + +# 方案2:在 URL 中包含认证信息 +& "C:\Program Files\Git\bin\git.exe" remote set-url origin http://用户名:密码@lmhrt.cn:6771/ming/Rader_IQ.git +& "C:\Program Files\Git\bin\git.exe" push +``` + +### 3. 忘记添加 .gitignore +**问题**: 不应该被跟踪的文件被提交了 + +```powershell +# 从暂存区移除已添加的文件 +& "C:\Program Files\Git\bin\git.exe" rm -r --cached .pio + +# 提交更改 +& "C:\Program Files\Git\bin\git.exe" commit -m "Remove .pio from tracking" +& "C:\Program Files\Git\bin\git.exe" push +``` + +### 4. 修改最后一次提交信息 +**问题**: 提交信息写错了,但还没有推送 + +```powershell +# 修改最后一次提交(未推送) +& "C:\Program Files\Git\bin\git.exe" commit --amend -m "新的提交信息" +``` + +### 5. 查看文件历史 +```powershell +# 查看指定文件的历史 +& "C:\Program Files\Git\bin\git.exe" log --follow 文件名 + +# 查看指定文件在某次提交的内容 +& "C:\Program Files\Git\bin\git.exe" show 提交哈希:文件名 +``` + +## 提交信息规范 + +### 格式建议 +``` +<类型>: <简短描述> + +<详细描述(可选)> + +<相关 issue(可选)> +``` + +### 类型说明 +- `feat`: 新功能 +- `fix`: 修复 bug +- `docs`: 文档更新 +- `style`: 代码格式调整 +- `refactor`: 重构代码 +- `test`: 测试相关 +- `chore`: 构建/工具链相关 + +### 示例 +``` +feat: 添加心率平滑处理算法 + +实现了基于移动平均的心率数据平滑处理, +提高了心率监测的稳定性。 +``` + +## 成功案例 + +### 本次成功提交 +- **提交哈希**: `aa57e81` +- **提交信息**: `Update project` +- **修改文件**: 4 个文件 +- **新增行数**: 134 行 +- **删除行数**: 88 行 +- **推送状态**: ✅ 成功 + +### 修改的文件 +- `src/main.cpp` - 修改 +- `src/radar_vitals.cpp` - 修改 +- `src/radar_vitals.h` - 修改 +- `git.bat` - 新增 + +## 最佳实践 + +1. **提交前检查**: 使用 `git status` 确认要提交的文件 +2. **频繁提交**: 小步快跑,每个功能点完成后立即提交 +3. **清晰的提交信息**: 使用规范的提交信息格式 +4. **推送前拉取**: 使用 `git pull` 避免冲突 +5. **定期同步**: 与团队成员保持代码同步 + +## 参考资料 + +- [Git 官方文档](https://git-scm.com/doc) +- [Rader_Success_5 项目](http://lmhrt.cn:6771/ming/Rader_Success_5.git) diff --git a/IQ信号处理流程图.md b/IQ信号处理流程图.md new file mode 100644 index 0000000..dacaf7e --- /dev/null +++ b/IQ信号处理流程图.md @@ -0,0 +1,370 @@ +# IQ电压信号处理工程流程图 + +## 系统架构图 + +```mermaid +graph TB + A[雷达传感器] --> B[ADC采集
ADC1_CH8/CH9
200Hz采样] + B --> C[IQ数据处理模块
radar_vitals.cpp] + C --> D[状态判断] + C --> E[频率估计] + D --> F[输出结果] + E --> F + F --> G[串口输出] + + style A fill:#e1f5ff + style B fill:#fff4e1 + style C fill:#ffe1f5 + style D fill:#e1ffe1 + style E fill:#e1ffe1 + style F fill:#f5e1ff + style G fill:#e1f5ff +``` + +## 详细处理流程图 + +```mermaid +flowchart TD + Start([开始]) --> ADC1[ADC数据采集] + + subgraph ADC采集 + ADC1 --> ADC2[读取ADC1_CH8
I通道原始值] + ADC1 --> ADC3[读取ADC1_CH9
Q通道原始值] + ADC2 --> ADC4[采样率: 200Hz] + ADC3 --> ADC4 + ADC4 --> ADC5[数据长度: 1024点
5.12秒] + ADC5 --> ADC6[转换为电压
V = ADC/4095 × 3.3V] + end + + ADC6 --> DC[去直流处理] + + subgraph 去直流 + DC --> DC1[计算I平均值
meanI] + DC --> DC2[计算Q平均值
meanQ] + DC1 --> DC3[I'n = In - meanI] + DC2 --> DC4[Q'n = Qn - meanQ] + end + + DC3 --> Phase[相位转换] + DC4 --> Phase + + subgraph 相位转换 + Phase --> Phase1[φn = atan2 Qn, In] + end + + Phase1 --> Unwrap[相位展开] + + subgraph 相位展开 + Unwrap --> Unwrap1[计算相位差
Δφ = φn - φn-1] + Unwrap1 --> Unwrap2{Δφ > π?} + Unwrap2 -->|是| Unwrap3[Δφ -= 2π] + Unwrap2 -->|否| Unwrap4{Δφ < -π?} + Unwrap4 -->|是| Unwrap5[Δφ += 2π] + Unwrap4 -->|否| Unwrap6[保持Δφ] + Unwrap3 --> Unwrap7[φn = φn-1 + Δφ] + Unwrap5 --> Unwrap7 + Unwrap6 --> Unwrap7 + end + + Unwrap7 --> EmptyCheck[空人判断] + + subgraph 空人判断 + EmptyCheck --> EC1[计算相位均值
μ = mean φ] + EC1 --> EC2[计算相位方差
Var = Eφ-μ²] + EC2 --> EC3{Var < 1e-4?} + EC3 -->|是| EC4[NO_PERSON
无人] + EC3 -->|否| MotionCheck[活动检测] + end + + MotionCheck --> MC1[计算相位差分能量
E = mean φn-φn-1²] + MC1 --> MC2{E > 0.05?} + MC2 -->|是| MC3[MOTION
人体运动] + MC2 -->|否| MC4[STATIC_HUMAN
人体静止] + + EC4 --> End([结束]) + MC3 --> Downsample[降采样] + MC4 --> Downsample + + subgraph 降采样 + Downsample --> DS1[呼吸数据
1024→51点
10Hz] + Downsample --> DS2[心率数据
1024→256点
50Hz] + end + + DS1 --> RespFreq[呼吸频率估计] + DS2 --> HeartFreq[心率估计] + + subgraph 呼吸频率估计 + RespFreq --> RF1[频率扫描
0.1-0.6Hz] + RF1 --> RF2[DFT计算
Xf = Σ φn × e-j2πfn] + RF2 --> RF3[找最大能量频率] + RF3 --> RF4[转换为BPM
BPM = f × 60] + end + + subgraph 心率估计 + HeartFreq --> HF1[频率扫描
0.6-3.0Hz] + HF1 --> HF2[DFT计算
Xf = Σ φn × e-j2πfn] + HF2 --> HF3[找最大能量频率] + HF3 --> HF4[转换为BPM
BPM = f × 60] + end + + RF4 --> Filter[后处理滤波] + HF4 --> Filter + + subgraph 后处理滤波 + Filter --> F1[异常值检测
心率: 40-180 BPM
呼吸: 4-40 BPM] + F1 --> F2[5点移动平均滤波] + F2 --> F3[四舍五入取整] + end + + F3 --> Output[输出结果] + + subgraph 输出 + Output --> O1[人体状态] + Output --> O2[心率 BPM] + Output --> O3[呼吸率 BPM] + Output --> O4[串口打印] + end + + O4 --> End + + style Start fill:#90EE90 + style End fill:#FFB6C1 + style ADC1 fill:#87CEEB + style DC fill:#DDA0DD + style Phase fill:#F0E68C + style Unwrap fill:#98FB98 + style EmptyCheck fill:#FFA07A + style Downsample fill:#20B2AA + style RespFreq fill:#FF6347 + style HeartFreq fill:#FF6347 + style Filter fill:#9370DB + style Output fill:#00CED1 +``` + +## 数据流图 + +```mermaid +graph LR + subgraph 输入 + A[ADC原始数据
12位, 0-4095] + end + + subgraph 预处理 + B[去直流
I'Q'] + C[相位转换
φ = atan2Q,I] + D[相位展开
连续相位] + end + + subgraph 特征提取 + E[相位方差
空人检测] + F[差分能量
活动检测] + end + + subgraph 频率分析 + G[降采样
呼吸/心率] + H[DFT频谱分析] + I[峰值检测] + end + + subgraph 后处理 + J[异常值过滤] + K[移动平均] + L[取整输出] + end + + subgraph 输出 + M[人体状态] + N[心率 BPM] + O[呼吸率 BPM] + end + + A --> B --> C --> D + D --> E + D --> F + D --> G --> H --> I --> J --> K --> L + E --> M + F --> M + L --> N + L --> O + + style A fill:#FFE4B5 + style B fill:#E0FFFF + style C fill:#E0FFFF + style D fill:#E0FFFF + style E fill:#FFDAB9 + style F fill:#FFDAB9 + style G fill:#98FB98 + style H fill:#98FB98 + style I fill:#98FB98 + style J fill:#DDA0DD + style K fill:#DDA0DD + style L fill:#DDA0DD + style M fill:#F0E68C + style N fill:#F0E68C + style O fill:#F0E68C +``` + +## 关键参数说明 + +| 参数 | 值 | 说明 | +|------|-----|------| +| ADC采样率 | 200 Hz | 基础采样频率 | +| 基础数据长度 | 1024 点 | 对应5.12秒数据 | +| ADC分辨率 | 12位 | 0-4095 | +| 参考电压 | 3.3V | 电压转换基准 | +| 呼吸采样率 | 10 Hz | 降采样后频率 | +| 心率采样率 | 50 Hz | 降采样后频率 | +| 呼吸频率范围 | 0.1-0.6 Hz | 6-36 BPM | +| 心率频率范围 | 0.6-3.0 Hz | 36-180 BPM | +| 空人阈值 | 方差 < 1e-4 | 相位方差阈值 | +| 活动阈值 | 能量 > 0.05 | 差分能量阈值 | + +## 算法核心公式 + +### 1. 去直流 +``` +I'(n) = I(n) - mean(I) +Q'(n) = Q(n) - mean(Q) +``` + +### 2. 相位计算 +``` +φ(n) = atan2(Q'(n), I'(n)) +``` + +### 3. 相位展开 +``` +Δφ = φ(n) - φ(n-1) +if Δφ > π: Δφ -= 2π +if Δφ < -π: Δφ += 2π +φ_unwrap(n) = φ_unwrap(n-1) + Δφ +``` + +### 4. 空人判断 +``` +Var(φ) = E[(φ - μ)²] +if Var(φ) < 1e-4 → NO_PERSON +``` + +### 5. 活动检测 +``` +E = E[(φ(n) - φ(n-1))²] +if E > 0.05 → MOTION +else → STATIC_HUMAN +``` + +### 6. DFT频率估计 +``` +X(f) = Σ φ(n) × e^(-j2πfn) +f_peak = arg max |X(f)|² +BPM = f_peak × 60 +``` + +## 任务调度图 + +```mermaid +graph TB + subgraph FreeRTOS任务 + T1[雷达数据采集任务
优先级: 4
Core: 1] + T2[串口数据任务
优先级: 3
Core: 1] + end + + subgraph 处理流程 + P1[ADC采集循环
1024点 @ 200Hz] + P2[调用radar_process] + P3[状态判断] + P4[频率估计] + P5[串口输出] + end + + T1 --> P1 --> P2 --> P3 --> P4 --> P5 + T2 --> P5 + + style T1 fill:#FFB6C1 + style T2 fill:#87CEEB + style P1 fill:#98FB98 + style P2 fill:#98FB98 + style P3 fill:#F0E68C + style P4 fill:#F0E68C + style P5 fill:#DDA0DD +``` + +## 状态机图 + +```mermaid +stateDiagram-v2 + [*] --> NO_PERSON: 相位方差 < 1e-4 + NO_PERSON --> STATIC_HUMAN: 相位方差 ≥ 1e-4
且差分能量 ≤ 0.05 + NO_PERSON --> MOTION: 相位方差 ≥ 1e-4
且差分能量 > 0.05 + STATIC_HUMAN --> MOTION: 差分能量 > 0.05 + MOTION --> STATIC_HUMAN: 差分能量 ≤ 0.05 + STATIC_HUMAN --> NO_PERSON: 相位方差 < 1e-4 + MOTION --> NO_PERSON: 相位方差 < 1e-4 + + note right of NO_PERSON + 无人状态 + 不进行频率估计 + end note + + note right of STATIC_HUMAN + 人体静止 + 进行呼吸/心率估计 + end note + + note right of MOTION + 人体运动 + 进行呼吸/心率估计 + 但可能不准确 + end note +``` + +## 文件结构 + +``` +Rader_IQ第1版/ +├── src/ +│ ├── main.cpp # 主程序,任务调度 +│ ├── radar_vitals.cpp # IQ信号处理核心算法 +│ ├── radar_vitals.h # 接口定义和常量 +│ ├── io_flash.cpp # Flash存储 +│ └── io_flash.h +├── include/ # 头文件目录 +├── lib/ # 库文件目录 +├── test/ # 测试目录 +└── platformio.ini # 项目配置 +``` + +## 核心函数调用关系 + +```mermaid +graph TD + A[main.cpp
radarDataTask] --> B[radar_process] + B --> C[去直流处理] + C --> D[相位转换] + D --> E[相位展开] + E --> F[空人判断] + E --> G[活动检测] + E --> H[降采样] + H --> I[呼吸频率估计] + H --> J[心率估计] + I --> K[后处理滤波] + J --> K + K --> L[radar_get_state] + K --> M[radar_get_heart_bpm] + K --> N[radar_get_resp_bpm] + + style A fill:#FFB6C1 + style B fill:#87CEEB + style C fill:#E0FFFF + style D fill:#E0FFFF + style E fill:#E0FFFF + style F fill:#FFDAB9 + style G fill:#FFDAB9 + style H fill:#98FB98 + style I fill:#F0E68C + style J fill:#F0E68C + style K fill:#DDA0DD + style L fill:#90EE90 + style M fill:#90EE90 + style N fill:#90EE90 +``` diff --git a/git.bat b/git.bat index 4db359b..f12303f 100644 --- a/git.bat +++ b/git.bat @@ -22,7 +22,11 @@ if "%commit_msg%"=="" set commit_msg=Update project %GIT_PATH% commit -m "%commit_msg%" echo. -echo [4/5] 推送到远程仓库... +echo [4/5] 拉取远程代码... +%GIT_PATH% pull +echo. + +echo [5/5] 推送到远程仓库... %GIT_PATH% push echo. diff --git a/src/main.cpp b/src/main.cpp index 42560f4..22043da 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,32 @@ static float I_buf[BASE_DATA_LEN]; static float Q_buf[BASE_DATA_LEN]; +//雷达芯片串口数据打印 +void uartDataTask(void *parameter) { + Serial.println("📡 串口数据读取任务启动"); + + while(1) { + if(Serial1.available()) { + byte data = Serial1.read(); + //Serial.printf("%02X ", data); + + + + uint16_t raw_i = adc1_get_raw(ADC1_CHANNEL_8); + uint16_t raw_q = adc1_get_raw(ADC1_CHANNEL_9); + float raw_i_voltage = (raw_i / 4095.0f) * 3.3f; + float raw_q_voltage = (raw_q / 4095.0f) * 3.3f; + + raw_i = adc1_get_raw(ADC1_CHANNEL_0); + raw_q = adc1_get_raw(ADC1_CHANNEL_1); + float raw_i_voltage2 = (raw_i / 4095.0f) * 3.3f; + float raw_q_voltage2 = (raw_q / 4095.0f) * 3.3f; + + Serial.printf("原:I=%.3f, Q=%.3f 放大:I=%.3f, Q=%.3f\n",raw_i_voltage, raw_q_voltage, raw_i_voltage2, raw_q_voltage2); + } + } +} + void radarDataTask(void *parameter) { Serial.println("📡 雷达数据采集任务启动"); @@ -17,8 +43,8 @@ void radarDataTask(void *parameter) { while(1) { for(int i = 0; i < BASE_DATA_LEN; i++) { - sample.i_value = adc1_get_raw(ADC1_CHANNEL_0); - sample.q_value = adc1_get_raw(ADC1_CHANNEL_1); + sample.i_value = adc1_get_raw(ADC1_CHANNEL_8); + sample.q_value = adc1_get_raw(ADC1_CHANNEL_9); sample.timestamp = millis(); I_buf[i] = (sample.i_value / 4095.0f) * 3.3f; @@ -39,10 +65,17 @@ void radarDataTask(void *parameter) { human_state_t state = radar_get_state(); + uint16_t raw_i = adc1_get_raw(ADC1_CHANNEL_0); + uint16_t raw_q = adc1_get_raw(ADC1_CHANNEL_1); + float raw_i_voltage = (raw_i / 4095.0f) * 3.3f; + float raw_q_voltage = (raw_q / 4095.0f) * 3.3f; + if (state == NO_PERSON) { - Serial.printf("👤 No person - IQ电压: I=%.3fV, Q=%.3fV\n", avgI, avgQ); + Serial.printf("0-原始电压: I=%.3fV, Q=%.3fV - 放大电压: I=%.3fV, Q=%.3fV\n", + raw_i_voltage, raw_q_voltage, avgI, avgQ); } else { - Serial.printf("👤 Human static - IQ电压: I=%.3fV, Q=%.3fV - 💓 心率: %.1f BPM, 呼吸: %.1f BPM\n", avgI, avgQ, radar_get_heart_bpm(), radar_get_resp_bpm()); + Serial.printf("1-原:I=%.3f, Q=%.3f 放大:I=%.3f, Q=%.3f -心率: %.1f BPM, 呼吸: %.1f BPM\n", + raw_i_voltage, raw_q_voltage, avgI, avgQ, radar_get_heart_bpm(), radar_get_resp_bpm()); } esp_task_wdt_reset(); @@ -65,6 +98,9 @@ void setup() { // 初始化雷达 radar_init(); + // 初始化Serial1串口 (RX:IO20, TX:IO19, 波特率:115200) + Serial1.begin(115200, SERIAL_8N1, 20, 19); + // 创建雷达数据任务 xTaskCreatePinnedToCore( radarDataTask, @@ -76,6 +112,17 @@ void setup() { 1 ); + // 创建串口数据任务 + xTaskCreatePinnedToCore( + uartDataTask, + "UART Data Task", + 4096, + NULL, + 3, + NULL, + 1 + ); + Serial.println("✅ FreeRTOS任务创建成功"); Serial.println("🎉 系统初始化完成,等待雷达数据...");