admin 管理员组

文章数量: 887016

已写文章链接

本专栏主要内容是记录基于ESP32的开发工作,包括介绍 ESP32 基础知识、开发环境搭建、基础外设使用、蓝牙、WiFi 、与微信小程序联动等知识,达到自己动手做一些智能硬件的目的。
开发过程中主要参考官方资料,包括官网、规格书、参考手册、编程指南、驱动包等。
本专栏适合对ESP32感兴趣,想要找一个简单入手教程的同学。

ESP32 基础知识(已完成)

(1)ESP32基础知识

开发环境搭建(已完成)

(2-1)开发环境搭建(基于Arduino)
(2-2)开发环境搭建(基于VS Code+PlatformIO)
(2-3)开发环境搭建(基于ESP-IDF软件)

基础外设使用(已完成)

(3-1)基础外设使用(GPIO)
(3-2)基础外设使用(USART)

蓝牙(已完成)

(4)蓝牙使用(Classic BT+BLE)

WiFi(已完成)

(5)WiFi使用(STA模式)

微信小程序(已完成)

(6)微信小程序(配网和开关灯)


前面章节我们已经实现了 ESP32 开发板蓝牙和 WiFi。从本章开始,我们实现微信小程序的部分。
由于笔者只做过嵌入式软件开发(Cortex-M 内核 MCU),对微信小程序开发所用到的JavaScriptWXMLWXSS等技术一概不熟,就不深入探究细节了,只求实现功能。
所有的参考链接和网址都放在本文最后一章。

需求

目前想的是实现两个基础的功能。一个是通过小程序给开发板联网,一个是通过小程序控制开发板硬件。
之前开发板与手机通过 BLE 通信的部分已经做完了,也就是手机可以通过 BLE 给开发板发指令,那就剩下小程序端的功能了,上面的两个功能可以放在一个小程序里实现,也没有多复杂,那就把需求放在一块写,到时候一条条实现,大概有以下需求。

  1. 小程序可以搜索附近的 BLE 设备,连接或者断开连接。
  2. 小程序需要有通过 BLE 方式向开发板发送指令/数据能力,方便传输 WiFi 信息。
  3. 小程序需要有一系列按钮(框),包括搜索附近 BLE 设备的搜索框、连接设备框、断开连接框。配网框(点击配网框之后要求用户输入ssid + password)、控制开发板灯亮/灭。
  4. 小程序需要有一些界面,比如搜索 BLE 时,展示附近的 BLE 设备信息(uuid+信号强度)。
  5. 小程序需要有一些提示信息,比如连接 WiFi 时给出连接结果(连接成功?连接失败?失败原因?),打开/关闭开发板灯时给出操作结果(操作成功?操作失败?)。

从界面来说,小程序需要有两个界面,一个是与蓝牙配对相关的,包括搜索蓝牙、配对、停止搜索,展示搜索结果,展示配对结果。一个是与具体逻辑相关的界面,比如配网界面和控制开发板硬件界面。两个界面的示意图如下。

获得小程序账号

注册账号

在此网址填写基本信息,注册小程序。

记录 AppID 和密钥

注册好之后在菜单 “开发”-“开发设置” 看到小程序的 AppID 了 。记录一下 AppID 和密钥。

安装开发工具

在此页面下载稳定版。

安装后打开登录。
右上角小齿轮选择不使用代理。

新建项目(Hello World)

填写好以下的信息(主要是 AppID),点击确定即可。

各文件含义

新建好的工程文件如下。
小程序包含一个描述整体程序的 app 和多个描述各自页面的 page。现在只有一个页面index。一个页面由 4 个文件组成,分别是.js .wxml .json .wxss

序号文件名文件作用
1app.js对整个小程序进行初始化,包含小程序的逻辑。
2app.json记录项目的一些静态配置,指明小程序包含哪些页面,必须至少有一个页面,例如现在的 index。此文件文件用于整个项目的配置,对于所有页面都有效。
3app.wxss小程序公共样式表
4index.js页面逻辑,目前是初始化了一个页面。
5index.wxml页面结构
6index.json页面配置
7index.wxss页面样式表

修改源码并编译

打开index.wxml,修改一下右边的两处,再点击编译。
左侧的展示栏已经给出了实时结果。

验证

点击预览按钮,使用微信扫描二维码,查看结果,实际运行与左边展示栏结果一致。


对项目做一些修改

本章节对于项目文件做一些修改,可以直观看到不同的修改对于显示效果的影响。
此处指的是修改index界面名称的大小和颜色,在 app 文件夹下进行对应修改也行,但是会影响到整个小程序界面,保险起见还是在各自的界面进行各自的修改。

修改界面名称

index.wxml文件中修改。

修改界面名称的大小和颜色

index.wxss文件中修改。

这两步只是体验一下这些参数对于小程序显示效果的影响,我们不会一步步所有框架都自己建,那样效率太低了。从下一章开始,我们会大量参考微信官方给出的示例,哎,不重复造轮子,会使用工具即可。

使用官方的 BLE 模板

打开模板

微信小程序官方的网站上有一个好用的功能,就是可以把要调用的 API 使用前面安装的开发者工具打开。例如,我想使用 BLE 功能,就提前打开微信开发者工具,找到 BLE 对应的 API,往下拉有一个在开发者工具中预览效果的链接,点击就会在开发者工具中打开。

如下图所示,在界面左侧有了开始扫描,停止扫描,结束流程的按钮。

此时可以试试效果,点击预览之后,点开始扫描,点击蓝牙名称,就可以配对成功,底下会显示出蓝牙的 UUID 和特性值。我们就以此为模板,开始后续开发。

修改按钮样式

添加 UI 库

BLE 的示例虽然可以看,但是有点丑,我们试着改一下按钮的样式。在表单组件中找到按钮,就采用示例中给出的绿色按钮。在开发者工具中预览效果。

样式如下图所示,在项目资源管理器中有一个lib,里边有一个文件weui.wxss。这个好像是微信官方出的一个 UI 库(不知道这样理解对不对哈,毕竟一开始就说了我不是个专业的🐶)。
右键lib库文件在资源管理器中打开,把lib库文件复制到我们的项目文件夹(bluetooth 示例)底下。复制完成后的项目文件夹如下。(项目文件夹就是bluetooth 示例文件夹,以下不再描述)


使用 UI 库

在刚才添加 UI 库的步骤里,导入了一个button 组件的示例库,打开示例库的index.wxml文件,看代码左侧绿色的按钮对应的代码就是右边的两行。

验证一下,把右边的代码复制到项目文件夹下的图示位置。能看到顶部已经出现了我们想要的样式。

接下来是把开始扫描的按钮换成页面顶部的primary
看一下原始的bindtap参数(bindtap 是绑定事件的意思),是openBluetoothAdapter,文档里也写了蓝牙设备使用之前需要先调函数初始化蓝牙适配器模块,那此处就是将primary换成开始扫描,并且把原先开始扫描按钮的绑定事件原封不动放到primary下。


将源码修改如下,能看到已经把primary按钮变成了开始扫描,并且把原先开始扫描绑定的事件也换上了。然后删除原先开始扫描的按钮代码(下面的第 4 行)。修改完成后的源码和显示效果如图。其他按钮同理,在此不赘述。

<button type="primary" size="{{primarySize}}" loading="{{loading}}" plain="{{plain}}"
disabled="{{disabled}}" bindtap="openBluetoothAdapter"> 开始扫描 </button>

  <button bindtap="openBluetoothAdapter" > 开始扫描 </button>
  <button bindtap="stopBluetoothDevicesDiscovery">停止扫描</button>
  <button bindtap="closeBluetoothAdapter" style="position: relative; left: -1rpx; top: -1rpx">结束流程</button>



添加图标样式

上一节我们已经成功修改了默认的按钮样式,需求里写到了需要显示蓝牙的连接状态,那我们就需要一个连接成功的图标。还是参考官方的文档中icon章节。我们最终就实现一个右侧显示的成功的图标。

icon的示例如下图所示。与成功图标有关的代码位于右侧框中。
但此时的图标是一组图标,我们只想添加一个图标,偶然发现使用左上角可视化的功能,双击组件部分的内容,例如bottontext可以添加默认的组件,组件对应的代码如右侧所示,那就简单了,我们添加一个icon,然后把它拖动到对应位置即可。

在项目代码中采用上述方法,添加一个成功的图标和连接状态的提示,但此时这些是默认一直显示的,肯定不能一直显示,我们的需求是连接成功之后才显示。

联想到之前的步骤中连接蓝牙之后,才会在下面显示蓝牙的信息,那就找找这些信息的显示逻辑对应的代码,我们把显示图标添加到这些代码的触发条件中。

已连接的信息对应的代码在下图位置,我们把图标添加到对应位置,查看显示效果。

能看到刚打开时不会显示图标,只有连接成功后才会显示图标,能满足显示要求,后面再调整一下下半部分界面的布局,把图标放到对应的位置即可。


添加切换页

目前关于蓝牙的界面放了挺多的元素,例如搜索按钮、展示区域等,还有 WiFi 配网和控制开发板灯的界面没做,这些东西全放在一个页面里有点挤,我们就新增一个界面,用来放这些元素。
刚开始想的是连接蓝牙成功之后添加一个跳转页,直接跳转过去,但在微信文档中没找见对应的说明。就看黑马的在 B 站的小程序教程,有个组件叫tabBar,也能实现新增一个界面的功能。

添加新界面文件

首先把项目文件夹底下的index文件夹整个复制-重命名。将新页面称为pages,将原先index文件夹下的文件名修改为pages。然后将pages文件夹整个复制到与index文件夹的同级目录下。此时项目资源管理器中已经出现了pages界面,但是小程序中依然只有一个界面。

修改app.json

接下来修改整个小程序的配置文件app.json。在文件中添加如下的代码。

要注意添加成员时后面的“,”,最后一个是没有“,”的。


然后就能看到新添加的页面了。此处我们只添加了最基础的且必须的元素,所以导航栏显得有点简陋,等完成了主要功能开发之后再调整这些显示效果。

到这呢,我们第一个界面就做的差不多了,而且也添加了第二个页面,接下来就是开发第二个界面了。附上第一个页面的大概布局。一些小细节等后面做完功能再完善。

添加开关按钮

控制开发板上的 LED 灯,可以按照前面章节选择增加两个按钮,但那种开关结果不太直观,我们采用下面这种效果。

还是选择在开发者工具中预览效果,打开示例后效果如下。与左侧显示效果相关的代码位于右侧框中,将右侧的代码复制到项目工程中。调整一下位置和文字即可。


接下来是给开关按钮关联对应的事件。查看网上一个基础的开关关联事件的案例。wxml的内容放在pages.wxml中,JavaScript的内容放在pages.js文件中。
添加完成之后的pages.js如下图所示。修改一下pages.wxml的内容,增加一个开关事件的绑定。


验证开关功能

验证一下开关的效果。


修改开关的功能

目前灯的开关是输出打印内容,我们需要将打印换成给开发板发对应的指令/数据。还是看官方文档,

运行示例后,有一个写数据的按钮,我们看一下写数据的具体逻辑。

绑定事件是writeBLECharacteristicValue,向蓝牙设备发送 16 进制数,只不过目前发的是随机数,我们换成发成自定义的数。


上图中的注释与代码对不上,因为看random是输出一个随机值,而非 0x00,查看官方文档对应的片段,注释与代码是对应的,要发送 0x00,那就将偏移和数据都设置为 0。想发送 0x12,那就给value传参 0x12 即可。


将上面writeBLECharacteristicValue事件中发送的数据变为 0x12。

此处需要先给开发板下载(4)蓝牙使用(Classic BT+BLE)中 BLE 例程的代码,打开开发板串口,运行日志如下。

然后在手机端打开小程序,连接蓝牙,点击写数据,观察开发板串口输出的信息。

在刚开始连接上蓝牙时,开发板收到了 0x12 数据,手机端点击写数据后,又接收到了一个 0x12。也就是说,在刚开始连接上蓝牙时,小程序执行了一次发送数据。这与我们的预期不相符。但是写数据的逻辑确实与我们设想的一样。

反复断开连接又重新连接,出现如下的接收值,而且在发送数据的函数内加的日志打印并没有被执行,那就说明跟我们的用户代码没啥关系,因为发送函数并没有调我们写的,那就不深究了。
曲线救国,我们可以设定一个逻辑,只有接收到特定数值,才开灯。收到其他值一律关灯。这样就可以避免上电时候的随机值。

pages.js文件中,灯开关对应的逻辑中加入下面代码,按理来说,连接蓝牙,执行开关打开操作时,就会执行writeBLECharacteristicValue函数,给开发板发 0x12。但是并没有。。。。。。。。


在这个地方卡了两个多小时,尝试过各种调用writeBLECharacteristicValue函数的方法,开发板始终收不到小程序发来的数据,但是在console中可以看到日志打印。于是又返回去看官方的 BLE 示例。尝试把写数据的按钮放到别的地方,且一直显示。但是很神奇,在这个页面就特别好用。
于是想想示例和项目最大的区别就是页面了,会不会只能在当前页面写数据按钮才有效。验证也简单,在示例工程下,按照添加切换页的方法,原封不动搞一个页面出来。

在两个页面中同一位置添加写数据按钮。

开始验证,实际测试左边index界面可以发数据,右边pages界面不能发数据。

那就实锤是页面的问题了,于是去看黑马的教程,发现原来还有跳转页面传参这种东西,而且tabBar页面的传参跟普通页面的传参还太不一样。原本以为调writeBLECharacteristicValue函数的话,index页面给pages页面传deviceIdserviceIdcharacteristicId就够了,但是实际测试按照官方文档写的,调不同的 API 获取上面那三个参数,结果还是没法在两个页面中发送。这也是不系统学习,只是凭经验搭积木的坏处了,只看了黑马教程中关于环境搭建,会编译之后剩下的全是自己摸索的,就导致对于这些基础知识不了解而耽搁时间,专业选手还是应该打好基础,磨刀不误砍柴工。
知道问题在哪,那就好办了,再次曲线救国,把本来放在两个页面中的东西塞到一个页面里,这样就不存在不同页面传参的问题了。

调整页面

初步页面调整后的效果如下,由于把所有功能全塞一个页面里了,显示有点挤。

修改开关的绑定事件

LED 灯开关绑定的处理函数主体如下。在处理函数中,调用了下面写好的开灯和关灯函数,其实就是变了一下发送给开发板的数据。肯定可以换一种更优雅的写法,就是给原本的writeBLECharacteristicValue函数去传递不同的入口参数,从而发送不同的数据。但为了快速验证功能,就不在意那些细节了。

注意下面的代码中注释没改。

handleSwitchChange: function (e) {
  // 处理开关点击事件  
  var switchOpen = e.detail.value; // 获取开关状态值  
  if (switchOpen) {
    // 执行开关打开时的操作  
    console.log("开关已打开");
    this.writeBLECharacteristicValue_on();
  } else {
    // 执行开关关闭时的操作  
    console.log("开关已关闭");
    this.writeBLECharacteristicValue_off();
  }
},

其中主要的是writeBLECharacteristicValue_onwriteBLECharacteristicValue_off

  writeBLECharacteristicValue_on() {
    // 向蓝牙设备发送一个0x00的16进制数据
    let buffer = new ArrayBuffer(1)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, 0x12)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },
  writeBLECharacteristicValue_off() {
    // 向蓝牙设备发送一个0x00的16进制数据
    let buffer = new ArrayBuffer(1)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, 0x21)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },

经过上面的修改,我们之前已经试过开关按钮的功能了,下面就直接与开发板联动起来。
在开发板端的代码中修改如下,主要是初始化了灯用到的 GPIO,在接收数据的位置加了根据接收数据改变灯状态的逻辑。

void setup()
{
  Serial.begin(115200);
  pinMode(16, OUTPUT);  //初始化灯的GPIO
  // Create the BLE Device
  BLEDevice::init("UART Service");

  // Create the BLE Server
  pServer = BLEDevice::createServer();
  pServer->setCallbacks(new MyServerCallbacks());

  // Create the BLE Service
  BLEService *pService = pServer->createService(SERVICE_UUID);

  // Create a BLE Characteristic
  pTxCharacteristic = pService->createCharacteristic(
      CHARACTERISTIC_UUID_TX,
      BLECharacteristic::PROPERTY_NOTIFY);

  pTxCharacteristic->addDescriptor(new BLE2902());

  BLECharacteristic *pRxCharacteristic = pService->createCharacteristic(
      CHARACTERISTIC_UUID_RX,
      BLECharacteristic::PROPERTY_WRITE);

  pRxCharacteristic->setCallbacks(new MyCallbacks());

  // Start the service
  pService->start();

  // Start advertising
  pServer->getAdvertising()->start();
  Serial.println("Waiting a client connection to notify...");
}

class MyCallbacks : public BLECharacteristicCallbacks
{
  void onWrite(BLECharacteristic *pCharacteristic)
  {
    std::string rxValue = pCharacteristic->getValue();

    if (rxValue.length() > 0)
    {
      Serial.println("*********");
      Serial.print("Received Value: ");
      for (int i = 0; i < rxValue.length(); i++)
      {
        Serial.print(rxValue[i], HEX);
      }
      Serial.println();
      Serial.println("*********");
      if (rxValue[0] == 0x12)
      {
        // Serial.println("Turning on the LED");
        digitalWrite(16, HIGH);
      }
      else
      {
        // Serial.println("Turning off the LED");
        digitalWrite(16, LOW);
      }
    }
  }
};

执行结果如下,已经可以控制开发板硬件了,我们的第一个需求实现。目前只是为了验证功能哈,所以还没定协议,后面会修改接收的部分。接下来就是用小程序给开发板配网了。



修改输入框绑定事件

按钮、图标、开关之前章节都解释了,剩下个输入框,大概描述一下。
还是参考官方文档。在此处我们需要获取两个参数,一个是用户输入的 WiFi 名称和密码,两者都是字符串形式的数据,还要获取到字符串的长度,因为我们要将这些信息发送给开发板配网用。

与输入框相关的代码如下。重点是输入框的处理函数。

输入框事件的e.detail.value是输入框的字符串值,输入框事件的e.detail.cursor是输入框的字符串值长度。因为输入框(WiFi 名称和密码)和配网按钮是两个组件,对应了两个响应事件,需要把输入框获取到的字符串值和长度两个参数传递给配网按钮事件。有很多办法可以传递参数,此处用了全局变量的方式。

  onIput_ssid: function (e) {
    //console.log(e.detail.cursor);
    console.log("输入的内容为:" + e.detail.value);
    const value = e.detail.value;
    this.setData({
      globalValue: value
    });
    console.log("输入内容的长度为:" + e.detail.cursor);
    const cursor = e.detail.cursor;
    this.setData({
      globalCursor: cursor
    });
  },

  button_handle: function (e) {
    const value = e.detail.value || this.data.globalValue; // 从全局变量中获取值,如果不存在则使用默认值  
    console.log("输入框的值为:" + value);
    const cursor = e.detail.cursor || this.data.globalCursor; // 从全局变量中获取值,如果不存在则使用默认值 
    console.log("输入框的值长度为:" + cursor);
  },

看一下结果。可以从输入框获取到值和长度。

测试按钮也可以获取到这些信息。

然后将这些字符串使用下面的函数转换成 16 进制数之后发送给开发板即可。

function stringToHex(str) {
  var hexStr = '';
  for (var i = 0; i < str.length; i++) {
    var code = str.charCodeAt(i);
    hexStr += code.toString(16).padStart(2, '0');
  }
  return hexStr;
}

例如我们发送字符串1234gh给开发板,开发板收到的是把这些字符串转成ascii码之后以 16 进制表示的值,共 6 字节, 最后面的 6 表示这段字符的长度。
ASCII码"1234gh"对应的16进制数表示如下:


此时在开发板端收到的是 16 进制数,而且是单独的 16 进制数,看下面的打印信息。也就是rxValue.length()的值为 13。1234gh转变为 16 进制后为 6 字节,长度占了 1 位,所以总位数为6 * 2 + 1 = 13

但是这与我们的预期不太相符,我们希望的它变成{0x31, 0x32, 0x33, 0x34, 0x67, 0x68},然后我们好将 16 进制数再转变为用户真正输入的 ssid 字符串。那就需要稍作处理。

      for (j = 0; j < (rxValue.length() / 2); j++)
      {
        Serial.print("num:");
        Serial.print(j);
        data[j] = (rxValue[i] << 4) | rxValue[i + 1];
        i = i + 2;
        Serial.print(",data:");
        Serial.print(data[j], HEX);
        Serial.println(); 
      }
      Serial.println("**************************");


再将其转变为用户输入的字符串即可。

开发板给小程序发数据

前面一直都是小程序通过 BLE 给开发板发信息,我们尝试一下用开发板给蓝牙发信息。其实在开发板端已经实现了,在之前使用蓝牙示例时,会在页面右下角不断打印开发板 BLE 特性值,从 0x00-0xFF。

简单修改一下,使得开发板可以发送特定值给小程序端。循环发送 0x21 和 0x22,一秒切换一次。

小程序端把特性值作为显示结果即可。

将代码改为下面的,开发板连接成功后给小程序发数据,小程序端根据返回的数据,就可以知道开发板联网是否成功。

<view class="test_info" >
  <view wx:for="{{chs}}" wx:key="index" style="position: absolute; font-size: 15px; left: 531rpx; top: 1300rpx;">
  <view wx:if="{{item.value == '12'}}">WiFi连接成功</view>  
  <view wx:else>WiFi连接失败</view>  
  </view>
  </view>

制订小程序与开发板之间的通信协议

经过上面的步骤,我们已经可以成功获取到用户输入的 WiFi 名称和密码,而且可以将这些输入字符串转成 16 进制数之后发送给开发板,还可以从开发板给小程序发数据。接下来就是从整体框架出发,制定一套通用的协议,把控制灯的开关、传输 WiFi 信息统一起来,在小程序端完成数据的打包、发送,在开发板端完成数据的解码、控制硬件、返回操作结果给小程序。
跟之前一样,我们先完成小程序端数据打包、发送,开发板端解码,最后再按照协议控制硬件。

序号帧头帧类型帧长度数据
1

0x5A
0x01:控制开发板灯0x010x12:开灯。0x21:关灯。
20x02:发送 WiFi 的 ssid未知未知
30x03:发送 WiFi 的 password未知未知
40x04:控制 WiFi0x010x12:连接 WiFi。0x21:断开 WiFi。
5——————

开关灯

修改一下开关灯的按钮事件,按照协议来发送。

 writeBLECharacteristicValue_on() {
    // 向蓝牙设备发送一个0x00的16进制数据
    let buffer = new ArrayBuffer(4)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, 0x5A)
    dataView.setUint8(1, 0x01)
    dataView.setUint8(2, 0x01)
    dataView.setUint8(3, 0x12)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },
  writeBLECharacteristicValue_off() {
    // 向蓝牙设备发送一个0x00的16进制数据
    let buffer = new ArrayBuffer(4)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, 0x5A)
    dataView.setUint8(1, 0x01)
    dataView.setUint8(2, 0x01)
    dataView.setUint8(3, 0x21)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },

开发板接收如图。

传输 WiFi ssid

修改一下 WiFi 的 ssid 输入框对应的事件,按照协议来发送。

    dataView.setUint8(0, 0x5A)
    dataView.setUint8(1, 0x02)
    dataView.setUint8(2, hexValues.length)
    // 设置每个元素的值  
    for (let i = 3; i < hexValues.length+3; i++) {
      dataView.setUint8(i, parseInt(hexValues[i-3], 16));  
    }

开发板接收如图。

传输 WiFi password

修改一下 WiFi 的 password 输入框对应的事件,按照协议来发送。

    dataView.setUint8(0, 0x5A)
    dataView.setUint8(1, 0x03)
    dataView.setUint8(2, hexValues.length)
    // 设置每个元素的值  
    for (let i = 3; i < hexValues.length+3; i++) {
      dataView.setUint8(i, parseInt(hexValues[i-3], 16));  
    }

开发板接收如图。

目前有个问题是 ssid 和 password 的输入框最大只能输入 10 个字符,因为其中maxlength="10",按照 WiFi 密码最大 16 位,WiFi 名称按照不同的系统和设备,一般可设置 32,此处设置 20。修改一下两个输入框中maxlength的值即可。测试一下最大长度。

配网

修改一下配网按钮对应的事件,按照协议来发送。

  button_handle: function (e) {
    let buffer = new ArrayBuffer(4)
    let dataView = new DataView(buffer)
    dataView.setUint8(0, 0x5A)
    dataView.setUint8(1, 0x04)
    dataView.setUint8(2, 0x01)
    dataView.setUint8(3, 0x01)
    wx.writeBLECharacteristicValue({
      deviceId: this._deviceId,
      serviceId: this._serviceId,
      characteristicId: this._characteristicId,
      value: buffer,
    })
  },

开发板接收如图。

将 WiFi 组件加入工程

万事俱备,只差开启 WiFi 。
将 WiFi 头文件加进来。

#include <Arduino.h>
#include <string.h>
#include <WiFi.h>

将开启 WiFi 的语句加上,若是连接成功,就打印 ip。

 if (configWiFiFlag)
  {
    configWiFiFlag = false;
    Serial.println("****************************");
    Serial.println("Start Connect WiFi");
    Serial.print("[WiFi-SSID]:");
    Serial.println(wifiSsid);
    Serial.print("[WiFi-PASSWORD]:");
    Serial.println(wifiPassword);
    Serial.println("[WiFi] Connectinging...");
    WiFi.begin(wifiSsid, wifiPassword);

    delay(5000);

    if (WiFi.status() == WL_CONNECTED)
    {
      Serial.println("[WiFi] WiFi is Connected!");
      Serial.print("[WiFi] IP address: ");
      Serial.println(WiFi.localIP());
    }
    else
    {
      Serial.println("[WiFi] WiFi is Connect Failed!");
    }
    Serial.println("****************************");
  }

但此时编译后提示程序占用空间过大。

参考网友的方法,添加了huge_app文件。

huge_app.csv
修改一下上图中platformio文件的内容,添加第 15 行代码。

; PlatformIO Project Configuration File
;
;   Build options: build flags, source filter
;   Upload options: custom upload port, speed and extra flags
;   Library options: dependencies, extra library storages
;   Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html

[env:esp32doit-devkit-v1]
platform = espressif32
board = esp32doit-devkit-v1
framework = arduino
board_build.partitions = huge_app.csv

再次编译就没错了。

最终测试

连接电脑热点

在电脑上开启一个 WiFi 热点,设置如下的 ssid 和 password。

打开小程序,输入 ssid ,点击“确认”。输入 password ,点击“确认”。再点击“配网”。等待 5 秒后,右下角会显示“WiFi 连接成功”字样,表示连接成功。

查看开发板的打印信息,显示联网成功,已获得 IP。

查看电脑端热点页面,显示有设备连接,且 IP 与开发板打印信息一致。

换一个错误的密码,右下角会显示“WiFi 连接失败”字样,表示连接失败。

再次测试开关灯按钮,功能正常。

连接路由器

路由器 2.4G 频段的 ssid 和 password 如下。

在手机端输入上述信息,依次点击后面的“确认”,最后点击“配网”。右下角会显示“WiFi 连接成功”字样,表示连接成功。

开发板打印信息如下。

最后附上完整视频操作。

微信小程序实现控制ESP32硬件

参考文档

微信官方文档
https://weui.io/
黑马程序员前端微信小程序开发教程

本文标签: 程序 微信小