0.废话前言
话说ESP32-CAM有多少人在用呢?
这种东西,属于是......
爱用不想用
虽然说扩展性很强,但是程序是真不爱写。
虽然说能联网,能拍照,但是FPS也太低了...
(话说ov2640是真的辣鸡)
那么回归主题
1.环境搭建
1-~.材料
ESP32-CAM(带ov2640摄像头) | ![]() |
CH340 USB转TTL模块 | ![]() |
两母头杜邦线 | ![]() |
开关(焊有杜邦线,选配) | ![]() |
1-a.安装Thonny
很简单,去Thonny官方下载对于你的系统比较合适的版本,我这里用的是Windows的Python3.10版本,下的慢的可以看我的文章顶部的Thonny下载。
1-b.安装固件
打开Thonny,点击右下角的<No backend>(也有可能是别的):
点击<配置解释器>:
点击<安装或更新 MicroPython (esptool)>:
点击三个小横线(窗口左下角可能会报Error!不用管,我们用不到自带下载的固件):
点击<Select local MicroPython image>:
然后去下载Micropython ES32-CAM固件,国内的GitCode,各位应该能下,或者看文章顶部的资源。
回到刚才的选择文件,选择刚下的固件:
然后将ESP32-CAM连接到USB转TTL模块上,连接方法:
USB转TTL模块 | ESP32-CAM模块 |
5V | 5V |
TXD/UOT | RXD |
RXD/UOR | TXD |
GND | GND |
特殊:ESP32-CAM的IO0 | GND |
将USB转TTL模块接到电脑上:
打开设备管理器
查看端口号:
(端口号多数人不会一样)
单击安装:
然后就开始下载固件了:
过程比较慢,稍等一会就好了(如果TimeOut报错或者没有回应数据,就检查你的IO0有没有接到GND上并复位,就是那个复位小按键,接好后上电按下再试试):
完成后拔下IO0接GND的那根线,按下复位键或重新上电,再关闭其他弹窗,点击Thonny右下角的按钮,选择<MicroPython (ESP32) · USB Serial @ 你的端口号>:
然后就好啦!
2.示例
2-a.拍照
import camera # 导入ESP32-CAM专用固件的特殊摄像库
camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM) # 初始化摄像头,fb_location是设置存储在哪个临时RAM(camera.RAM和camera.PSRAM,PSRAM更大但有些设备不支持,可自行设置)
camera.quality(10) # 设置质量,10为最好,63为最差
camera.framesize(camera.FRAME_SVGA) # 设置分辨率,见官方文档,FHD最佳(1920*1080),此处用到的为800*600
buf = camera.capture() # 拍照(buf为图片二进制数据,不要晃动摄像头,快门需要时间)
camera.deinit() # 反初始化摄像头,释放临时RAM,防止再次运行此程序导致重复初始化报错或RAM占用过多报错
with open(f"Photo.jpg", "wb") as f: # 打开并覆盖文件
f.write(buf) # 写入数据
# 温馨提示:有时初始化后第一张照片会偏色(我的是绿色)可以写程序再次拍照(再次拍照不用反初始化)
# 曝光不足也有可能偏色
2-b.录像
由于文件较大,使用了Micro SD卡,请提前插入Micro SD卡
声明一点:ESP32-CAM最好使用FAT32文件系统,格式化时选择,务必备份,本人不承担任何因为自行格式化导致数据丢失的责任!
.H264文件需要自行转为MP4,ESP32-CAM无法输出MP4
import camera
import time
from machine import SDCard
# 初始化相机
camera.init(0, format=camera.JPEG)
# 挂载 SD 卡(不需要可以注释掉)
uos.mount(SDCard(), '/sd')
# 设置相机参数
camera.framesize(camera.FRAME_SVGA) # 设置分辨率
camera.quality(10) # 设置图片质量
# 开始录像
camera.start_recording('/sd/video.h264') # 指定录像文件路径(不要SD卡可以将"/sd"删除)
# 录像一段时间
time.sleep(10)
# 停止录像
camera.stop_recording()
# 释放资源
camera.deinit()
uos.umount('/sd') # 不需要可以注释掉
2-c.网络服务器
别忘了改网络SSID和密码
import network
import socket
import camera
import image
import time
# 连接到Wi-Fi网络
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
wlan.connect('SSID', 'Password') # 改为你的网络SSID和密码
while not wlan.isconnected():
time.sleep(1)
print('WiFi connected')
print('IP address:', wlan.ifconfig()[0])
# 初始化摄像头
camera.init(0, format=camera.JPEG)
camera.framesize(camera.QVGA) # 设置分辨率为QVGA
camera.quality(90) # 设置JPEG质量
# 创建Web服务器
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(('', 80))
s.listen(1)
print('Listening on socket...')
conn, addr = s.accept()
print('Connected by', addr)
while True:
# 捕获图像
img = camera.capture()
img_bytes = img.to_bytes()
# 发送图像
conn.send(img_bytes)
2-d.我自己做的微型相机
硬件:按钮两头一端接3.3V(有可能标为3V3,是ESP32-CAM模块上的),一头接IO12
为了防止内存爆炸与偏色,使用了闪光灯、第一次重复拍照以及次数限制(20张),不可使用SD卡,因为会与闪光灯冲突(顺手做了个板载指示灯)
不要忘记提前创建pic文件夹
from machine import Timer, Pin
import os
# enable station interface and connect to WiFi access point
import camera
import time
(ST_INIT, ST_READY, ST_BUSY) = (300, 0, 100)
num = 0
is_t = False
def toggle_led(led_pin):
led_pin.value(not led_pin.value())
def led_blink_timed(timer, led_pin, state):
if state == 'READY':
timer.deinit()
led_pin.value(ST_READY)
elif state == 'INIT':
timer.init(period=ST_INIT, mode=Timer.PERIODIC, callback=lambda t: toggle_led(led_pin))
elif state == 'BUSY':
timer.init(period=ST_BUSY, mode=Timer.PERIODIC, callback=lambda t: toggle_led(led_pin))
else:
print('not define yet')
# 声明引脚 D2 作为LED的引脚
led_pin = Pin(33, Pin.OUT)
lighter = Pin(4, Pin.OUT)
press = Pin(12, Pin.IN, Pin.PULL_DOWN)
timer = Timer(1) # 创建定时器对象
# 定时器触发
led_blink_timed(timer, led_pin, state='INIT')
# camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM)
# camera.quality(10)
# camera.framesize(camera.FRAME_SVGA)
led_blink_timed(timer, led_pin, state='READY')
def take_photo():
camera.init(0, format=camera.JPEG, fb_location=camera.PSRAM)
camera.quality(10)
camera.framesize(camera.FRAME_SVGA )
led_blink_timed(timer, led_pin, state='BUSY')
global num
if num >= 20:
lighter.value(1)
time.sleep(0.1)
lighter.value(0)
time.sleep(0.1)
lighter.value(1)
time.sleep(0.1)
lighter.value(0)
time.sleep(0.1)
return
if num == 0:
lighter.value(1)
time.sleep(0.1)
buf = camera.capture()
with open(f"Photo{num}.png", "wb") as f:
f.write(buf)
print("FA")
camera.quality(10)
camera.framesize(camera.FRAME_SVGA)
time.sleep(0.1)
buf = camera.capture()
camera.deinit()
with open(f"Photo{num}.png", "wb") as f:
f.write(buf)
print("Suc")
num += 1
time.sleep(0.3)
lighter.value(0)
led_blink_timed(timer, led_pin, state='READY')
return
lighter.value(1)
time.sleep(0.1)
buf = camera.capture()
camera.deinit()
with open(f"Photo{num}.png", "wb") as f:
f.write(buf)
print("Suc")
num += 1
time.sleep(0.3)
lighter.value(0)
led_blink_timed(timer, led_pin, state='READY')
def copy(std, tdd):
with open(std, "rb") as fs:
with open(tdd + "/" + std.split("/")[-1], "wb") as f:
f.write(fs.read())
def cf(folder_path="./", extension="png", td="./pic"):
for filename in os.listdir(folder_path):
if filename.endswith(extension):
file_path = folder_path + "/" + filename
copy(file_path, "pic")
def df(folder_path="./", extension="png"):
for filename in os.listdir(folder_path):
if filename.endswith(extension):
file_path = folder_path + "/" + filename
os.remove(file_path)
df(folder_path="./pic")
cf()
df()
while True:
if press.value() == 1:
if is_t:
continue
take_photo()
is_t = True
else:
is_t = False
3.总结
什么也没有......(多看官方文档!)