PiZero W 连接到两个外设(GPIO 和 USB):如何同时连续读取? [英] PiZero W connected to two peripherals (GPIO and USB): how to continuously read from both at same time?

查看:65
本文介绍了PiZero W 连接到两个外设(GPIO 和 USB):如何同时连续读取?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 raspberry pizero W,它通过 GPIO 引脚连接到流量计和 USB 连接到条形码扫描仪.我有 python 脚本,它使用回调函数在检测到 GPIO 输入时发出警报.这个 python 脚本需要在 pizero 上持续运行,以便识别流量计何时被激活并处理输入.

I have a raspberry pizero W that is connected via GPIO pins to a flowmeter and USB to a barcode scanner. I have python script that uses a callback function to be alerted when the GPIO input is sensed. This python script needs to be continuously running on the pizero in order to recognize when the flowmeter is activated and process the input.

问题是我还有一个通过 USB 连接到 pizero 的条形码扫描仪.我希望 pizero 也能识别何时扫描条形码并处理该输入.

The problem is that I also have a barcode scanner attached via USB to the pizero. I would like the pizero to also recognize when a barcode is scanned and process that input as well.

然后 pizero 应发送一条消息,其中包含来自流量计的信息和来自条码扫描仪的信息.

The pizero should then send a message that incorporates both information from the flowmeter and information from the barcode scanner.

有没有办法在同一个 python 脚本中做到这一点?我怎样才能让 pizero 同时从两个输入中收听和处理?将其分成两个不同的脚本会更容易实现吗?如果是这样,我可以同时运行它们并以某种方式统一它们在第三个连续运行的脚本中提供的信息吗?

Is there a way to do this in the same python script? How can I have the pizero listen and process from two inputs simultaneously? Would separating this into two different scripts be easier to implement, and if so, can I run them both at the same time and somehow unify the information they provide in a 3rd continuously running script?

谢谢!

每条评论的一些说明(感谢您的输入):

Some clarifications per comments (thank you for the input):

  • 流量计的输入引脚是 GPIO 17 这是一个 SPI 连接
  • 还连接了 5V 电源和接地引脚.
  • input pin from the flowmeter is GPIO 17 which is an SPI connection
  • also have a 5V power and ground pin connected.

脚本需要在系统启动时运行.我会看看 systemctl,因为在提到它之前我没有听说过.

The script needs to be run at system startup. I will look at systemctl as I hadn't heard of it until it was mentioned.

当未连接流量计时,Pi 通常会将正在扫描的条形码识别为键盘输入(即一系列数字后跟换行符).

The Pi normally recognizes a barcode being scanned as keyboard input (i.e. a series of digits followed by a newline character) when the flowmeter is not attached.

当我发送一条包含流量计和条形码信息的消息时,我需要从 python 发送一个 JSON 对象,其中包括信息片段和接收信息的时间戳.

When I send a message that includes the flowmeter and barcode information, I need to send a JSON object from python that includes both pieces of information and a time stamp of when the information was received.

此 JSON 对象将通过 wifi 发送到树莓派服务器,该服务器具有与 pizero 位于同一家庭网络上的静态 IP.树莓派服务器可以访问 Django 数据库,该数据库应该将 JSON 对象信息合并到数据库中.

This JSON object will be sent over wifi to a raspberry pi server with a static ip on the same home network as the pizero. The raspberry pi server has access to a Django database that should incorporate the JSON object information into the database.

推荐答案

更新答案

我为条形码阅读器添加了一些代码.我这样做是为了让条码阅读器花费不同的时间,最多 5 秒来读取读数,而流量计花费恒定的 0.5 秒,因此您可以看到不同的线程以不同的速度相互独立.

I have added some code for the barcode reader. I made it so that the barcode reader takes a variable amount of time, up to 5 seconds to take a reading and the flowmeter takes a constant 0.5 seconds so you can see that different threads are progressing at different rates independently of one another.

#!/usr/bin/env python3

from threading import Lock
import threading
import time
from random import seed
from random import random

# Dummy function to read SPI as I don't have anything attached
def readSPI():
    # Take 0.5s to read
    time.sleep(0.5)
    readSPI.static += 1
    return readSPI.static
readSPI.static=0

class FlowMeter(threading.Thread):
    def __init__(self):
        super(FlowMeter, self).__init__()
        # Create a mutex
        self.mutex = Lock()
        self.currentReading = 0

    def run(self):
        # Continuously read flowmeter and safely update self.currentReading
        while True:
            value = readSPI()
            self.mutex.acquire()
            self.currentReading = value
            self.mutex.release()

    def read(self):
        # Main calls this to get latest reading, we just grab it from internal variable
        self.mutex.acquire()
        value = self.currentReading
        self.mutex.release()
        return value

# Dummy function to read Barcode as I don't have anything attached
def readBarcode():
    # Take variable time, 0..5 seconds, to read
    time.sleep(random()*5)
    result = "BC" + str(int(random()*1000))
    return result

class BarcodeReader(threading.Thread):
    def __init__(self):
        super(BarcodeReader, self).__init__()
        # Create a mutex
        self.mutex = Lock()
        self.currentReading = 0

    def run(self):
        # Continuously read barcode and safely update self.currentReading
        while True:
            value = readBarcode()
            self.mutex.acquire()
            self.currentReading = value
            self.mutex.release()

    def read(self):
        # Main calls this to get latest reading, we just grab it from internal variable
        self.mutex.acquire()
        value = self.currentReading
        self.mutex.release()
        return value

if __name__ == '__main__':

    # Generate repeatable random numbers
    seed(42)

    # Instantiate and start flow meter manager thread
    fmThread = FlowMeter()
    fmThread.daemon = True
    fmThread.start()

    # Instantiate and start barcode reader thread
    bcThread = BarcodeReader()
    bcThread.daemon = True
    bcThread.start()

    # Now you can do other things in main, but always get access to latest readings
    for i in range(20):
        fmReading = fmThread.read()
        bcReading = bcThread.read()
        print(f"Main: i = {i} FlowMeter reading = {fmReading}, Barcode={bcReading}")
        time.sleep(1)

样本输出

Main: i = 0 FlowMeter reading = 0, Barcode=0
Main: i = 1 FlowMeter reading = 1, Barcode=0
Main: i = 2 FlowMeter reading = 3, Barcode=0
Main: i = 3 FlowMeter reading = 5, Barcode=0
Main: i = 4 FlowMeter reading = 7, Barcode=BC25
Main: i = 5 FlowMeter reading = 9, Barcode=BC223
Main: i = 6 FlowMeter reading = 11, Barcode=BC223
Main: i = 7 FlowMeter reading = 13, Barcode=BC223
Main: i = 8 FlowMeter reading = 15, Barcode=BC223
Main: i = 9 FlowMeter reading = 17, Barcode=BC676
Main: i = 10 FlowMeter reading = 19, Barcode=BC676
Main: i = 11 FlowMeter reading = 21, Barcode=BC676
Main: i = 12 FlowMeter reading = 23, Barcode=BC676
Main: i = 13 FlowMeter reading = 25, Barcode=BC86
Main: i = 14 FlowMeter reading = 27, Barcode=BC86
Main: i = 15 FlowMeter reading = 29, Barcode=BC29
Main: i = 16 FlowMeter reading = 31, Barcode=BC505
Main: i = 17 FlowMeter reading = 33, Barcode=BC198
Main: i = 18 FlowMeter reading = 35, Barcode=BC198
Main: i = 19 FlowMeter reading = 37, Barcode=BC198

原答案

我建议您查看 systemdsystemctl 以在每次系统启动时启动您的应用程序 - 例如 此处.

I would suggest you look at systemd and systemctl to get your application started at every system startup - example here.

关于同时监控两件事,我建议您使用 Python 的 线程 模块.这是一个快速示例,我创建了一个从 threading 子类化的对象,该对象通过不断读取它并将当前值保存在主程序可以随时读取的变量中来管理您的流量计.您可以启动另一个类似的程序来管理您的条码阅读器并并行运行它们.我不想那样做并且用双倍的代码来迷惑你.

As regards monitoring two things at once, I would suggest you use Python's threading module. Here is a quick example, I create an object subclassed from threading that manages your flow meter by constantly reading it and holding the current value in a variable that the main program can read at any time. You could start another similar one that manages your bar code reader and run them I parallel. I didn't want to do that and confuse you with double the code.

#!/usr/bin/env python3

from threading import Lock
import threading
import time

# Dummy function to read SPI as I don't have anything attached
def readSPI():
    readSPI.static += 1
    return readSPI.static
readSPI.static=0

class FlowMeter(threading.Thread):
    def __init__(self):
        super(FlowMeter, self).__init__()
        # Create a mutex
        self.mutex = Lock()
        self.currentReading = 0

    def run(self):
        # Continuously read flowmeter and safely update self.currentReading
        while True:
            value = readSPI()
            self.mutex.acquire()
            self.currentReading = value
            self.mutex.release()
            time.sleep(0.01)

    def read(self):
        # Main calls this to get latest reading, we just grab it from internal variable
        self.mutex.acquire()
        value = self.currentReading
        self.mutex.release()
        return value

if __name__ == '__main__':

    # Instantiate and start flow meter manager thread
    fmThread = FlowMeter()
    fmThread.start()

    # Now you can do other things in main, but always get access to latest reading
    for i in range(100000):
        fmReading = fmThread.read()
        print(f"Main: i = {i} FlowMeter reading = {fmReading}")
        time.sleep(1)

您可以考虑使用 logging 来协调和统一您的调试和日志记录消息 - 请参阅 这里.

You could look at using logging to coordinate and unify your debugging and logging messages - see here.

您可以查看 events 以让其他线程知道当某事达到临界水平时需要做某事 - 例如 这里.

You could look at events to let other threads know something needs doing when something reaches a critical level - example here.

这篇关于PiZero W 连接到两个外设(GPIO 和 USB):如何同时连续读取?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆