Matlab串口如何同步读取二进制流
How to synchronize readout of binary streams on serial port of Matlab
我遇到的问题部分与 Matlab 相关,部分与通用编程相关,我希望有人能帮我集思广益寻找解决方案。
我有一个外部微控制器,它每 400 毫秒生成大量二进制数据流 (~40kb),并通过 UART 将其发送到 PC 运行 Matlab 脚本。数据不是用十六进制或十进制字符编码的,而是真正的二进制(因此,没有定义终止符,因为所有 256 个值都是可能的,数据的有效组合)。波特率设置为1024000。简而言之,发送整个数据流大约需要375ms,流与流之间有25ms的死时间
在 Matlab 中,串口配置正确(也是 1024000、8x 位、1x 停止位、无奇偶校验、无硬件流控制等)。我能够正确读出我通过微控制器发送的数据(即没有数据损坏),但我无法在 Matlab 上同步串行读出。我的脚本如下:
function data_show = GetDATA
if ~isempty(instrfind)
fclose(instrfind);
end
DATA_TOTAL_SIZE = 38400;
DATA_buffer = uint8(zeros(DATA_TOTAL_SIZE,1));
DATA_show = reshape(DATA_buffer(1:2:end)',[160,120])';
f_data_in = false;
f_data_out = true;
serialport = serial('COM11','BaudRate',1024000,'DataBits',8,'FlowControl','none','Parity','none','StopBits',1,...
'BytesAvailableFcnCount',DATA_TOTAL_SIZE,'BytesAvailableFcnMode','byte','InputBufferSize',DATA_TOTAL_SIZE * 2,...
'BytesAvailableFcn',@GetPortData);
fopen(serialport);
while (get(serialport,'BytesAvailable') ~= 0) % Skip first packet which might be incomplete
fread(serialport,DATA_TOTAL_SIZE,'uint8');
end
f_data_out = true;
while (1)
if (f_data_in)
DATA_buffer = fread(serialport,DATA_TOTAL_SIZE,'uint8');
DATA_show = reshape(DATA_buffer(1:2:end)',[160,120])'; %Reshape array as matrix
DATAsc(DATA_show);
disp('DATA');
end
pause(0.01);
end
fclose(serialport);
delete(serialport);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function GetPortData (obj,~)
if f_data_out
f_data_in = true;
end
end
end
我看到的问题是我最后读到的总是正确的大小,但是属于多个流,因为我还没有找到方法告诉Matlab这25ms的没有数据应该用来同步(即空白期之前和之后的数据应该属于不同的流)。
有人对此有什么建议吗?
非常感谢!
为了完整起见,我想 post 我已解决此问题的当前实现,这可能不是在所有情况下都合适的解决方案,但在某些情况下可能有用。
我采用的方法是转向双向通信协议,其中 Matlab 通过发送一个非常短的命令作为触发器(例如,单个不可打印的字符)来启动流式传输。鉴于高波特率,它不会因微控制器端的处理而增加显着的延迟。
微控制器在收到此触发器后,继续仅传输一个完整的包(与以 5Hz 速率连续流式传输包相反)。通过强制 Matlab 在发出触发器后立即拾取已知长度的串行包,它确保只收到一个包并且没有同步问题。
然后只需将 Matlab 脚本封装在一个由定时器给出的 5Hz 节拍的例程中,在该例程中重复序列(发送触发器、检索包、进行任何处理,然后重复)。
这样做的好处:
- 它解决了同步问题
这样做的缺点:
- 在计时器滴答上使用 Matlab 运行 并不能确保完美的周期性,因此触发器可能并不总是以恰好 5Hz 的频率发送。如果微控制器在 "inconvenient" 次发送触发器,则可能需要跳过数据包,以避免仍在传输时在内存中更新数据包(因为传输占用了 200 毫秒时隙的很大一部分)
- 根据经验,性能可能会因 PC 运行 Matlab 正在执行的操作而有很大差异。例如,当 PC 自行进行采集时它工作正常,但如果使用另一个程序(例如 Chrome),Matlab 开始滞后并导致触发传输延迟。
如上所述,这不是一个完整的答案,但它是一种在某些情况下可能就足够的方法。如果有人有更好的选择,欢迎分享!
我遇到的问题部分与 Matlab 相关,部分与通用编程相关,我希望有人能帮我集思广益寻找解决方案。
我有一个外部微控制器,它每 400 毫秒生成大量二进制数据流 (~40kb),并通过 UART 将其发送到 PC 运行 Matlab 脚本。数据不是用十六进制或十进制字符编码的,而是真正的二进制(因此,没有定义终止符,因为所有 256 个值都是可能的,数据的有效组合)。波特率设置为1024000。简而言之,发送整个数据流大约需要375ms,流与流之间有25ms的死时间
在 Matlab 中,串口配置正确(也是 1024000、8x 位、1x 停止位、无奇偶校验、无硬件流控制等)。我能够正确读出我通过微控制器发送的数据(即没有数据损坏),但我无法在 Matlab 上同步串行读出。我的脚本如下:
function data_show = GetDATA
if ~isempty(instrfind)
fclose(instrfind);
end
DATA_TOTAL_SIZE = 38400;
DATA_buffer = uint8(zeros(DATA_TOTAL_SIZE,1));
DATA_show = reshape(DATA_buffer(1:2:end)',[160,120])';
f_data_in = false;
f_data_out = true;
serialport = serial('COM11','BaudRate',1024000,'DataBits',8,'FlowControl','none','Parity','none','StopBits',1,...
'BytesAvailableFcnCount',DATA_TOTAL_SIZE,'BytesAvailableFcnMode','byte','InputBufferSize',DATA_TOTAL_SIZE * 2,...
'BytesAvailableFcn',@GetPortData);
fopen(serialport);
while (get(serialport,'BytesAvailable') ~= 0) % Skip first packet which might be incomplete
fread(serialport,DATA_TOTAL_SIZE,'uint8');
end
f_data_out = true;
while (1)
if (f_data_in)
DATA_buffer = fread(serialport,DATA_TOTAL_SIZE,'uint8');
DATA_show = reshape(DATA_buffer(1:2:end)',[160,120])'; %Reshape array as matrix
DATAsc(DATA_show);
disp('DATA');
end
pause(0.01);
end
fclose(serialport);
delete(serialport);
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
function GetPortData (obj,~)
if f_data_out
f_data_in = true;
end
end
end
我看到的问题是我最后读到的总是正确的大小,但是属于多个流,因为我还没有找到方法告诉Matlab这25ms的没有数据应该用来同步(即空白期之前和之后的数据应该属于不同的流)。
有人对此有什么建议吗?
非常感谢!
为了完整起见,我想 post 我已解决此问题的当前实现,这可能不是在所有情况下都合适的解决方案,但在某些情况下可能有用。
我采用的方法是转向双向通信协议,其中 Matlab 通过发送一个非常短的命令作为触发器(例如,单个不可打印的字符)来启动流式传输。鉴于高波特率,它不会因微控制器端的处理而增加显着的延迟。
微控制器在收到此触发器后,继续仅传输一个完整的包(与以 5Hz 速率连续流式传输包相反)。通过强制 Matlab 在发出触发器后立即拾取已知长度的串行包,它确保只收到一个包并且没有同步问题。
然后只需将 Matlab 脚本封装在一个由定时器给出的 5Hz 节拍的例程中,在该例程中重复序列(发送触发器、检索包、进行任何处理,然后重复)。
这样做的好处:
- 它解决了同步问题
这样做的缺点:
- 在计时器滴答上使用 Matlab 运行 并不能确保完美的周期性,因此触发器可能并不总是以恰好 5Hz 的频率发送。如果微控制器在 "inconvenient" 次发送触发器,则可能需要跳过数据包,以避免仍在传输时在内存中更新数据包(因为传输占用了 200 毫秒时隙的很大一部分)
- 根据经验,性能可能会因 PC 运行 Matlab 正在执行的操作而有很大差异。例如,当 PC 自行进行采集时它工作正常,但如果使用另一个程序(例如 Chrome),Matlab 开始滞后并导致触发传输延迟。
如上所述,这不是一个完整的答案,但它是一种在某些情况下可能就足够的方法。如果有人有更好的选择,欢迎分享!