使用Python通过串行读取MATLAB单曲

时间:2019-08-09 15:45:35

标签: python matlab serial-port

摘要

我有一个MATLAB脚本,使用一对遥测无线电将串行消息发送到Python脚本。 MATLAB数据均为单打(32位浮点型,IEEE Standard 754)。但是,当Python接收到串行消息时,它将每个数字解释为单个字节,而不是4。

背景

我正在运行Windows 10,MATLAB R2018a,Python 3.7,并使用一对Holybro Telemetry Radios进行通信。这些无线电对于两个MATLAB脚本之间的串行通信工作正常,这使我相信问题与Python解释MATLAB单数据类型有关。

我的代码

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)。

Python接收器

这是接收消息的代码:

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接收器(用于比较)

为了进行比较,我在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端,它已将消息的每个元素塞满了一个字节(p112x033,依此类推向前)。 使用whois dataToSend确认它是一个1x5的单字节数组,由20个字节组成(或者至少在接收之前是这样)。

问题

是否知道为什么会这样以及如何使python将MATLAB单身识别为32位/ 4字节?

更新

因此,事实证明,即使是MATLAB也无法正确解释其单打。我已经意识到,MATLAB接收器脚本会等我4次调用MATLAB发送器,因为它只能将每个单个消息解释为字节(这意味着消息大小仅为5个字节,而不是20个字节)。此外,当消息的元素更改为小数(例如5.7)时,在输出处将其舍入为6。

1 个答案:

答案 0 :(得分:1)

您的字节在那里,您只是看不到它们。

替换您的:

print(buffer)

使用:

print(ord(buffer))

它们应该神奇地出现在空中。

您可能想使用struct.unpack来获得想要的单打。

编辑:如下所述,问题是您需要明确说明要用于从Matlab写入端口的精度。如果不这样做,它将使用无符号的8位默认值。

这样做:

fwrite(s, dataToSend, 'single')

解决了这个问题。