相机启动提示RuntimeError: sensor(0) run error, vicap init failed(-1)

Viewed 68

问题描述


使用相机id=0和id=2启动相机启动不了,提示RuntimeError: sensor(0) run error, vicap init failed(-1),但使用id=2的可以,程序运行时若相机正常可看到如下情况,非正常情况为以下这样,相机id修改的核心代码为固件用的是链接里的固件[烧录固件]

from machine import UART, Pin, FPIOA, ADC, WDT, RTC, Timer, TOUCH, PWM
from libs.YOLO import YOLO11,YOLOv5
from libs.Utils import *
#from sdcard.Utils import *
import ulab.numpy as np
import time, os, urandom, sys,gc, utime,uos
from media.sensor import *
from media.display import *
from media.media import *
import image
import io
import json  # 如果数据是JSON格式
import math
import random
#from mpp import pm
#pm.cpu.set_profile(3)

class Servent:
    def __init__(self):

        # 初始化系统设置
        self._init_system()

        # 初始化硬件引脚
        self._init_pins()

        # 初始化显示相关设置
        self._init_display()
        
        # 相机初始化
        self._init_camera()

        # 初始化参数设置
        self._init_parameters()

    def _init_system(self):
        """初始化系统设置"""
        os.exitpoint(os.EXITPOINT_ENABLE)  # 启用退出点

    def _init_pins(self):
        """初始化FPIOA和GPIO引脚"""
        # 创建FPIOA对象并为引脚功能分配
        fpioa = FPIOA()

        # 引脚配置
        fpioa.set_function(62, FPIOA.GPIO62)   # 红灯
        fpioa.set_function(20, FPIOA.GPIO20)   # 绿灯
        fpioa.set_function(63, FPIOA.GPIO63)   # 蓝灯
        fpioa.set_function(19, FPIOA.GPIO19)   # 拍照按键
        fpioa.set_function(18, FPIOA.GPIO18)    # 灯
        fpioa.set_function(43, FPIOA.PWM1)    # 配置蜂鸣器IO口功能

        # 串口和485通信接口
        fpioa.set_function(40, FPIOA.UART1_TXD)
        fpioa.set_function(41, FPIOA.UART1_RXD)
        fpioa.set_function(47, FPIOA.GPIO47)  # DE 发送模式 高电平有效 RE 接收模式 低电平有效

        # 单片机串口
        fpioa.set_function(48, FPIOA.UART4_TXD)
        fpioa.set_function(49, FPIOA.UART4_RXD)

        # GH1.25串口2
        fpioa.set_function(11, FPIOA.UART2_TXD)
        fpioa.set_function(12, FPIOA.UART2_RXD)

        # 初始化LED (共阳:高电平熄灭,低电平亮)
        self.LED_R = Pin(62, Pin.OUT, pull=Pin.PULL_NONE, drive=7)  # 红灯
        self.LED_G = Pin(20, Pin.OUT, pull=Pin.PULL_NONE, drive=7)  # 绿灯
        self.LED_B = Pin(63, Pin.OUT, pull=Pin.PULL_NONE, drive=7)  # 蓝灯
        self.button_photo = Pin(19, Pin.IN, pull=Pin.PULL_DOWN, drive=7)  # 拍照按键
        self.button = Pin(53, Pin.IN, Pin.PULL_DOWN)
        self.LED = Pin(18, Pin.OUT, pull=Pin.PULL_NONE, drive=7)     # 灯
        self.DHRL = Pin(47, Pin.OUT, pull=Pin.PULL_NONE, drive=7)

        # 默认熄灭所有LED
        self.LED_R.high()
        self.LED_G.high()
        self.LED_B.high()

    def _init_display(self):
        """初始化显示相关设置"""
        # 3.1寸屏幕模式
        self.DISPLAY_WIDTH = 800
        self.DISPLAY_HEIGHT = 480

        # 创建用于绘图的图像对象
        self.img_show = image.Image(self.DISPLAY_WIDTH, self.DISPLAY_HEIGHT, image.RGB565)


        # 定义画布中的按钮区域
        # ====================== 新 ================================
        self.test_button_area = (250, 150, 250, 130)  # 拍照按钮区域
        # 初始化显示
        Display.init(Display.ST7701, width=self.DISPLAY_WIDTH, height=self.DISPLAY_HEIGHT, to_ide=False)


        self.deinit_flag = 1

    def _create_directories(self):
        """创建必要的目录"""
        status_folder = "/sdcard/status"
        arg_folder = "/sdcard/arg"
        self.image_folder = "/data/images"

        for folder in [status_folder, arg_folder, self.image_folder]:
            try:
                os.stat(folder)
            except OSError:
                os.mkdir(folder)

    def _init_parameters(self):
        """初始化参数设置"""
        self.last_displayed_percent = -1
        self.power_value = None

        # 模型加载
        self.kmodel_path="/sdcard/best.kmodel"
        self.labels = ["甲虫","粉螟"]
        self.model_input_size=[1280,736]
        self.confidence_threshold = 0.4
        self.nms_threshold=0.45

        self.colors=get_colors(len(self.labels))

        # 待机状态参数
        self.is_stand = 0

        # 虫情数量初始化
        self.insect_jia = 0
        self.insect_fenming = 0

        # 自动拍照相关参数
        self.start_photo_auto = 0
        self.auto_time_flag = 1

        # 加载自动定时时间
        try:
            with open("/sdcard/arg/auto_time.txt", 'r') as f:
                self.auto_time = int(f.read())
        except:
#            self.auto_time = 86400000  # 默认一天
            self.auto_time = 10 * 1000

        # 设置自动拍照启动标志
        self.start_photo_auto = 1 if self.auto_time else 0
        with open("/sdcard/arg/start_photo_auto.txt", 'w') as f:
            f.write(str(self.start_photo_auto))

    def _init_camera(self):
        """初始化相机"""
        self.fps = time.clock()
        sensor_id = 1
        self.sensor = Sensor(id=sensor_id, fps=60)
        self.sensor.reset()

        # 拍照用通道
        self.sensor.set_framesize(framesize=self.sensor.FHD, chn=1)
        self.sensor.set_pixformat(Sensor.RGB565, chn=1)

        # LCD屏幕显示画面
        self.sensor.set_framesize(width=800, height=480, chn=CAM_CHN_ID_0)
        self.sensor.set_pixformat(Sensor.RGB565, chn=CAM_CHN_ID_0)
#        self.sensor.set_framesize(width=800, height=480, chn=2)

        # 初始化媒体管理器
        MediaManager.init()
        self.sensor.run()
    # =================================================================

    def lckfb_save_jpg(self, img, filename, quality=95):
        """
        将图像压缩成JPEG后写入文件 (不依赖第一段 save_jpg/MediaManager.convert_to_jpeg 的写法)
        :param img:    传入的图像对象 (Sensor.snapshot() 得到)
        :param filename: 保存的目标文件名 (含路径)
        :param quality:  压缩质量 (1-100)
        """

        # 将图像压缩为 JPEG 格式数据
        # quality=95 表示压缩质量越高,图片越清晰,文件体积越大,这个也会导致明明都是800*480分辨率的图片,有的图片大,有的图片小。
        compressed_data = img.compress(quality=quality)

        with open(filename, "wb") as f:
            f.write(compressed_data)


    def auto_photo(self):
        self.all_image_count_and_reset("/data/images/")
        self.auto_old_ms = utime.ticks_ms()
        self.LED.high()
        self.yolo_auto=YOLO11(task_type="detect",mode="image",kmodel_path=self.kmodel_path,labels=self.labels,rgb888p_size=[1920,1080],model_input_size=self.model_input_size,conf_thresh=self.confidence_threshold,nms_thresh=self.nms_threshold,max_boxes_num=50,debug_mode=0)
        self.yolo_auto.config_preprocess()
        s_date = "日期: " + str(2025) + "年 " + str(8) + "月 " + str(18) + "日 " + str(16) + ":" + str(0)
#        self.tim.init(period=self.auto_time, mode=Timer.PERIODIC, callback=self.auto_photo)
        with open("/sdcard/arg/real_auto_time.txt",'w') as f:
            f.write(str(self.auto_time))
        self.auto_time_flag = "0"
        with open("/sdcard/arg/auto_time_flag.txt",'w') as f:
            f.write(self.auto_time_flag)
        try:
            with open("/sdcard/arg/image_count_auto.txt",'r') as f:
                image_count_auto = f.read()
                self.image_count_auto = int(image_count_auto)
        except:
            pass

        print("相机启动")
        # 启动传感器
        self.sensor.run()

    #    global image_count_all
        # 丢掉前面100帧数据,防止摄像头还不稳定
        for i in range(100):
            self.sensor.snapshot()
        #抓取通道0的图像
#        img_show = self.sensor.snapshot(chn=2)
#        self.insect_jia = self.reconize_jia(img_show)
#        self.insect_fenming = self.reconize_fenming(img_show)
        img_photo_auto = self.sensor.snapshot(chn=1)
        img_rgb888=img_photo_auto.to_rgb888()
        img_hwc=img_rgb888.to_numpy_ref()
        shape=img_hwc.shape
        img_tmp = img_hwc.reshape((shape[0] * shape[1], shape[2]))
        img_tmp_trans = img_tmp.transpose()
        img_res=img_tmp_trans.copy()
        img = img_res.reshape((shape[2],shape[0],shape[1]))
        res=self.yolo_auto.run(img)
        self.insect_jia = res[1].count(0)
        self.insect_fenming = res[1].count(1)
        img_photo_auto.draw_string_advanced(2, 1080-35, 32, s_date, color=(0, 255, 0))
        img_photo_auto.draw_string_advanced(2, 0, 32, "甲虫:"+str(self.insect_jia), color=(0, 255, 0))
        img_photo_auto.draw_string_advanced(2, 35, 32, "粉螟:"+str(self.insect_fenming), color=(0, 255, 0))
        # 拍照并保存
        self.image_count_auto += 1
#        filename = f"{self.image_folder}/auto_{self.image_count_auto:05d}_{img_photo_auto.width()}x{img_photo_auto.height()}.jpg"
#        print(filename)
    #    print("当前文件总数: "+str(image_count_all))
        # 直接调用自定义的 lckfb_save_jpg() 函数
#        self.lckfb_save_jpg(img_photo_auto, filename, quality=95)
        with open("/sdcard/arg/insect_jia.txt",'w') as f:
            f.write(str(self.insect_jia))
        with open("/sdcard/arg/insect_fenming.txt",'w') as f:
            f.write(str(self.insect_fenming))
        with open("/sdcard/arg/image_count_auto.txt",'w') as f:
            f.write(str(self.image_count_auto))
        self.LED.low()
#        self.yolo.deinit()

    def all_image_count_and_reset(self,directory):
        image_count_all = 0
#        image_count_all = int(self.image_count_unauto) + int(self.image_count_auto)
        for f in os.listdir(directory):
            full_path = directory + f
            if os.stat(full_path)[0] == 33206:  # 检查是否是文件
                image_count_all += 1
        if image_count_all >= 100:
            self.image_count_unauto = "0"
            self.image_count_auto = "0"
            with open("/sdcard/arg/image_count_unauto.txt",'w') as f:
                f.write(self.image_count_unauto)
            with open("/sdcard/arg/image_count_auto.txt",'w') as f:
                f.write(self.image_count_auto)
    #    print("总照片数: " + str(image_count_all))

    # ======================================================================================

    def run(self):
        try:
            i = 0
            p_flag = 1
            if self.start_photo_auto:
                self.auto_old_ms = utime.ticks_ms()
            while(True):
                if self.start_photo_auto:
                    self.auto_new_ms = utime.ticks_ms()
                    with open("/sdcard/arg/auto_new_ms.txt",'w') as f:
                        f.write(str(self.auto_new_ms))
                if p_flag:
                    if self.start_photo_auto:
                        self.auto_photo()
                        p_flag = 0

                time.sleep(1)  # 暂停1秒
#                        os.exitpoint()  # 可用的退出点
        except KeyboardInterrupt as e:
            print("用户终止:", e)  # 捕获键盘中断异常
        except BaseException as e:
            print(f"异常:{e}")  # 捕获其他异常
        finally:
            os.exitpoint(os.EXITPOINT_ENABLE_SLEEP)  # 启用睡眠模式的退出点
            time.sleep_ms(100)  # 延迟100毫秒
            MediaManager.deinit()
            gc.collect()

servent = Servent()
servent.run()

## 复现步骤
----------
将相机接在CSI_1的位置,启动程序即可

## 硬件板卡
----------
庐山派

## 软件版本
----------
CanMV v1.3-48-g1e83acc(based on Micropython e00a144) on 2025-07-15; k230_canmv_lckfb with K230

## 其他信息
----------
[烧录固件](https://kvftsfijpo.feishu.cn/file/PCo8botGaoAw5txlSancgLLOnRc?from=from_copylink)
2 Answers

你好,请问接到其他csi口会有问题吗,以及请检查是否有引脚冲突。

谢谢,已经解决了