zoukankan      html  css  js  c++  java
  • 手机与Arduino蓝牙串口通讯实验及完整例程

    安卓手机与Arduino之间采用蓝牙串口通讯,是很多智能装置和互动装置常用的控制方法,简单而有效,无需网络环境,很实用的技术。

    实验采用Arduino UNO板,加了一块1602LCD屏做显示(因为只有一个串口,用来做蓝牙通讯,再用串口助手不方便,也不直观)。蓝牙模块使用十几元一个的HC-06。一个LED接在11脚作为演示。手机端做了一个简单的界面,有按键和滑动条。用按键控制LED点亮和熄灭,演示开关量控制。滑动条控制LED的亮度,演示模拟量控制(0-100范围)。LCD屏实时显示传送的数据。模块接线按标准接法,大家都玩过的,请参考各种教程或书籍。硬件图片如下。

    <ignore_js_op>

    关于蓝牙串口通讯的几个要点:

    1. Arduino的串口,print()和println()函数都是用ASCII字符的方式传送数据,无论是int、float还是string,都自动转换成ASCII码传送。其中println()函数在传送的数据后面加了回车和换行符(" "和" ")。换行符正好可以作为结束符来让手机端识别。

    2. 蓝牙串口是异步传输方式,每次Serial.read()只读一个字节,在一个loop()循环中可能收不全一条数据信息,必须要有一个全局变量来收集接收到的字符。如果要通讯可靠,使用结束符来确定收到了一条完整的信息,是非常必要的。手机端也是一样。

    3. 例程中用的Serial.parseInt()函数,作用是在收到的字符流中,找到数字字符,并累积在一起,直到收到一个非数字字符时,将前面收到的数字字符转换成一个整数。如果要传送多个数值,中间用逗号等分隔符隔开即可。比如三个数值,”12,325,993“,后面加一个自定义的结束符,作为字符串发给Arduino。(例程中用字符"X”作为结束符。)这样接收数据完整而可靠。接收float可以用Serial.parseFloat()函数,用法一样。

    安卓手机端可以用蓝牙串口助手APP。但是建议自己写一个简单的APP,才真正完整的知道怎么通讯。再说了,如果真的做一个产品或服务,总是要自己做手机端APP的,蓝牙串口助理不能当产品用。

    Arduino完整例程如下。IDE 1.6.3编译通过,运行正常。欢迎大家修改使用,完全开源。例程内有详细注释。

    /* 本例程演示从手机蓝牙串口接收指令,点亮或熄灭11脚的LED,或者调整亮度。
     
    * 接收指令格式:“101X”点亮,“102X"熄灭,”000X"调整亮度。(000为0-100的整数,表示亮度值,X是结束符。)
     
    * 串口是异步接收的,用parseInt()查找第一个有效整数,检测到结束符后开始处理。
     
    * 接收数据显示在1602LCD屏上。
     
    * 点亮或熄灭LED后,将收到数据回传给手机。用pringln()函数,数据后面加了" "和" "两个字符,可以用作结束符。
     
    * 串口传送的是ASCII字符,数据格式可以自动转换。
     
    */
       
     
    #include <Wire.h>                  // 包含LCD库。
     
    #include <LiquidCrystal_I2C.h>
     
    LiquidCrystal_I2C lcd(0x27,16,2);  // 初始化LCD对象,地址为0x27,每行16个字符,共两行。
     
    int p;                             // 定义整数型全局变量,保存接收的数据。
       
     
    void setup() {
     
      lcd.init();                      // 初始化LCD。
     
      lcd.backlight();                 // 打开LCD背光。
     
      Serial.begin(9600);              // 打开串口(蓝牙)
     
      pinMode(11,OUTPUT);              // 定义11脚为输出。(数字或PWM)
     
    }
       
     
    void loop() {
     
      while (Serial.available() > 0) {   // 串口收到字符数大于零。
     
        p = Serial.parseInt();           // 在串口数据流中查找一个有效整数。
     
        if (Serial.read() == 'X') {      // 收到结束符后开始处理数据。
     
          lcd.clear();                   // LCD清屏。
     
          lcd.print(p);                  // LCD显示收到的数据(整数)。
     
          switch (p) {                   // 判断数据内容。
     
          case 101:
     
            digitalWrite(11,HIGH);       // 点亮LED。
     
            Serial.println(p);           // 回传数据。
     
            break;
     
          case 102:
     
            digitalWrite(11,LOW);        // 熄灭LED。
     
            Serial.println(p);           // 回传数据。
     
            break;
     
          default:
     
            p = map(p,0,100,0,255);      // 转换数据范围到PWM输出值。
     
            analogWrite(11,p);           // 调整LED亮度。(PWM)
     
          }
     
        }
     
      }
    }

    机端编程用的是E4A中文安卓编程软件,简单省力。基本功能都是齐全的。现在版本是4.7

    /* 本例程通过蓝牙串口发送指令给Arduino,点亮或熄灭LED,也可以通过滑块调整LED亮度.
     
    * 手机界面上的按键1发送"101X",点亮LED,按键2发送"102X",熄灭LED.
     
    * 拖动界面上的滑块后,发送0-100之间的整数,表示亮度值,后面加一个"X"为结束符..
     
    * 接收Arduino传回的数据,收到"101X",滑块到最大位置.收到"102X",滑块的最小位置.
     
    * 蓝牙串口接收是异步的,必须在收到数据事件中累积收到的ASCII字符,检测到结束符后再处理.
     
    * Arduino的println()函数发出的数据后面会加上回车和换行符,可以作为结束符使用.
     
    * 处理数据时或转换格式时,要去掉回车换行符.(字符长度要减2).
     
    */
       
     
    变量 返回值 为 文本型     // 定义全局变量,保存接收数据.
     
            
     
    事件 主窗口.创建完毕()        
     
        返回值 = ""
     
            如果 蓝牙1.是否已开启() = 假 则     //开启手机蓝牙.
     
                    蓝牙1.开启蓝牙()
     
            结束 如果
     
    结束 事件
       
     
    事件 蓝牙1.蓝牙设置完毕(设置结果 为 整数型)
     
            判断 设置结果
     
                    分支 1           //蓝牙已开启.
     
                            弹出提示("蓝牙已开启")
     
                            蓝牙1.置可被发现()           //置可被发现
     
                    分支 2                        '蓝牙未开启
     
                            信息框("信息","蓝牙未被开启,程序将退出!","确定")
     
                            结束程序()
     
                    分支 3                       //已置可被发现
     
                            弹出提示("蓝牙已设置为可被发现")
     
                    分支 4                       //不可被发现
     
                            信息框("信息","蓝牙未被设置为可被发现,程序将退出!","确定")
     
                            结束程序()
     
            结束 判断
     
            蓝牙1.置工作模式(1)       //置工作模式为串口通讯.
     
    结束 事件
       
     
    事件 按钮10.被单击()
     
        蓝牙1.搜索设备()          //搜索设备
     
            弹出提示("正在搜索")
     
    结束 事件
       
     
    事件 蓝牙1.发现设备(设备名称 为 文本型,设备地址 为 文本型,是否已配对 为 逻辑型)   //发现蓝牙设备.
     
            列表框1.可视 = 真            //显示列表框.
     
            列表框1.添加项目(设备名称 & "_" & 设备地址 & "_" & 是否已配对)   //列表框显示搜索到的蓝牙设备.
     
    结束 事件
       
     
    事件 列表框1.表项被单击(项目索引 为 整数型)            //单击列表框选择要通讯的设备.
     
            变量 设备信息 为 文本型
     
            变量 文本数组 为 文本型()
     
            变量 设备地址 为 文本型
     
            设备信息 = 列表框1.取项目内容(项目索引)
     
            文本数组 = 分割文本(设备信息,"_")           //可以自定义分隔符,不要与设备名称重复即可..
     
            设备地址 = 文本数组(1)
     
            弹出提示(设备地址)
     
            蓝牙1.连接设备(设备地址)           //连接设备
     
            弹出提示("正在连接")        
     
    结束 事件
       
     
    事件 蓝牙1.连接完毕(连接结果 为 逻辑型,设备名称 为 文本型,设备地址 为 文本型,连接模式 为 整数型)
     
            如果 连接结果 = 真 则        //已连接设备,关闭列表框显示.
     
                    列表框1.可视 = 假
     
                    主窗口.标题 = "已连接:" & 设备名称
     
                    弹出提示("连接成功")
     
            否则
     
                    弹出提示("连接失败")         //连接失败,可以点击列表框再次连接.
     
            结束 如果
     
    结束 事件
       
     
    事件 蓝牙1.收到数据(数据 为 字节型(),设备名称 为 文本型,设备地址 为 文本型)    //收到串口数据
     
            返回值 = 返回值 & 字节到文本(数据,"UTF8")       //累积到文本变量中.
     
            如果  取文本右边(返回值,1) = " " 则                //发现结束符后开始处理数据.
     
                判断 取文本左边(返回值,取文本长度(返回值)-2)     //去掉回车换行符,
     
                    分支 "101"                 //滑块到最大值.
     
                            水平滑块条1.位置 = 100
     
                    分支 "102"                 //滑块到最小值.
     
                            水平滑块条1.位置 = 0
     
                结束 判断
     
                    返回值 = ""        //清空接收字符串,等待下一次接收.
     
            结束 如果
       
     
    结束 事件
       
     
    事件 按钮1.被单击()        
     
            蓝牙1.发送数据(文本到字节("101X","UTF8"))      //按键1发送.
     
    结束 事件
       
     
    事件 按钮11.被单击()            //结束按钮点击处理.
     
            蓝牙1.发送数据(文本到字节("102X","UTF8"))     //关掉LED.
     
            蓝牙1.断开连接()            //退出处理,释放资源,结束内部处理线程
     
            结束程序()
     
    结束 事件
       
       
     
    事件 按钮2.被单击()
     
            蓝牙1.发送数据(文本到字节("102X","UTF8"))   //按键2发送.
     
    结束 事件
       
     
    事件 水平滑块条1.停止拖动()     //滑块动作处理.
     
            变量 数值 为 文本型
     
            数值 = 整数到文本(水平滑块条1.位置) & "X"    //添加结束符.
     
            蓝牙1.发送数据(文本到字节(数值,"UTF8"))      //发送滑块位置数据.
     
    结束 事件
       
  • 相关阅读:
    LeetCode 023 Merge k Sorted Lists
    LeetCode 022 Generate Parentheses
    LeetCode 020 Valid Parentheses
    LeetCode 019 Remove Nth Node From End of List
    LeetCode 018 4Sum
    LeetCode 017 Letter Combinations of a Phone Number
    Linux常用命令详解(3)
    Linux常用命令详解(2)
    Linux常用命令详解(1)
    部署cobbler服务器
  • 原文地址:https://www.cnblogs.com/anandexuechengzhangzhilu/p/10711994.html
Copyright © 2011-2022 走看看