草庐IT

在 python 中从各种 USB 设备读取和存储各种数据

codeneng 2023-03-28 原文

read and stock various data from various usb devices in python

我是 python 的初学者,我正在尝试从通过 USB 集线器连接到计算机的多个传感器(湿度、温度、压力传感器......)读取数据。我的主要目标是每五分钟记录一次这些传感器的不同值,然后将其存储起来进行分析。

我有我的传感器(来自 Hygrosens Instruments)的所有数据表和手册,我知道它们是如何工作的以及它们发送什么样的数据。但我不知道如何阅读它们。下面是我尝试过的,使用 pyserial.

1
2
3
4
5
6
7
8
9
10
import serial #import the serial library
from time import sleep #import the sleep command from the time library
import binascii

output_file = open('hygro.txt', 'w') #create a file and allow you to write in it only. The name of this file is hygro.txt

ser = serial.Serial("/dev/tty.usbserial-A400DUTI", 9600) #load into a variable 'ser' the information about the usb you are listening. /dev/tty.usbserial.... is the port after plugging in the hygrometer, 9600 is for bauds, it can be diminished
count = 0
while 1:
    read_byte = ser.read(size=1)

所以现在我想找到数据行的结尾,因为我需要的测量信息在以"V"开头的行中,如果我的传感器的数据表,它说一行结束by ,所以我想一次读取一个字节并查找'<',然后是'c',然后是'r',然后是'>'。所以我想这样做:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
while 1:
    read_byte = ser.read(size=8) #read a byte
    read_byte_hexa =binascii.hexlify(read_byte) #convert the byte into hexadecimal

    trad_hexa = int(read_byte_hexa , 16) #convert the hexadecimal into an int in purpose to compare it with another int
    trad_firstcrchar = int('3c' , 16) #convert the hexadecimal of the '<' into a int to compare it with the first byte    
    if (trad_hexa == trad_firstcrchar ): #compare the first byte with the '<'    
        read_byte = ser.read(size=1) #read the next byte (I am not sure if that really works)
        read_byte_hexa =binascii.hexlify(read_byte)# from now I am doing the same thing as before
        trad_hexa = int(read_byte_hexa , 16)
        trad_scdcrchar = int('63' , 16)
        print(trad_hexa, end='/')# this just show me if it gets in the condition
        print(trad_scdcrchar)    
        if (trad_hexa == trad_scdcrchar ):    
            read_byte = ser.read(size=1) #read the next byte
            read_byte_hexa =binascii.hexlify(read_byte)
            trad_hexa = int(read_byte_hexa , 16)
            trad_thirdcrchar = int('72' , 16)
            print(trad_hexa, end='///')
            print(trad_thirdcrchar)    
            if (trad_hexa == trad_thirdcrchar ):    
                read_byte = ser.read(size=1) #read the next byte
                read_byte_hexa =binascii.hexlify(read_byte)
                trad_hexa = int(read_byte_hexa , 16)
                trad_fourthcrchar = int('3e' , 16)
                print(trad_hexa, end='////')
                print(trad_fourthcrchar)    
                if (trad_hexa == trad_fourthcrchar ):    
                    print ('end of the line')

但我不确定它是否有效,我的意思是我认为它没有时间读取第二个字节,我正在读取的第二个字节,它不完全是第二个字节。所以这就是我想使用缓冲区的原因,但我真的不明白我该怎么做。我要去寻找它,但如果有人知道一种更简单的方法来做我想做的事,我已经准备好尝试了!
谢谢

  • 请向我们展示您的代码示例,以便我们可以看到您到目前为止所做的尝试。
  • 如果您举例说明传感器如何通过 USB 传输数据,也会很方便。
  • 我添加了一些信息,希望现在对您来说更好!


您似乎认为该传感器的通信协议的行尾字符是 4 个不同的字符:<cr>。然而,这里所指的是回车,通常用 <cr> 表示,在许多编程语言中只用 \
表示(尽管它看起来像 2 个字符,但它只表示一个字符)。

由于协议是结构化的,因此您可以通过逐行读取传感器的数据来大大简化您的代码。以下内容可帮助您入门:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import time

def parse_info_line(line):
    # implement to your own liking
    logical_channel, physical_probe, hardware_id, crc = [line[index:index+2] for index in (1, 3, 5, 19)]
    serialno = line[7:19]
    return physical_probe

def parse_value_line(line):
    channel, crc = [line[ind:ind+2] for ind in (1,7)]
    encoded_temp = line[3:7]
    return twos_comp(int(encoded_temp, 16), 16)/100.

def twos_comp(val, bits):
   """compute the 2's compliment of int value `val`"""
    if (val & (1 << (bits - 1))) != 0: # if sign bit is set e.g., 8bit: 128-255
        val = val - (1 << bits)        # compute negative value
    return val                         # return positive value as is

def listen_on_serial(ser):
    ser.readline() # do nothing with the first line: you have no idea when you start listening to the data broadcast from the sensor
    while True:
        line = ser.readline()
        try:
            first_char = line[0]
        except IndexError:  # got no data from sensor
            break
        else:
            if first_char == '@':  # begins a new sensor record
                in_record = True
            elif first_char == '$':
                in_record = False
            elif first_char == 'I':
                parse_info_line(line)
            elif first_char == 'V':
                print(parse_value_line(line))
            else:
                print("Unexpected character at the start of the line:\
{}"
.format(line))
            time.sleep(2)

twos_comp 函数是由 travc 编写的,如果您有足够的声誉并且打算使用他的代码(即使您不这样做,它仍然是一个不错的选择),我们鼓励您支持他的答案回答,我刚刚投了赞成票)。 listen_on_serial 也可以改进(许多 Python 程序员会识别开关结构并使用字典而不是 if... elif... elif... 来实现它),但这只是为了让您入门。

作为测试,以下代码摘录模拟传感器发送一些数据(以行分隔,使用回车作为行尾标记),这些数据是我从您链接到的 pdf 中复制的 (FAQ_terminalfenster_E. pdf).

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
>>> import serial
>>> import io
>>>
>>> ser = serial.serial_for_url('loop://', timeout=1)
>>> serio = io.TextIOWrapper(io.BufferedRWPair(ser, ser), newline='\
'
, line_buffering=True)
>>> serio.write(u'A1A0\
'
 # simulation of starting to listen halfway between 2 records
...     '$\
'
             # marks the end of the previous record
...     '@\
'
             # marks the start of a new sensor record
...     'I0101010000000000001B\
'
 # info about a sensor's probe
...     'V0109470D\
'
             # data matching that probe
...     'I0202010000000000002B\
'
 # other probe, same sensor
...     'V021BB55C\
'
)             # data corresponding with 2nd probe
73L
>>>
>>> listen_on_serial(serio)
23.75
70.93
>>>

请注意,当行尾字符不是 \
(换行符)时,pyserial 文档建议使用 TextIOWrapper,这里也已回答。

  • 非常感谢你!现在可以了!我什么都看不到,因为我的波特率(9600)错误,文档的第一部分是基于这个波特率的。如果有人想查看我的(丑陋的)代码,请告诉我我仍在改进它。

有关在 python 中从各种 USB 设备读取和存储各种数据的更多相关文章

  1. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  2. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  3. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  4. Ruby 写入和读取对象到文件 - 2

    好的,所以我的目标是轻松地将一些数据保存到磁盘以备后用。您如何简单地写入然后读取一个对象?所以如果我有一个简单的类classCattr_accessor:a,:bdefinitialize(a,b)@a,@b=a,bendend所以如果我从中非常快地制作一个objobj=C.new("foo","bar")#justgaveitsomerandomvalues然后我可以把它变成一个kindaidstring=obj.to_s#whichreturns""我终于可以将此字符串打印到文件或其他内容中。我的问题是,我该如何再次将这个id变回一个对象?我知道我可以自己挑选信息并制作一个接受该信

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  7. Python 相当于 Perl/Ruby ||= - 2

    这个问题在这里已经有了答案:关闭10年前。PossibleDuplicate:Pythonconditionalassignmentoperator对于这样一个简单的问题表示歉意,但是谷歌搜索||=并不是很有帮助;)Python中是否有与Ruby和Perl中的||=语句等效的语句?例如:foo="hey"foo||="what"#assignfooifit'sundefined#fooisstill"hey"bar||="yeah"#baris"yeah"另外,类似这样的东西的通用术语是什么?条件分配是我的第一个猜测,但Wikipediapage跟我想的不太一样。

  8. java - 什么相当于 ruby​​ 的 rack 或 python 的 Java wsgi? - 2

    什么是ruby​​的rack或python的Java的wsgi?还有一个路由库。 最佳答案 来自Python标准PEP333:Bycontrast,althoughJavahasjustasmanywebapplicationframeworksavailable,Java's"servlet"APImakesitpossibleforapplicationswrittenwithanyJavawebapplicationframeworktoruninanywebserverthatsupportstheservletAPI.ht

  9. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  10. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

随机推荐