记一次诡异的摄像头调试经历

文章描述了一种在新主板上点亮摄像头时遇到的问题,即部分摄像头的ID无法被正确读取。通过逐步排查,最终发现是由于摄像头的powerdown脚没有正确配置导致的。通过对上电时序的调整,成功解决了这一问题。

       新主板回来,需要点亮摄像头。主板摄像头情况(前后摄像的i2c和mclk都是独立的)。将驱动文件移植好之后(后摄sp2507 前摄sp0a09),后摄能点亮,看内核打印信息,sp0a09不到id。按https://blog.youkuaiyun.com/mike8825/article/details/106163001里的检查方法检查后,没发现异常。这些摄像头在另一个项目上是能点亮的,而这两个项目的camera引脚能完全对上(缺货,替代方案)cam_rst,cam_pdn,cam_i2c,vcamd,vcamio,vcama,mclk都有信号输出,但就是读不到id。怀疑是上电的问题,但量信号没看出有异常。刚好前摄像也有sp2507的模组,配置上去有,前摄也能点亮。但为什么sp0a09读不到id呢。

       再点另一组模组gc02m1/gc030a,实验结果也是后摄gc02m1能点亮,gc030a读不到id。

       继续点另两组模组bf2553/bf2253和bf2253和bf20a1(为什么会有这么多模组,跟目前的半导体器件缺货有关,cpu要有备份,tp和lcd也要备份几家供应商),这次只有bf2553点亮了,bf2253作为后摄居然没点亮,前面的两组都是前摄点不亮。

        从目前的实验情况看,点亮的模组有sp2507/gc02m1/bf2553,成功率约为一半,而且后摄和前摄都有点不亮的情况。因为现象跟着摄像头走,一度怀疑是主板信号有问题,才出现此类问题,但量信号又量不出问题。

        比亚迪的fae说camera的powerdown脚可能没拉低,导致读不到id,让将powerdown脚拉倒地试下。

### 使用PID算法控制摄像头转动圈数 要实现使用PID算法控制摄像头的转动圈数,可以按照以下方式设计控制系统: #### 1. **定义目标位置** 设定摄像头的目标旋转角度或圈数作为期望值(Setpoint)。这可以通过编码器或其他反馈装置测量实际转角。 #### 2. **获取实时反馈** 通过安装在马达上的编码器或者陀螺仪等设备,读取摄像头的实际旋转角度(Process Variable, PV),并将其与目标角度进行比较以获得误差值 \( e(t) \)[^1]。 #### 3. **计算误差信号** 误差信号表示为目标值与当前实际值之间的差值: \[ e(t) = SP - PV \] 其中, - \( SP \): 设定的目标角度/圈数; - \( PV \): 实际检测到的角度/圈数。 #### 4. **应用PID控制器** 根据误差信号,利用PID公式计算出控制量 \( u(t) \),该值将被用来驱动电机调整摄像头的位置。标准的连续时间PID表达式如下: \[ u(t) = K_p e(t) + K_i \int_{0}^{t} e(\tau)d\tau + K_d \frac{de(t)}{dt} \][^2] 离散形式通常更适合于嵌入式系统中的实现,例如Arduino平台下的代码可能看起来像这样: ```cpp float computePID(float error, float dt){ static float integral = 0; static float previous_error = 0; // 计算积分项 integral += error * dt; // 计算微分项 float derivative = (error - previous_error)/dt; // 更新前一时刻误差 previous_error = error; // 返回总的控制输出 return kp*error + ki*integral + kd*derivative; } ``` 此处 `kp`, `ki`, 和 `kd` 是分别对应的比例、积分和微分增益参数[^3]。 #### 5. **发送指令至执行机构** 将由上述函数返回的结果转化为PWM信号或者其他适合的形式传递给伺服电机或步进电机,从而完成对摄像头方向的具体操控动作。 #### 6. **调参过程** 由于不同机械结构存在差异,在初次部署时需经历多次试验逐步修改三个系数直到达到满意效果为止。一般先单独测试P部分再加入I最后加上D成分逐层完善整个体系响应特性直至满足精度需求。 --- ### 示例代码片段 下面给出一段简单的伪代码示例展示如何结合硬件接口操作来构建这样一个闭环控制系统: ```cpp #include <Servo.h> // 初始化变量和服务对象 const int ENCODER_PIN_A = A0; // 假设连接到了模拟输入A0端口上用于监测脉冲计数值的变化情况 volatile long encoderPos = 0; // 定义全局变量存储当前位置信息 Servo myservo; // 创建servo实例名为myservo void setup() { Serial.begin(9600); // 开启串行通信以便打印调试数据 attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), updateEncoderPosition, RISING); myservo.attach(9); // 将舵机绑定到数字管脚9处运行 } void loop(){ const double TARGET_POSITION_DEGREES = 90; // 设置理想终点坐标为正向直角位置度数单位表 double currentPositionDegrees = map(encoderPos,-MAX_COUNTS, MAX_COUNTS , MIN_ANGLE, MAX_ANGLE ); double error = TARGET_POSITION_DEGREES - currentPositionDegrees ; unsigned long now = millis(); double controlSignal = computePID(error,(now-lastTime)*0.001); lastTime=now; myservo.write(map(controlSignal,MIN_CONTROL_SIGNAL,MAX_CONTROL_SIGNAL,SERVOMIN,SERVOMAX)); } ``` 此段程序展示了基本框架逻辑但并未包含全部细节比如边界条件处理等内容需要开发者自行补充完整。
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值