我如何“合并”这些 i2c 传感器脚本(如果有的话)?

问题描述 投票:0回答:1

我正在开发一个基于终端、RPI 控制的传感器阵列项目!问题是,我是一名临时 Java 开发人员,没有使用 Python 的经验,而且我的所有组件都在后者上运行。以下脚本包含我用来确保相关五个设备均正常运行的代码。目前,我想做的是将它们合并到一个文件中,该文件在执行时生成一个简单的 HUD,聚合并显示每个板的实时数字读数(或者在 MLX90640 的情况下为 ASCII 艺术) .

BME688

# i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a m>
bme680 = adafruit_bme680.Adafruit_BME680_I2C(i2c, debug=False)

# change this to match the location's pressure (hPa) at sea level
bme680.sea_level_pressure = 1013.25

# You will usually have to add an offset to account for the temperature of
# the sensor. This is usually around 5 degrees but varies by use. Use a
# separate temperature sensor to calibrate this one.
temperature_offset = -5

while True:
    print("\nTemperature: %0.1f C" % (bme680.temperature + temperature_offset))
    print("Gas: %d ohm" % bme680.gas)
    print("Humidity: %0.1f %%" % bme680.relative_humidity)
    print("Pressure: %0.3f hPa" % bme680.pressure)
    print("Altitude = %0.2f meters" % bme680.altitude)

    time.sleep(1)

BNO08x

# SPDX-FileCopyrightText: 2020 Bryan Siepert, written for Adafruit Industries
#
# SPDX-License-Identifier: Unlicense
import time
import board
import busio
from adafruit_bno08x import (
    BNO_REPORT_ACCELEROMETER,
    BNO_REPORT_GYROSCOPE,
    BNO_REPORT_MAGNETOMETER,
    BNO_REPORT_ROTATION_VECTOR,
)
from adafruit_bno08x.i2c import BNO08X_I2C

i2c = busio.I2C(board.SCL, board.SDA, frequency=400000)
bno = BNO08X_I2C(i2c)

bno.enable_feature(BNO_REPORT_ACCELEROMETER)
bno.enable_feature(BNO_REPORT_GYROSCOPE)
bno.enable_feature(BNO_REPORT_MAGNETOMETER)

while True:
    time.sleep(0.5)
    print("Acceleration:")
    accel_x, accel_y, accel_z = bno.acceleration  # pylint:disable=no-member
    print("X: %0.6f  Y: %0.6f Z: %0.6f  m/s^2" % (accel_x, accel_y, accel_z))
    print("")

    print("Gyro:")
    gyro_x, gyro_y, gyro_z = bno.gyro  # pylint:disable=no-member
    print("X: %0.6f  Y: %0.6f Z: %0.6f rads/s" % (gyro_x, gyro_y, gyro_z))
    print("")

    print("Magnetometer:")
    mag_x, mag_y, mag_z = bno.magnetic  # pylint:disable=no-member
    print("X: %0.6f  Y: %0.6f Z: %0.6f uT" % (mag_x, mag_y, mag_z))
    print("")

    print("Rotation Vector Quaternion:")
    quat_i, quat_j, quat_k, quat_real = bno.quaternion  # pylint:disable=no-mem>
    print(
 "I: %0.6f  J: %0.6f K: %0.6f  Real: %0.6f" % (quat_i, quat_j, quat_k, q>
    )
    print("")

MLX90640

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
import busio
import adafruit_mlx90640

PRINT_TEMPERATURES = False
PRINT_ASCIIART = True

i2c = busio.I2C(board.SCL, board.SDA, frequency=800000)

mlx = adafruit_mlx90640.MLX90640(i2c)
print("MLX addr detected on I2C")
print([hex(i) for i in mlx.serial_number])

mlx.refresh_rate = adafruit_mlx90640.RefreshRate.REFRESH_2_HZ

frame = [0] * 768
while True:
    stamp = time.monotonic()
    try:
        mlx.getFrame(frame)
    except ValueError:
        # these happen, no biggie - retry
        continue
    print("Read 2 frames in %0.2f s" % (time.monotonic() - stamp))
    for h in range(24):
        for w in range(32):
            t = frame[h * 32 + w]
            if PRINT_TEMPERATURES:
                print("%0.1f, " % t, end="")
            if PRINT_ASCIIART:
                c = "&"
                # pylint: disable=multiple-statements
                if t < 20:
                    c = " "
                elif t < 23:
                    c = "."
                elif t < 25:
                    c = "-"
                elif t < 27:
                    c = "*"
                elif t < 29:
                    c = "+"
                elif t < 31:
                    c = "x"
                elif t < 33:
                    c = "%"
                elif t < 35:
                    c = "#"
                elif t < 37:
                    c = "X"
                # pylint: enable=multiple-statements
                print(c, end="")
        print()
    print()

迷你GPS

import time
import sys
import board
import busio

import adafruit_gps

i2c = board.I2C()

gps = adafruit_gps.GPS_GtopI2C(i2c, debug=False)  # Use I2C interface

# Initialize the GPS module by changing what data it sends and at what rate.
gps.send_command(b"PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0")
# Turn on just minimum info (RMC only, location):
# gps.send_command(b'PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn off everything:
# gps.send_command(b'PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0')
# Turn on everything (not all of it is parsed!)
# gps.send_command(b'PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0')

# Set update rate to once a second (1hz) which is what you typically want.
gps.send_command(b"PMTK220,1000")
# Or decrease to once every two seconds by doubling the millisecond value.
# Be sure to also increase your UART timeout above!
# gps.send_command(b'PMTK220,2000')
# You can also speed up the rate, but don't go too fast or else you can lose
# data during parsing.  This would be twice a second (2hz, 500ms delay):
# gps.send_command(b'PMTK220,500')

# Main loop runs forever printing the location, etc. every second.
last_print = time.monotonic()
while True:
    gps.update()

    current = time.monotonic()
    if current - last_print >= 1.0:
        last_print = current
        if not gps.has_fix:
            # Try again if we don't have a fix yet.
            print("Waiting for fix...")
           continue
        # We have a fix! (gps.has_fix is true)
        # Print out details about the fix like location, date, etc.
        print("=" * 40)  # Print a separator line.
        print(
            "Fix timestamp: {}/{}/{} {:02}:{:02}:{:02}".format(
                gps.timestamp_utc.tm_mon,  # Grab parts of the time from the
                gps.timestamp_utc.tm_mday,  # struct_time object that holds
                gps.timestamp_utc.tm_year,  # the fix time.  Note you might
                gps.timestamp_utc.tm_hour,  # not get all data like year, day,
                gps.timestamp_utc.tm_min,  # month!
                gps.timestamp_utc.tm_sec,
            )
        )
        print("Latitude: {0:.6f} degrees".format(gps.latitude))
        print("Longitude: {0:.6f} degrees".format(gps.longitude))
        print(
            "Precise Latitude: {} degs, {:2.4f} mins".format(
                gps.latitude_degrees, gps.latitude_minutes
            )
        )
        print(
            "Precise Longitude: {} degs, {:2.4f} mins".format(
                gps.longitude_degrees, gps.longitude_minutes
            )
        )
        print("Fix quality: {}".format(gps.fix_quality))
        # Some attributes beyond latitude, longitude and timestamp are optional
        # and might not be present.  Check if they're None before trying to use!
        if gps.satellites is not None:
            print("# satellites: {}".format(gps.satellites))
        if gps.altitude_m is not None:
            print("Altitude: {} meters".format(gps.altitude_m))
        if gps.speed_knots is not None:
            print("Speed: {} knots".format(gps.speed_knots))
        if gps.track_angle_deg is not None:
            print("Track angle: {} degrees".format(gps.track_angle_deg))
        if gps.horizontal_dilution is not None:
            print("Horizontal dilution: {}".format(gps.horizontal_dilution))
        if gps.height_geoid is not None:
            print("Height geoid: {} meters".format(gps.height_geoid))

APDS9960

# SPDX-FileCopyrightText: 2021 ladyada for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
from adafruit_apds9960.apds9960 import APDS9960

i2c = board.I2C()  # uses board.SCL and board.SDA
# i2c = board.STEMMA_I2C()  # For using the built-in STEMMA QT connector on a m>
apds = APDS9960(i2c)

apds.enable_proximity = True

while True:
    print(apds.proximity)
    time.sleep(0.2)

ChatGPT 和我尝试了一下并取得了一些成果,但最终并没有走得太远。我们一起设法从数组中获取数据,显示它,并按一定时间间隔刷新它。 但是,这里出了问题。

  • 执行后,控制台会生成一条错误消息,该消息在开始任何有效输出之前会在屏幕上保留几分钟。
  • 当控制台开始打印读数时,它们被错误地格式化为部分片段(例如,只有一行 ASCII 字符,而不是 IR 摄像头的整个“帧”,只有 GPS 的经度等)。

代码

import subprocess
import time
import sys

# Define functions to run each sensor script and capture its ou>
def run_sensor_script(script_name):
    return subprocess.Popen([sys.executable, script_name], stdo>

# Define HUD display function
def display_hud(sensor_outputs):
    # Parse and display data from each sensor
    for sensor_name, output in sensor_outputs.items():
        print(f"--- {sensor_name} ---")
        print(output.decode().strip())  # Print decoded output >
        print()  # Add newline for clarity

if __name__ == "__main__":
    # Define the list of sensor scripts to run
    sensor_scripts = {
        "BME680": "i2c-air-test.py",
        "BNO08X": "i2c-dof-test.py",
        "MLX90640": "i2c-ir-test.py",
        "GPS": "i2c-gps-test.py",
        "APDS9960": "i2c-light-test.py"
    }

    # Start subprocesses for each sensor script
    sensor_processes = {name: run_sensor_script(script) for nam>

    try:
        while True:
            # Read output from each sensor subprocess
            sensor_outputs = {name: proc.stdout.readline() for >

            # Display the HUD with live sensor readouts
            display_hud(sensor_outputs)

            # Wait a short interval before updating HUD (adjust>
            time.sleep(1)

   except KeyboardInterrupt:
        # Terminate all subprocesses if the program is interrup>
        for proc in sensor_processes.values():
            proc.terminate()

错误

*/home/raziel/i2c-example/i2c/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py:30: RuntimeWarning: I2C frequency is not settable in python, ignoring!
  warnings.warn(
/home/raziel/i2c-example/i2c/lib/python3.11/site-packages/adafruit_blinka/microcontroller/generic_linux/i2c.py:30: RuntimeWarning: I2C frequency is not settable in python, ignoring!
  warnings.warn(
Traceback (most recent call last):
  File "/home/raziel/i2c-example/i2c-array-test/i2c-dof-test.py", line 26, in <module>
    accel_x, accel_y, accel_z = bno.acceleration  # pylint:disable=no-member
                                ^^^^^^^^^^^^^^^^
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 598, in acceleration
    self._process_available_packets()
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 803, in _process_available_packets
    self._handle_packet(new_packet)
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 863, in _handle_packet
    raise error
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 858, in _handle_packet
    _separate_batch(packet, self._packet_slices)
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 373, in _separate_batch
    required_bytes = _report_length(report_id)
                     ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/raziel/.local/lib/python3.11/site-packages/adafruit_bno08x/__init__.py", line 362, in _report_length
    return _AVAIL_SENSOR_REPORTS[report_id][2]
           ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^
KeyError: 123*

输出

========================================

--- APDS9960 ---
0

--- BME680 ---
Pressure: 995.852 hPa

--- BNO08X ---


--- MLX90640 ---
************-*-*-*---*-*--******

--- GPS ---
Fix timestamp: 4/14/2024 03:39:43

--- APDS9960 ---
0

--- BME680 ---
Altitude = 145.87 meters

--- BNO08X ---


--- MLX90640 ---
*********-**--***---------***-**

--- GPS ---
Latitude: 32.963751 degrees

--- APDS9960 ---
0

--- BME680 ---


--- BNO08X ---


--- MLX90640 ---
**********-*-*-*-------*---*-***

--- GPS ---
Longitude: -96.697693 degrees

--- APDS9960 ---
0

--- BME680 ---
Temperature: 21.0 C

--- BNO08X ---


--- MLX90640 ---
*********--**-**------*-*-*-*-**

--- GPS ---
Precise Latitude: 32 degs, 57.8251 mins

--- APDS9960 ---
0

--- BME680 ---
Gas: 69245 ohm

--- BNO08X ---


--- MLX90640 ---
**********-**--*---*---*-***--**

--- GPS ---
Precise Longitude: -96 degs, 41.8616 mins

--- APDS9960 ---
0

--- BME680 ---
Humidity: 39.6 %

--- BNO08X ---


--- MLX90640 ---
*********---*-***-*----*--***-**

--- GPS ---
Fix quality: 2

--- APDS9960 ---
0

--- BME680 ---
Pressure: 995.853 hPa

--- BNO08X ---


--- MLX90640 ---
****************-----*-*--**-***

--- GPS ---
# satellites: 7

--- APDS9960 ---
1

--- BME680 ---
Altitude = 145.86 meters

--- BNO08X ---


--- MLX90640 ---
*********-**--**---**-*---**-***

--- GPS ---
Altitude: 204.1 meters

--- APDS9960 ---
0

--- BME680 ---


--- BNO08X ---


--- MLX90640 ---
************-****--***-*--**-***

--- GPS ---
Speed: 0.93 knots

--- APDS9960 ---
0

--- BME680 ---
Temperature: 21.1 C

--- BNO08X ---


--- MLX90640 ---
*************-**---*****--******

--- GPS ---
Track angle: 65.26 degrees

--- APDS9960 ---
0

--- BME680 ---
Gas: 69811 ohm

--- BNO08X ---


--- MLX90640 ---
************-***-*-*************

--- GPS ---
Horizontal dilution: 1.25

--- APDS9960 ---
0

--- BME680 ---
Humidity: 39.5 %

--- BNO08X ---


--- MLX90640 ---
*************-***-**************

--- GPS ---
Height geoid: -24.1 meters

--- APDS9960 ---
0

--- BME680 ---
Pressure: 995.855 hPa

--- BNO08X ---


--- MLX90640 ---
************-***-***************

--- GPS ---
========================================

--- APDS9960 ---
0

--- BME680 ---
Altitude = 145.84 meters

--- BNO08X ---


--- MLX90640 ---


--- GPS ---
Fix timestamp: 4/14/2024 03:39:45

--- APDS9960 ---
0

--- BME680 ---


--- BNO08X ---


--- MLX90640 ---
Read 2 frames in 1.23 s

--- GPS ---
Latitude: 32.963746 degrees

--- APDS9960 ---
0

--- BME680 ---
Temperature: 21.1 C

--- BNO08X ---


--- MLX90640 ---
++***************************+**

--- GPS ---
Longitude: -96.697683 degrees

--- APDS9960 ---
0

--- BME680 ---
Gas: 69868 ohm

--- BNO08X ---


--- MLX90640 ---
x++*****************************

--- GPS ---
Precise Latitude: 32 degs, 57.8248 mins

--- APDS9960 ---
0

--- BME680 ---
Humidity: 39.5 %

--- BNO08X ---


--- MLX90640 ---
#%++****************************

--- GPS ---
Precise Longitude: -96 degs, 41.8610 mins

--- APDS9960 ---
0

--- BME680 ---
Pressure: 995.851 hPa

--- BNO08X ---


--- MLX90640 ---
#%x+*************************-**

--- GPS ---
Fix quality: 2

--- APDS9960 ---
0

--- BME680 ---
Altitude = 145.88 meters

--- BNO08X ---


--- MLX90640 ---
%%xx+*****-***********-*--******

--- GPS ---
# satellites: 7

--- APDS9960 ---
0

--- BME680 ---


--- BNO08X ---


--- MLX90640 ---
xxxx++***************--**-**--**

--- GPS ---
Altitude: 204.1 meters

--- APDS9960 ---
0

--- BME680 ---
Temperature: 21.1 C

--- BNO08X ---


--- MLX90640 ---
xx+x+++*****-*****-*-*-*-****--*

--- GPS ---
Speed: 0.33 knots

--- APDS9960 ---
0

--- BME680 ---
Gas: 70271 ohm

--- BNO08X ---


--- MLX90640 ---
xx++++***-**--***-**--**-*******

--- GPS ---
Track angle: 65.26 degrees

--- APDS9960 ---
0

--- BME680 ---
Humidity: 39.5 %

--- BNO08X ---


--- MLX90640 ---
++++******-*-***--*---*---******

--- GPS ---
Horizontal dilution: 1.25

--- APDS9960 ---
0

--- BME680 ---
Pressure: 995.855 hPa

--- BNO08X ---


--- MLX90640 ---
++********--*-***---*-**-*******

--- GPS ---
Height geoid: -24.1 meters

--- APDS9960 ---
0

--- BME680 ---
Altitude = 145.84 meters

--- BNO08X ---


--- MLX90640 ---
**********-*---*-------*--***-**

--- GPS ---
python raspberry-pi sensors i2c adafruit
1个回答
0
投票

您遇到的很可能是硬件限制,如此讨论所示。

您有几个脚本几乎同时尝试访问 i2c,并且全部实例化新的 i2c 总线,您可能会因此感到头疼。

由于您的某些脚本有 1 秒的延迟,我假设速度或时间对此应用程序并不重要。上面的线程提到一一运行每个脚本并捕获脚本输出,而不是尝试维护 4 个活动子进程,每个子进程都尝试访问 i2c 硬件。

如果您的所有 i2c 设备都可以以相同的时钟速度运行(例如 100000Hz,默认 rpi),您可以尝试创建 i2c 总线的单个实例并在传感器类之间共享该实例。这意味着有一个脚本实例化并读取所有传感器。

© www.soinside.com 2019 - 2024. All rights reserved.