仔爸 发表于 2023-9-12 20:27:50

网络照相机-FireBeetle 2 ESP32-S3+CircuitPython+OV2640摄像头

本帖最后由 仔爸 于 2023-9-12 20:28 编辑

  经过N天的熬夜肝项目,终于在碰到无数个困难之后,完成了一个还算过得去的小项目。本项目将展示通过电脑上的一款通信软件通过网络发送指定的命令字符,FireBeetle 2 ESP32-S3(以下简称ESP32-S3)通过无线接收消息命令,并实现拍照并存储的功能。一、准备工作之前打算采用一直在使用的MicroPython(以下简称Mpy)在ESP32-S3上进行编程,但本次项目采用了CircuitPython(以下简称Cpy),因为Mpy目前无法实现拍照(书到用时方恨少)。至于如何将Cpy烧录到ESP32-S3上,请参考此文:《基于CircuitPython实现的FireBeetle 2 ESP32-S3延时相机》,我不再赘述。另外仔爸本来打算采用网络进行图像传输,结果尝试了无数种方案也没有成功,留待以后学习完善。(主要是Cpy与Mpy库的使用差别较大,学习较慢)。不成功的想法:1.   ESP32-S3拍照后通过UDP套接字将照片文件传输到电脑;2.   ESP32-S3拍照后通过UDP套接字将图像数据传输到电脑并保存在文件;3.   ESP32-S3拍照后直接以流媒体的方式通过网络传输到电脑服务端进行展示(视频展示);4.   使用SioT物联网来控制ESP32-S3上的摄像头进行拍照(SioT.py是基于Mpy的,移植到Cpy目前吃不消);5.   在网络上(国内国外,github,gitee)搜索了无数个基于ESP32驱动OV2640摄像头拍照的代码,不成功。最后仔爸只能退而求其次,在PC端采用“网络调试助手”以UDP的方式向ESP32-S3发送字符命令,ESP32-S3接收发过来的字符进行拍照并保存。二、实现原理有了初步想法之后,我们需要明白一些基本原理,并对这个想法实例化。这里我们将PC作为发送端,而ESP32-S3是接收端,中间通过UDP协议进行信息的传递。PC端不需要编程,下载“网络调试助手”即可。因此重点是在ESP32-S3上完成消息接收和拍照两个主要功能。三、实现消息传递消息传递是基于Wifi无线网络的,在Mpy中使用network模块,而在Cpy中则使用wifi模块。按照Cpy帮助文档和一些样例中的写法,首先在ESP32-S3的根目录创建一个secrets.py的文档用于存储要连接的无线网络的ssid和password。如下:secrets = {

    'ssid':'无线网络标识',

    'password':'密码',

}
以下代码实现无线网络的连接并且显示本机IP:#连接无线网络

try:

    from secrets import secrets#获取无线网络的ssid和password

except ImportError:

    print("WiFi secrets are kept in secrets.py, please add them there!")

    raise

print("Connecting to WiFi...")

wifi.radio.connect(secrets["ssid"], secrets["password"])#连接无线网络

print("Connected to WiFi!")

print(wifi.radio.ipv4_address)#显示本机IP地址

Mpy中使用socket库来实现网络通信,而在Cpy中没有该库,但有一个socketpool库(为什么要改不同的名字和方法呢?),其功能与Mpy中的socket相差不大,但因为名字和模块里面的方法使用不同,增加了学习的难度,只能硬着头皮查Cpy的文档资料。我们在ESP32-S3中编程实现通过UDP进行数据通信,实现发送和接收两个功能。为什么还要发送呢?这是为了让“网络调试助手”接收到ESP32-S3的消息,并明确ESP32-S3的发送端口。代码如下:pool = socketpool.SocketPool(wifi.radio)

s = pool.socket(pool.AF_INET, pool.SOCK_DGRAM)#SOCK_DGRAM是UDP协议,SOCK_STREAM是TCP协议

s.connect((HOST,PORT))

s.sendto("ready take",(HOST,PORT))   #发送字符串

buf=bytearray(100) #设定一个接收数据的长度,其实如果用1或0表示,则这个数字可以更小

s.recv_into(buf) #接收消息

print(buf.decode())


s.close()
四、根据命令拍照实现了PC和ESP32-S3之间消息的传递,接下来我们只要根据接收到的指定消息命令实现拍照,并且将拍的照片以图片的文件方式存储在板子上即可。在ESP32-S3上刷了Cpy是为了使用里面的espcamera模块,否则就直接使用Mpy了。再配合Dfrobot提供的AXP313A电源芯片管理模块,实现拍照。这里要使用了board、busio、time、espcamera等系统模块,还要用到AXP313A模块(需手工上传到板子上)。# 数据引脚定义 data pins

CAMERA_DATA = (

    board.GPIO39,

    board.GPIO40,

    board.GPIO41,

    board.GPIO4,

    board.GPIO7,

    board.GPIO8,

    board.GPIO46,

    board.GPIO48

)



# 控制引脚定义 controll pins

CAMERA_PCLK=board.GPIO5

CAMERA_VSYNC=board.GPIO6

CAMERA_HREF=board.GPIO42

CAMERA_XCLK=board.GPIO45



# 延时函数定义 delay function

delay = lambda n: time.sleep(n/1000)



print("i2c init")

try:

    i2c = busio.I2C(scl=board.GPIO2, sda=board.GPIO1)#初始化I2C

except Exception as e:

    i2c.deinit()



while not i2c.try_lock():

    print("try lock");

    delay(1000)

i2c.unlock()



delay(1000)

print("AXP313A init")

axp = AXP313A.AXP313A(i2c)



delay(1000)

print("AXP313A begin")

while not axp.begin():

    print("init error");

    delay(1000)



delay(1000)

print("AXP313A enable_camera_power")

axp.enable_camera_power(AXP313A.eOV2640) # 设置摄像头供电 power on

delay(1000)



print("Initializing camera")

cam = espcamera.Camera(#espcamera模块中的Camera方法的参数有点吓人

    data_pins=CAMERA_DATA,

    external_clock_pin=CAMERA_XCLK,

    pixel_clock_pin=CAMERA_PCLK,

    vsync_pin=CAMERA_VSYNC,

    href_pin=CAMERA_HREF,

    pixel_format=espcamera.PixelFormat.JPEG,#RGB565,#

    frame_size=espcamera.FrameSize.QVGA,

    i2c=i2c,

    external_clock_frequency=20_000_000,

    framebuffer_count=1)

print("initialized")



buf = cam.take(1)#拍照

print("capture")

fname = f'test_01.jpg'   #存储文件

with open(fname, "wb") as f:


    f.write(buf)

完整的源程序下载,除了提供的网络调试助手,其他均需上传到ESP32-S3板子上:

页: [1]
查看完整版本: 网络照相机-FireBeetle 2 ESP32-S3+CircuitPython+OV2640摄像头