当前位置:   article > 正文

使用Arduino UNO和蓝牙模块制作智能小车_arduino蓝牙模块控制小车

arduino蓝牙模块控制小车

目录

概述

1 硬件结构

1.1 硬件组成

1.2 蓝牙模块介绍

1.3 控制板IO引脚定义

2 机械结构

3 固件设计

4 App设计

5 参考文献


概述

       本文主要介绍使用Arduino UNO作为主板,用于控制电机和接收蓝牙模块数据。蓝牙模块用于从手机App上接收控制信号,使用L298N作为驱动板设计一台智能小车,可通过手机上的App来控制小车的运行状态。

项目代码 git 地址:Arduino_project: 基于Arduino板卡的开源项目 (gitee.com)

1 硬件结构

1.1 硬件组成

         本系统硬件结构是以Arduino为主控板,蓝牙模块上RX和TX与Arduino上的TX和RX相连。L298N作为电源管理模块和驱动模块,分别为控制板、蓝牙模块提供电源。电池模块提供整个系统的工作电压,采用可充电的锂电池,单个电池电压为: 3.7V, 电池盒中总共装载4节锂电池。硬件列表如下。

名称功能介绍注释
Arduino UNO控制板处理蓝牙数据和控制电机
L298N驱动模块驱动四个电机:正转、反转、停止
HC-05 蓝牙模块接收/发送控信号传送App发送的信号
3.7V 锂电池系统供电4节锂电池构成供电盒

1.2 蓝牙模块介绍

       HC-08蓝牙串口通信模块是新一代的基于Bluetooth Specification V4.0 BLE 蓝牙协议的数传模块。无线工作频段为 2.4GHz ISM,调制方式是 GFSK。模块最大发射功率为4dBm,接收灵敏度-93dBm,空旷环境下和 手机可以实现 80 米超远距离通信。

        其和MCU之间通过串口通信,软件设计也简单便捷,且不需要考虑蓝牙协议栈问题,非常适合做速成产品。

蓝牙模块与MCU之间连接图:

1.3 控制板IO引脚定义

引脚功能定义如下:

控制板引脚功能介绍
AI-0连接控制板: IN-1左侧电机控制信号引脚
AI-1连接控制板: IN-2左侧电机控制信号引脚
AI-2连接控制板: IN-3右侧电机控制信号引脚
AI-3连接控制板: IN-4右侧电机控制信号引脚
RX/TX连接HC-08蓝牙模块 TX/RX

2 机械结构

       系统采用集成底盘结构,四个电机固定在最底层底板上,L298N放在最底层的顶层板上,顶层板用于支撑控制板和电池模块。其具体框架结构如下:

3 固件设计

       固件主要使用电机控制和蓝牙模块数据的发送和接收。其具体代码如下,工程采用Arduino IDE开发:

系统代码:

  1. // ATMEL ATMEGA8 & 168 / ARDUINO
  2. //
  3. // +-\/-+
  4. // PC6 1| |28 PC5 (AI 5)
  5. // (D 0) PD0 2| |27 PC4 (AI 4)
  6. // (D 1) PD1 3| |26 PC3 (AI 3)
  7. // (D 2) PD2 4| |25 PC2 (AI 2)
  8. // PWM+ (D 3) PD3 5| |24 PC1 (AI 1)
  9. // (D 4) PD4 6| |23 PC0 (AI 0)
  10. // VCC 7| |22 GND
  11. // GND 8| |21 AREF
  12. // PB6 9| |20 AVCC
  13. // PB7 10| |19 PB5 (D 13)
  14. // PWM+ (D 5) PD5 11| |18 PB4 (D 12)
  15. // PWM+ (D 6) PD6 12| |17 PB3 (D 11) PWM
  16. // (D 7) PD7 13| |16 PB2 (D 10) PWM
  17. // (D 8) PB0 14| |15 PB1 (D 9) PWM
  18. // +----+
  19. #include <Arduino.h>
  20. //电机控制接口
  21. #define PIN_A0 (14)
  22. #define PIN_A1 (15)
  23. #define PIN_A2 (16)
  24. #define PIN_A3 (17)
  25. static const uint8_t MA0 = PIN_A0;
  26. static const uint8_t MA1 = PIN_A1;
  27. static const uint8_t MA2 = PIN_A2;
  28. static const uint8_t MA3 = PIN_A3;
  29. // BLUE TOOTH
  30. char command;
  31. void setup()
  32. {
  33. // put your setup code here, to run once:
  34. Serial.begin(9600);
  35. pinMode(MA0, OUTPUT);
  36. pinMode(MA1, OUTPUT);
  37. pinMode(MA2, OUTPUT);
  38. pinMode(MA3, OUTPUT);
  39. }
  40. void loop()
  41. {
  42. while(Serial.available())
  43. {
  44. command =Serial.read();
  45. switch(command )
  46. {
  47. case 0x18: //前进
  48. digitalWrite(MA0, LOW);
  49. digitalWrite(MA1, HIGH);
  50. digitalWrite(MA2, LOW);
  51. digitalWrite(MA3, HIGH);
  52. break;
  53. case 0x52: //后退
  54. digitalWrite(MA0, HIGH);
  55. digitalWrite(MA1, LOW);
  56. digitalWrite(MA2, HIGH);
  57. digitalWrite(MA3, LOW);
  58. break;
  59. case 0x08: // 左转
  60. digitalWrite(MA0, HIGH);
  61. digitalWrite(MA1, LOW);
  62. digitalWrite(MA2, LOW);
  63. digitalWrite(MA3, HIGH);
  64. break;
  65. case 0x5a: //右转
  66. digitalWrite(MA0, LOW);
  67. digitalWrite(MA1, HIGH);
  68. digitalWrite(MA2, HIGH);
  69. digitalWrite(MA3, LOW);
  70. break;
  71. case 0x45:
  72. default:
  73. digitalWrite(MA0, LOW);
  74. digitalWrite(MA1, LOW);
  75. digitalWrite(MA2, LOW);
  76. digitalWrite(MA3, LOW);
  77. break;
  78. }
  79. }
  80. }

4 App设计

        使用微信小程序开发App,其特点是集成在微信App内,不用单独安装,搜索到该App既可以使用。该程序主要实现4个按钮,实现小车前进、后退、左转、右转功能。

App UI:

开发工具:

核心代码如下: 

  1. const utils = require('utils.js')
  2. const ble = require('bluetooth.js')
  3. Page({
  4. /**
  5. * 页面的初始数据
  6. */
  7. data: {
  8. pageload: false,
  9. connected: false,
  10. send_hex: false,
  11. send_string: true,
  12. send_string_val: 'Hex',
  13. recv_string: true,
  14. recv_string_val: 'Hex',
  15. recv_value: '',
  16. send_number: 0,
  17. recv_number: 0,
  18. recv_hex: true,
  19. try_cnt:0,
  20. deviceArray: []
  21. },
  22. /**
  23. * 生命周期函数--监听页面加载
  24. */
  25. onLoad: function (options) {
  26. var that = this;
  27. console.log(options);
  28. this.setData({
  29. pageload:true,
  30. connected: false,
  31. deviceId: options.id,
  32. try_cnt:0,
  33. deviceName: options.name
  34. });
  35. console.log("detail: onLoad");
  36. wx.stopBluetoothDevicesDiscovery({
  37. success: function (res) {
  38. console.log('停止搜索设备', res)
  39. }
  40. })
  41. that.closeBLEConnection(that.data.deviceId);
  42. that.createBLEConnection(that.data.deviceId, that.data.deviceName);
  43. },
  44. onHide () {
  45. var that = this;
  46. // Do something when hide.
  47. // 断开连接
  48. console.log("detail: onHide");
  49. },
  50. onShow:function()
  51. {
  52. // var that = this;
  53. // connect bluetooth
  54. // that.closeBLEConnection(that.data.deviceId);
  55. // that.createBLEConnection(that.data.deviceId, that.data.deviceName);
  56. },
  57. onUnload() {
  58. var that = this;
  59. this.setData({
  60. pageload:true,
  61. connected: false,
  62. try_cnt:0,
  63. });
  64. console.log("page: onUnload ");
  65. that.offBLEMonitor();
  66. that.closeBLEConnection(that.data.deviceId);
  67. that.closeBluetoothAdapter();
  68. wx.showToast({
  69. title: '断开蓝牙',
  70. icon: 'success',
  71. duration: 2000
  72. })
  73. },
  74. DisConnectTap:function()
  75. {
  76. var that = this;
  77. that.setData({
  78. pageload:true,
  79. connected: false,
  80. try_cnt:0,
  81. });
  82. ble.openBluetoothAdapter(that.data.deviceId, that.data.deviceName);
  83. that.createBLEConnection(that.data.deviceId, that.data.deviceName);
  84. },
  85. RecvCleanTap: function () {
  86. this.setData({
  87. recv_value: '',
  88. recv_number: 0
  89. });
  90. },
  91. /**
  92. * 创建连接
  93. * @param {*} deviceId
  94. * @param {*} name
  95. */
  96. createBLEConnection(deviceId, name)
  97. {
  98. wx.createBLEConnection({
  99. deviceId,
  100. success: (res) => {
  101. console.log('createBLEConnection - success: ', res)
  102. this.getBLEDeviceServices(deviceId)
  103. },
  104. fail: (res) => {
  105. console.error('createBLEConnection - fail: ', res)
  106. if(res.errCode == 10006 ){
  107. this.createBLEConnection(deviceId, name)
  108. }
  109. else{
  110. ble.openBluetoothAdapter(deviceId, name)
  111. this.createBLEConnection(deviceId, name)
  112. }
  113. this.setData({
  114. connected: false,
  115. })
  116. }
  117. })
  118. },
  119. getBLEDeviceServices(deviceId)
  120. {
  121. var that = this;
  122. wx.getBLEDeviceServices({
  123. deviceId,
  124. success: (res) =>
  125. {
  126. console.log('getBLEDeviceServices - success: ', res)
  127. for (let i = 0; i < res.services.length; i++)
  128. {
  129. var ergodic_UUID =res.services[i].uuid; //取出服务里面的UUID
  130. var UUID_slice = ergodic_UUID.slice(4, 8); //截取4到8位
  131. console.log('getBLEDeviceServices, service ID = ', res.services[i].uuid);
  132. if ( res.services[i].isPrimary && (UUID_slice == "FFE0") )
  133. {
  134. that.setData({
  135. serviceId: res.services[i].uuid,
  136. });
  137. break;
  138. }
  139. }
  140. wx.getConnectedBluetoothDevices({
  141. services: res.services,
  142. success: (res) =>
  143. {
  144. console.log("getConnectedBluetoothDevices - success: " + res)
  145. },
  146. fail: (res) => {
  147. console.error('getConnectedBluetoothDevices - fail: ', res)
  148. ble.openBluetoothAdapter(deviceId, that.data.deviceName)
  149. }
  150. })
  151. that.getBLEDeviceCharacteristics(deviceId, that.data.serviceId);
  152. },
  153. fail: (res) => {
  154. console.error('getBLEDeviceServices - fail: ', res)
  155. // try it again
  156. ble.openBluetoothAdapter(deviceId, that.data.deviceName)
  157. that.monitor_connected();
  158. }
  159. });
  160. },
  161. getBLEDeviceCharacteristics(deviceId, serviceId)
  162. {
  163. var that = this;
  164. let falg = false;
  165. wx.getBLEDeviceCharacteristics({
  166. deviceId,
  167. serviceId,
  168. success: (res) =>
  169. {
  170. that.setData({
  171. connected: true,
  172. })
  173. console.log('getBLEDeviceCharacteristics success', res.characteristics)
  174. for (let i = 0; i < res.characteristics.length; i++)
  175. {
  176. let item = res.characteristics[i]
  177. console.log('getBLEDeviceCharacteristics, Characteristics ID = ', item.uuid)
  178. // 该特征值:可读
  179. if (item.properties.read)
  180. {
  181. wx.readBLECharacteristicValue({
  182. deviceId,
  183. serviceId,
  184. characteristicId: item.uuid,
  185. })
  186. }
  187. // 该特征值:可写
  188. if (item.properties.write)
  189. {
  190. this.setData({
  191. canWrite: true
  192. })
  193. this._deviceId = deviceId
  194. this._serviceId = serviceId
  195. this._characteristicId = item.uuid
  196. this.writeValue()
  197. }
  198. if (item.properties.notify || item.properties.indicate)
  199. {
  200. that.setData({
  201. characteristicId: item.uuid
  202. });
  203. falg = true;
  204. break;
  205. }
  206. }
  207. if( falg )
  208. {
  209. console.debug('getBLEDeviceCharacteristics - deviceId : ', deviceId)
  210. console.debug('getBLEDeviceCharacteristics - serviceId : ', serviceId)
  211. console.debug('getBLEDeviceCharacteristics - characteristicId: ', that.data.characteristicId)
  212. // read device character value
  213. that.readBLECharacteristicValue(deviceId, serviceId, that.data.characteristicId)
  214. that.notifyBLECharacteristicValueChange(deviceId, serviceId, that.data.characteristicId)
  215. }
  216. },
  217. fail: (res) => {
  218. console.error('getBLEDeviceCharacteristics -- fail: ', res)
  219. this.setData({
  220. connected: false,
  221. })
  222. if (res.errCode === 10006)
  223. {
  224. that.offBLEMonitor();
  225. that.createBLEConnection(deviceId, that.data.deviceName);
  226. }
  227. }
  228. })
  229. },
  230. readBLECharacteristicValue(deviceId,serviceId, characteristicId )
  231. {
  232. wx.readBLECharacteristicValue({
  233. // 这里的 deviceId 需要已经通过 createBLEConnection 与对应设备建立链接
  234. deviceId,
  235. // 这里的 serviceId 需要在 getBLEDeviceServices 接口中获取
  236. serviceId,
  237. // 这里的 characteristicId 需要在 getBLEDeviceCharacteristics 接口中获取
  238. characteristicId,
  239. success (res) {
  240. console.log('readBLECharacteristicValue:', res.errCode)
  241. }
  242. })
  243. },
  244. notifyBLECharacteristicValueChange(deviceId,serviceId, characteristicId )
  245. {
  246. var that = this;
  247. wx.notifyBLECharacteristicValueChange({
  248. state: true, // enable notify
  249. deviceId,
  250. serviceId,
  251. characteristicId,
  252. success: (res) => {
  253. console.info('notifyBLECharacteristicValueChange success: ', res.errMsg)
  254. // read data here
  255. // 操作之前先监听,保证第一时间获取数据
  256. wx.onBLECharacteristicValueChange(function(res)
  257. {
  258. that.data.connected = true;
  259. console.info('onBLECharacteristicValueChange', res);
  260. console.info(`characteristic ${res.characteristicId} has changed, now is ${res.value}`);
  261. var result = res.value;
  262. var hex = utils.buf2hex(result);
  263. var _hex_ss = utils.hex2string(hex);
  264. console.info("hex: " + hex);
  265. console.info("string: " + _hex_ss);
  266. var recv_number_1 = that.data.recv_number + _hex_ss.length / 2;
  267. var recv_number = Math.round(recv_number_1);
  268. that.setData({
  269. recv_number: recv_number,
  270. recv_value: that.data.recv_value + _hex_ss,
  271. });
  272. let _ss = that.data.recv_value
  273. if( _ss.includes("TM(C):") && _ss.includes("HM:") && _ss.includes("\n"))
  274. {
  275. let buff = _ss.split(' ')
  276. console.log( _ss )
  277. console.log(buff)
  278. that.data.recv_value = "";
  279. that.data.recv_number = 0;
  280. that.setData({
  281. temphtValue: buff[2],
  282. humidityValue: buff[4],
  283. });
  284. }
  285. that.monitor_connected();
  286. })
  287. },
  288. fail: (res) => {
  289. console.error('notifyBLECharacteristicValueChange fail: ', res)
  290. that.monitor_connected();
  291. }
  292. })
  293. },
  294. monitor_connected_action()
  295. {
  296. var that = this;
  297. let deviceId = that.data.deviceId;
  298. wx.onBLEConnectionStateChange(function(res) {
  299. // 该方法回调中可以用于处理连接意外断开等异常情况
  300. console.log( "onBLEConnectionStateChange ----- " + `device ${res.deviceId} state has changed, connected: ${res.connected}`)
  301. if( res.deviceId == deviceId && res.connected == false )
  302. {
  303. wx.closeBLEConnection({
  304. deviceId,
  305. success: (res) => {
  306. console.debug('detail: closeBLEConnection success', res);
  307. that.offBLEMonitor();
  308. that.createBLEConnection(deviceId, that.data.deviceName);
  309. },
  310. fail: (res) => {
  311. console.error('detail: closeBLEConnection fail', res);
  312. if (res.errCode === 10006) {
  313. that.offBLEMonitor();
  314. that.createBLEConnection(deviceId, that.data.deviceName);
  315. }
  316. }
  317. })
  318. that.setData({
  319. try_cnt: that.data.try_cnt + 1,
  320. })
  321. }
  322. else{
  323. that.data.try_cnt = 0;
  324. }
  325. })
  326. },
  327. monitor_connected()
  328. {
  329. var that = this;
  330. setTimeout(that.monitor_connected_action, 200);
  331. },
  332. writeValue( val )
  333. {
  334. // 向蓝牙设备发送一个0x00的16进制数据
  335. let buffer = new ArrayBuffer(1);
  336. let dataView = new DataView(buffer);
  337. dataView.setUint8(0, val);
  338. console.debug('getBLEDeviceCharacteristics - deviceId : ', this._deviceId)
  339. console.debug('getBLEDeviceCharacteristics - serviceId : ', this._serviceId)
  340. console.debug('getBLEDeviceCharacteristics - characteristicId: ', this._characteristicId)
  341. wx.writeBLECharacteristicValue({
  342. deviceId: this._deviceId,
  343. serviceId: this._serviceId,
  344. characteristicId: this._characteristicId,
  345. value: buffer,
  346. success: (res) => {
  347. console.debug('writeBLECharacteristicValue success', res);
  348. },
  349. fail: (res) => {
  350. console.error(' writeBLECharacteristicValue fail', res);
  351. this.setData({
  352. connected: false,
  353. })
  354. }
  355. })
  356. },
  357. closeBluetoothAdapter()
  358. {
  359. wx.closeBluetoothAdapter({
  360. success (res) {
  361. console.log(res)
  362. }
  363. })
  364. this.setData({
  365. connected: false,
  366. }),
  367. this._discoveryStarted = false
  368. },
  369. closeBLEConnection( deviceId )
  370. {
  371. wx.closeBLEConnection({
  372. deviceId,
  373. success: (res) => {
  374. console.debug('detail: closeBLEConnection success', res);
  375. },
  376. fail: (res) => {
  377. console.error('detail: closeBLEConnection fail', res);
  378. }
  379. })
  380. this.setData({
  381. connected: false,
  382. canWrite: false,
  383. })
  384. },
  385. run_up:function()
  386. {
  387. var that = this;
  388. var val = 0x18 ;
  389. that.writeValue( val );
  390. },
  391. run_down:function()
  392. {
  393. var that = this;
  394. var val = 0x52;
  395. that.writeValue( val );
  396. },
  397. run_left:function()
  398. {
  399. var that = this;
  400. var val = 0x08;
  401. that.writeValue( val );
  402. },
  403. run_right:function()
  404. {
  405. var that = this;
  406. var val = 0x5a;
  407. that.writeValue( val );
  408. },
  409. whiteLightValueSliderChange:function(e)
  410. {
  411. var that = this;
  412. // 向蓝牙设备发送一个0x00的16进制数据
  413. var val = Math.random() * 255 | 0;
  414. that.writeValue( val );
  415. },
  416. offBLEMonitor(){
  417. this.setData({
  418. connected: false,
  419. }),
  420. wx.offBLEPeripheralConnectionStateChanged();
  421. wx.offBLEConnectionStateChange();
  422. wx.offBLECharacteristicValueChange();
  423. wx.offBLEMTUChange();
  424. }
  425. })

5 参考文献

1)使用Arduino UNO硬件平台制作智能小车-CSDN博客

2)汇承HC-08蓝牙串口模块使用规格书(含指令集).pdf

3)概览 | 微信开放文档 (qq.com)

4)Arduino 实验室 – Arduino中文站,提供丰富的Arduino教程和DIY资讯 (nxez.com)

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/繁依Fanyi0/article/detail/1014726
推荐阅读
相关标签
  

闽ICP备14008679号