You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派硬件类中初始化Picamera2失败问题排查

问题:树莓派Picamera2跨模块实例化类时初始化失败

在树莓派上开发Python机器人,将所有硬件交互整合到Hardware类后,除Picamera2外其他硬件均正常工作。直接在IDLE中运行该类文件无问题,但在其他模块中实例化类时抛出以下错误:

Traceback (most recent call last):
  File "/home/sox/Documents/Sox/main.py", line 6, in <module>
    soxHardware = Hardware()
  File "/home/sox/Documents/Sox/utils/HardwareUtils.py", line 72, in __init__
    self.picam2 = Picamera2()
  File "/usr/lib/python3/dist-packages/picamera2/picamera2.py", line 249, in __init__
    raise RuntimeError("Camera __init__ sequence did not complete.")
RuntimeError: Camera __init__ sequence did not complete.

相关代码

Hardware类代码

#NOTE: ALL FUNCTIONS CAN BE BYPASSED
#Just call the object directly
#import time
import board


import digitalio
import time

#for battery
import smbus
import struct

#for gyro
import adafruit_mpu6050

#for touch
import adafruit_mpr121

#for servoDriver
from adafruit_pca9685 import PCA9685
from adafruit_motor import servo

#for camera
from picamera2 import Picamera2




class Hardware:

     def __init__(self):
          #setup all IO ports
          self.ledRed = digitalio.DigitalInOut(board.D11)
          self.ledGreen = digitalio.DigitalInOut(board.D9)
          self.ledBlue = digitalio.DigitalInOut(board.D10)

          self.ledEars = digitalio.DigitalInOut(board.D22)
          self.ledLaser = digitalio.DigitalInOut(board.D27)

          self.speakerMute = digitalio.DigitalInOut(board.D17)


          #set port direction as output
          self.ledRed.direction = digitalio.Direction.OUTPUT
          self.ledGreen.direction = digitalio.Direction.OUTPUT
          self.ledBlue.direction = digitalio.Direction.OUTPUT

          self.ledEars.direction = digitalio.Direction.OUTPUT
          self.ledLaser.direction = digitalio.Direction.OUTPUT

          self.speakerMute.direction = digitalio.Direction.OUTPUT

          #i2c setup
          i2c = board.I2C()  # uses board.SCL and board.SDA
          #gyro
          self.gyro = adafruit_mpu6050.MPU6050(i2c, 0x69)
          #touch
          self.touch = adafruit_mpr121.MPR121(i2c)
          #servoDriver
          pca = PCA9685(i2c)
          pca.frequency = 50
          self.servo0 = servo.Servo(pca.channels[0])

          #battery
          self.I2C_ADDR    = 0x36
          self.bus = smbus.SMBus(1) # 0 = /dev/i2c-0 (port I2C0), 1 = /dev/i2c-1 (port I2C1)


          #set up camera
          self.picam2 = Picamera2()
          camera_config = self.picam2.create_preview_configuration()
          self.picam2.configure(camera_config)
          self.picam2.start()
          time.sleep(2)


     def readVoltage(self):
          read = self.bus.read_word_data(self.I2C_ADDR, 2)
          swapped = struct.unpack("<H", struct.pack(">H", read))[0]
          voltage = swapped * 1.25 /1000/16
          return voltage

     def readCapacity(self):
          read = self.bus.read_word_data(self.I2C_ADDR, 4)
          swapped = struct.unpack("<H", struct.pack(">H", read))[0]
          capacity = swapped/256
          return capacity



     def laser(self, status):
         self.ledLaser.value = status
         return True

     def flashlight(self, status):
         self.ledRed.value = status
         self.ledGreen.value = status
         self.ledBlue.value = status
         return True

     def ears(self, status):
         self.ledEars.value = status
         return True

     def muteSpeaker(self, status):
         self.speakerMute.value = status
         return True

     def checkBatteryStatus(self):
         print(self.readVoltage())
         print(self.readCapacity())
         return True

     def readGyro(self):
         print("Acceleration: X:%.2f, Y: %.2f, Z: %.2f m/s^2" % (self.gyro.acceleration))
         print("Gyro X:%.2f, Y: %.2f, Z: %.2f rad/s" % (self.gyro.gyro))
         print("Temperature: %.2f C" % self.gyro.temperature)
         print("")

     def getTouch(self, index):
         return self.touch[index].value

     def getTouchArray(self):
         array = [False]*12
         for i in range(12):
             array[i] = self.touch[i].value
         return array

     def takeImage(self,path):
          self.picam2.capture_file(path)


if __name__ == '__main__':
     hardware=Hardware()
     hardware.checkBatteryStatus()
     hardware.readGyro()
     print(hardware.getTouch(0))
     print(hardware.getTouchArray())


     hardware.takeImage("img.png")

     while True:
         hardware.servo0.angle = 0
         time.sleep(1)
         hardware.servo0.angle = 180
         time.sleep(1)

测试报错代码

from utils.HardwareUtils import Hardware


soxHardware = Hardware()

解决方法

1. 延迟相机初始化

将相机初始化从__init__方法中移出,延迟到第一次使用相机时再执行,避免类导入阶段的资源竞争:

修改Hardware类的相关代码:

class Hardware:
    def __init__(self):
        # 其他硬件初始化代码保持不变...
        # 暂时不初始化相机
        self.picam2 = None

    def _init_camera(self):
        """内部相机初始化方法"""
        if self.picam2 is None:
            self.picam2 = Picamera2()
            camera_config = self.picam2.create_preview_configuration()
            self.picam2.configure(camera_config)
            self.picam2.start()
            time.sleep(2)

    def takeImage(self, path):
        # 使用相机前先确保已初始化
        self._init_camera()
        self.picam2.capture_file(path)

2. 确保主程序的正确执行上下文

将类实例化放在主程序的if __name__ == '__main__':块中,避免模块导入时意外执行初始化:

修改测试代码:

from utils.HardwareUtils import Hardware

if __name__ == '__main__':
    soxHardware = Hardware()

3. 检查环境变量与权限

  • 确保运行程序的用户属于video组(相机访问权限),执行命令:
    sudo usermod -aG video $USER
    
    然后重启会话生效。
  • 如果是无桌面环境运行,手动设置DISPLAY环境变量:
    import os
    os.environ['DISPLAY'] = ':0'
    

4. 更新Picamera2版本

旧版本可能存在初始化bug,执行以下命令更新:

sudo apt update && sudo apt install --upgrade python3-picamera2

内容的提问来源于stack exchange,提问作者Collin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 17:37:10