微信小程序是一种新的应用,用户不需要下载应用只用通过扫二维码或者打开链接就能使用,使用完后不需要卸载,直接关闭就行了。微信在2017年初推出微信小程序开发环境。任何企业,媒体,个人都可以注册开发。是一种全新的 开发模式。微信也因此受到许多程序员的一致好评,尤其是微信小程序的云开发,提供大量数据处理接口,让初学者也可以很快入手。不需要后端数据库的支持,自己一个人就可以开发前端和后台。

微信小程序为蓝牙模块提供了18个API。其中低功率蓝牙9个,传统蓝牙9个。本次设计使用了其中的9个接口:

(1) openBluetoothAdapter,这个API用来初始化蓝牙适配器;

(2) startBluetoothDevicesDiscovery,开始搜索蓝牙设备;

(3) onBluetoothDeviceFound,判断搜索到的蓝牙设备的信号强度;

(4) createBLEConnection,连接搜索到的蓝牙设备;

(5) stopBluetoothDevicesDiscovery,关闭搜索蓝牙设备;

(6) getBLEDeviceServices,获取蓝牙的deviceId;

(7) getBLEDeviceCharacteristics,获取蓝牙设备服务的所有特征值;

(8) notycharacteristicsId,启用低功耗蓝牙特征值的notify功能;

(9) writeBLECharacteristicValue,通过微信小程序向蓝牙模块发送命令。

 js源代码

  1. Page({
  2. /**
  3. * 页面的初始数据
  4. */
  5. data: {
  6. connect: false,
  7. send_hex: false,
  8. send_string: true,
  9. send_string_val: \'Hex\',
  10. recv_string: true,
  11. recv_string_val: \'Hex\',
  12. recv_value: \'\',
  13. send_number: 0,
  14. recv_number: 0,
  15. recv_hex: true,
  16. wendu: 30,
  17. yanwu: 60
  18. },
  19. /*** 生命周期函数--监听页面加载 */
  20. onLoad: function (options) {
  21. wx.stopBluetoothDevicesDiscovery({
  22. success: function (res) {
  23. console.log(\'停止搜索设备\', res)
  24. }
  25. })
  26. console.log(options);
  27. this.setData({
  28. deviceId: options.id,
  29. deviceName: options.name
  30. });
  31. console.log(\'设备的ID\', this.data.deviceId);
  32. },
  33. /*** 生命周期函数--监听页面显示 */
  34. onShow: function () {
  35. wx.stopBluetoothDevicesDiscovery({
  36. success: function (res) {
  37. console.log(\'停止搜索设备\', res)
  38. }
  39. })
  40. var that = this;
  41. /* 连接中动画 */
  42. wx.showLoading({
  43. title: \'连接中...\',
  44. });
  45. /* 开始连接蓝牙设备 */
  46. wx.createBLEConnection({
  47. deviceId: that.data.deviceId,
  48. success: function (res) {
  49. console.log(\'连接成功\', res);
  50. wx.hideLoading();
  51. /* 获取设备的服务UUID */
  52. wx.getBLEDeviceServices({
  53. deviceId: that.data.deviceId,
  54. success: function (service) {
  55. that.setData({
  56. serviceId: "0000FFE0-0000-1000-8000-00805F9B34FB" //确定需要的服务UUID
  57. });
  58. console.log(\'需要的服务UUID\', that.data.serviceId)
  59. that.Characteristics(); //调用获取特征值函数
  60. },
  61. });
  62. that.setData({
  63. connect: true
  64. })
  65. },
  66. })
  67. },
  68. Characteristics: function () {
  69. var that = this;
  70. var device_characteristics = [];
  71. var characteristics_uuid = {};
  72. wx.getBLEDeviceCharacteristics({
  73. deviceId: that.data.deviceId,
  74. serviceId: that.data.serviceId,
  75. success: function (res) {
  76. var characteristics = res.characteristics; //获取到所有特征值
  77. var characteristics_length = characteristics.length; //获取到特征值数组的长度
  78. console.log(\'获取到特征值\', characteristics);
  79. console.log(\'获取到特征值数组长度\', characteristics_length);
  80. that.setData({
  81. notycharacteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB", //需确定要的使能UUID
  82. characteristicsId: "0000FFE1-0000-1000-8000-00805F9B34FB" //暂时确定的写入UUID
  83. });
  84. console.log(\'使能characteristicsId\', that.data.notycharacteristicsId);
  85. console.log(\'写入characteristicsId\', that.data.characteristicsId);
  86. that.notycharacteristicsId(); //使能事件
  87. },
  88. })
  89. },
  90. /* 使能函数 */
  91. notycharacteristicsId: function () {
  92. var that = this;
  93. var recv_value_ascii = "";
  94. var string_value = "";
  95. var recve_value = "";
  96. wx.notifyBLECharacteristicValueChange({
  97. deviceId: that.data.deviceId,
  98. serviceId: that.data.serviceId,
  99. characteristicId: that.data.notycharacteristicsId,
  100. state: true,
  101. success: function (res) {
  102. console.log(\'使能成功\', res);
  103. /* 设备返回值 */
  104. wx.onBLECharacteristicValueChange(function (res) {
  105. var length_hex = [];
  106. var turn_back = "";
  107. var result = res.value;
  108. var hex = that.buf2hex(result);
  109. console.log(\'返回的值\', hex);
  110. if (that.data.recv_string == true) {
  111. /* 成功接收到的值的展示 */
  112. that.setData({
  113. recv_value: that.data.recv_value + hex
  114. });
  115. /* 接收成功的值的字节 */
  116. var recv_number_1 = that.data.recv_number + hex.length / 2;
  117. var recv_number = Math.round(recv_number_1);
  118. that.setData({
  119. recv_number: recv_number
  120. });
  121. } else {
  122. console.log(\'设备返回来的值\', hex);
  123. var f_hex = hex;
  124. var length_soy = f_hex.length / 2;
  125. var length = Math.round(length_soy);
  126. for (var i = 0; i < length; i++) {
  127. var hex_spalit = f_hex.slice(0, 2);
  128. length_hex.push(hex_spalit);
  129. f_hex = f_hex.substring(2);
  130. }
  131. console.log(\'length_hex\', length_hex);
  132. for (var j = 0; j < length_hex.length; j++) {
  133. var integar = length_hex[j]; //十六进制
  134. recve_value = parseInt(integar, 16); //十进制
  135. console.log(\'recve_value\', recve_value);
  136. turn_back = turn_back + String.fromCharCode(recve_value);
  137. console.log(\'turn_back\', turn_back);
  138. }
  139. console.log(\'最终转回来的值\', turn_back)
  140. var recv_number_1 = that.data.recv_number + turn_back.length;
  141. var recv_number = Math.round(recv_number_1);
  142. that.setData({
  143. recv_number: recv_number,
  144. recv_value: that.data.recv_value + turn_back
  145. })
  146. }
  147. });
  148. },
  149. fail: function (res) {
  150. console.log(\'使能失败\', res);
  151. }
  152. })
  153. },
  154. /* 断开连接 */
  155. DisConnectTap: function () {
  156. var that = this;
  157. wx.closeBLEConnection({
  158. deviceId: that.data.deviceId,
  159. success: function (res) {
  160. console.log(\'断开设备连接\', res);
  161. wx.reLaunch({
  162. url: \'../index/index\',
  163. })
  164. }
  165. });
  166. },
  167. /*** 生命周期函数--监听页面卸载 */
  168. onUnload: function () {
  169. var that = this;
  170. wx.closeBLEConnection({
  171. deviceId: that.data.deviceId,
  172. success: function (res) {
  173. console.log(\'断开设备连接\', res);
  174. }
  175. });
  176. },
  177. /* 清除Recv Bytes */
  178. CleanNumberRecv: function () {
  179. this.setData({
  180. recv_number: 0
  181. })
  182. },
  183. /* ArrayBuffer类型数据转为16进制字符串 */
  184. buf2hex: function (buffer) { // buffer is an ArrayBuffer
  185. var hexArr = Array.prototype.map.call(
  186. new Uint8Array(buffer),
  187. function (bit) {
  188. return (\'00\' + bit.toString(16)).slice(-2)
  189. }
  190. )
  191. return hexArr.join(\'\');
  192. },
  193. switch1Change: function (e) {
  194. var that = this;
  195. let buffer = new ArrayBuffer(1)
  196. let dataView = new DataView(buffer)
  197. if (e.detail.value) {
  198. dataView.setUint8(0, 0)
  199. } else {
  200. dataView.setUint8(0, 1)
  201. }
  202. wx.writeBLECharacteristicValue({
  203. deviceId: that.data.deviceId,
  204. serviceId: that.data.serviceId,
  205. characteristicId: that.data.characteristicsId,
  206. value: buffer,
  207. success: function (res) {
  208. console.log(\'数据发送成功\', res);
  209. console.log(buffer);
  210. },
  211. fail: function (res) {
  212. console.log(\'调用失败\', res);
  213. /* 调用失败时,再次调用 */
  214. wx.writeBLECharacteristicValue({
  215. deviceId: that.data.deviceId,
  216. serviceId: that.data.serviceId,
  217. characteristicId: that.data.characteristicsId,
  218. value: buffer,
  219. success: function (res) {
  220. console.log(\'2次数据发送成功\', res);
  221. }
  222. })
  223. }
  224. })
  225. },
  226. switch1Change1: function (e) {
  227. var that = this;
  228. let buffer = new ArrayBuffer(1)
  229. let dataView = new DataView(buffer)
  230. if (e.detail.value) {
  231. dataView.setUint8(0, 2)
  232. } else {
  233. dataView.setUint8(0, 3)
  234. }
  235. wx.writeBLECharacteristicValue({
  236. deviceId: that.data.deviceId,
  237. serviceId: that.data.serviceId,
  238. characteristicId: that.data.characteristicsId,
  239. value: buffer,
  240. success: function (res) {
  241. console.log(\'数据发送成功\', res);
  242. console.log(buffer);
  243. },
  244. fail: function (res) {
  245. console.log(\'调用失败\', res);
  246. /* 调用失败时,再次调用 */
  247. wx.writeBLECharacteristicValue({
  248. deviceId: that.data.deviceId,
  249. serviceId: that.data.serviceId,
  250. characteristicId: that.data.characteristicsId,
  251. value: buffer,
  252. success: function (res) {
  253. console.log(\'2次数据发送成功\', res);
  254. }
  255. })
  256. }
  257. })
  258. },
  259. add: function (e) {
  260. var id = e.target.id;
  261. if (this.data[id] > 98) {
  262. wx.showToast({
  263. title: \'已超过最大数值\',
  264. icon: \'loading\',
  265. duration: 2000
  266. })
  267. return;
  268. }
  269. this.setData({
  270.       [id]: +this.data[id] + 1
  271. });
  272. this.numbers(id)
  273. },
  274. lessen: function (e) {
  275. var id = e.target.id;
  276. if (this.data[id] < 1) {
  277. wx.showToast({
  278. title: \'已小于最小数值\',
  279. icon: \'loading\',
  280. duration: 2000
  281. })
  282. return;
  283. }
  284. this.setData({
  285.        [id]: +this.data[id] - 1
  286. });
  287. this.numbers(id)
  288. },
  289. changeVal: function (e) {
  290. var id = e.target.id;
  291. if (e.detail.value < 1 || e.detail.value > 100) {
  292. wx.showToast({
  293. title: \'请输入有效数值\',
  294. icon: \'loading\',
  295. duration: 2000
  296. })
  297. return;
  298. }
  299. this.setData({
  300.       [id]: e.detail.value
  301. });
  302. this.numbers(id)
  303. },
  304. numbers: function (id) {
  305. var that = this;
  306. var number = \'9\';
  307. let buffer = new ArrayBuffer(1)
  308. let dataView = new DataView(buffer)
  309. console.log(id)
  310. if (id == \'wendu\') {
  311. number = \'8\' + that.data[id];
  312. dataView.setUint8(0, 8)
  313. } else {
  314. number = number + that.data[id];
  315. dataView.setUint8(0, number)
  316. }
  317. wx.writeBLECharacteristicValue({
  318. deviceId: that.data.deviceId,
  319. serviceId: that.data.serviceId,
  320. characteristicId: that.data.characteristicsId,
  321. value: buffer,
  322. success: function (res) {
  323. console.log(\'数据发送成功\', res);
  324. console.log(buffer);
  325. }
  326. })
  327. }
  328. })
  1. wxss源代码
  1. .connect_box {
  2. width: 100%;
  3. height: 30px;
  4. line-height: 30px;
  5. font-size: 32rpx;
  6. color: #666;
  7. font-family: "Microsoft YaHei";
  8. }
  9. .connect_device_name{
  10. float: left;
  11. padding-left: 10px;
  12. color: #39beff;
  13. }
  14. .connect_state {
  15. float: right;
  16. padding-right: 10px;
  17. text-decoration: underline;
  18. color: #39beff;
  19. }
  20. .fan{
  21. width: 2rem;
  22. height: 2rem;
  23. vertical-align: middle;
  24. margin-left: 2.25rem;
  25. margin-right: 0.25rem;
  26. }
  27. .water{
  28. width: 2.5rem;
  29. height: 2rem;
  30. vertical-align: middle;
  31. margin-left: 2rem;
  32. }
  33. .name{
  34. display: inline-block;
  35. width: 22%;
  36. margin-left: 1.5rem;
  37. font-size: 0.9rem;
  38. }
  39. .key{
  40. float: right;
  41. margin-right: 2rem;
  42. margin-top: 0.2rem;
  43. }
  44. .detail_box{
  45. padding: 1.5rem 0;
  46. border-bottom: 1px solid #ccc;
  47. }
  48. .num {
  49. display: inline-block;
  50. width: 45%;
  51. text-align: right;
  52. vertical-align: middle;
  53. }
  54. .num input {
  55. display: inline-block;
  56. width: 2rem;
  57. text-align: center;
  58. border: 1px solid #f2f2f2;
  59. border-left: none;
  60. border-right: none;
  61. color: #a2a2a2;
  62. }
  63. .num text {
  64. display: inline-block;
  65. width: 1.4rem;
  66. height: 1.4rem;
  67. line-height: 1.4rem;
  68. text-align: center;
  69. border: 1px solid #f2f2f2;
  70. vertical-align: top;
  71. color: #dcdcdc;
  72. }
  73. .wendu{
  74. width:1.9rem;
  75. height:2rem;
  76. vertical-align:middle;
  77. margin-left:2.3rem;
  78. margin-right:.3rem;
  79. }
  1. wxml源代码
  1. <view class="connect_box">
  2. <text class=\'connect_device_name\'>{{deviceName}}</text>
  3. <text wx:if="{{connect}}" class="connect_state" catchtap="DisConnectTap">已连接</text>
  4. <text wx:else class="connect_state">未连接</text>
  5. </view>
  6. <view >
  7. <view class="detail_box">
  8. <image src=\'../../images/airFan.png\' class="fan"></image>
  9. <view class=\'name\'>风扇</view>
  10. <switch bindchange="switch1Change" class=\'key\' />
  11. </view>
  12. <view class="detail_box">
  13. <image src=\'../../images/waterPump.png\' class="water"></image>
  14. <view class=\'name\'>水泵</view>
  15. <switch bindchange="switch1Change1" class=\'key\' />
  16. </view>
  17. <view class="detail_box">
  18. <image src=\'../../images/temperature.png\' class="wendu"></image>
  19. <view class=\'name\'>温度阀值</view>
  20. <view class=\'num\'>
  21. <text style=\'border-radius: 3px 0 0 3px;\' id=\'wendu\' bindtap=\'lessen\'>-</text>
  22. <input type=\'number\' value=\'{{wendu}}\' name=\'piece\' id=\'wendu\' bindblur="changeVal" />
  23. <text style=\'border-radius: 0 3px 3px 0;\' id=\'wendu\' bindtap=\'add\'>+</text>
  24. </view>
  25. </view>
  26. <view class="detail_box">
  27. <image src=\'../../images/smog.png\' class="water"></image>
  28. <view class=\'name\'>烟雾阀值</view>
  29. <view class=\'num\'>
  30. <text style=\'border-radius: 3px 0 0 3px;\' id=\'yanwu\' bindtap=\'lessen\'>-</text>
  31. <input type=\'number\' value=\'{{yanwu}}\' name=\'piece\' id=\'yanwu\' bindblur="changeVal" />
  32. <text style=\'border-radius: 0 3px 3px 0;\' id=\'yanwu\' bindtap=\'add\'>+</text>
  33. </view>
  34. </view>
  35. </view>

 微信小程序展示页面

        

  微信小程序不能在电脑上模拟,智能用手机操作,我们需要用手机打开我们的微信小程序。首先如果手机蓝牙没有打开回提醒打开蓝牙重新加载。如果手机蓝牙打开了就会去搜索附近的蓝牙模块,搜索到自己的低功率蓝牙,点击就可以连接到自己的蓝牙。我们就到了控制页面。
  我们可以通过微信小程序风扇和水泵。点击开关时会调用writeBLECharacteristicValue接口通过蓝牙模块给单片机发送指令,控制单片机上的风扇和水泵等硬件设备。

2.硬件设备介绍

  1.   硬件部分主要介绍单片机、低功率蓝牙、风扇和水泵。单片机用什么型号的都行,都能与蓝牙模块正常通信,收发数据。低功率蓝牙主要优点是功率低,寿命长,价格便宜。多用于硬件连接上位机软件。风扇和水泵是外接设备,由单片机控制。

1.单片机
  单片机的型号是stc89c52rc,STC89C52RC是STC公司生产的一种低功耗、高性能CMOS8位微控制器,具有8K字节系统可编程Flash存储器。STC89C52使用经典的MCS-51内核,但是做了很多的改进使得芯片具有传统的方法51单片机不具备的功能。在单芯片上,拥有灵巧的8 位CPU 和在系统可编程Flash,使得STC89C52为众多嵌入式控制应用系统提供高灵活、超有效的解决方案。
2.蓝牙模块
  我用的是蓝牙型号是HC-06,给HC-06上电之后,HC-06的指示灯会不停地闪烁,这个时候就标志着进入AT模式了,配置的时候,HC-06的Rx和Tx 接到 51单片机的 Rx和 Tx,一般是P3.0,和P3.1,正常工作时,HC-06的Rx和Tx 接到 51单片机的 Tx和 Rx,8位数据位,1位结束位,无奇偶校验。一般HC-06模块的默认名称就是hc-06,默认配对密码是1234或0000。我们如果连接微信小程序,我们要把密码取消,这样微信小程序才能直接来连接。
3.风扇和水泵  
  风扇和水泵是直接供电就可以使用,我们只需要一个继电器就可以控制这两个设备,我选择了P3.5,P3.4这两个引脚来控制,高电平驱动,低电平关闭,这两个外接设备主要是测试数据有没有接受成功。

单片机程序主程序

  1. void ctrl(unsigned char a) //单字节数据接收
  2. { //注意:若单片机TXD(P3.1)无上拉能力,必须在P3.1端接上拉电阻。本次测试需要接上拉电阻
  3. TI=0;
  4. SBUF=a;
  5. while(TI==0);
  6. TI=0;
  7. Mode=1;
  8. if(SBUF==0){
  9. LED_yanwu=0;
  10. baojing=0;
  11. fs=0;
  12. led1=0;
  13. led2=0;
  14. }else if(SBUF==1){
  15. LED_yanwu=1;
  16. baojing=1;
  17. fs=1;
  18. Mode=0;
  19. }else if(SBUF==2){
  20. baojing=0;
  21. LED_wendu=0;
  22. fs1=0;
  23. }else if(SBUF==3){
  24. baojing=1;
  25. LED_wendu=1;
  26. fs1=1;
  27. led1=0;
  28. led2=0;
  29. Mode=0;
  30. }
  31. }
  32. void main()
  33. {
  34. check_wendu();
  35. check_wendu();
  36. Init1602();
  37. ES=0; //关中断
  38. SCON = 0x50; // REN=1允许串行接受状态,串口工作模式1,
  39. //10位UART(1位起始位,8位数据位,1位停止位,无奇偶校验),波特率可变
  40. TMOD = 0x20; // 定时器1工作于方式2,8位自动重载模式, 用于产生波特率
  41. TH1=TL1=0xFD; // 波特率9600 (本次测试采用晶振为11.0592)
  42. PCON &= 0x7f; // 波特率不倍增
  43. TR1 = 1; //定时器1开始工作,产生波特率
  44. TI=0; //接收标志位置0
  45. RI=0;
  46. ES=1;
  47. while(1)
  48. {
  49. temp=ADC0809();
  50. check_wendu();
  51. Key();
  52. if(RI==1) // 是否有数据到来
  53. {
  54. RI = 0;
  55. ctrl(SBUF);
  56. }
  57. Display_1602(yushe_wendu,yushe_yanwu,c,temp); //c温度值,temp烟雾值
  58. if(Mode==0)
  59. {
  60. if(temp>=yushe_yanwu)
  61. {
  62. LED_yanwu=0;
  63. baojing=0;
  64. fs=0;
  65. }
  66. else
  67. {
  68. LED_yanwu=1;
  69. }
  70. if(c>800){
  71. c = 0;
  72. }
  73. if(c>=(yushe_wendu*10))
  74. {
  75. baojing=0;
  76. LED_wendu=0;
  77. fs1=0;
  78. }
  79. else
  80. {
  81. LED_wendu=1;
  82. }
  83. if((temp<yushe_yanwu)&&(c<(yushe_wendu*10)))
  84. {
  85. baojing=1;
  86. fs=1;
  87. fs1=1;
  88. }
  89. }
  90. }
  91. }

硬件实物图

       

  数据采集显示正常,微信小程序可以正常控制单片机的水泵和风扇,通信正常无异常。硬件部分我就简单的拿出来说了一下,所涉及到的知识肯定比我展示到的多,软件部分主要是对低功率蓝牙的搜索,连接,发送数据比较麻烦。

    视频链接:http://v.youku.com/v_show/id_XNDE1ODI1NzI2NA==.html?x&sharefrom=android&sharekey=f051256eda08cc3764d9d6d7a5d231788

版权声明:本文为liuzhou1原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://www.cnblogs.com/liuzhou1/p/10772905.html