### 方法2的集成与实时电压监测图表显示正确数据
为了确保方法2能够正确集成到现有MATLAB代码中,并解决实时电压监测图表中没有数据的问题,需要对程序进行以下调整和扩展。
#### 1. 数据解析与验证
在主循环中,当接收到串口数据时,必须确保数据解析的准确性。如果解析失败或数据格式不符合预期,则可能导致图表无法显示数据。因此,增加数据验证步骤以确保解析后的电压值有效[^1]。
```matlab
if startsWith(data, "VOLT:")
try
voltages = str2double(split(extractAfter(data,"VOLT:"), ","))';
if all(~isnan(voltages)) && numel(voltages) == 4
% 数据有效,继续处理
else
disp(['! 数据无效: ', data]);
continue;
end
catch
disp(['! 数据异常: ', data]);
continue;
end
end
```
#### 2. 滤波器设计与初始化
在程序开始部分定义并初始化低通滤波器,确保其参数在整个程序中可用。这里使用巴特沃斯滤波器来平滑电压数据[^2]。
```matlab
% 设计低通滤波器
fs = 100; % 假设采样频率为100Hz
fc = 5; % 截止频率为5Hz
[b, a] = butter(2, fc / (fs / 2), 'low'); % 设计滤波器
% 初始化滤波器状态变量
zf = zeros(max(length(a)-1, length(b)-1), 4);
```
#### 3. 数据平滑处理
在接收到新的电压数据后,应用低通滤波器对其进行平滑处理。这一步骤确保最终存储到缓冲区中的电压值是经过滤波的,从而减少噪声影响[^2]。
```matlab
% 应用低通滤波器对电压数据进行平滑处理
[smoothedVoltages, zf] = filter(b, a, voltages', [], zf);
% 存储平滑后的电压值
voltageBuffer(idx,:) = smoothedVoltages';
```
#### 4. 曲线更新逻辑
在更新曲线时,确保仅使用有效的数据点。通过检查时间缓冲区和电压缓冲区中的非NaN值,避免将无效数据添加到曲线中[^1]。
```matlab
% 更新所有曲线
for ch = 1:4
clearpoints(h(ch)); % 清除当前曲线的所有点
validIdx = ~isnan(timeBuffer); % 找出有效的时间索引
addpoints(h(ch), timeBuffer(validIdx), voltageBuffer(validIdx,ch)); % 添加新点
end
```
#### 5. 动态X轴调整
动态调整X轴范围以确保图表始终显示最新的电压数据。此操作通过计算当前时间缓冲区的最大值和最小值来实现[^1]。
```matlab
% 动态调整X轴
ax.XLim = [max(0, timeBuffer(idx)-10), max(10, timeBuffer(idx))];
drawnow limitrate;
```
#### 6. 完整代码示例
以下是整合后的完整代码示例:
```matlab
function realTimeVoltagePlot()
% 清理环境
close all force;
delete(instrfindall);
try
% 串口初始化
ports = serialportlist("available");
if isempty(ports)
error('无可用串口');
end
s = serialport(ports(1), 9600);
configureTerminator(s, "LF");
disp(['已连接: ', ports(1)]);
% 图形初始化
fig = figure('Name','多通道电压监测','NumberTitle','off');
ax = axes('Parent',fig);
colors = lines(4); % 4条不同颜色的曲线
h = gobjects(1,4);
for i = 1:4
h(i) = animatedline(ax, 'Color', colors(i,:), 'DisplayName',['A',num2str(i-1)]);
end
legend('Location','northeast');
grid on;
ylim([0 5]);
xlabel('时间 (秒)');
ylabel('电压 (V)');
title('实时电压监测');
% 设计低通滤波器
fs = 100; % 假设采样频率为100Hz
fc = 5; % 截止频率为5Hz
[b, a] = butter(2, fc / (fs / 2), 'low'); % 设计滤波器
% 初始化滤波器状态变量
zf = zeros(max(length(a)-1, length(b)-1), 4);
% 数据记录
startTime = tic;
maxPoints = 500;
timeBuffer = nan(maxPoints,1);
voltageBuffer = nan(maxPoints,4);
dataCount = 0;
% 主循环
while ishandle(fig)
if s.NumBytesAvailable > 0
data = readline(s);
% 数据解析
if startsWith(data, "VOLT:")
try
voltages = str2double(split(extractAfter(data,"VOLT:"), ","))';
if all(~isnan(voltages)) && numel(voltages) == 4
% 应用低通滤波器对电压数据进行平滑处理
[smoothedVoltages, zf] = filter(b, a, voltages', [], zf);
% 记录数据
dataCount = dataCount + 1;
idx = mod(dataCount-1, maxPoints) + 1;
timeBuffer(idx) = toc(startTime);
voltageBuffer(idx,:) = smoothedVoltages';
% 更新所有曲线
for ch = 1:4
clearpoints(h(ch));
validIdx = ~isnan(timeBuffer);
addpoints(h(ch), timeBuffer(validIdx), voltageBuffer(validIdx,ch));
end
% 动态调整X轴
ax.XLim = [max(0, timeBuffer(idx)-10), max(10, timeBuffer(idx))];
drawnow limitrate;
else
disp(['! 数据无效: ', data]);
end
catch
disp(['! 数据异常: ', data]);
end
end
end
pause(0.01);
end
catch ME
errordlg(['错误: ', ME.message]);
end
% 清理
if exist('s','var'), delete(s); end
end
```
---