- 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。
系列一:ESP32系列模组基础学习系列笔记
1、 爬坑学习新旅程,虚拟机搭建esp32开发环境,打印 “Hellow World”。
2、 巧用eclipes编辑器,官方教程在在Windows下搭建esp32开发环境,打印 “Hellow World”。
3、 认识基本esp32的GPIO接口,开始点亮您的第一盏 LED和中断回调实现按键功能 。
4、体会esp32的强大的定时器功能, 实现定时2s闪烁一盏LED灯。
5、接触实践esp32的pwm宽度脉冲功能, 实现呼吸效果闪烁一盏LED灯。
6、smartConfig和微信airKiss在esp32的实现,一键配网轻松快捷连接路由器。
7、利用GPIO中断做一个按键的短按和长按的回调事件,再也无须担心触发源。
8、esp32上实现本地 UDP 客户端和服务端角色,在局域网内实现通讯。
9、esp32上实现本地 TCP 客户端和服务端角色,可断线重连原路返回数据。
10、乐鑫esp32 SDK编程利用rmt驱动ws2812七彩灯,实现彩虹渐变效果。
11、入门 乐鑫esp-adf 音频框架开发,esp32造一个蓝牙耳机,实现切换歌曲,获取歌曲信息等功能。
12、开源一个微信公众号airkiss配网esp32以及局域网发现功能的工程,分享一个airkiss配网小工具。
13、esp32 内置 dns 服务器,无需外网访问域名返回指定网页。
14、esp32 sdk编程实现门户强制认证,连接esp32热点之后,自动强制弹出指定的登录界面。
15、认识本地离线语音唤醒识别框架 esp-skainet ,实现较低成本的硬件语音本地识别控制。
16、学习本地语音唤醒离线识别框架 esp-skainet ,如何修改唤醒词? 如何自定义命令词?如何做意图动作?
17、全网首发,乐鑫esp32 sdk直连京东微联·小京鱼 · IoT开放平台,实现叮咚音响语音智能控制。
18、入门京东微联·小京鱼的控制面板H5开发,读懂vue语法,做自己的控制页面。
19、重磅开源,如何在微信小程序上ble蓝牙配网esp32,blufi的那些事!
20、一篇好文,开发过程中编译esp32固件太大,无法正常启动?教你如何自定义分区表partitions.csv。
21、 esp32蓝牙配网blufi的高度封装,集成简单、使用简单、容易上手,提高开发效率!
22、讨论下程序员 “青春饭” 那些事,分享在esp32实现多种加密算法md5 |AES CBC-ECB| Sha1 | Sha256 等!
23、安信可 esp32-a1s 音频开发板移植最新 esp-adf 音频框架,小试牛刀如何实现在线文字转语音播放。
25、分享在 esp32 SDK实现冷暖光色温平滑调节的封装,轻松集成到您的项目去。
26、分享下如何在window下使用CMake编译,编译速度提高传统 make 编译一个档次,支持 ESP32 和 ESP32-C3。
27、windows10平台下自带的Linux安装 ESP8266/ESP32 环境,再无需额外安装虚拟机了。
系列二:ESP32-Camera 摄像头开发板系列笔记
1、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现MQTT远程拍照传输到私有服务器。
2、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,实现本地视频流监控。
3、安信可 ESP32-Cam 摄像头开发板二次开发 C SDK编程,拍照图片通过有线串口传到上位机PC端。
系列三:ESP32-C3 模组系列笔记
1、【蓝牙Mesh笔记 ①】ESP32-C3 模组上实现天猫精灵蓝牙 BLE Mesh AliGenie 接入,无需WiFi 连接也可以实现天猫精灵语音控制。
文章目录
前言
前面我在学 PyQT5
,忽然有想法配合ESP32-CAM做一个上位机的显示的小玩意,几经折腾,搞了出来,全部开源,现在分享给大家, 欢迎继续关注我的公众号。
人生阅历告诉我,做人不能好为人师,看到网上许多的有技术的文章,几乎是做营销一样,提着 “授人以鱼,不如授之以渔” 名声写技术文章,写着标题却是没有文字的文章,不禁在想,这究竟怎么了。
但我写文章不会这样的,应该以脚踏实地地写好每一篇技术文章,有思想地封装每个代码模块,解耦各个功能模块,变量方法类命名规则符合阿里巴巴JAVA手册,这样是我所追求和推崇的;
越走越远,勿忘初心,从2016年开始写文章到如今,绝对不是为了做教案,更不是只为了零零几块钱而去逼迫自己学习,而是内心感受到敲代码所带来上的精神满足,那种修复 bug 废寝忘食的日日夜夜,正是我所追求的,当然了,这必然会带来财富的增益。
做人做事,要有长远眼光和大格局。
一、原理:
下载固件 的时候 ESP32-cam
的 io0
要接 GND
,下载结束后,必须断开io0
和GND
的连接,再按下复位按键重启设备。ESP-CAM 接线下载固件图如上。
拍照显示的原理如下:
二、JPEG
图片格式:
整个项目的难点是电脑端如何根据一端buff
去解析出来一张图片,于是乎,不禁去翻阅资料:《jpeg图片格式详解》。
JPEG图片的二进制格式:
SOI(文件头)+APP0(图像识别信息)+ DQT(定义量化表)+ SOF0(图像基本信息)+ DHT(定义Huffman表) + DRI(定义重新开始间隔)+ SOS(扫描行开始)+ EOI(文件尾)
总的来说,我们拿到一段二进制图片,判断开头和结尾就好了。
描述 | 数值 |
---|---|
开头两个字节: | 0xFFD8 |
结尾两个字节: | 0xFFD9 |
三、设计通信协议
为了更好调试,我使用了2个串口,一个串口用于通信,另外一个是用于看运行日志,接线:
开发板 | USB-TTL | 用途 |
---|---|---|
U0TXD ( GPIO1 ) | RXD | 用于看运行日志 |
U0RXD ( GPIO3 ) | TXD | 用于看运行日志 |
GPIO2 | TXD | 串口通信 |
GPIO4 | RXD | 串口通信 |
- 波特率:115200
- 数据位: 8
- 停止位:1
- 校验位:none
- 流控:无
3.1 获取图片
电脑发送:0xF0 0xA0
,模块返回一张图片的buff给到上位机。
3.2 设备重启
电脑发送:0xF0 0xA1
,模块2秒后重启。
四、设备代码
4.1 配置串口
uart_config_t uart_config = {
.baud_rate = 115200,
.data_bits = UART_DATA_8_BITS,
.parity = UART_PARITY_DISABLE,
.stop_bits = UART_STOP_BITS_1,
.flow_ctrl = UART_HW_FLOWCTRL_DISABLE
};
uart_param_config(UART_NUM_1, &uart_config);
//配置串口1作为日志运行
uart_set_pin(UART_NUM_1, ECHO_LOG_TXD, ECHO_LOG_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
uart_driver_install(UART_NUM_1, BUF_SIZE * 2, 0, 0, NULL, 0);
//配置串口0作为通信
uart_param_config(UART_NUM_0, &uart_config);
uart_set_pin(UART_NUM_0, ECHO_TEST_TXD, ECHO_TEST_RXD, ECHO_TEST_RTS, ECHO_TEST_CTS);
uart_driver_install(UART_NUM_0, BUF_SIZE, 0, 0, NULL, 0);
4.2 处理数据并返回数据
我没有把处理收到的数据放在串口回调任务里面,而是另外开启了一个消息队列做处理。
/*
* @Description: 解析下发数据的队列逻辑处理
* @param: null
* @return:
*/
void Task_ParseJSON(void *pvParameters)
{
char data[] = {0xB0, 0, 0};
size_t _jpg_buf_len;
uint8_t *_jpg_buf;
camera_fb_t *pic = NULL;
esp_err_t res = ESP_OK;
size_t fb_len = 0;
while (1)
{
struct __User_data *pMqttMsg;
xQueueReceive(ParseJSONQueueHandler, &pMqttMsg, portMAX_DELAY);
printf("Task_ParseJSON_Message xQueueReceive get [%s] ... \n", pMqttMsg->allData);
首先整体判断是否为一个json格式的数据
cJSON *pJsonRoot = cJSON_Parse(pMqttMsg->allData);
//如果是否json格式数据
if (pJsonRoot == NULL)
{
printf("[SY] Task_ParseJSON_Message xQueueReceive not json ... \n");
data[1] = 0xA0;
goto __cJSON_Delete;
}
cJSON *pJSON_Item_cmd = cJSON_GetObjectItem(pJsonRoot, "cmd");
if (strcmp(pJSON_Item_cmd->valuestring, "Reboot") == 0)
{
data[2] = data[1] + 0xB0;
uart_write_bytes(UART_NUM_1, (const char *)data, 3);
ESP_LOGE(TAG, "reboot after 2s ...");
//延迟2秒后重启设备
vTaskDelay(2000 / portTICK_PERIOD_MS);
esp_restart();
}
else if (strcmp(pJSON_Item_cmd->valuestring, "Get Picture") == 0)
{
//开始拍照
pic = esp_camera_fb_get();
if (!pic)
{
ESP_LOGE(TAG, "Camera capture failed");
}
else
{
//拍照成功,获取其大小、尺寸等信息
ESP_LOGI(TAG, "Camera capture OK , Its size was: %zu bytes", pic->len);
ESP_LOGI(TAG, "Camera capture OK , Its width was: %d", pic->width);
ESP_LOGI(TAG, "Camera capture OK , Its height was: %d ", pic->height);
//写入串口
uart_write_bytes(UART_NUM_1, (const char *)pic->buf, pic->len);
//vTaskDelay(200 / portTICK_RATE_MS);
}
esp_camera_fb_return(pic);
}
__cJSON_Delete:
cJSON_Delete(pJsonRoot);
}
}
五、上位机代码
因为设备发送一段图片的数据,上位机会分几次接受到 ,所以我们代码上要处理拼接这些数据,然后再显示出来:
# 收到的数据
buff = (obj['data'])
# 收到的数据长度
length = obj['length']
# 拼接
picBuff.append(buff)
# 假如拼接之后的末端是 FF D9 ,则开始解析显示。
if buff[length - 1] == 217 and buff[length - 2] == 255:
print('图片 buff', (picBuff))
# 将bytes结果转化为字节流
bytes_stream = BytesIO(picBuff)
# 读取到图片
roiimg = Image.open(bytes_stream)
imgByteArr = BytesIO() # 初始化一个空字节流
roiimg.save(imgByteArr, format('PNG')) # 把我们得图片以‘PNG’保存到空字节流
imgByteArr = imgByteArr.getvalue() # 无视指针,获取全部内容,类型由io流变成bytes。
img_name = '1.jpg'
with open(os.path.join('', img_name), 'wb') as f:
f.write(imgByteArr)
image = QPixmap(img_name)
ui.label.setPixmap(image)
picBuff.clear()
六、效果
日志串口信息:
[0;32mI (493) sccb: pin_sda 26 pin_scl 27
[0m
[0;32mI (503) gpio: GPIO[32]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m
[0;32mI (653) camera: Detected OV2640 camera[0m
[0;32mI (663) camera: Allocating 1 frame buffers (37 KB total)[0m
[0;32mI (663) camera: Allocating 37 KB frame buffer in OnBoard RAM[0m
[0;32mI (823) gpio: GPIO[4]| InputEn: 0| OutputEn: 1| OpenDrain: 0| Pullup: 0| Pulldown: 0| Intr:0 [0m
[SY] Task_ParseJSON_Message creat ...
Task_ParseJSON_Message xQueueReceive wait [217108] ...
Task_ParseJSON_Message xQueueReceive get [{"cmd":"Get Picture"}] ...
[0;32mI (11913) TAG:: Camera capture OK , Its size was: 7643 bytes[0m
[0;32mI (11913) TAG:: Camera capture OK , Its width was: 640[0m
[0;32mI (11913) TAG:: Camera capture OK , Its height was: 480 [0m
Task_ParseJSON_Message xQueueReceive wait [217060] ...
其他
- 关注本人微信公众号 “徐宏blog” 或扫描下方二维码,发送 210507 获取源码!
另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,也欢迎留言哈!
- 玩转
esp8266
带你飞、加群QQ
群,不喜的朋友勿喷勿加:434878850 - 个人邮箱:xuhongv@yeah.net 24小时在线,有发必回复!
- esp8266源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
- esp32源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32
- 关注下面微信公众号二维码,干货多多,第一时间推送!