分享三个例程:使用ESP32做一个实时语音对讲机,MQTT协议实现公网对讲,ESP32-CAM 上传图像数据到网络。并附上例程链接。

原博主的网站shumei52.top,分享三个例程:使用ESP32做一个实时语音对讲机,MQTT协议实现公网对讲,ESP32-CAM 上传图像数据到网络。并附上例程链接。可以比对着看来学习NOW,MQTT使用方法。想办法把图像和语音代码融合在一起,实现声音和图像同步传输。

一:使用ESP32做一个实时语音对讲机

2022-08-05 C/C++编程,ESP32/ESP8266 4 条评论 3311 次阅读
最近突发奇想,制作一个数字式的音频通信系统,顺便学习一下I2S与ESP-NOW协议

刚开始查阅资料,发现油管上的已经有人做过了,但是使用的C++,并用了数据流的处理流程,比较晦涩难懂,代码量也很大,属于是炫技的作品,我这篇文章使用C重新写一遍,并且代码量大大降低,也很容易理解,let’s get started!

上一篇博客中已经详细讲解了I2S通信协议,在ESP32中有两个硬件I2S,我们可以通过简单的配置使用它

ESP-NOW是乐鑫的私有协议,相比于传统的七层协议,ESP-NOW只保留了物理层与数据连接层,在其之上封装了ESP-NOW协议,但是这个协议是不开源的,意味着我们看不到这个协议的源码,只能使用封装出来的接口。
1.png
使用的硬件:
麦克风:INMP441
功放:MAX98357
主控:ESP32*2
按键与指示灯:板载

使用的软件:
Arduino IDE
ESP32扩展包 2.0.4(最新)

编程思路:
发送:初始化I2S采集后,数据会源源不断的存放在DMAbuf中,按下按键,将数据取出,转换成需要的格式,最终转换成8bit数据发送出去。
接受:在ESP-NOW接受回调函数中,将接收到的数据重新转换为16位, 发送到I2S中的DMA去。注意,在没有接收到消息的是否,需清空dambuf,要不然会重复播放上一帧的音频,发出很大的噪音。
数据流向:I2S采集->原始32bit->16bit->8bit->esp-now发送->接收到数据8bit->转换为16bit->I2S播放

具体配置:
麦克风采集配置

const i2s_config_t rec_i2s_config = {
.mode = i2s_mode_t(I2S_MODE_MASTER | I2S_MODE_RX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_32BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_RIGHT,
.communication_format = i2s_comm_format_t(I2S_COMM_FORMAT_I2S| I2S_COMM_FORMAT_I2S_MSB),
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 2,
.dma_buf_len = 256,
}
扬声器采集配置:

const i2s_config_t spk_i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
.sample_rate = SAMPLE_RATE,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT, //2-channels
.communication_format =(i2s_comm_format_t)(I2S_COMM_FORMAT_I2S),
.intr_alloc_flags = 0,
.dma_buf_count = 2,
.dma_buf_len = 256,
};
其中,dambuf的两个参数的设定比较有讲究,可以点击这里学习。

硬件连接:
INMP441:
BCK —>>>IO4
WS —>>>IO15
data—>>>IO13

MAX98357:
BCK —>>>IO26
WS —>>>IO22
data—>>>IO25

开源github链接:https://gitlab.ifengyu.com/tianshuaikang/esp32-audio-communication

二:MQTT协议实现公网对讲

使用MQTT做一个公网对讲机

上一篇博客中,使用ESP32与ESP-NOW协议做了一个短距离对讲机(https://www.bilibili.com/video/BV1qT411L7WX),发布了一个视频在B站。

在这里插入图片描述
评论区中,很多B友希望可以实现无限距离对讲,这样的话需要服务器转发,刚开始我想使用python写一个TCP或者UDP的转发功能,但是考虑到很多小白没有公网服务器,并且也不会使用python,于是我想到了互联网中的MQTT协议,MQTT协议天生为转发而生;MQTT协议是TCP协议的应用,是一个基于客户端-服务器的消息发布/订阅传输协议,MQTT使用的发布/订阅消息模式,提供了一对多的消息分发机制,从而实现与应用程序的解耦。这是一种消息传递模式,消息不是直接从发送器发送到接收器(即点对点),而是由MQTT server(或称为 MQTT Broker)分发的。

我曾经也有一篇文章简单的叙述了MQTT的工作原理与搭建过程(怎样在自己的电脑上搭建MQTT),MQTT可以运行在几乎所有的设备上,例如公网服务器(Linux、Windows系统等)、树莓派、局域网电脑等,当然,如果MQTT服务运行在局域网中,那就只能实现局域网的消息转发。如果你没有公网服务器,可以使用我的MQTT地址,我的MQTT服务器将会免费开放到2025年。我使用的MQTT Broker为EMQ免费开源版,并且修改了cfg文件,将速率与可接入设备限制调高。

如果你只想实现无限对讲,不想关注MQTT,那就看下面的代码吧,代码git链接放在文章最后!

首先需要在Arduino中安装pubsubclient库,这个库是可以运行在ESP上的MQTT库,源码也非常简单,非常值得学习。
代码上基于上个视频的硬件与代码,硬件连接完全相同,软件只进行了通信协议的修改。(重点:)代码中需要修改的只有两个地方,第一个地方是WIFI账号与密码(2.4G),第二个地方是修改角色,发送端或者接收端,具体位于AudioMqtt.h中的SENDER宏定义,你需要将该项设置为1,编译烧录给带有麦克风的设备,再将该项设置为0,编译烧录给带有扬声器的设备。烧录给两个设备,按下发射端的板载按钮说话,你应该就可以听到扬声器中你的声音了。

我们已经了解了MQTT协议的工作原理,我们也可以在电脑上写一段python脚本订阅发布的音频数据并且播放出来,python需要的库为paho-mqtt与pyaudio,代码也在git中,是audiotest.py。

git地址:https://gitlab.ifengyu.com/tianshuaikang/esp32audiomqtt

三:ESP32-CAM 上传图像数据到网络

ESP32-CAM上传图像数据到Python上位机

预防踩坑放在前面:目前安信可官方版的CAM模块已经停售,库存货比较贵,市面上的都是仿制的,质量良莠不齐,给开发带来了很多困扰,经过实际测试,发现山寨货主要有以下几个坑:
1、发热严重,不加散热片长时间运行几乎到了烫手的地步,加上散热片也不会好很多
2、在分辨率大于640*480后,信号变得异常的差,丢包严重,但如果用手捏着天线,数据传输又会稳定很多
第二个原因上网查原因可能是山寨CAM天线附近包了一层地,那么如何避免踩坑?
目前网上的山寨CAM主要有以下两种,位于卡槽右下角的电阻,一种是四个电阻,另一种是六个电阻,建议买四个电阻的(官方板是四个电阻),效果比六个电阻的好很多。

cam1.png
在这里插入图片描述
强烈建议外置天线,视频信号穿墙也不是问题,使用外置天线需要修改一个电阻,将原来的电阻拆掉,一坨锡搞过来,买个天线装上就可以了
IMG_6882.JPG
烧录接线:
一句话讲明白下载:IO0为低电平,复位后为程序下载模式,IO0为高电平,复位后为程序运行模式,所以要进入下载模式,按照这样接线
USB-TTL-------ESP32CAM
TX------------UOR
RX------------UOT
5V------------5V
GND-----------GND
GND-----------IO0
按下小小的复位按钮,就进入下载模式,可以用Arduino烧录程序
下载完成后,将IO0上的线拔掉,复位后就可以运行程序了

程序原理:
初始化ov2640,设定引脚、速率、图片像素、图像格式等参数,另外,板载的SRAM可以设定更大的像素
重点:为什么使用jpeg的图片格式?jpeg是图片的一种有损压缩格式,我们使用网络传输可以节省很多带宽,提升帧率,举个例子,一张320*240像素的图像原始大小为15.36KB,压缩后可能只有2KB。而且OV2640可以直接输出jpeg格式的图片,不用处理器压缩占用时间

我们使用arduino上封装好的库,可以直接获取图片数组,因为ESP32 UDP每个包最大只有1460字节,因此还需要分包发送,我将图片分为1400个字节+1字节的索引,索引代表这个图片的第几个包,如果为0XFF代表这长图片传输完成了,分包代码如下:

uint8_t *P_temp = fb->buf;                            //暂存指针初始位置
int pic_length = fb->len;                             //获取图片字节数量
int pic_pack_quantity = pic_length / max_packet_byte; //将图片分包时可以分几个整包
int remine_byte = pic_length % max_packet_byte;       //余值,即最后一个包的大小
for (int j = 0; j < pic_pack_quantity; j++) //发送图片信息,这是按分包循环发送,每一次循环发送一个包
{
    sendImgAray(fb->buf, max_packet_byte,j); //将图片分包发送
    fb->buf+=max_packet_byte; //图片内存指针移动到相应位置
}
sendImgAray(fb->buf, remine_byte,0xFF); //发送最后一个包,剩余的数据

python上位机:
python上位机用UDP协议,修改为当前机器的IP地址和端口号,接受数据后通过判断数据最后一位确定图片是否传输完成,将接收到的数组转换成opencv的img图像,图像就显示出来了,可以通过w、s按钮调整灯光亮度。如果没有图像数据,整个界面是卡死的状态。

代码开源地址:https://gitlab.ifengyu.com/tianshuaikang/espcam2pc.git

请大家访问原博主的网站:shumei52.top

### 实现ESP32对讲机功能于Linux环境 为了实现在Linux环境下使用ESP32开发对讲机应用的目标,需遵循一系列配置与编码实践。首先,确保安装了必要的工具链和支持库来支持ESP-IDF框架的运作。 #### 安装依赖项和设置环境变量 在Linux环境中准备ESP32开发所需的基础设施至关重要。这涉及到安装特定版本的Python以及通过官方指南获取初始化ESP-IDF SDK[^3]。对于ESP-IDF v5.1及以上版本的支持尤为重要,因为这些更新带来了性能改进和新特性,有助于更稳定地运行复杂的应用程序如对讲机服务。 ```bash sudo apt-get update sudo apt-get install git wget flex bison gperf python3 python3-pip cmake ninja-build ccache libffi-dev libssl-dev dfu-util ``` 接着,克隆ESP-IDF仓库至本地: ```bash git clone --recursive https://github.com/espressif/esp-idf.git cd esp-idf ./install.sh source ./export.sh ``` 上述命令不仅下载了最新的ESP-IDF源码及其子模块,还设置了必需的路径以便后续操作能够顺利调用相关工具。 #### 配置项目结构 创建一个新的ESP-IDF工程文件夹,复制来自参考资料中的示例代码作为起点[^1]。此步骤允许开发者基于已验证的工作模型快速启动原型设计阶段。具体来说,可以从提供的链接中找到关于如何利用ESP32构建实时语音通信系统的指导说明和技术细节。 #### 编写核心逻辑 针对对讲机的核心需求——即双向音频流处理,应重点关注麦克风输入采集、压缩算法选择(例如Opus)、网络传输机制(比如WebRTC或MQTT),还有扬声器输出播放等方面的设计实现。这里特别提到MQTT协议用于公网对讲的优势在于它能有效降低延迟提高消息传递效率,非常适合移动设备间的即时通讯场景。 ```c #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "mqtt_client.h" void app_main(void){ // 初始化WiFi连接... // 创建MQTT客户端实例... } ``` 以上片段展示了应用程序入口函数`app_main()`内的初步布局,其中包含了WiFi联网准备工作及MQTT会话建立的关键部分。实际部署时还需加入更多具体的业务流程控制语句以完成整个通话周期管理。 #### 测试与优化 最后一步是在真实物理节点间进行全面的功能性和稳定性测试。考虑到不同地区可能存在信号强度差异等因素影响用户体验质量,建议尽可能多地覆盖各种典型应用场景来进行详尽评估。同时也要注意监控资源消耗情况,适时调整参数设定从而达到最佳平衡状态。
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值