三、软件介绍1)遥控器
我们做了一个微信小程序,用来控制蓝牙小车行动并实时显示摄像头拍摄的画面,详见《》。
使用效果(摄像遥控小车怼扫地机器人):
2)小车程序
小车程序一共包含电机控制、摄像头、SD卡、OLED等模块。因小车需要使用蓝牙遥控,并使用WIFI进行图像传输,所以我们使用了双线程,分别控制,避免干扰。程序代码分解如下:
① 导入相关库,调整CPU频率:
from machine import Pin,freq,SDCard,Timer,SoftI2C
from time import sleep_ms,sleep
import bluetooth,network,camera,_thread,ssd1306,ufont
from microdot import Microdot
# 设置CPU的工作频率为 240 MHz
freq(240000000)
设置CPU的频率可以提高图像效果。
② 初始化OLED:
# 初始化OLED
i2c = SoftI2C(scl=Pin(4), sda=Pin(5))
display = ssd1306.SSD1306_I2C(128, 64, i2c) # 定义oled
font = ufont.BMFont("unifont-14-12917-16.v3.bmf") # 定义字体库
相关驱动详见《》。
③ 初始化SD卡,使用SDIO协议:
# 初始化SD卡
sd = SDCard(
slot=1 , width=1, cd=None, wp=None,
sck=1,miso=3,mosi=2,
cs=None ,freq=20000000
) #定义SD卡
os.mount(sd, '/sd') #挂载SD卡
参考《》。
④ 定义小车电机引脚和动作函数:
''' 定义小车电机引脚和动作函数 '''
Left0 = Pin(6,Pin.OUT) # O6引脚,左前轮电机向前
Left1 = Pin(7,Pin.OUT) # O7引脚,左前轮电机向后
Right0 = Pin(41,Pin.OUT) # 41引脚,右前轮电机向前
Right1 = Pin(42,Pin.OUT) # 42引脚,右前轮电机向后
# 车向前进
def cargo():
Left1.value(1)
Left0.value(0)
Right1.value(1)
Right0.value(0)
# 车向后退
def carback():
Left1.value(0)
Left0.value(1)
Right1.value(0)
Right0.value(1)
# 车停止
def carstop():
Left1.value(0)
Left0.value(0)
Right1.value(0)
Right0.value(0)
# 车向左转
def carleft():
Left1.value(0)
Left0.value(1)
Right1.value(1)
Right0.value(0)
# 车向右转
def carright():
Left1.value(1)
Left0.value(0)
Right1.value(0)
Right0.value(1)
参考《》。
⑤ 初始化摄像头,定义拍照、网页图传相关函数:
i=0
'''定义网页图传相关函数,以及一些定义'''
#拍照
def take_picture():
global i
i = i+1
buf = camera.capture()
with open('/sd/{}.jpg'.format(i),'wb') as f:
f.write(buf)
print("拍照成功!")
sleep(0.01)
def connect():
wlan = network.WLAN(network.STA_IF)# 定义模式为连接热点
wlan.active(True)
if not wlan.isconnected(): #是否连接热点
wlan.connect('SSID', 'password') #连接网络,SSID和password改成目前的2.4G网络的名称(SSID)和密码(password)
while not wlan.isconnected():
pass
connect() # 联网
wlan = network.WLAN(network.STA_IF)# 定义模式为连接热点
ifconfig = wlan.ifconfig() # 获取网络信息
font.text(display, '请在浏览器打开:', 0, 0, show=True,clear=True, auto_wrap=True)
font.text(display, str('{}:5000'.format(ifconfig[0])), 0, 16,show=True, auto_wrap=True) # 提示网页图传的对应网址
app = Microdot() # 定义构建网站变量。
# 初始化摄像头
cam = camera.init(0, d0=38, d1=47, d2=14, d3=13, d4=12, d5=11, d6=10, d7=9,
format=camera.JPEG, framesize=camera.FRAME_HVGA,fb_location=camera.PSRAM,
xclk_freq=camera.XCLK_20MHz,
href=18, vsync=17, reset=8, pwdn=-1,
sioc=16, siod=15, xclk=40, pclk=39)#y2-d0
#调整camera参数
camera.brightness(2)
camera.contrast(2)
camera.quality(10)
camera.speffect(camera.EFFECT_NONE)
#camera.whitebalance(camera.WB_CLOUDY)
# 定义网站html代码。
def index(request):
return '''
ESP32S3蓝牙小车网页图传
ESP32S3蓝牙小车网页图传:
''', 200, {'Content-Type': 'text/html; charset=utf-8'}
# 网页图传
def video_feed(request):
def stream():
yield b'--framern'
while True:
frame = camera.capture()
yield b'Content-Type: image/jpegrnrn' + frame +
b'rn--framern'
return stream(), 200, {'Content-Type':
'multipart/x-mixed-replace; boundary=frame'}
参考《》。
⑥ 初始化蓝牙模块:
BLE_MSG = ""
class ESP32_BLE():
#蓝牙初始化
def __init__(self, name):
self.led = Pin(48, Pin.OUT) #配置LED灯引脚为输出模式
self.timer1 = Timer(0) #配置定时器
self.name = name
self.ble = bluetooth.BLE() #创建蓝牙对象
self.ble.active(True) #开启蓝牙
self.ble.config(gap_name=name) #配置蓝牙信息
self.disconnected() #设置定时器中断
self.ble.irq(self.ble_irq) #蓝牙时间处理
self.register() #配置蓝牙的uuid
self.ble.gatts_write(self.rx, bytes(100))#默认蓝牙只接收20字节,这里更改为接收100字节
self.advertiser() #蓝牙广播
self.ok = 0
#蓝牙连接,关闭LED灯
def connected(self):
self.timer1.deinit()
self.led.value(0)
print("connected ok")
#蓝牙未连接,LED闪烁
def disconnected(self):
self.timer1.init(period=100, mode=Timer.PERIODIC, callback=lambda t: self.led.value(not self.led.value()))
#蓝牙事件处理
def ble_irq(self, event, data):
global BLE_MSG
if event == 1: #_IRQ_CENTRAL_CONNECT 手机连接了此设备
self.connected()
elif event == 2: #_IRQ_CENTRAL_DISCONNECT 手机断开此设备
if self.ok==0:
self.advertiser()
self.disconnected()
elif event == 3: #_IRQ_GATTS_WRITE 手机发送了数据
buffer = self.ble.gatts_read(self.rx)
BLE_MSG = buffer.decode('UTF-8').strip()
#蓝牙UUID配置
def register(self):
service_uuid = '6E400001-B5A3-F393-E0A9-E50E24DCCA9E'
reader_uuid = '6E400002-B5A3-F393-E0A9-E50E24DCCA9E'
sender_uuid = '6E400003-B5A3-F393-E0A9-E50E24DCCA9E'
services = (
(
bluetooth.UUID(service_uuid),
(
(bluetooth.UUID(sender_uuid), bluetooth.FLAG_NOTIFY),
(bluetooth.UUID(reader_uuid), bluetooth.FLAG_WRITE),
)
),
)
((self.tx, self.rx,), ) = self.ble.gatts_register_services(services)
#蓝牙广播配置
def advertiser(self):
name = bytes(self.name, 'UTF-8')
adv_data = bytearray(b'x02x01x02') + bytearray((len(name) + 1, 0x09)) + name
self.ble.gap_advertise(100, adv_data)
print("等待连接:%s" % adv_data)
print("rn")
⑦ 定义线程1,启动网页图传:
'''定义线程1网页图传函数'''
def main_cam(*args, **kwargs):
app.run(debug=True)#启动网页,并执行前面的网页图传相关函数
⑧ 定义线程2,启动蓝牙小车:
'''定义线程2蓝牙小车函数'''
def main_car(*args, **kwargs):
global BLE_MSG,e
try:
# 车先待命
carstop()
# 配置蓝牙
ble = ESP32_BLE("ESP32S3BLE")
# 配置LED
led = Pin(48, Pin.OUT)
while True:
if len(BLE_MSG)>0:
if BLE_MSG in ["!B507","!B606","!B705","!B804","!B10;","!B20:","!B309","!B408","stop"]: #松开按键停止
print(">>%s<<————停止" % BLE_MSG)
carstop()
elif BLE_MSG in ["!B516","upup"]: # 按下小程序的上键向前
print(">>%s<<————向前" % BLE_MSG)
cargo()
elif BLE_MSG in ["!B615","down"]: # 按下小程序的下键向后
print(">>%s<<————向后" % BLE_MSG)
carback()
elif BLE_MSG in ["!B714","left"]: # 按下小程序的左键向左运动
print(">>%s<<————向左" % BLE_MSG)
carleft()
elif BLE_MSG in ["!B813","right"]: # 按下小程序的右键向右运动
print(">>%s<<————向右" % BLE_MSG)
carright()
elif BLE_MSG in ["!B11:","act1"]: # 按下小程序的A键拍照
print(">>%s<<————拍照" % BLE_MSG)
take_picture()
BLE_MSG = ""
sleep_ms(100)
except KeyboardInterrupt:
pass
按键A用来拍照,并保存一张照片到SD卡上。按键B暂时没有设计。
⑨ 最后是主函数和执行代码:
'''定义主函数'''
def main():
thread_1 = _thread.start_new_thread(main_cam, (None,)) #定义线程1
thread_2 = _thread.start_new_thread(main_car, (None,)) #定义线程2
'''运行'''
if __name__ == "__main__":
try:
main()
except KeyboardInterrupt: #当出现KeyboardInterrupt异常
camera.deinit() #释放摄像头避免运行第二次出先错误提示
print("ok")
四、测试效果
摄像遥控小车寻找躲在床底下的猫猫:
测试视频(农田探险):
发表回复