当在Raspberry Pi上运行时,脚本使用过多的CPU功率



我有此代码片段在Raspberry Pi上运行。基本上,它为人们进出我房间的照片拍照。

import RPi.GPIO as GP
import os
import socket

def opencallback(channel):
    print(GP.input(channel))
    if GP.input(channel):
        global closeEvent
        closeEvent = 1
    else:
        global openEvent
        openEvent = 1

def transmit(message):
    s = socket.create_connection((host, port))
    s.send(message)
    s.close()

def capture(cam, gpiolist, quick):
    GP.output(cam1, gpiolist[0])
    GP.output(cam2, gpiolist[1])
    GP.output(cam3, gpiolist[2])
    if quick:
        cmd = "raspistill -o capture_%d.jpg -t 2" % cam
    else:
        cmd = "raspistill -o capture_%d.jpg" % cam
    os.system(cmd)

# init
GP.setwarnings(False)
GP.setmode(GP.BOARD)
cam1 = 7
cam2 = 11
cam3 = 12
doorIn = 40
ledOut = 38
GP.setup(cam1, GP.OUT)  # camera Mux1
GP.setup(cam2, GP.OUT)  # camera Mux2
GP.setup(cam3, GP.OUT)  # camera Mux3
GP.setup(ledOut, GP.OUT)  # LED OUT GPIO 20
GP.setup(doorIn, GP.IN)  # Door detector in GPIO 21
GP.add_event_detect(doorIn, GP.BOTH, callback=opencallback)
GP.output(ledOut, False)
openEvent = 0
closeEvent = 0
host = '192.168.1.111'
port = 13579
# main
while True:
    if openEvent == 1:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")
        openEvent = 0
    else:
        pass
    if closeEvent == 1:
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")
        closeEvent = 0
    else:
        pass

通常,我只需通过命令行使用标准调用即可运行它,并且不会加载系统。

但是,我最近将其转换为使用SystemD/SystemCTL的服务,因为我想在启动PI时将该脚本加载到后台。现在,此脚本本身正在吞噬整个处理器核心(HTOP报道(。在过渡期间,我没有将任何内容更改为代码本身,当我以旧的方式运行它时,它仍然可以正常工作。在大多数情况下,它只是在运行WALE循环什么都不做并等待GPIO的回调,然后执行一些功能并返回While Pass行为。

我的问题是:是什么导致两种执行方法之间计算功耗的差异?有没有办法解决此问题?

边缘检测/回调代码是有效的,只有在发生事件时被调用。但是,顶级while True:循环极度效率低下。

考虑以下修改:

try:
    import Queue as queue # Python 2.x
except ImportError:
    import queue          # Python 3.x
eventQueue = queue.Queue()
def opencallback(channel):
    eventQueue.put(GP.input(channel))
# ...your existing setup code here, specifically including:
GP.add_event_detect(doorIn, GP.BOTH, callback=opencallback)
while True:
    event = eventQueue.get()
    if event:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")
    else:
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")

请注意,这与SystemD 无关 - 您也将使用任何其他调用方法存在相同的CPU使用问题。

为什么没有回调直接触发打开和关闭事件的操作?只需循环短时间运行。

def opencallback(channel):
    print(GP.input(channel))
    if GP.input(channel):
        transmit("2-02")
        GP.output(ledOut, True)
        capture(3, (False, False, True), False)
        GP.output(ledOut, False)
        transmit("2-04")
        closeEvent = 0
    else:
        transmit("2-01")
        capture(2, (False, True, False), True)  # front cam
        transmit("2-03")

最新更新