微信小程序蓝牙+WiFi双控制ESP32-C3模组应用示范

本文转自安信可科技官微。

目前市场上的 Combo 方案(Ble+WiFi)越来越成为一种趋势,如乐鑫的ESP32-C3,平头哥的TG7100C方案等。为了让大家理解并学会如何高效使用蓝牙和wifi通讯,我们做了个这样快速入门的demo给各位,奉献于物联网

本项目适合的模组有:ESP32-S系列/ESP32-C3系列模组;

本开源工程用到的技术点有:

1、乐鑫物联网操作框架 esp-idf 的 freeRtos 实时操作系统熟悉,包括任务创建/消息队列/进程间通讯;

2、微信小程序开发基础,包括MQTT库/低功耗蓝牙API接口使用,包括搜索/连接/通讯;

3、使用乐鑫封装 RMT 驱动层单线驱动WS2812B,实现彩虹等效果;

4、对ESP32/C3芯片的外设开发熟悉,对BLE API接口使用熟悉,包括自定义广播/名字/自定义UUID;

一、设备核心代码

1.1蓝牙控制

设置蓝牙广播名字

  1. esp_ble_gap_set_device_name(TEST_DEVICE_NAME);

设置服务UUID

  1. gl_profile_tab[0].service_id.is_primary = true;
  2.  gl_profile_tab[0].service_id.id.inst_id = 0x00;
  3.  gl_profile_tab[0].service_id.id.uuid.len = ESP_UUID_LEN_16;
  4.  gl_profile_tab[0].service_id.id.uuid.uuid.uuid16 = GATTS_SERVICE_UUID_TEST_A;

主动通知上位机数据发生改动:

  1. case ESP_GATTS_READ_EVT:
  2.     {
  3.         esp_gatt_rsp_t rsp;
  4.         memset(&rsp, 0, sizeof(esp_gatt_rsp_t));
  5.         rsp.attr_value.handle = param->read.handle;
  6.         rsp.attr_value.len = 3;
  7.         rsp.attr_value.value[0] = red;
  8.         rsp.attr_value.value[1] = green;
  9.         rsp.attr_value.value[2] = blue;
  10.         esp_ble_gatts_send_response(gatts_if, param->read.conn_id, param->read.trans_id, ESP_GATT_OK, &rsp);
  11. break;
  12.     }

上位机主动发送数据到此并做出对应的处理:

  1. case ESP_GATTS_WRITE_EVT:
  2.     {
  3. if (!param->write.is_prep)
  4.         {
  5.             ESP_LOGI(GATTS_TAG, "GATT_WRITE_EVT, value len %d, value :", param->write.len);
  6.             esp_log_buffer_hex(GATTS_TAG, param->write.value, param->write.len);
  7. //发送数据到队列
  8.             struct __User_data *pTmper;
  9.             sprintf(user_data.allData, "{\"red\":%d,\"green\":%d,\"blue\":%d}", param->write.value[0], param->write.value[1], param->write.value[2]);
  10.             pTmper = &user_data;
  11.             user_data.dataLen = strlen(user_data.allData);
  12.             xQueueSend(ParseJSONQueueHandler, (void *)&pTmper, portMAX_DELAY);
  13.             ESP_LOGI(GATTS_TAG, "%02x %02x %02x ", param->write.value[0], param->write.value[1], param->write.value[2]);
  14.         }
  15.         example_write_event_env(gatts_if, &a_prepare_write_env, param);
  16. break;
  17.     }

1.2WIFI控制

设置MQTT远程连接的参数

  1. /* 
  2.  * @Description: MQTT参数连接的配置
  3.  * @param: 
  4.  * @return: 
  5. */
  6. void TaskXMqttRecieve(void *p)
  7. {
  8. //连接的配置参数
  9. esp_mqtt_client_config_t mqtt_cfg = {
  10.         .host = "www.xuhong.com",  //连接的域名 ,请务必修改为您的
  11.         .port = 1883,              //端口,请务必修改为您的
  12.         .username = "admin",       //用户名,请务必修改为您的
  13.         .password = "xuhong123456",   //密码,请务必修改为您的
  14.         .client_id = deviceUUID,
  15.         .event_handle = MqttCloudsCallBack, //设置回调函数
  16.         .keepalive = 120,                   //心跳
  17.         .disable_auto_reconnect = false,    //开启自动重连
  18.         .disable_clean_session = false,     //开启 清除会话
  19.     };
  20.     client = esp_mqtt_client_init(&mqtt_cfg);
  21.     esp_mqtt_client_start(client);
  22.     vTaskDelete(NULL);
  23. }

服务器下发的处理数据,送往消息队列处理:

  1. //服务器下发消息到本地成功接收回调
  2. case MQTT_EVENT_DATA:
  3.     {
  4.         printf("TOPIC=%.*s \r\n", event->topic_len, event->topic);
  5.         printf("DATA=%.*s \r\n\r\n", event->data_len, event->data);
  6. //发送数据到队列
  7. struct __User_data *pTmper;
  8.         sprintf(user_data.allData, "%s", event->data);
  9.         pTmper = &user_data;
  10.         user_data.dataLen = event->data_len;
  11.         xQueueSend(ParseJSONQueueHandler, (void *)&pTmper, portMAX_DELAY);
  12. break;
  13.     }

1.3外设驱动

七彩灯WS2812B的驱动代码初始化:

  1. /**
  2.  * @description:  封装一层设置RGB灯效果
  3.  * @param {uint16_t} Red 入参 红色
  4.  * @param {uint16_t} Green 入参 绿色
  5.  * @param {uint16_t} Blue 入参 蓝色
  6.  * @return {*}
  7.  */
  8. void set_rgb(uint16_t Red, uint16_t Green, uint16_t Blue)
  9. {
  10. for (int i = 0; i < 24; i++)
  11.     {
  12.         strip->set_pixel(strip, i, Red, Green, Blue);
  13.     }
  14.     red = Red;
  15.     green = Green;
  16.     blue = Blue;
  17.     strip->refresh(strip, 10);
  18. }
  19. /**
  20.  * @description: 初始化LED 
  21.  * @param {*}
  22.  * @return {*}
  23.  */
  24. void init_led()
  25. {
  26. rmt_config_t config = RMT_DEFAULT_CONFIG_TX(4, RMT_TX_CHANNEL);
  27. // set counter clock to 40MHz
  28.     config.clk_div = 2;
  29.     ESP_ERROR_CHECK(rmt_config(&config));
  30.     ESP_ERROR_CHECK(rmt_driver_install(config.channel, 0, 0));
  31. // install ws2812 driver
  32. led_strip_config_t strip_config = LED_STRIP_DEFAULT_CONFIG(24, (led_strip_dev_t)config.channel);
  33.     strip = led_strip_new_rmt_ws2812(&strip_config);
  34. if (!strip)
  35.     {
  36.         ESP_LOGE(TAG, "install WS2812 driver failed");
  37.     }
  38. // Clear LED strip (turn off all LEDs)
  39.     ESP_ERROR_CHECK(strip->clear(strip, 100));
  40.     set_rgb(0, 254, 0);
  41. }

消息队列处理逻辑:

  1. /*
  2.  * @Description: 解析下发数据的队列逻辑处理
  3.  * @param: null
  4.  * @return: 
  5. */
  6. void Task_ParseJSON(void *pvParameters)
  7. {
  8. printf("[SY] Task_ParseJSON_Message creat ... \n");
  9. while (1)
  10.     {
  11. struct __User_data *pMqttMsg;
  12. printf("Task_ParseJSON_Message xQueueReceive wait [%d] ... \n", esp_get_free_heap_size());
  13.         xQueueReceive(ParseJSONQueueHandler, &pMqttMsg, portMAX_DELAY);
  14. printf("Task_ParseJSON_Message xQueueReceive get [%s] ... \n", pMqttMsg->allData);
  15.         首先整体判断是否为一个json格式的数据
  16.         cJSON *pJsonRoot = cJSON_Parse(pMqttMsg->allData);
  17. //如果是否json格式数据
  18. if (pJsonRoot == NULL)
  19.         {
  20. printf("[SY] Task_ParseJSON_Message xQueueReceive not json ... \n");
  21. goto __cJSON_Delete;
  22.         }
  23.         cJSON *pJSON_Item_Red = cJSON_GetObjectItem(pJsonRoot, "red");
  24.         cJSON *pJSON_Item_Green = cJSON_GetObjectItem(pJsonRoot, "green");
  25.         cJSON *pJSON_Item_Blue = cJSON_GetObjectItem(pJsonRoot, "blue");
  26.         set_rgb(pJSON_Item_Red->valueint, pJSON_Item_Green->valueint, pJSON_Item_Blue->valueint);
  27.     __cJSON_Delete:
  28.         cJSON_Delete(pJsonRoot);
  29.     }
  30. }

二、微信小程序核心代码

代码架构,UI主要采用第三方库:有 WeUI、Vant-UI库,其中的MQTT库采用开源的MQTT.JS库。

2.1蓝牙搜索

  1. wx.onBluetoothDeviceFound(function (devices) {
  2. var isnotexist = true
  3. if (devices.deviceId) {
  4. if (devices.advertisData) {
  5.           devices.advertisData = app.buf2hex(devices.advertisData)
  6.         } else {
  7.           devices.advertisData = ''
  8.         }
  9. for (var i = 0; i < that.data.devicesList.length; i++) {
  10. if (devices.deviceId == that.data.devicesList[i].deviceId) {
  11.             isnotexist = false
  12.           }
  13.         }
  14. if (isnotexist && devices[0].name === that.data.filterName ) {
  15.           that.data.devicesList.push(devices[0])
  16.         }
  17.       }
  18.       that.setData({
  19.         devicesList: that.data.devicesList
  20.       })
  21.     })
  22.   }

2.2蓝牙服务发现

发现服务列表:wx.getBLEDeviceServices()

发现特征值列表:wx.getBLEDeviceCharacteristics()

发送设备,判断是否为蓝牙控制或wifi控制:

  1.  SendTap: function (red, green, blue) {
  2. var that = this
  3. if (!this.data.isCheckOutControl) {
  4. if (this.data.connected) {
  5. var buffer = new ArrayBuffer(that.data.inputText.length)
  6. var dataView = new Uint8Array(buffer)
  7.         dataView[0] = red;
  8.         dataView[1] = green;
  9.         dataView[2] = blue;
  10.         wx.writeBLECharacteristicValue({
  11. deviceId: that.data.connectedDeviceId,
  12. serviceId: that.data.serviceId,
  13. characteristicId: "0000FF01-0000-1000-8000-00805F9B34FB",
  14. value: buffer,
  15. success: function (res) {
  16. console.log('发送成功')
  17.           }, fail() {
  18.             wx.showModal({
  19. title: '提示',
  20. content: '蓝牙已断开',
  21. showCancel: false,
  22. success: function (res) {
  23.               }
  24.             })
  25.           }
  26.         })
  27.       } else {
  28.         wx.showModal({
  29. title: '提示',
  30. content: '蓝牙已断开',
  31. showCancel: false,
  32. success: function (res) {
  33.             that.setData({
  34. searching: false
  35.             })
  36.           }
  37.         })
  38.       }
  39.     } else {
  40. //MQTT通讯发送
  41. if (this.data.client && this.data.client.connected) {
  42. this.data.client.publish('/esp32-c3/7cdfa1322e68/devSub', JSON.stringify({red,green,blue}));
  43.       } else {
  44.         wx.showToast({
  45. title: '请先连接服务器',
  46. icon: 'none',
  47. duration: 2000
  48.         })
  49.       }
  50.     }
  51.   }

相关链接:

乐鑫物联网操作系统:https://github.com/espressif/esp-idf

腾讯WeUI框架:https://github.com/Tencent/weui-wxss

有赞Vant框架:https://vant-contrib.gitee.io/vant-weapp

本博文的源码下载:https://github.com/xuhongv/ESP32WiFiBleControlProject

 

你想把广告放到这里吗?

发表评论

您必须 登录 才能发表留言!