编程语言
首页 > 编程语言> > python-记录数据并同时检查条件的最有效方法?

python-记录数据并同时检查条件的最有效方法?

作者:互联网

我正在尝试为rapspbery pi编写一个python代码,以控制一个非常特殊的设备,该设备是一个杠杆(在其末端有一个旋转编码器)和几个LED.
本质上是将操纵杆拉至特定位置范围,正确完成操作后,LED会亮起,表明您处于目标位置.
操纵杆可能会在编码器计数的一定范围内移动,您仍然可以成功完成试用.
我的问题是,在记录杠杆位置数据的同时能够检查杠杆是否在正确位置范围内的最佳方法是什么?

我已经为该程序的简单版本编写了软件,该软件仅使用开关而不是旋转编码器作为操纵杆.编码器的优势在于,我可以非常精确地测量杠杆位置,从而获得更多数据!我可以想到记录数据的方法,唯一的问题是它将很慢.我正在考虑使用嵌套的while循环,在该循环中该循环将检查并记录杠杆的位置,但是我担心此选项可能会具有非常低的采样率.

我也在考虑使用线程来实现此目标,但是我不知道如何使用线程来做到这一点,因为我以前从未使用过它们.

我已经拥有与编码器本身连接的软件和硬件,我能够获得非常好的操纵杆位置数据,但是我希望能够记录尽可能多的这些数据点,而同时仍然能够检查杠杆是否在正确的位置范围内.

如果您可以向我展示一个简单的代码来执行此操作,并且我应该能够将其实现为我的代码,我将非常感激.

这是我目前正在考虑编写代码的简单示例:

minCorrectPos = 100
maxCorrectPos = 200
timeToHoldLever = 5.0 #Seconds

while True:
    currentPos = encoder.readEncoderPos() #Function returns int
    writeToFile(str(currentPos)) #Records the data pos of the lever. I want this to happen as often as physically possible so as to lose the least amount of data.
    if currentPos < minCorrectPos or currentPos > maxCorrectPos:
        print 'Lever is out of range, wrong trial'
        writeData(timestamp)
    if time.time()-t_trialBegin > timeToHoldLever:
        print 'Lever has been held for enough time within correct range of positions. Rewarding person.'
        break
    #... 
    #Potentially checking for more things, like status of subject, whether he or she is still touching the lever, etc.

我不喜欢上面的代码的原因是,由于树莓派可能由于持续的while循环(缓慢的采样率)而无法足够快地轮询杠杆的位置,因此恐怕会丢失数据.这就是为什么我认为线程可能是解决此问题的正确方法的原因,因为在给定拉杆的对象名称的情况下,我将单独运行一条专用于记录杆位置的单独线程.可悲的是,我需要编写这种类型的代码的帮助.

解决方法:

我建议使用multiprocessing模块而不是线程,因为全局解释器锁(GIL)可以防止Python同时执行线程,即使使用多个内核也是如此.多处理模块避免了此限制.

这是一个小示例,展示了如何通过使用multiprocessing.Pipe在父进程和子进程之间发送currentPos,来拥有一个专门用于将currentPos写入文件的子进程.

import multiprocessing as mp

def writeToFile(conn):
    with open(filename, "a") as f: # Just leave the file open for performance reasons.
        while True:
            currentPos = conn.recv()        
            f.write("{}\n".format(currentPos))

if __name__ == "__main__":
    parent_conn, child_conn = mp.Pipe()
    p = mp.Process(target=writeToFile, args=(child_conn,))
    p.start()
    while True:
        currentPos = encoder.readEncoderPos()
        parent_conn.send(currentPos)
        if currentPos < minCorrectPos or currentPos > maxCorrectPos:
            print 'Lever is out of range, wrong trial'
            writeData(timestamp)
        if time.time()-t_trialBegin > timeToHoldLever:
            print 'Lever has been held for enough time within correct range of positions. Rewarding pe'
            break

请注意,尽管我之前关于Python无法很好地处理线程的声明,但在此特定示例中,与多处理相比,它们的执行效果可能很好.这是因为子进程主要在执行I / O,从而可以释放GIL.您可以使用线程模块尝试类似的实现并比较性能.

另外,您可能希望仅在每N个currentPos值收到后,才使writeToFile实际上执行f.write.文件I / O速度很慢,因此执行较少的较大写入操作可能会更好.

标签:multithreading,raspberry-pi,python
来源: https://codeday.me/bug/20191029/1960439.html