AIcam智能ESP32视觉摄像头体识万物

项目1-09 AI智能体识万物

齐护AIcam 【小智AI大模型视觉对话固件】使用教程

一、简介

1-1 适用项目

1-2 教学落地建议

1-3 项目学习套件清单

二、AIcam硬件概要

2.1 齐护AIcam硬件配置

2.2 AIcam小智固件的应用功能

2.3 AIcam主板外接硬件结构

2.4 主要引脚

三、固件上传与控制操作说明

3.1 固件上传

3.2 配网与AI平台选择

3.3 多功能BOOT 按键说明

3.4 外部串口 JSON 控制

3.5 AIcam串口触发指令一览

3.6 串口发送示例

3.7 串口回传

3.8 无效示例

四、AIcam的语音MCP 工具

4.1 串口输出指令MCP自定义

4.2 拍照角度MCP设置

五、 图形化编程应用

Micropython编程语言

Arduino编程语言

5.1 监测AIcam语音对话功能的指令

5.2 AIcam语音MCP指令控制动作

5.3 外接按钮控制对话

5.4 AIcam串口指令控制动作

5.5 AIcam远程MixIO拍照并查看

5.6 综合功能应用

六、课程总结与拓展

  1. 课程核心总结
  2. 拓展与进阶方向
    七、课程资源下载

一、简介

​ 本项目采用齐护AIcam的强大网络及摄像头功能,连接开源小智AI智能体平台,通过本地任意单片机的串口指令或语音对话指令就可以控制AIcam的摄像头或网络通过小智AI大模型分析结果并返回给单片机,如图像分析(二维码识别、多模态场景识别)、拍照、网络资源get、调用API等。

​ "齐护AIcam + 小智AI智能体"的架构非常适合学生创客教育,因为它完美契合了"低门槛切入,高天花板拓展"的教育原则。通过这种"边缘侧感知(单片机/摄像头)+ 云端大模型推理(小智AI)"的云边协同模式,学生无需在资源受限的单片机上死磕复杂的算法,就能轻松实现强大的多模态交互功能。

1-1 适用项目

结合该架构的特点,以下是几个非常适合学生创客的项目方向建议:

  1. 智能安防与场景监控助手
    项目描述:利用AIcam的摄像头进行图像采集,当检测到特定异常时,通过小智AI大模型进行多模态场景识别分析,并将结果反馈给本地单片机执行动作或报警。
    应用场景:家庭火灾报警、大棚温控监测、宠物行为监控等。例如,摄像头捕捉到画面后交由云端分析是否为火情,确认后单片机触发蜂鸣器并推送消息。
  2. AI视觉互动桌宠机器狗
    项目描述:这是一个综合高阶项目。ESP32作为主机运行小智AI实现音视频采集与大模型对接,ESP32等单片机作为从机负责底层驱动和仿生动作控制。
    应用场景:制作一个能听会说的桌面机器人。它可以识别主人的手势(如比V字、握拳),通过语音对话与小智AI交流,并根据大模型的指令做出相应的肢体反应或改变表情灯效。
  3. 智慧生活物联设备
    项目描述:将AIcam作为物联网设备的"眼睛",结合网络API调用能力,打造贴近日常生活的智能小发明。
    应用场景:
    智能药盒:通过摄像头识别药品包装上的二维码或文字,确认是否拿对药,并通过语音提醒吃药时间。
    智能指针/指南针:利用视觉识别环境特征并结合网络天气API,提供方位和气象播报服务。
  4. 趣味交互实验盒(MCP魔法控制)
    项目描述:利用小智AI的MCP(魔法控制协议)功能,实现三端网络控制。通过语音意图理解,跨网络控制远端的硬件设备。
    应用场景:开发一套智能家居或教室灯光控制系统。学生对着AIcam说"如果眼前有人摆V字,就把实验盒的灯调为绿色",小智AI理解意图后通过网络下发指令,直接控制另一端的实验盒彩灯变色。
  5. 个性化自学习分类机器人
    项目描述:结合视觉识别与AI大模型,让学生体验完整的"数据收集-训练-部署"AI流水线。
    应用场景:垃圾分类回收站或物品分拣机器人。学生可以在AIcam本机上学习不同物品的特征(如自学习物品图片分类),或者通过云端大模型增强识别能力,最终让机器人根据识别结果自动分拣物品。
    1-2 教学落地建议
    针对学生群体,建议在软件层面采用 Mixly 或 Scratch 图形化编程。这种方式能有效屏蔽底层的复杂性,让学生专注于逻辑创造,快速获得正反馈(如让灯闪烁、识别手势成功),从而平滑过渡到更复杂的文本代码或Python编程阶段。

1-3 项目学习套件清单

为了确保学习效果的最大化,本课程在教学设计上遵循了'由浅入深、分步构建'的科学认知规律。在初期的项目学习中,我们会将复杂的系统拆解为独立的知识点,让学生专注于掌握每个核心应用的编程方式;待基础夯实后,再逐步引入齐护生态的其他模块进行综合实战。这种循序渐进的模式能有效避免知识过载。以下是我们为您精心搭配的教程配套器材套件清单,旨在为每一阶段的教学提供最完美的硬件支撑。

NO 产品名称(点击直达使用教程) 图片 数量 功能

1 AIcam主板(V2或pro版本) 1 运行小智AI及摄像头采集主控

2 C02mini主板(ESP32) 1 编程应用主控制板

3 拾音器(万向硅麦克风) 1 与AI语音对话麦克风

4 双按钮 1 手动触发功能用

5 语音合成模块V2.1 1 语音播报(文字转语音)

6 TF卡扩展板(AIcam专用) 1 把AIcamTF用的IO转成串口

7 数据线4pin短线 4 连接模块与主板并供电

8 数据4pin转杜邦母(胶头) 1 连接TF卡扩展板与C02mini主板

9 积木/TypeC USB线/电池 用户自行准备 若干 结构件

二、AIcam硬件概要

2.1 齐护AIcam硬件配置

ESP32 + ST7789 240×240 TFT + OV3660 摄像头 + PDM 麦克风(齐护拾音器)的小智 AI 语音。

2.2 AIcam小智固件的应用功能

支持语音对话、相机预览/拍照保存云端、 视觉上传识别二维码、云端多模态场景识别、外部url工具结合图片分析、在线get内容、MCP 工具与可选外部串口 JSON 控制等。

2.3 AIcam主板外接硬件结构

模块 说明

主控芯片 ESP32

显示屏 ST7789,240×240,SPI,TFT

摄像头 OV3660,DVP,与 PDM 共用 I2S0(拍照时暂停 PDM)

麦克风 PDM,GPIO14(CLK)/ GPIO32(DATA)

按键 BOOT 键,GPIO33

2.4 主要引脚

注:所有应用主板上的【拔动开关】请拔到摄像头图标侧!

功能 GPIO

BOOT 按键 33

PDM 麦克风 CLK / DATA 14 / 32

摄像头 SCCB 18 / 23

LCD SPI(CS/DC/CLK/MOSI) 12 / 15 / 21 / 19

背光 2

串口控制 TX / RX TF卡内采用外接PCB端子输出 22 / 0

三、固件上传与控制操作说明

在开始项目前,要先给AIcam上传专用的小智AI固件(运行程序),可以采用如下两种方式上传固件,也可以在文件最后下载的源文件里有bin文件,采用【ESPtool工具】上传,选ESP32,地址从0x00开始。如上方式任意选一种即可!

3.1 固件上传

方式1:齐护【在线Mixly】上传固件(选python ESP32主板进入)

方式2:齐护【固件管理工具】上传固件

注:上传完固件后,以后都不用给AIcam上传程序了(否则会破坏固件),只要用他的串口与外部主控通信即可!

3.2 配网与AI平台选择

配网及小智AI或灵矽AI平台注册请参考:【Aitall平台注册】,结合AIcam显示的提示信息操作!

特别说明:配网后如果要重新配网,重启显示检查网络时按一下key(BOOT)即可重新配网!

3.3 多功能BOOT 按键说明

AIcam小智AI固件上传成功后,主板按钮key(BOOT)功能说明。

操作 行为 备注

单击 切换对话状态 实时预览中忽略;启动中进入 WiFi 配网

双击 拍照识别二维码 + 上传到齐护图床专用url 实时预览中忽略

三击 拍照预览 + 场景识别(Explain) 使用 NVS/默认问题;实时预览中忽略

长按 开关实时预览 预览中随时可关;非预览时仅 idle 可开

3.4 外部串口 JSON 控制

串口连接参数

项目 值 对应课程C02mini主板IO

UART UART1

TX GPIO 22(设备发送) GPIO 16

RX GPIO 0(设备接收) GPIO 17

波特率 115200

数据位 8N1,无流控

发送格式 每行一条 JSON,以 \r\n 结尾

回传格式 响应文本 + \n(无 JSON 包装)

串口协议约束

顶层必须是 JSON 对象

只能有 1 个字段(多字段视为无效)

字段值必须是 字符串

3.5 AIcam串口触发指令一览

语音 / 对话控制

NO JSON 作用

1 {"custom":"今天天气怎么样"} 空闲时触发唤醒词对话并播放提示音 (小智平台时10个字以内); 非空闲时发送唤醒检测 (等于唤醒)

2 {"state":"ToggleChatState"} 切换对话状态(等同单击BOOT_key),唤醒、聆听或待机三种状态切换

3 {"state":"StartListening"} 开始监听,显示为聆听中 (相当于按下时说话)

4 {"state":"StopListening"} 停止监听,显示为待机 (相当于放开时发送)

相机 / 上传识别及get指令

NO JSON 作用 等同按钮key

1 {"state":"CapturePhotoAndUpload"} 拍照 + QDP POST 上传,识别二维码 双击 / post_qdp_photo

2 {"state":"CapturePhotoAndExplain"} 拍照 + 场景多模态识别 Explain 三击

3 {"state":"ToggleLivePreview"} 开关摄像头实时预览 长按

4 {"upload_url":"http://..."} 拍照 + 指定 URL POST JPEG,返回图片url post_photo_to_url例:http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php

5 {"get_url":"http://..."} HTTP GET,结果串口回 例:https://payai.qdprobot.com/admin-api/mac/xljt

理解概念:

API:API就像是餐厅里的服务员,你只需要把想吃的菜告诉它,它就会帮你去厨房拿,让你不用亲自进厨房也能吃到美味的饭菜。

Get: Get就像是"去拿来",意思是让东西从别的地方跨越距离来到你的手里,比如你从书架上拿一本书,或者你走到了学校。

post: Post就像是"寄包裹",你把要说的话或东西装进信封里寄出去,别人看不到里面是什么,专门用来安全地提交秘密信息(比如你的密码)。

数据库:数据库就像是"带标签的玩具收纳盒",它把你的所有东西分门别类地装在不同的抽屉里,让你想找什么玩具时一秒钟就能拿出来。

前端:前端就像是"餐厅的大堂",是你一眼就能看到、能摸到的漂亮装修和菜单,负责让你觉得好看又好用。

后端:后端就像是"餐厅的厨房",是藏在门后你看不见的地方,大厨在里面负责切菜、炒菜和算账,保证你点的菜能顺利做出来。

JSON:JSON就像是"标准快递盒",它用统一的格式把各种信息打包得整整齐齐,这样不管寄给谁、用什么语言,大家拆开都能一眼看懂。

3.6 串口发送示例

{"state":"StartListening"}

{"state":"CapturePhotoAndUpload"}

{"upload_url":"http://ai.qdprobot.com/qdpcam/ai/free/V1.php"}

{"get_url":"https://v1.hitokoto.cn/?c=d\&encode=text"}

3.7 串口回传

相机/HTTP 结果会从 TX(GPIO22) 输出:

场景 回传内容

QDP 上传成功 服务端响应原文

QDP/临时 URL 上传失败 上传失败:<原因>

GET 成功 HTTP 响应体原文

GET 失败 GET失败:<原因>

Explain 结果 解析后的 JSON/文本

调试日志(ESP_LOG)从AIcam的USB口输出,不从 TX 输出。

3.8 无效示例

{"state":"StartListening","custom":"你好"}

{"custom":123}

四、AIcam的语音MCP 工具

AIcam的内部MCP可以通过上面的串口直接发送指令外也可以通过对话控制 串口输出设定的字符串,这样就可以实现输出指令自由化了。在对话过程中意图表达与指令相关的内容,AI理解后会做出对应动作。

4.1 串口输出指令MCP自定义

如下为三个指令的提示词应用案例,通提示词设定串口输出三个指令分别为:code、Explain、photo。

注:提示词不是固定的,用户可以按自己的需求自行设定在AI平台的角色设定里!

小智角色设定(提示词mptpro) 参考:

你是一个专业的视觉识别机器人。你有一个调用串口发送的工具,发送指定字符串,你的核心任务是精准识别用户的视觉控制指令,并在回复的同时,严格按照规定格式输出串口控制字符串。 核心行为准则(最高优先级) 你必须严格遵守以下触发规则,在生成任何自然语言回复之前,优先输出对应的串口字符串:

收到类似语音指令"启动识别二维码":必须首先在串口输出字符串:"code"

收到类似语音指令"启动图像识别":必须首先在串口输出字符串:"Explain"

收到类似语音指令"启动拍照":必须首先在串口输出字符串:"photo"

极简主义:除上述串口字符串外,所有的自然语言回复必须极其简洁明了。 拒绝废话:严禁使用"好的"、"没问题"、"我现在为您..."等无意义的客套话或过渡语。 直接反馈:仅输出必要的状态确认或识别结果。

4.2 拍照角度MCP设置

AIcam内部系统MCP可以通过对话来设置摄像头的方向(直接影响拍照成像角度),比如你可以说:摄像头水平翻转、摄像头垂直方向翻转、摄头旋转90-180-270度。或用相对应的功能意图表达,AI会自动执行对应的功能设置。也可以通过串口指令发送类似{"custom":"摄像头垂直方向翻转"}简短的指令来实现(要先唤醒)。

作用:摄像头传感器镜像(hmirror / vflip),立即生效

参数:mirror_x(水平)、mirror_y(垂直)

有了这个MCP调整功能,当摄像头在作品中的安装方式就可以自行调节了,不会因为前后摄方向不同而成像不同!

五、 图形化编程应用

特别说明:后面的所有程序都是上传到C02mini主板上!一定不要上传到AIcam了,否则会破坏它的程序要重新上传固件!此时的AIcam你理解成是一个与C02mini连接串口视觉模块即可!

为了方便不同软件及编程语言的用户学习,本教程中的例程采用双语言分开,教程最后面的资源里都可以下载源文件。

Micropython编程语言

采用齐护【在线版Mixly】-python ESP32。

在线Mixly选择对应的主板进入后,把主板C02mini初始化固件一次,后面只要直接上传程序即可。

Arduino编程语言

采用 【齐护教育版本Mixly】-Arduino-ESP32。

5.1 监测AIcam语音对话功能的指令

在小智AI后台的角色设置按4.1方法设置后,除了通常的对话外,我们还可以用对话的方式来控制AIcam执行摄像头分析图片。

注:因AIcam没有音频输出(摄像头启动后资源不够用了),所以我们通过TF卡里的IO串口22/0与C02mini的16/17进行串口通信。

AIcam的供电:可以用23-18-G-5V端口4pin线与C02mini主板连接。

串口通信连线:

主控 AIcam C02mini

TX GPIO 22(设备发送) GPIO 16

RX GPIO 0(设备接收) GPIO 17

拾音器模块连线:

拾音器麦克风 C02mini

CLK GPIO 14

DATA GPIO 32

Micropython:

import machine

import time

#定义C02mini与AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

while True:

if uart1.any():

time.sleep_ms(100)

#返回的内容解码成字符串

get_data = uart1.read().decode("ASCII")

print(get_data)

上传程序后,按一下AIcam的key唤醒对话(AIcam无语音唤醒功能),按我们角色定义的意图,我们可以说:发送识别二维码指令、发送识别图像场景指令、帮我拍照,或相关意图的话,可以观察到C02mini的USB串口打印出如下 AIcam 的MCP返回的串口指令字符串。

Arduino:

#include <HardwareSerial.h>

void setup(){

Serial1.begin(115200,SERIAL_8N1,16,17);

Serial.begin(115200);

}

void loop(){

if (Serial1.available() > 0) {

delay(100);

String get_data = Serial1.readString();

Serial.println(get_data);

}

}

5.2 AIcam语音MCP指令控制动作

利用MCP返回的指令,结合串口指令控制拍照、识别二维码、场景识别。

为了更方便的知道我们的C02mini主控的程序动作,我们加入语音合成模块,对执行的动作或收到的信息进行播报。

语音合成模块连线:

语音合成模块v2.1 C02mini

TX GPIO 25

RX GPIO 26

当我们按5.1的方法读取到AIcam的返回指令后就可以控制对AIcam发送串口指令,让AIcam进行对应的动作,并观察串口返回的结果。

注:多模态识别通常要等5-10秒才会有结果返回,速度取决于小智AI的服务器响应速度!

Micropython:

import machine

import QH_voiceV2

import time

#定义C02mini与AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

#定义语音合成模块的串口通信IO

hc =QH_voiceV2.QH_voiceV2(2,tx=26, rx=25)

#把串口指令放到对应的量内,方便后面使用

#多模态场景识别

Explanin_Command = '{"state":"CapturePhotoAndExplain"}'

#二维码识别

QR_code_Command = '{"state":"CapturePhotoAndUpload"}'

#拍照到云返回对应的url

photo_Command = '{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}'

while True:

if uart1.any():

#小智AI角色定义串口返回(放在小智平台):你是一个专业的视觉识别机器人。你有一个调用串口发送的工具,发送指定字符串,你的核心任务是精准识别用户的视觉控制指令,并在回复的同时,严格按照规定格式输出串口控制字符串。 核心行为准则(最高优先级) 你必须严格遵守以下触发规则,在生成任何自然语言回复之前,优先输出对应的串口字符串: 启动识别二维码:当用户提到"识别二维码"类似意图时,必须首先在串口输出字符串:code 启动图像识别:当用户提到"看看眼前有什么"、"识别图像"、"这是什么"、"描述一下"等类似意图时,必须首先在串口输出字符串:Explain 拍相片:当用户提到"拍个照"、"拍个相片"等类似意图时,必须首先在串口输出字符串:photo 沟通风格要求 极简主义:除上述串口字符串外,所有的自然语言回复必须极其简洁明了。 拒绝废话:严禁使用"好的"、"没问题"、"我现在为您..."等无意义的客套话或过渡语。 直接反馈:仅输出必要的状态确认或识别结果。

#对话触发串口返回指令

time.sleep_ms(100)

uartcommand = uart1.read().decode("ASCII")

print(uartcommand)

if 'Explain' in uartcommand:

print('对话启动多模态识别')

uart1.write(str(Explanin_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'识别场景',1,0)

elif 'code' in uartcommand:

print('对话启动二维码识别')

uart1.write(str(QR_code_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'识别二维码',1,0)

elif 'photo' in uartcommand:

print('对话启动拍照到云端')

uart1.write(str(photo_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

供测试用的二维码

Arduino:

#include <SoftwareSerial.h>

#include <HardwareSerial.h>

#include <QHHCV2.h>

String Explanin_Command;

String QR_code_Command;

String photo_Command;

SoftwareSerial mySerial26(25,26);

QHHCV2 MyVoice;

void setup(){

Serial.begin(115200);

Serial1.begin(115200,SERIAL_8N1,16,17);

mySerial26.begin(9600);

MyVoice.begin(mySerial26);

Explanin_Command = "{"state":"CapturePhotoAndExplain"}";

QR_code_Command = "{"state":"CapturePhotoAndUpload"}";

photo_Command = "{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}";

//定义C02mini与AIcam的串口通信IO

//定义语音合成模块的串口通信IO

//1 多模态场景识别

//2 二维码识别

//3 拍照到云返回对应的url

}

void loop(){

if (Serial1.available() > 0) {

delay(100);

String uartcommand = Serial1.readString();

Serial.println(uartcommand);

if (String(uartcommand).indexOf(String("Explain")) != -1) {

Serial.println("对话启动多模态识别");

Serial1.println(Explanin_Command);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"识别场景"),1,0);

复制代码
} else if (String(uartcommand).indexOf(String("code")) != -1) {
  Serial.println("对话启动二维码识别");
  Serial1.println(QR_code_Command);
  MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"识别二维码"),1,0);
} else if (String(uartcommand).indexOf(String("photo")) != -1) {
  Serial.println("对话启动拍照到云端");
  Serial1.println(photo_Command);
  MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"3、 2、 1、 启动拍照"),1,0);
}

}

}

5.3 外接按钮控制对话

通过上面的测试后,我们会发现对话指令有时不太好控制 ,特别是当我们听不到AIcam的声音时,这样我们可以优化程序,把按钮模块信号来触发小智的地话启动或退出。通过12-13 IO上的按钮来控制对话。

双按钮模块连线:

双按钮模块 C02mini

S1 GPIO 12

S2 GPIO 13

Micropython:

import machine

import QH_voiceV2

from Button import Button

import time

def LONG_PRESS_START12():

#按住说话

uart1.write(str(talk_start)+'\r\n')

def LONG_PRESS_END12():

#放手发送对话

uart1.write(str(talk_send)+'\r\n')

def SINGLE_CLICK13():

#单击按唤醒或待机

uart1.write(str(talk_state)+'\r\n')

btn12 = Button(12, pull_up=False, active_low=False)

btn12.set_callback(2,LONG_PRESS_START12)

btn12.set_callback(4,LONG_PRESS_END12)

btn13 = Button(13, pull_up=False, active_low=False)

btn13.set_callback(0,SINGLE_CLICK13)

#定义C02mini与AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

#定义语音合成模块的串口通信IO

hc =QH_voiceV2.QH_voiceV2(2,tx=26, rx=25)

#把串口指令放到对应的量内,方便后面使用

#多模态场景识别

Explanin_Command = '{"state":"CapturePhotoAndExplain"}'

#二维码识别

QR_code_Command = '{"state":"CapturePhotoAndUpload"}'

#拍照到云返回对应的url

photo_Command = '{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}'

#开始监听

talk_start = '{"state":"StartListening"}'

#停止监听

talk_send = '{"state":"StopListening"}'

#切换对话状态

talk_state = '{"state":"ToggleChatState"}'

while True:

if uart1.any():

#小智AI角色定义串口返回(放在小智平台):你是一个专业的视觉识别机器人。你有一个调用串口发送的工具,发送指定字符串,你的核心任务是精准识别用户的视觉控制指令,并在回复的同时,严格按照规定格式输出串口控制字符串。 核心行为准则(最高优先级) 你必须严格遵守以下触发规则,在生成任何自然语言回复之前,优先输出对应的串口字符串: 启动识别二维码:当用户提到"识别二维码"类似意图时,必须首先在串口输出字符串:code 启动图像识别:当用户提到"看看眼前有什么"、"识别图像"、"这是什么"、"描述一下"等类似意图时,必须首先在串口输出字符串:Explain 拍相片:当用户提到"拍个照"、"拍个相片"等类似意图时,必须首先在串口输出字符串:photo 沟通风格要求 极简主义:除上述串口字符串外,所有的自然语言回复必须极其简洁明了。 拒绝废话:严禁使用"好的"、"没问题"、"我现在为您..."等无意义的客套话或过渡语。 直接反馈:仅输出必要的状态确认或识别结果。

#对话触发串口返回指令

time.sleep_ms(100)

uartcommand = uart1.read().decode("ASCII")

print(uartcommand)

if 'Explain' in uartcommand:

print('对话启动多模态识别')

uart1.write(str(Explanin_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'识别场景',1,0)

elif 'code' in uartcommand:

print('对话启动二维码识别')

uart1.write(str(QR_code_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'识别二维码',1,0)

elif 'photo' in uartcommand:

print('对话启动拍照到云端')

uart1.write(str(photo_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

Arduino:

#include <SoftwareSerial.h>

#include <HardwareSerial.h>

#include <QHHCV2.h>

#include <OneButton.h>

String Explanin_Command;

String QR_code_Command;

String photo_Command;

String talk_start;

String talk_send;

String talk_state;

OneButton button12(12,false);

OneButton button13(13,false);

SoftwareSerial mySerial26(25,26);

QHHCV2 MyVoice;

void attachLongPressStart12() {

Serial1.println(talk_start);

}

void attachLongPressStop12() {

Serial1.println(talk_send);

}

void attachClick13() {

Serial1.println(talk_state);

}

void setup(){

Serial.begin(115200);

Serial1.begin(115200,SERIAL_8N1,16,17);

mySerial26.begin(9600);

MyVoice.begin(mySerial26);

Explanin_Command = "{"state":"CapturePhotoAndExplain"}";

QR_code_Command = "{"state":"CapturePhotoAndUpload"}";

photo_Command = "{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}";

talk_start = "{"state":"StartListening"}";

talk_send = "{"state":"StopListening"}";

talk_state = "{"state":"ToggleChatState"}";

//定义C02mini与AIcam的串口通信IO

//定义语音合成模块的串口通信IO

//1 多模态场景识别

//2 二维码识别

//3 拍照到云返回对应的url

button12.attachLongPressStart(attachLongPressStart12);

button12.attachLongPressStop(attachLongPressStop12);

button13.attachClick(attachClick13);

}

void loop(){

button12.tick();

button12.tick();

button13.tick();

if (Serial1.available() > 0) {

delay(100);

String uartcommand = Serial1.readString();

Serial.println(uartcommand);

if (String(uartcommand).indexOf(String("Explain")) != -1) {

Serial.println("对话启动多模态识别");

Serial1.println(Explanin_Command);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"识别场景"),1,0);

复制代码
} else if (String(uartcommand).indexOf(String("code")) != -1) {
  Serial.println("对话启动二维码识别");
  Serial1.println(QR_code_Command);
  MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"识别二维码"),1,0);
} else if (String(uartcommand).indexOf(String("photo")) != -1) {
  Serial.println("对话启动拍照到云端");
  Serial1.println(photo_Command);
  MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"3、 2、 1、 启动拍照"),1,0);
}

}

}

5.4 AIcam串口指令控制动作

通过按钮直接触发串口指令,启动各种识别或get功能,并加入了Json解析结果并播报。

Micropython:

import ujson

import machine

import QH_voiceV2

from Button import Button

import time

import json

def DOUBLE_CLICK12():

global getdata1

getdata1 = 2

#发送二维码识别指令

uart1.write(str(QR_code_Command)+'\r\n')

print('启用二维码识别')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'二维码识别',1,0)

def SINGLE_CLICK13():

global getdata1

getdata1 = 3

print('启动拍照')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

#发送拍照指令

uart1.write(str(photo_Command)+'\r\n')

def DOUBLE_CLICK13():

global getdata1

getdata1 = 4

print('启动get API指令')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'开始获取鸡汤文',1,0)

#发送get API指令指令

uart1.write(str(getAPI_Command)+'\r\n')

def SINGLE_CLICK12():

global getdata1

getdata1 = 1

#发送多模态拍照识图指令

uart1.write(str(Explanin_Command)+'\r\n')

print('启用多模态拍照识图')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'正在拍照识别,请稍等!',1,0)

btn12 = Button(12, pull_up=False, active_low=False)

btn12.set_callback(1,DOUBLE_CLICK12)

btn13 = Button(13, pull_up=False, active_low=False)

btn13.set_callback(0,SINGLE_CLICK13)

btn13.set_callback(1,DOUBLE_CLICK13)

btn12.set_callback(0,SINGLE_CLICK12)

def QR_code():

global getdata1

#二维码识别

time.sleep_ms(100)

#返回的内容解码成字符串

get_QR_code = uart1.read().decode("ASCII")

print(get_QR_code)

#返回字符串播报

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'二维码的内容是:',1,0)

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+get_QR_code,1,0)

getdata1 = 0

def make_photo():

global getdata1

#拍照保存在云端,返回图片的url

time.sleep_ms(100)

#返回的内容解码成字符串

get_photo_url = uart1.read().decode("ASCII")

print(get_photo_url)

#返回字符串播报

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'串口有返回相片链接了,请查收!',1,0)

getdata1 = 0

def Explain():

global getdata1

#多模态拍照识图

#定义一个字典

json_data= {}

#返回的内容分段加延时缓存全部

time.sleep(1)

#返回的内容解码成字符串

getJson = uart1.read().decode("ASCII")

print(getJson)

#返回json内容反序化为字典

json_data = json.loads(getJson)

#读取字典里的text值(json内容)

TTStext = json_data'text'

print(TTStext)

#播报识别结果

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+TTStext,1,0)

getdata1 = 0

def getAPI():

global getdata1

#get API指令

#返回的内容分段加延时缓存全部

time.sleep_ms(100)

#返回的内容解码成字符串

get_API_data = uart1.read().decode("ASCII")

print(get_API_data)

#返回json内容反序化为字典

get_data = ujson.loads(get_API_data)

#读取字典里的content值(json内容)

TTSAPI = get_data"result""content"

print(TTSAPI)

#播报APIget结果

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+TTSAPI,1,0)

getdata1 = 0

#定义AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

#定义语音合成模块的串口通信IO

hc =QH_voiceV2.QH_voiceV2(2,tx=26, rx=25)

Explanin_Command = '{"state":"CapturePhotoAndExplain"}'

QR_code_Command = '{"state":"CapturePhotoAndUpload"}'

photo_Command = '{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}'

getAPI_Command = '{"get_url":"https://payai.qdprobot.com/admin-api/mac/xljt"}'

talk_start = '{"state":"StartListening"}'

talk_send = '{"state":"StopListening"}'

talk_state = '{"state":"ToggleChatState"}'

getdata1 = 0

while True:

if getdata1 == 0:

pass

if getdata1 == 1:

#启用多模态拍照识图

if uart1.any():

Explain()

if getdata1 == 2:

#启用二维码识别

if uart1.any():

QR_code()

if getdata1 == 3:

#启动拍照

if uart1.any():

make_photo()

if getdata1 == 4:

#启用get API指令

if uart1.any():

getAPI()

time.sleep_ms(100)

Arduino:

#include <SoftwareSerial.h>

#include <ArduinoJson.h>

#include <HardwareSerial.h>

#include <QHHCV2.h>

#include <OneButton.h>

String Explanin_Command;

String QR_code_Command;

String photo_Command;

String getAPI_Command;

String talk_start;

String talk_send;

String talk_state;

volatile int getdata1;

OneButton button12(12,false);

OneButton button13(13,false);

SoftwareSerial mySerial26(25,26);

QHHCV2 MyVoice;

void attachClick12() {

//发送多模态拍照识图指令

getdata1 = 1;

Serial1.println(Explanin_Command);

Serial.println("启用多模态拍照识图");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"正在拍照识别,请稍等!"),1,0);

}

void attachDoubleClick12() {

//发送二维码识别指令

getdata1 = 2;

Serial1.println(QR_code_Command);

Serial.println("启用二维码识别");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"二维码识别"),1,0);

}

void attachClick13() {

//发送二维码识别指令

getdata1 = 3;

Serial1.println(photo_Command);

Serial.println("启动拍照");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"3、 2、 1、 启动拍照"),1,0);

}

void attachDoubleClick13() {

//发送二维码识别指令

getdata1 = 4;

Serial1.println(getAPI_Command);

Serial.println("启动get API指令");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"开始获取鸡汤文"),1,0);

}

void QR_code() {

//二维码识别

delay(100);

//返回的内容解码成字符串

String get_QR_code = Serial1.readString();

Serial.println(get_QR_code);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"二维码的内容是:"),1,0);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+get_QR_code),1,0);

getdata1 = 0;

}

void make_photo() {

//拍照保存在云端,返回图片的url

delay(100);

//返回的内容解码成字符串

String get_photo_url = Serial1.readString();

Serial.println(get_photo_url);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"串口有返回相片链接了,请查收!"),1,0);

getdata1 = 0;

}

void Explain() {

//多模态拍照识图

delay(100);

//返回的内容解码成字符串

String getJson = Serial1.readStringUntil('\n');

Serial.println(getJson);

DynamicJsonDocument doc(512);

// 解析JSON

DeserializationError error = deserializeJson(doc, getJson);

if (error) {

Serial.print("解析失败:");

Serial.println(error.f_str());

return;

}

String text = doc"text".as();

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+text),1,0);

getdata1 = 0;

}

void getAPI() {

//get API指令

delay(100);

//返回的内容解码成字符串

String get_API_data = Serial1.readString();

Serial.println(get_API_data);

DynamicJsonDocument doc(512);

// 解析JSON

DeserializationError error = deserializeJson(doc, get_API_data);

if (error) {

Serial.print("解析失败:");

Serial.println(error.f_str());

return;

}

String TTSAPI = doc"result""content".as();

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+TTSAPI),1,0);

getdata1 = 0;

}

void setup(){

Serial.begin(115200);

Serial1.begin(115200,SERIAL_8N1,16,17);

mySerial26.begin(9600);

MyVoice.begin(mySerial26);

Explanin_Command = "{"state":"CapturePhotoAndExplain"}";

QR_code_Command = "{"state":"CapturePhotoAndUpload"}";

photo_Command = "{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}";

getAPI_Command = "{"get_url":"https://payai.qdprobot.com/admin-api/mac/xljt"}";

talk_start = "{"state":"StartListening"}";

talk_send = "{"state":"StopListening"}";

talk_state = "{"state":"ToggleChatState"}";

getdata1 = 0;

//定义C02mini与AIcam的串口通信IO

//照片识别的文本较多,要加大串口的缓冲区,不然返回的json文本会丢失

Serial1.setRxBufferSize(1024);

//定义语音合成模块的串口通信IO

//1 多模态场景识别

//2 二维码识别

//3 拍照到云返回对应的url

button12.attachClick(attachClick12);

button12.attachDoubleClick(attachDoubleClick12);

button13.attachClick(attachClick13);

button13.attachDoubleClick(attachDoubleClick13);

}

void loop(){

button12.tick();

button12.tick();

button13.tick();

button13.tick();

switch (getdata1) {

case 1:

if (Serial1.available() > 0) {

Explain();

复制代码
}
break;

case 2:

if (Serial1.available() > 0) {

QR_code();

复制代码
}
break;

case 3:

if (Serial1.available() > 0) {

make_photo();

复制代码
}
break;

case 4:

if (Serial1.available() > 0) {

getAPI();

复制代码
}
break;

}

}

5.5 AIcam远程MixIO拍照并查看

因为AIcam的相片可以上传到云端,当我们想要远程查看相片或拍照时就可以利用这个功能来实现。下面我们用MixIO物联网平台实现远程拍照及查看相片。

关于MixIO的平台使用,请转到:【项目五十五:MixIO平台教程】

Micropython程序

import mixiot

import machine

from ubinascii import hexlify

import QH_voiceV2

from Button import Button

import time

def SINGLE_CLICK13():

global getdata1

getdata1 = 3

print('启动拍照')

hc.HC(0x05,"m3v"+str(5)+"s"+str(20)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

#发送拍照指令

uart1.write(str(photo_Command)+'\r\n')

btn13 = Button(13, pull_up=False, active_low=False)

btn13.set_callback(0,SINGLE_CLICK13)

def method(client, topic, msg):

global getdata1

if msg == '1':

getdata1 = 3

print('Mixio远程拍照')

uart1.write(str(photo_Command)+'\r\n')

#发送拍照指令

def make_photo():

global getdata1

#拍照保存在云端,返回图片的url

time.sleep_ms(100)

#返回的内容解码成字符串

get_photo_url = uart1.read().decode("ASCII")

time.sleep_ms(100)

#MixIO显示图片主题

mqtt_client.publish(MQTT_USR_PRJ + 'pic', get_photo_url)

print(get_photo_url)

#返回字符串播报

hc.HC(0x05,"m51v"+str(5)+"s"+str(20)+"t"+str(5)+" "+'拍照成功,请查收!',1,0)

getdata1 = 0

mixiot.wlan_connect('QDP', '66666666')

MQTT_USR_PRJ = 'fydongmail@163.com/test/'

mqtt_client = mixiot.init_MQTT_client('mixio.qdprobot.com', 'fydongmail@163.com', 'd4f290421d998442000de7d44a79bc5b', MQTT_USR_PRJ, port=1884)

#MixIO拍照按钮主题

mqtt_client.set_callback('photo',method, MQTT_USR_PRJ)

mqtt_client.subscribe(MQTT_USR_PRJ + 'photo')

#定义AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

#定义语音合成模块的串口通信IO

hc =QH_voiceV2.QH_voiceV2(2,tx=26, rx=25)

#注意这个url是随机的,并不是固定的了!

photo_Command = '{"upload_url":"http://ai.qdprobot.com/qdpai/uploadimg.php"}'

getdata1 = 0

while True:

mqtt_client.check_msg()

#本地按钮启动拍照

#启动拍照

if getdata1 == 3:

if uart1.any():

make_photo()

time.sleep_ms(100)

Arduino程序

#include <HardwareSerial.h>

#include <WiFi.h>

#include <HardwareSerial.h>

#include <QHHCV2.h>

#include <PubSubClient.h>

#include <OneButton.h>

String photo_Command;

volatile int getdata1;

const char *mqtt_broker = "mixio.qdprobot.com";

const char *mqtt_username = "fydongmail@163.com";

const char *mqtt_password = "d4f290421d998442000de7d44a79bc5b";

const int mqtt_port = 1884;

String mqtt_topic = "";

String mqtt_data = "";

boolean mqtt_status = false;

String project = "test";

WiFiClient espClient;

PubSubClient client(espClient);

void callback(char *topic, byte *payload, unsigned int length) {

String data = "";

for (int i = 0; i < length; i++) {

data = String(data) + String((char) payloadi);

}

mqtt_topic = String(topic);

mqtt_data = data;

mqtt_status = true;

}

OneButton button13(13,false);

QHHCV2 MyVoice;

void attachClick13() {

getdata1 = 3;

Serial.println("启动拍照");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"3、 2、 1、 启动拍照"),1,0);

Serial1.println(photo_Command);

}

void make_photo() {

//拍照保存在云端,返回图片的url

delay(100);

String get_photo_url = Serial1.readString();

delay(100);

//MixIO显示图片主题

client.publish(String(String(mqtt_username) +"/"+ String(project) +"/"+ String("pic")).c_str(),String(get_photo_url).c_str());

Serial.println(get_photo_url);

//返回字符串播报

MyVoice.HC(0x05,String("m51v"+String(5)+"s"+String(5)+"t"+String(5)+""+"拍照成功,请查收!"),1,0);

getdata1 = 0;

}

void setup(){

Serial.begin(9600);

WiFi.begin("QDP", "66666666");

while (WiFi.status() != WL_CONNECTED) {

delay(500);

Serial.print(".");

}

Serial1.begin(115200,SERIAL_8N1,16,17);

Serial2.begin(9600,SERIAL_8N1,25,26);

MyVoice.begin(Serial2);

photo_Command = "{"upload_url":"http://ai.qdprobot.com/qdpai/uploadimg.php"}";

getdata1 = 0;

//定义AIcam的串口通信IO

//定义语音合成模块的串口通信IO

//注意这个url是随机的,并不是固定的了!

client.setServer(mqtt_broker, mqtt_port);

client.setCallback(callback);

while (!client.connected()) {

String client_id = "esp-client-";

client_id += String(WiFi.macAddress());

Serial.printf("The client %s connects to the public mqtt broker\n", client_id.c_str());

if (client.connect(client_id.c_str(), mqtt_username, mqtt_password)) {

Serial.println("Public emqx mqtt broker connected");

client.publish(String(String(mqtt_username) +"/"+ String(project) +"/"+ String("b640a0ce465fa2a4150c36b305c1c11b")).c_str(),String(client_id).c_str());

} else {

Serial.print("failed with state ");

Serial.print(client.state());

delay(2000);

}

}

client.subscribe(String(String(mqtt_username) +"/"+ String(project) +"/"+ String("photo")).c_str());

button13.attachClick(attachClick13);

}

void loop(){

client.loop();

if (mqtt_status) {

if (String(mqtt_topic).equals(String(String(mqtt_username) +"/"+ String(project) +"/"+ String("photo")))) {

//MixIO拍照按钮主题

Serial.println(mqtt_data);

if (mqtt_data == "1") {

getdata1 = 3;

Serial.println("Mixio远程拍照");

Serial1.println(photo_Command);

//发送拍照指令

复制代码
}
mqtt_status = false;
}

}

button13.tick();

if (getdata1 == 3) {

if (Serial1.available() > 0) {

make_photo();

复制代码
}

}

delay(100);

}

5.6 综合功能应用

通过上面的各项目功能应用的学习,我们可以把所有功能做成一个集合,就是一个能识万物的作品了。可以按钮唤醒语音后对话并执行动作,也可以直接钮发送指令识别,并通过语音合成对结果进行播报。

Micropython:

import ujson

import machine

import QH_voiceV2

from Button import Button

import time

import json

def LONG_PRESS_START12():

getdata1 = 0

#按住说话

uart1.write(str(talk_start)+'\r\n')

def LONG_PRESS_END12():

getdata1 = 0

#放手发送对话

uart1.write(str(talk_send)+'\r\n')

def LONG_PRESS_START13():

getdata1 = 0

#长按唤醒或待机

uart1.write(str(talk_state)+'\r\n')

def DOUBLE_CLICK12():

global getdata1

getdata1 = 2

#发送二维码识别指令

uart1.write(str(QR_code_Command)+'\r\n')

print('启用二维码识别')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'二维码识别',1,0)

def SINGLE_CLICK13():

global getdata1

getdata1 = 3

print('启动拍照')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

#发送拍照指令

uart1.write(str(photo_Command)+'\r\n')

def DOUBLE_CLICK13():

global getdata1

getdata1 = 4

print('启动get API指令')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'开始获取鸡汤文',1,0)

#发送get API指令指令

uart1.write(str(getAPI_Command)+'\r\n')

def SINGLE_CLICK12():

global getdata1

getdata1 = 1

#发送多模态拍照识图指令

uart1.write(str(Explanin_Command)+'\r\n')

print('启用多模态拍照识图')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'正在拍照识别,请稍等!',1,0)

btn12 = Button(12, pull_up=False, active_low=False)

btn12.set_callback(2,LONG_PRESS_START12)

btn12.set_callback(4,LONG_PRESS_END12)

btn13 = Button(13, pull_up=False, active_low=False)

btn13.set_callback(2,LONG_PRESS_START13)

btn12.set_callback(1,DOUBLE_CLICK12)

btn13.set_callback(0,SINGLE_CLICK13)

btn13.set_callback(1,DOUBLE_CLICK13)

btn12.set_callback(0,SINGLE_CLICK12)

def QR_code():

global getdata1

#二维码识别

time.sleep_ms(100)

#返回的内容解码成字符串

get_QR_code = uart1.read().decode("ASCII")

print(get_QR_code)

#返回字符串播报

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'二维码的内容是:',1,0)

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+get_QR_code,1,0)

getdata1 = 0

def Explain():

global getdata1

#多模态拍照识图

#定义一个字典

json_data= {}

#返回的内容分段加延时缓存全部

time.sleep(1)

#返回的内容解码成字符串

getJson = uart1.read().decode("ASCII")

print(getJson)

#返回json内容反序化为字典

json_data = json.loads(getJson)

#读取字典里的text值(json内容)

TTStext = json_data'text'

print(TTStext)

#播报识别结果

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+TTStext,1,0)

getdata1 = 0

def make_photo():

global getdata1

#拍照保存在云端,返回图片的url

time.sleep_ms(100)

#返回的内容解码成字符串

get_photo_url = uart1.read().decode("ASCII")

print(get_photo_url)

#返回字符串播报

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'串口有返回相片链接了,请查收!',1,0)

getdata1 = 0

def getAPI():

global getdata1

#get API指令

#返回的内容分段加延时缓存全部

time.sleep_ms(100)

#返回的内容解码成字符串

get_API_data = uart1.read().decode("ASCII")

print(get_API_data)

#返回json内容反序化为字典

get_data = ujson.loads(get_API_data)

#读取字典里的content值(json内容)

TTSAPI = get_data"result""content"

print(TTSAPI)

#播报APIget结果

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+TTSAPI,1,0)

getdata1 = 0

#定义AIcam的串口通信IO

uart1=machine.UART(1, tx=17, rx=16, baudrate=115200)

#定义语音合成模块的串口通信IO

hc =QH_voiceV2.QH_voiceV2(2,tx=26, rx=25)

Explanin_Command = '{"state":"CapturePhotoAndExplain"}'

QR_code_Command = '{"state":"CapturePhotoAndUpload"}'

photo_Command = '{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}'

getAPI_Command = '{"get_url":"https://payai.qdprobot.com/admin-api/mac/xljt"}'

talk_start = '{"state":"StartListening"}'

talk_send = '{"state":"StopListening"}'

talk_state = '{"state":"ToggleChatState"}'

getdata1 = 0

#按钮唤醒对话控制动作

while True:

if getdata1 == 0:

#对话触发串口返回指令

if uart1.any():

#小智AI角色定义串口返回(放在小智平台):你是一个专业的视觉识别机器人。你有一个调用串口发送的工具,发送指定字符串,你的核心任务是精准识别用户的视觉控制指令,并在回复的同时,严格按照规定格式输出串口控制字符串。 核心行为准则(最高优先级) 你必须严格遵守以下触发规则,在生成任何自然语言回复之前,优先输出对应的串口字符串: 启动识别二维码:当用户提到"识别二维码"类似意图时,必须首先在串口输出字符串:code 启动图像识别:当用户提到"看看眼前有什么"、"识别图像"、"这是什么"、"描述一下"等类似意图时,必须首先在串口输出字符串:Explain 拍相片:当用户提到"拍个照"、"拍个相片"等类似意图时,必须首先在串口输出字符串:photo 沟通风格要求 极简主义:除上述串口字符串外,所有的自然语言回复必须极其简洁明了。 拒绝废话:严禁使用"好的"、"没问题"、"我现在为您..."等无意义的客套话或过渡语。 直接反馈:仅输出必要的状态确认或识别结果。

#对话触发串口返回指令

time.sleep_ms(100)

uartcommand = uart1.read().decode("ASCII")

print(uartcommand)

if 'Explain' in uartcommand:

print('对话启动多模态识别')

getdata1 = 1

uart1.write(str(Explanin_Command)+'\r\n')

elif 'code' in uartcommand:

print('对话启动二维码识别')

getdata1 = 2

uart1.write(str(QR_code_Command)+'\r\n')

elif 'photo' in uartcommand:

print('对话启动拍照到云端')

getdata1 = 3

uart1.write(str(photo_Command)+'\r\n')

hc.HC(0x05,"m3v"+str(5)+"s"+str(8)+"t"+str(5)+" "+'3、 2、 1、 启动拍照',1,0)

if getdata1 == 1:

#启用多模态拍照识图

if uart1.any():

Explain()

if getdata1 == 2:

#启用二维码识别

if uart1.any():

QR_code()

if getdata1 == 3:

#启动拍照

if uart1.any():

make_photo()

if getdata1 == 4:

#启用get API指令

if uart1.any():

getAPI()

time.sleep_ms(100)

Arduino:

#include <SoftwareSerial.h>

#include <ArduinoJson.h>

#include <HardwareSerial.h>

#include <QHHCV2.h>

#include <OneButton.h>

String Explanin_Command;

String QR_code_Command;

String photo_Command;

String getAPI_Command;

String talk_start;

String talk_send;

String talk_state;

volatile int getdata1;

OneButton button12(12,false);

OneButton button13(13,false);

SoftwareSerial mySerial26(25,26);

QHHCV2 MyVoice;

void attachLongPressStart12() {

//按住说话

getdata1 = 0;

Serial1.println(talk_start);

}

void attachLongPressStop12() {

//放手发送对话

getdata1 = 0;

Serial1.println(talk_send);

}

void attachLongPressStart13() {

//长按唤醒或待机

getdata1 = 0;

Serial1.println(talk_state);

}

void attachClick12() {

//发送多模态拍照识图指令

getdata1 = 1;

Serial1.println(Explanin_Command);

Serial.println("启用多模态拍照识图");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"正在拍照识别,请稍等!"),1,0);

}

void attachDoubleClick12() {

//发送二维码识别指令

getdata1 = 2;

Serial1.println(QR_code_Command);

Serial.println("启用二维码识别");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"二维码识别"),1,0);

}

void attachClick13() {

//发送二维码识别指令

getdata1 = 3;

Serial1.println(photo_Command);

Serial.println("启动拍照");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"3、 2、 1、 启动拍照"),1,0);

}

void attachDoubleClick13() {

//发送二维码识别指令

getdata1 = 4;

Serial1.println(getAPI_Command);

Serial.println("启动get API指令");

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"开始获取鸡汤文"),1,0);

}

void QR_code() {

//二维码识别

delay(100);

//返回的内容解码成字符串

String get_QR_code = Serial1.readString();

Serial.println(get_QR_code);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"二维码的内容是:"),1,0);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+get_QR_code),1,0);

getdata1 = 0;

}

void make_photo() {

//拍照保存在云端,返回图片的url

delay(100);

//返回的内容解码成字符串

String get_photo_url = Serial1.readString();

Serial.println(get_photo_url);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"串口有返回相片链接了,请查收!"),1,0);

getdata1 = 0;

}

void Explain() {

//多模态拍照识图

delay(100);

//返回的内容解码成字符串

String getJson = Serial1.readStringUntil('\n');

Serial.println(getJson);

DynamicJsonDocument doc(512);

// 解析JSON

DeserializationError error = deserializeJson(doc, getJson);

if (error) {

Serial.print("解析失败:");

Serial.println(error.f_str());

return;

}

String text = doc"text".as();

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+text),1,0);

getdata1 = 0;

}

void getAPI() {

//get API指令

delay(100);

//返回的内容解码成字符串

String get_API_data = Serial1.readString();

Serial.println(get_API_data);

DynamicJsonDocument doc(512);

// 解析JSON

DeserializationError error = deserializeJson(doc, get_API_data);

if (error) {

Serial.print("解析失败:");

Serial.println(error.f_str());

return;

}

String TTSAPI = doc"result""content".as();

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+TTSAPI),1,0);

getdata1 = 0;

}

void setup(){

Serial.begin(115200);

Serial1.begin(115200,SERIAL_8N1,16,17);

mySerial26.begin(9600);

MyVoice.begin(mySerial26);

Explanin_Command = "{"state":"CapturePhotoAndExplain"}";

QR_code_Command = "{"state":"CapturePhotoAndUpload"}";

photo_Command = "{"upload_url":"http://ai.qdprobot.com/qdpai/qdprobot/upload_image.php"}";

getAPI_Command = "{"get_url":"https://payai.qdprobot.com/admin-api/mac/xljt"}";

talk_start = "{"state":"StartListening"}";

talk_send = "{"state":"StopListening"}";

talk_state = "{"state":"ToggleChatState"}";

getdata1 = 0;

//定义C02mini与AIcam的串口通信IO

//照片识别的文本较多,要加大串口的缓冲区,不然返回的json文本会丢失

Serial1.setRxBufferSize(1024);

//定义语音合成模块的串口通信IO

//1 多模态场景识别

//2 二维码识别

//3 拍照到云返回对应的url

button12.attachLongPressStart(attachLongPressStart12);

button12.attachLongPressStop(attachLongPressStop12);

button13.attachLongPressStart(attachLongPressStart13);

button12.attachClick(attachClick12);

button12.attachDoubleClick(attachDoubleClick12);

button13.attachClick(attachClick13);

button13.attachDoubleClick(attachDoubleClick13);

}

void loop(){

button12.tick();

button12.tick();

button13.tick();

button12.tick();

button12.tick();

button13.tick();

button13.tick();

switch (getdata1) {

case 1:

if (Serial1.available() > 0) {

Explain();

复制代码
}
break;

case 2:

if (Serial1.available() > 0) {

QR_code();

复制代码
}
break;

case 3:

if (Serial1.available() > 0) {

make_photo();

复制代码
}
break;

case 4:

if (Serial1.available() > 0) {

getAPI();

复制代码
}
break;

default:

if (Serial1.available() > 0) {

delay(100);

String uartcommand = Serial1.readString();

Serial.println(uartcommand);

if (String(uartcommand).indexOf(String("Explain")) != -1) {

Serial.println("对话启动多模态识别");

Serial1.println(Explanin_Command);

MyVoice.HC(0x05,String("m3v"+String(5)+"s"+String(5)+"t"+String(5)+""+"识别场景"),1,0);

复制代码
  } else if (String(uartcommand).indexOf(String("code")) != -1) {
    Serial.println("对话启动二维码识别");
    Serial1.println(QR_code_Command);
    MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"识别二维码"),1,0);
  } else if (String(uartcommand).indexOf(String("photo")) != -1) {
    Serial.println("对话启动拍照到云端");
    Serial1.println(photo_Command);
    MyVoice.HC(0x05,String("[m3][v"+String(5)+"][s"+String(5)+"][t"+String(5)+"]"+"3、 2、 1、 启动拍照"),1,0);
  }

}
break;

}

}

六、课程总结与拓展

  1. 课程核心总结
    本课程通过"齐护AIcam + 小智AI智能体"的创新组合,带领大家完成了一个完整的AIoT(人工智能物联网)项目实践。我们不再需要在资源受限的单片机上死磕复杂的算法,而是利用"边缘侧感知 + 云端大模型推理"的云边协同模式,实现了强大的多模态交互功能。

核心知识点回顾:

硬件架构:我们掌握了双板协同工作的原理,即 AIcam (ESP32) 作为视觉与网络终端(眼睛),负责采集图像和联网;C02mini (ESP32) 作为逻辑控制中心(大脑),负责处理数据和控制外设。

通信协议:深入理解了串口通信的重要性,特别是 JSON 数据格式的封装与解析。我们学会了如何通过 UART 串口发送标准指令(如 {"state":"CapturePhotoAndExplain"})来控制硬件行为。

AI 能力集成:实践了如何利用大模型的多模态能力进行场景识别、二维码识别以及自然语言处理(NLP),并结合 MCP(魔法控制协议) 实现了语音指令对硬件的精准控制。

全链路开发:从固件烧录、硬件接线、网络配置到图形化编程(Mixly/MicroPython),构建了一个闭环的智能硬件开发流程。

  1. 拓展与进阶方向

掌握了基础功能后,你可以从以下几个维度进行深度拓展,创造出更具个性和实用价值的作品:

A. 硬件层面的拓展

外设联动:在现有基础上增加 舵机、机械臂 或 继电器 模块。例如,制作一个"AI视觉分类垃圾桶",当摄像头识别到垃圾类别后,单片机控制对应的舵机打开箱盖。

结构设计:利用 3D 打印技术为你的 AIcam 设计专属外壳,将其封装成一个独立的智能终端(如桌面机器人、安防巡逻车),而不仅仅是一块裸露的电路板。

传感器融合:结合温湿度传感器、火焰传感器等,让 AI 不仅能"看",还能"感"。例如:"如果看到明火 且 温度超过阈值,才判定为火灾并报警"。

B. 软件与逻辑层面的拓展

精细化 Prompt 工程(提示词工程):

当前的 MCP 指令较为基础。你可以尝试优化 AI 的角色设定(提示词),让它不仅能返回简单的指令,还能返回结构化的 JSON 数据。

进阶案例:让 AI 分析图片后,直接返回 {"action": "move", "direction": "left", "steps": 10},从而控制机械臂进行精准抓取。

上下文记忆与对话流:尝试在主控代码中维护一个简单的对话历史记录,让 AI 具备短期记忆。例如,你问"这个多少钱?",AI 能结合上一轮识别的"苹果"图像,回答"苹果的价格是..."。

Web 端可视化:利用 AIcam 获取的图片 URL 或传感器数据,通过前端网页(HTML/JavaScript)进行展示,打造一个专属的物联网监控大屏。

C. 创新应用场景探索

智慧农业助手:将设备部署在植物旁,通过语音询问"我的花需要浇水吗?",AI 结合摄像头观察土壤湿度(视觉判断)和环境数据,给出养护建议。

个性化学习教具:制作一个"AI 指读机器人",利用摄像头识别书本上的文字或题目,通过云端 API 调用翻译或解题思路,并通过语音模块朗读出来。

结语: 本课程只是一个起点。"低门槛切入,高天花板拓展"是创客教育的魅力所在。希望你能利用好手头的齐护套件,大胆想象,动手实践,创造出属于你的 AI 智能新物种!

七、课程资源下载

1.【课程齐护在线Mixly_Micropython源程序下载】

2.【课程齐护教育版本Mixly-Arduino-ESP32例程下载】

3.【Aicam小智AI固件下载】

4.【课程视频PPT下载】

相关推荐
林三的日常1 小时前
一周AI核弹级热点
人工智能·搜索引擎
happyprince1 小时前
06_verl-单控制器与分布式调度
人工智能·架构·强化学习
FL16238631291 小时前
智慧建筑室内外构件要素识别分割数据集labelme格式5516张13类别
人工智能
米核AI易山1 小时前
扣子工作流设计模式:5 种可复用的架构模板
人工智能·架构·需求分析·coze·扣子工作流·米核ai易山
小王毕业啦1 小时前
2012-2024年 上市公司-企业业务招待费数据 (xlsx+文献)
大数据·人工智能·数据挖掘·数据分析·社科数据·实证分析·经管数据
承渊政道2 小时前
【从零开始大模型开发与微调:基于PyTorch与ChatGLM】(从环境搭建到第一个训练闭环:PyTorch2.0深度学习入门实战)
人工智能·pytorch·深度学习·机器学习·语言模型·自然语言处理·pycharm
Tangyuewei2 小时前
我用 AI 辅助开发了一个发型 App,然后打包成了 APK
android·人工智能·ai编程
delishcomcn2 小时前
AI赋能的薄膜分切机:从自动化到自优化
运维·人工智能·自动化·薄膜分切机
拓朗工控2 小时前
工控机核心应用场景与落地价值解析
人工智能·视觉检测·工控机·工业电脑