一、系统概述

OpenMV Cam 本质是基于STM32H7微控制器的开源机器视觉模块,集成摄像头传感器(如OV5640)与图像处理单元。本设计以STM32H743VI(OpenMV Cam H7 Plus核心)为平台,用C语言实现底层驱动与视觉算法,通过DCMI接口采集图像,DMA传输数据,结合UART/USB与机器人主控通信,实现目标识别、颜色追踪、避障导航等功能,适用于教育机器人、工业分拣、智能巡检等对实时性要求高的场景。

核心优势

  • C语言高效性:直接操作寄存器/HAL库,执行效率高于MicroPython,满足实时图像处理需求;

  • 硬件可控性:自定义摄像头参数(分辨率、帧率、曝光),优化资源占用;

  • 易集成性:与机器人主控(如STM32F4/F7)通过UART/USB无缝对接,支持自定义通信协议。

二、硬件设计

1. 核心硬件组成

模块 型号/参数 功能
主控制器 STM32H743VI(Cortex-M7,480MHz,2MB Flash,1MB RAM) 图像处理、算法运行、外设控制
摄像头 OV5640(500万像素,RGB565,DCMI接口) 图像采集(支持VGA@30fps、QVGA@60fps)
通信接口 UART3(TX=PB10,RX=PB11)、USB_OTG_FS 与机器人主控通信(UART)、调试(USB)
存储 16MB SPI Flash(W25Q128)、32MB SDRAM(IS42S16400J) 存储图像、程序、临时数据
电源 3.7V锂电池(1000mAh)+ TPS63020(DC-DC) 系统供电(3.3V/1.8V双电压域)

2. 系统架构

DCMI

图像数据

UART3

USB_OTG_FS

I2C1

GPIO

3.3V/1.8V

2.8V

DMA传输

OV5640摄像头

机器人主控 STM32F4

PC调试 OpenMV IDE

IMU MPU6050

LED/按键

电源管理

3. 关键电路设计

(1)DCMI摄像头接口(OV5640)
  • 引脚连接

    OV5640引脚 STM32H7引脚 功能
    SIOC PB8 I2C1_SCL(配置摄像头)
    SIOD PB9 I2C1_SDA
    VSYNC PA4 DCMI_VSYNC(场同步)
    HREF PA6 DCMI_HSYNC(行同步)
    PCLK PA8 DCMI_PIXCLK(像素时钟)
    D0-D7 PC6-PC9, PD3-PD6 DCMI数据线(8位并行)
  • 配置要点:DCMI接口设为8位数据、连续采集模式,DMA通道用DMA2 Stream1,优先级设为,确保图像数据无丢失。

(2)UART通信接口(与机器人主控)
  • 参数:波特率115200bps,8位数据位,1位停止位,无校验(8N1);

  • 抗干扰:TX/RX线加10kΩ上拉电阻,用TVS管(SMAJ3.3A) 防静电,走线长度<20cm。

三、软件设计(C语言实现)

1. 开发环境

  • IDE:STM32CubeIDE(V1.13.0)

  • :STM32 HAL库(V1.11.0)、OV5640驱动(自定义)、图像处理算法库(C语言实现)

  • 调试工具:ST-Link V2、OpenMV IDE(通过USB虚拟串口)

2. 主程序流程

#include "stm32h7xx_hal.h"
#include "ov5640.h"
#include "dcmi.h"
#include "dma.h"
#include "image_processing.h"
#include "uart_comm.h"

// 系统状态
typedef struct {
  uint8_t frame_ready;       // 图像帧就绪标志
  uint8_t* image_buffer;     // 图像数据缓冲区(QVGA: 320×240×2=153600字节)
  uint16_t width, height;    // 图像分辨率
} SystemState;

int main(void) {
  // 1. 系统初始化
  HAL_Init();
  SystemClock_Config();     // 配置系统时钟(480MHz)
  Periph_Init();            // 外设初始化(GPIO、I2C、DCMI、DMA、UART)
  OV5640_Init();            // 摄像头初始化(QVGA@30fps,RGB565)
  ImageProcessing_Init();   // 图像处理模块初始化
  UART_Comm_Init();         // 通信协议初始化

  // 2. 分配图像缓冲区(SDRAM)
  SystemState sys_state;
  sys_state.image_buffer = (uint8_t*)0xC0000000;  // SDRAM起始地址
  sys_state.width = 320;
  sys_state.height = 240;
  sys_state.frame_ready = 0;

  // 3. 启动DCMI+DMA采集
  DCMI_StartCapture(sys_state.image_buffer, sys_state.width * sys_state.height * 2);

  // 4. 主循环
  while (1) {
    if (sys_state.frame_ready) {
      // 4.1 图像处理(颜色识别+目标检测)
      TargetInfo target = Image_Process(sys_state.image_buffer, sys_state.width, sys_state.height);
      
      // 4.2 通信:发送目标信息给机器人主控
      UART_SendTargetInfo(&target);
      
      // 4.3 清除标志,准备下一帧
      sys_state.frame_ready = 0;
    }
    // 低功耗:无图像时进入Sleep模式
    else {
      HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
    }
  }
}

3. 关键模块实现

(1)摄像头驱动(OV5640,C语言)

通过I2C配置摄像头寄存器,实现分辨率、帧率、曝光参数设置:

// OV5640寄存器配置(QVGA@30fps,RGB565)
void OV5640_Init(void) {
  // 1. 软复位
  OV5640_WriteReg(0x3008, 0x82);
  HAL_Delay(100);
  OV5640_WriteReg(0x3008, 0x42);
  HAL_Delay(100);
  
  // 2. 配置DCMI时序(QVGA: 320×240)
  OV5640_WriteReg(0x3800, 0x00);  // HREF起始高8位
  OV5640_WriteReg(0x3801, 0x00);  // HREF起始低8位
  OV5640_WriteReg(0x3802, 0x00);  // VREF起始高8位
  OV5640_WriteReg(0x3803, 0x00);  // VREF起始低8位
  OV5640_WriteReg(0x3804, 0x01);  // HREF宽度高8位(320-1=319=0x013F)
  OV5640_WriteReg(0x3805, 0x3F);
  OV5640_WriteReg(0x3806, 0x00);  // VREF高度高8位(240-1=239=0x00EF)
  OV5640_WriteReg(0x3807, 0xEF);
  
  // 3. 设置输出格式(RGB565)
  OV5640_WriteReg(0x4300, 0x6F);  // RGB565
  OV5640_WriteReg(0x501F, 0x01);  // 输出格式选择
  
  // 4. 启动预览
  OV5640_WriteReg(0x4202, 0x00);  // 关闭自动对焦
  OV5640_WriteReg(0x3008, 0x02);  // 启动传感器
}

// I2C写寄存器
void OV5640_WriteReg(uint16_t reg, uint8_t data) {
  uint8_t buf[3] = {reg >> 8, reg & 0xFF, data};
  HAL_I2C_Master_Transmit(&hi2c1, OV5640_ADDR, buf, 3, 100);
}
(2)图像处理算法(C语言)
① 颜色识别(RGB转HSV+阈值分割)

将RGB565图像转换为HSV空间,通过阈值分割提取目标颜色(如红色):

// RGB565转HSV(简化版,忽略V通道)
void RGB565_to_HSV(uint16_t rgb, float* h, float* s) {
  // 提取R、G、B分量(RGB565: 高5位R,中6位G,低5位B)
  uint8_t r = (rgb >> 11) & 0x1F;
  uint8_t g = (rgb >> 5) & 0x3F;
  uint8_t b = rgb & 0x1F;
  // 归一化到0-1
  float r_norm = r / 31.0f, g_norm = g / 63.0f, b_norm = b / 31.0f;
  
  // 计算HSV
  float max = fmaxf(r_norm, fmaxf(g_norm, b_norm));
  float min = fminf(r_norm, fminf(g_norm, b_norm));
  float delta = max - min;
  
  *h = 0;
  if (delta > 0.001f) {
    if (max == r_norm) *h = 60 * fmodf((g_norm - b_norm)/delta, 6);
    else if (max == g_norm) *h = 60 * ((b_norm - r_norm)/delta + 2);
    else *h = 60 * ((r_norm - g_norm)/delta + 4);
  }
  if (*h < 0) *h += 360;
  
  *s = (max > 0) ? (delta / max) : 0;
}

// 颜色阈值分割(找红色目标)
Blob Find_Red_Blobs(uint8_t* image, uint16_t width, uint16_t height) {
  Blob max_blob = {0};
  for (uint16_t y=0; y<height; y++) {
    for (uint16_t x=0; x<width; x++) {
      uint16_t rgb = *(uint16_t*)(image + (y*width + x)*2);  // RGB565(小端)
      float h, s;
      RGB565_to_HSV(rgb, &h, &s);
      // 红色阈值:H=0-10°或350-360°,S>0.3
      if ((h < 10 || h > 350) && s > 0.3) {
        // 连通域分析(略),记录Blob位置、面积
        Update_Blob(x, y, &max_blob);
      }
    }
  }
  return max_blob;
}
② 形状检测(轮廓提取+圆度计算)

通过Canny边缘检测霍夫圆变换识别圆形目标:

// 霍夫圆检测(简化版)
Circle Find_Circle(uint8_t* edge_image, uint16_t width, uint16_t height) {
  Circle best_circle = {0};
  for (uint16_t r=10; r<50; r++) {  // 半径范围
    for (uint16_t x=r; x<width-r; x++) {
      for (uint16_t y=r; y<height-r; y++) {
        if (edge_image[y*width + x]) {  // 边缘点
          // 计算圆心(略),计算圆度(实际半径与理论半径偏差)
          float deviation = fabs(sqrtf((x-cx)*(x-cx)+(y-cy)*(y-cy)) - r);
          if (deviation < 2.0f) {  // 圆度阈值
            best_circle.x = cx; best_circle.y = cy; best_circle.r = r;
            return best_circle;
          }
        }
      }
    }
  }
  return best_circle;
}
(3)通信协议(UART数据打包,C语言)

自定义帧格式,确保数据可靠传输:

字段 帧头(0xAA) 类型(0x01=目标,0x02=障碍) 数据长度(1B) 数据(nB) 校验和(1B)
长度 1B 1B 1B 3-6B(目标x,y,面积) 1B

C语言实现帧打包

// 发送目标信息(x,y,面积)
void UART_SendTargetInfo(TargetInfo* target) {
  uint8_t frame[8];
  frame[0] = 0xAA;          // 帧头
  frame[1] = 0x01;          // 类型:目标
  frame[2] = 0x03;          // 数据长度:3字节(x,y,面积)
  frame[3] = target->x;     // x坐标(0-319,1字节)
  frame[4] = target->y;     // y坐标(0-239,1字节)
  frame[5] = target->area;  // 面积(0-255,1字节)
  // 校验和(异或)
  frame[6] = frame[0] ^ frame[1] ^ frame[2] ^ frame[3] ^ frame[4] ^ frame[5];
  frame[7] = 0x0A;          // 帧尾(换行符,可选)
  // 通过UART3发送
  HAL_UART_Transmit(&huart3, frame, 8, 100);
}

四、机器人主控(STM32F4)集成

1. 控制逻辑(C语言)

机器人主控通过UART接收目标信息,用PID算法控制电机实现目标跟踪:

// UART接收中断(解析OpenMV Cam发送的帧)
void USART2_IRQHandler(void) {
  if (USART_GetITStatus(USART2, USART_IT_RXNE)) {
    uint8_t data = USART_ReceiveData(USART2);
    if (data == 0xAA) {  // 帧头
      rx_buffer[0] = data;
      rx_index = 1;
    } else if (rx_index > 0 && rx_index < 8) {
      rx_buffer[rx_index++] = data;
      if (rx_index == 8) {  // 完整帧
        if (Check_Sum(rx_buffer)) {  // 校验和正确
          if (rx_buffer[1] == 0x01) {  // 目标类型
            TargetInfo target = {rx_buffer[3], rx_buffer[4], rx_buffer[5]};
            PID_Control(&target);  // PID控制
          }
        }
        rx_index = 0;
      }
    }
  }
}

// PID控制(差速转向)
void PID_Control(TargetInfo* target) {
  int error = target->x - 160;  // 目标x与图像中心(160)偏差
  int output = Kp*error + Ki*error_sum + Kd*(error - last_error);
  last_error = error;
  error_sum += error;
  // 控制左右电机
  motor_left = BASE_SPEED + output;
  motor_right = BASE_SPEED - output;
  Motor_SetSpeed(motor_left, motor_right);
}

参考代码 STM32 机器人视觉摄像机OpenMV Cam设计 www.youwenfan.com/contentcst/160972.html

五、系统测试与优化

1. 测试指标

参数 指标 测试方法
图像采集帧率 30fps@QVGA(RGB565) 示波器测量DCMI_PIXCLK周期(33ms/帧)
目标识别精度 ±3像素(目标直径>20像素) 固定目标,测量识别中心与实际中心偏差
通信延迟 <30ms(UART 115200bps) 发送-接收时间戳差(示波器抓包)
工作电流 150mA@3.3V(采集+处理) 万用表串联测量

2. 优化方向

  • DMA双缓冲:使用2个图像缓冲区,交替采集/处理,消除帧等待时间;

  • 算法轻量化:用查表法替代浮点运算(如RGB转HSV的H分量查表),用定点数优化圆度计算;

  • 低功耗:无目标时关闭DCMI时钟,STM32H7进入Stop模式(电流<5mA);

  • 抗干扰:图像数据加CRC16校验,通信线用屏蔽双绞线,摄像头电源加磁珠滤波

六、总结

本设计用C语言实现了基于STM32H7的OpenMV Cam视觉摄像机,通过DCMI+DMA高效采集图像,C语言算法实现颜色/形状识别,结合UART通信与机器人主控协同工作,具备实时性、高效性、易集成特点。系统可扩展为多目标跟踪、AprilTag定位、SLAM导航等复杂应用,为机器人视觉提供低成本、高可靠的解决方案。

Logo

DAMO开发者矩阵,由阿里巴巴达摩院和中国互联网协会联合发起,致力于探讨最前沿的技术趋势与应用成果,搭建高质量的交流与分享平台,推动技术创新与产业应用链接,围绕“人工智能与新型计算”构建开放共享的开发者生态。

更多推荐