我有一个MATLAB脚本,使用一对遥测无线电将串行消息发送到Python脚本。 MATLAB数据均为单打(32位浮点型,IEEE Standard 754)。但是,当Python接收到串行消息时,它将每个数字解释为单个字节,而不是4。
我正在运行Windows 10,MATLAB R2018a,Python 3.7,并使用一对Holybro Telemetry Radios进行通信。这些无线电对于两个MATLAB脚本之间的串行通信工作正常,这使我相信问题与Python解释MATLAB单数据类型有关。
这是发送消息的代码:
comport = 'COM6'
s = serial(comport);
s.BaudRate = 57600;
try
fopen(s);
headerToSend = single([112 112]);
packetToSend = single([3 4 5]);
dataToSend = [headerToSend packetToSend];
fwrite(s,dataToSend);
disp('Data sent is: ')
disp(dataToSend)
fclose(s);
delete(s);
whos dataToSend
catch ME
disp(ME.message)
end
请注意,消息中可以包含不能转换为整数的整数,这些整数将转换为单数或十进制数字(例如0.1
)。
这是接收消息的代码:
import serial
import time
import sys
dat = []
# Open serial port
ser = serial.Serial(
port='COM3',
baudrate=57600,
parity=serial.PARITY_NONE,
stopbits=serial.STOPBITS_ONE,
timeout=0.1)
try:
# Main loop
while (True):
buffer = ser.read(4)
print("Buffer: ")
print(buffer)
time.sleep(1)
except KeyboardInterrupt:
ser.close()
sys.exit()
为了进行比较,我在MATLAB中复制了一个接收器以验证发送器是否正常运行:
clc;clear;
comport = 'COM3';
s = serial(comport);
s.BaudRate = 57600;
try
fopen(s);
data = [];
% Receive response data
pause(0.5);
expectedDataLength = 20; % 2 headers and 3 msg, each 4 bytes
data = fread(s,expectedDataLength)
fclose(s);
delete(s);
catch ME
disp(ME.message)
end
if isempty(data)
disp('Unable to read any data.');
else
%Logic to find the packet after stripping the header
data = data';
header = single([112 112]);
%Find the starting indices of 'header' in the 'data' received. It is
%expected to be 112 in this case
k = strfind(data,header);
if ~isempty(k) && any(ismember(k,1))
%get the packet data by stripping the header
packet = data(length(header)+1:expectedDataLength);
end
% The msg values are in the order x, y, and z.
msg1 = typecast(single(packet(1)),'single');
msg2 = typecast(single(packet(2)),'single');
msg3 = typecast(single(packet(3)),'single');
%display the msg data on screen
disp(['Message Data ', num2str(msg1),' | ', num2str(msg2), ' | ', num2str(msg3), '.'])
end
我希望缓冲区读取:
b'x00\x00\x00\x70'
b'x00\x00\x00\x70'
b'x00\x00\x00\x03'
b'x00\x00\x00\x04'
b'x00\x00\x00\x05'
对于包含[112 112 3 4 5]
使用上面显示的MATLAB阅读器时,它可以正确解释消息。请参阅底部的更新。
相反,缓冲区读取:
b'pp\x03\x04'
b'\x05'
似乎在python端,它已将消息的每个元素塞满了一个字节(p
为112
,x03
为3
,依此类推向前)。
使用whois dataToSend
确认它是一个1x5的单字节数组,由20个字节组成(或者至少在接收之前是这样)。
是否知道为什么会这样以及如何使python将MATLAB单身识别为32位/ 4字节?
因此,事实证明,即使是MATLAB也无法正确解释其单打。我已经意识到,MATLAB接收器脚本会等我4次调用MATLAB发送器,因为它只能将每个单个消息解释为字节(这意味着消息大小仅为5个字节,而不是20个字节)。此外,当消息的元素更改为小数(例如5.7)时,在输出处将其舍入为6。
答案 0 :(得分:1)
您的字节在那里,您只是看不到它们。
替换您的:
print(buffer)
使用:
print(ord(buffer))
它们应该神奇地出现在空中。
您可能想使用struct.unpack
来获得想要的单打。
编辑:如下所述,问题是您需要明确说明要用于从Matlab写入端口的精度。如果不这样做,它将使用无符号的8位默认值。
这样做:
fwrite(s, dataToSend, 'single')
解决了这个问题。