加入星计划,您可以享受以下权益:

  • 创作内容快速变现
  • 行业影响力扩散
  • 作品版权保护
  • 300W+ 专业用户
  • 1.5W+ 优质创作者
  • 5000+ 长期合作伙伴
立即加入

【RT‐Thread 作品秀】基于RT‐Thread的网络照相机

2020/12/19
1372
服务支持:
技术交流群

完成交易后在“购买成功”页面扫码入群,即可与技术大咖们分享疑惑和经验、收获成长和认同、领取优惠和红包等。

虚拟商品不可退

当前内容为数字版权作品,购买后不支持退换且无法转移使用。

加入交流群
扫码加入
获取工程师必备礼包
参与热点资讯讨论
放大
方块图(2)
  • 方案介绍
  • 相关文件
  • 相关推荐
  • 电子产业图谱
申请入驻 产业图谱

【RT-Thread 作品秀】基于RT-Thread的网络照相机

作者:吴顶顶

概述

随着科技的进步和互联网的发展,基于物联网的可拍照设备也越来越多的融入到人们的生活中来,例如在超市中,管理者利用拍照设备定时抓取货架照片,分析货物状态,并补充、优化货物摆放;在酒吧里,管理者会利用拍照设备定时抓拍酒架照片,传送到网络平台供大众浏览,以招揽更多顾客。本网络照相机基于STM32H7+RTThread平台,采集摄像头数据,并通过无线网络传送到服务器,提供SD卡配网、手动拍摄、定时拍摄、照片推送等功能,并提供windows上位机提供控制和照片显示功能。

主要功能有:

格式化sd卡:格式化sd卡,但是会保留网络配置文件,其他文件全部删除
设备重启:重启设备
实时拍照:发送指令给照相机,照相机拍照,并把照片回传
定时拍照:照相机依据下发的拍照时间,在时间到达时拍摄一张照片,并传给服务器
按键拍照:点击板上用户按钮,拍摄一张照片,并传给服务器
定时任务:可以新建/删除/查询定时拍照任务,任务存储在sd卡中,重启有效

开发环境

硬件:ART-PI(STM32H750主控)+ OV2640模组
RT-Thread版本:4.0.3
SDK 版本:1.0.1
开发工具及版本:RT-Thread Studio 1.1.5, Qt5.14.0

RT-Thread使用情况概述

内核部分:调度器,信号量,互斥锁,内存管理

调度器:多任务调度
信号量:用于唤醒对应任务
互斥锁:用于互斥资源独占访问
内存管理:动态内存申请与释放

组件部分:虚拟文件系统,IPCI2C,RTC,NTP

虚拟文件系统:文件操作,sd卡、照片文件
IPC:mqtt发送数据需要
I2C:配置摄像头模块需要
RTC和NTP:同步时间

软件包部分:paho mqtt,cJSON,netutils

pahomqtt:用于和服务器通信
cJSON:解析、封装mqtt消息
netutils:NTP网络对时

其他:base64

用于将图片文件转换成字符串,便于mqtt传输

硬件框架

总体的硬件框架如下图所示:

 

本网络摄像机硬件结果较为简单,即art-pi连接一个摄像头模组,art-pi板上用到了AP6212无线模块,外部内存,led指示灯,和sd卡。其中,摄像头模块用于采集图像信号;AP6212用于和服务器进行通信;因一张图像数据量较大,片内内存不够,故而使用外部内存;led灯用于指示设备工作状态;sd卡用于保存网络、服务器、和定时任务配置。

软件框架说明

整体的软件框架如下图所示,网络照相机内部有一个proxy线程,负责和云端进行通信,在接收到云端消息后会解析,并分发到其他的线程执行,然后将执行结果返回到云端;照相机发生了其他的事件,例如用户按键拍照,也会将数据传给proxy线程,proxy线程再将数据发送到云端。用户通过上位机终端软件连接上云服务器,实现与照相机的通信及控制。

整个系统支持接入多个照相机,如下图所示,不同的照相机通过sd卡配置文件中sn进行区分,上位机软件可以显示所有在线的照相机,但同一时间只支持操作一个。

软件模块说明

1. 用户线程创建流程

如下图所示为用户线程创建流程

用户线程作用描述如下:
main:用于创建sd_card 线程,检测按键事件,闪灯;
sd_card:用于管理与sd卡相关的工作,包括拍照,网络配置,定时任务;
network:负责联网,根据sd卡的配置文件连接到指定的wifi网络;
proxy:负责启动mqtt,并管理与云端的通信,其他线程都需要通过proxy线程与云端交互数据;
event:定时任务和按键任务,在定时时间到达时,或者用户按键时拍摄照片并通过proxy上传云端。

2. 通信接口及流程

2.1 MQTT订阅主题

  • 设备向服务器订阅主题:
    /ter/query/discovery,用于接收设备发现消息
    /ter/sn/request,用于接收针对该设备的指令,其中sn为设备的SN号,下同

  • 客户端向服务器订阅主题:
    /dev/response/discovery,用于接收设备发现回复
    /dev/response/will,用于接收设备遗嘱消息
    /dev/sn/response,用于接收设备操作指令回复
    /dev/sn/event,用于接收设备的通知

2.2 设备发现

所有的设备均订阅/ter/query/discovery主题,客户端向该主题发布发现消息,所有收到消息的设备向/dev/response/discovery回复一条消息,而客户端又订阅了/dev/response/discovery主题,故而便可以知道哪些设备在线了。
设备连上服务器的时候,会定义一个遗嘱消息,主题为/dev/sn/will,客户端订阅了该主题,当设备因为某些原因掉线,则超过一定时间之后,客户端便可收到该消息,进而知道该设备掉线。

  • 客户端发起设备发现流程,topic: /ter/query/discovery
{
    "params": {
        "code": "0x01",
        "param": {}
    },
    "ecode": 0
}
  • 设备端回复发现命令,topic: /dev/response/discovery
{
    "params": {
        "code": "0x01",
        "sn":"SN-1234",
        "param": {
            "ip":"192.168.1.100",
            "mac":"01:0F:0A:0B"
        }
    },
    "ecode":0
}
  • 设备端掉线通知,topic: /dev/response/will
{
    "params": {
        "code": "0x11",
        "sn": "SN-1234",
        "param": {}
    },
    "ecode":0
}

2.3 摄像机操作

客户端订阅/dev/sn/response,并通过 /ter/sn/request发送请求指令,设备端订阅 /ter/sn/request,并通过/dev/sn/response返回操作结果,进而实现客户端对设备端的操作。
客户端和设备端通过消息中的code字段区分不同的操作。

  • 设备重启指令,topic: /ter/sn/request
{
    "params": {
        "code": "0x21",
        "param": {}
    },
    "ecode":0
}
  • 设备重启指令回复,topic: /dev/sn/response
{
    "params": {
        "code": "0x21",
        "sn": "SN-1234",
        "param": {
            "action":1    //1,重启;0,不重启
        }
    },
    "ecode":0
}
  • 格式化sd卡指令,topic: /ter/sn/request
{
    "params": {
        "code": "0x22",
        "param": {}
    },
    "ecode":0
}
  • 格式化sd卡指令回复,topic: /dev/sn/response
{
    "params": {
        "code": "0x22",
        "sn": "SN-1234",
        "param": {
            "result":1    //1,成功;0,失败
        }
    },
    "ecode":0
}
  • 实时截图指令,topic: /ter/sn/request
{
    "params": {
        "code": "0x23",
        "param": {}
    },
    "ecode":0
}
  • 实时截图回复,topic: /dev/sn/response
{
    "params":{
        "code": "0x23",
        "sn": "SN-1234",
        "param": {
            "result":1,      //截图结果,1-成功,0-失败
            "time":1235,
            "pic":"xxxx"    //base64编码后的图片字符串,成功时才有
        }
    },
    "ecode":0
}
  • 下发截图定时任务,topic: /ter/sn/request
{
    "params":{
        "code": "0x24",
        "param": {
            "total": 3,
            "time_list":[
                1234,
                1244,
                1254
            ]
        }
    },
    "ecode":0
}
  • 下发截图定时任务回复,topic: /dev/sn/response
{
    "params": {
        "code":"0x24",
        "sn": "SN-1234",
        "param":{
            "result":0
        }
    }
    "ecode":0
}
  • 查询截图定时任务,topic: /ter/sn/requestsn为设备的SN号
{
    "params": {
        "code": "0x25",
        "param":{}
    }
    "ecode":0
}
  • 返回查询定时任务结果,topic: /dev/sn/response
{
    "params": {
        "code":"0x25",
        "sn":"SN-1234",
        "param": {
            "result":1, 1--查询正常,0--查询出错
            "total":3,
            "time_list":[
                1234,
                1244,
                1254
            ]
        }
    },
    "ecode":0
}
  • 删除截图定时任务,topic: /ter/sn/request
{
    "params": {
        "code": "0x26"
        "param":{
            "total":3,
            "time_list":[
                1234,
                1244,
                1254
            ]
        }
    }
    "ecode":0
}
  • 返回删除定时任务结果,topic: /dev/sn/response
{
    "params": {
        "code":"0x26",
        "sn":"SN-1234",
        "param": {
            "result":0
        }
    },
    "ecode":0
}

2.4 摄像机通知

客户端订阅/dev/sn/event主题,当设备端发生某些事件(目前只有定时拍照事件和按键拍照事件)的时候,向该主题发布一条消息,客户端进而刷新显示。

  • 定时/按键照相通知,topic: /dev/sn/eventsn为设备的SN号
{
    "params": {
        "code":"0xF0",
        "sn":"SN-1234",
        "param": {
            "type":0,    //1,定时截图; 2,按键截图
            "pic":"xxx"
        }
    }
    "ecode":0
}

演示效果

演示视频

拍照功能

定时拍照任务

实物图

比赛感悟

本次比赛主要学习了RT-Thread嵌入式操作系统的使用方法,学习了RT-Thread线程创建以及线程通信方法,学习了stm32 dcmi接口获取摄像头图像的方法。
在项目的过程中遇到了很多困,有些解决了,典型的有一下两个:

  1. ov2640驱动,sdk代码上没有开启dma中断,导致使用sdk源码始终无法获取到图片,困扰了好久,最后不得不去读stm32芯片手册,ov2640模块手册,并参考开源代码,最后找到了问题根源,解决了该问题;
  2. mqtt不能发送超过512字节的数据,原因在于默认IPC pipo最大只能传512字节,而且ringbuf采用了一个16位的变量作为长度,并且最高位作为一个镜像的标记,进而理论上一次性最大只能传输32768字节数据,仍不足以传输一张照片,最后通过讲ringbuf改为32字节作为长度,讲IPC pipo最大长度设置位65535,成功解决了该问题。

也有一些问题没能解决,最后通过其他手段绕过去了,典型有:

  1. sqlite数据有问题,不能用,sqlite数据库可以成功的创建数据库和数据表,但是线程一旦进入循环,便不能操作了,包括数据插入和数据表创建,该问题原因未知,最后也没能解决,便没有存储照片索引到本地sd卡;
  2. sd卡驱动有些问题,在线程中存储的照片过多,便会出现错误的文件,并且后续的照片基本都保存不成功,该问题也未能找到原因,没能解决,便没有存储照片到本地,二是作为照片缓存,只保存一张,传到服务器。

本次比赛让我认识到学无止尽,开源世界需要我们每个人都添砖加瓦,才能变得更好。

  • 代码地址.txt
    描述:代码地址
  • 【RT‐Thread 作品秀】基于RT‐Thread的网络照相机.pdf
    描述:设计文档

相关推荐

电子产业图谱