Arduino101学习笔记(十一)—— 蓝牙BLE_KEVINZHAO124517的博客-程序员秘密

技术标签: 移动开发  设计模式  

一、BLE技术简介

      第四代蓝牙既包括传统的蓝牙,现在标有“蓝牙经典”,和新的低功耗蓝牙(Bluetooth LE,或BLE)。低数据速率,低功耗优化。

      蓝牙LE广播就像一个社区公告栏。连接到它的计算机就像是阅读公告板的社区成员一样。每一个无线电作为一个公告板或读者。如果你的收音机是一个公告板(称为蓝牙LE的说法一个外围设备)揭示数据中的所有收音机在社区看。如果你的收音机是一个读者(称为blueooth乐方面中央装置)它读任何的公告板(外围设备),它所关心的信息。

      您也可以将外围设备作为客户端服务器事务中的服务器,因为它们包含了读写器所要求的信息。同样,中央设备是蓝牙世界的客户,因为他们阅读的信息可用的外设。

image

      认为一个蓝牙勒外围设备作为一个公告板和中央设备作为一个观众。

      中央设备查看服务,获取数据,然后继续。每一个事务都是快速的(几毫秒),所以多个中央设备可以从一个外设获取数据。

      由外围设备提供的信息是结构化的服务,其中每一个被细分为特征。您可以将服务视为公告栏上的通知,以及这些通知的各个段落的特点。如果你是一个外围设备,你只需更新每个服务的特性,当它需要更新,不担心中央设备是否读取它们。如果你是一个中心设备,你连接到外围然后读你想要的。如果一个给定的特征是可读写的,然后外周和中枢都可以改变它。

 

1、通知

      蓝牙规范中的一个机制,被称为通知,当数据发生改变让你知道。

      当通知上的一个特性是启用的,外围设备写它,新的值自动广播出去,不需要关注中央设备。这是常用的流式数据,如加速度计或其他传感器读数。但一般中央设备可以发送一个ACK来确认包是否被接受

      蓝牙的客户端-服务器结构,结合通知的特点,通常被称为publish-and-subscribe model。

2、更新特性

      当外设发生显著变化的时候,应该更新特性。例如,当模拟传感器发生显著变化时,更新其特性。

      正如写的一个特点,可以定时更新特性,但这样会浪费101的处理能力以及消耗能量。

3、中央和外围设备

      中央设备是客户。他们从外围设备读取和写入数据。

      外围设备是服务器,提供来自传感器的数据,提供的可读可写和读的特性通知。

4、服务、特点和UUIDs

      一个BLE设备会提供服务,换句话说提供特性。您可以定义自己的服务,或使用标准服务。

      服务是由独特的数字称为UUID来识别。标准的服务有一个16位的UUID而定制服务有一个128位的UUID。定义服务和特性的能力取决于你使用的无线电和它的固件。

5、服务设计模式

     一个特征值可以高达20字节长。这是设计服务的一个关键约束。

     鉴于这一限制,你应该考虑如何最好地存储关于您的传感器和执行器的数据最有效地为您的应用程序。最简单的设计模式是不同的特性来存储一个传感器或致动器每个特征值。

Characteristic Value
Accelerometer X 200
Accelerometer Y 134
Accelerometer Z 150

     这是最昂贵的内存条款,并且读取时间最长。但它最简单进行开发和调试。

    您也可以将读数组合成一个单一的特性。 加速度计X,Y,Z 200133150

6、外围设备为中央设备服务的四个特性

      阅读:要求外周发送回特性的当前值。通常用于不经常改变的特性,例如用于配置的特性、版本号等。

      写:修改特性的值。通常用于那些像命令的东西,例如告诉外围设备打开或关闭电机。

      指示和通知:要求外周不断发送更新的价值观的特点,而不需要中央不断要求它。

 

 

二、UUID介绍

1、定义

       UUID的含义是通用唯一识别码 (Universally Unique Identifier),其目的是让分布式系统中的所有元素都有唯一识别的资讯,每个人都可以建立与其他人不冲突的UUID,并且还要保证在同一时空中所有机器都是唯一的。

2、组成

(1) 当前的时间(如果现在生成一个UUID后,过几秒又生成一个UUID,则第一个部分不同,其他相同。

(2)时钟序列

(3)全局唯一的IEEE机器识别号,如果有网卡,从网卡获取mac地址,没有就从其他地方获取。

       在curie中,一个BLE外设在提供服务,进而提供特征,也可以定制自己的特征。标准服务是一个16位的UUID,而定制服务是一个128位的UUID,这个也取决于你使用的无线方式和固件。

 

三、一些API

1、BLEPeripheral 类库成员函数

/*************************BLEPeripheral  ************************/
功能:给BLE外围设备命名。 
语法:BLEPeripheral yourBlePeripheralName 
参数:无 
返回值:无
/***********************************************************/
BLEPeripheral yourBlePeripheralName ;

/*************************begin() ************************/
// 功能:初始化BLE所有功能。
// 语法:yourBlePeripheralName.begin()
// 参数:无
// 返回值:初始化成功返回真,否则返回假。
/***********************************************************/
yourBlePeripheralName.begin()


/*************************end() ************************/
// 功能:关闭所有BLE外设功能。
// 语法:yourBlePeripheralName.end()
// 参数:无
// 返回值:初始化成功返回真,否则返回假。
/***********************************************************/          
yourBlePeripheralName.end()


/*************************setAdvertisedServiceUuid() ************************/
// 功能:设置广播服务UUID。
// 语法:yourBlePeripheralName.setAdvertisedServiceUuid(const char*advertisedServiceUuid)
// 参数:advertisedServiceUuid: TBD
// 返回值:无。
/************************************************************************************/          
yourBlePeripheralName.setAdvertisedServiceUuid(const char*advertisedServiceUuid)
   

/*************************setLocalName()************************/
// 功能:设置BLE外设的本地名。
// 语法:yourBlePeripheralName.setLocalName(const char* localName)
// 参数:localName: the name to be set
// 返回值:无。
/*********************************************************************/    
yourBlePeripheralName.setLocalName(const char* localName)


/*************************setDeviceName()************************/
// 功能:设置BLE外设的设备名称。
// 语法:yourBlePeripheralName.setLocalName(const char* deviceName)
// 参数:localName: the name to be set
// 返回值:无。
/*********************************************************************/  
yourBlePeripheralName.setLocalName(const char* deviceName)


/************************setAppearance()************************/
// 功能:待定。
// 语法:yourBlePeripheralName.setAppearance(unsigned int appearance)
// 参数:appearance: 待定
// 返回值:无。
/*********************************************************************/  
yourBlePeripheralName.setAppearance(unsigned int appearance)

/************************setEventHandler()************************/
// 功能:设置回掉函数与触发事件的关系。
// 语法:yourBlePeripheralName.setEventHandler()
//参数:event: the chosen matching event. It can assume one of the followingvalues:
//                                                                  BLEConnected
//                                                                  BLEDisconnected
//                                                                  BLEPeripheralEventLast
//          callback:the name of the function to call in case of match
// 返回值:无。
/*********************************************************************/  
yourBlePeripheralName.setEventHandler(BLEPeripheralEvent event, BLEPeripheralEventHandler callback)


/************************addAttribute()***********************/
//功能:添加外围设备的属性。
//语法:yourBlePeripheralName.addAttribute(BLEAttribute attributeName)
//参数:attributeName: 要添加的特征或服务的名称作为属性
// 返回值:无。
/****************************************************************/  
yourBlePeripheralName.addAttribute(BLEAttribute attributeName)


/************************disconnect()***********************/
//功能:断开连接。
//语法:yourBlePeripheralName.disconnect()
//参数:五
//返回值:true/false
/****************************************************************/   
yourBlePeripheralName.disconnect()


/************************central()***********************/
//功能:检查中心连接是否工作。
//语法:yourBlePeripheralName.central()
//参数:五
//返回值:true/false
/****************************************************************/ 
yourBlePeripheralName.central()


/************************connected()***********************/
//功能:检查设备是否连接。
//语法:yourBlePeripheralName.connected()
//参数:五
//返回值:true/false
/****************************************************************/ 
yourBlePeripheralName.connected()

2、BLEDescriptor 类库成员函数

特征值的描述以及定义

/************************BLEDescriptor()***********************/
//功能:描述特征值的属性。
//语法:BLEDescriptor(const char* uuid, const unsigned charvalue[],unsigned char valueSize);
//           BLEDescriptor(constchar* uuid, const char* value);  
//参数: UUID: standard 16-bit characteristic UUID
//           properties: what remote clients will be able to getnotifications if this characteristic changes. It can //                             assume the followingvalues:BLERead
//                                                                         BLEWrite
//                                                                         BLENotify
//           uuid: UUID of descriptor
//           value: value data
//           valueLength: length of value data in bytes

//返回值:无
/****************************************************************/ 
BLEDescriptor()

image

3、BLECentral 类库成员函数

BLECentral 
//功能:BLE中心设备通常访问外围设备的数据。
//语法:BLECentral yourBleCentralName
//参数:无
//返回值:无

connected()
//功能: 检查设备是否连接
//语法:yourBleCentralName.connected()
//参数:/
//返回值:连接成功返回true,否则返回false

address()
//功能:返回中心设备的地址
//语法:yourBleCentralName.address()
//参数:无
//返回值:中心设备地址

disconnect()
//功能:断开连接
//语法:yourBleCentralName.disconnect()
//参数:如果成功则返回true,否则返回false
//返回值:无

 

4、BLECharacteristic 类库成员函数

BLECharacteristic
//功能: 特征包至少包含两个属性:一个特征声明,其中包含有关数据的元数据,和特征值,其中包含数据本身
//特征:   names
//              UUIDs
//              values
//              read/write/notifyproperty

//下面提供众多的构造函数,可以根据计划使用这些特性。
//语法:

·     BLEBoolCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLECharCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEUnsignedCharCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEShortCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEUnsignedShortCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEIntCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEUnsignedIntCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLELongCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEUnsignedLongCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEFloatCharacteristic yourCharacteristicName(UUID, properties, maxLen)

·     BLEDoubleCharacteristic yourCharacteristicName(UUID, properties, maxLen)

//参数:

//-UUID:标准的16bit的UUID

//-Properties:如果特征值改变,远程客户端就能得到通知。

//可以采用以下值:

//BLERead

//BLEWrite

//BLENotify

 

5、BLEService 类库成员函数BLEService

功能:可使用BLE服务创建由BLE设备显示的服务

语法:BLEService (const char* uuid)

参数:UUID(由BLE定义的标准16bit或128bit的)

返回值:无

 

四、一个Demo

1、下载一个App

      nRF Master Control Panel (BLE) forAndroid and iOS

2、电路原理

       将电位器中间的引脚连接到101的模拟输入I/O空A0上,使用Arduino 101的AD功能对电位器的电压值采样模拟电池电压的变化

3、Code思路

        101嵌入了一个低功耗蓝牙模块,因此它是足够的板连接到计算机,并使用串行监视器读取由草图发送的消息。电位计被连接到3.3V,GND和A0至模拟电池的充电。这部分代码实现了标准的BLE电池检测功能

在setup()中,初始化13脚为输出来驱动板载LED,blePeripheral用来初始化板子的外设,如果多个板子运行这个代码,需要修改本地名,这样两者可以被区分,例如:

blePeripheral.setLocalName(“BatteryMonitorSketch”) 改为  blePeripheral.setLocalName(“BatteryMonitorSketch1”);

         在主循环中,成功连接中心设备后打开LED,每200ms进行一次连接测试,如果是正常的,updateBatteryLevel被调用。当连接丢失,LED会被关闭

 

/*******************头文件******************/
#include <CurieBLE.h>

/*******************宏定义******************/
#define LED_Pin 13


/*******************全局变量******************/
BLEPeripheral BlueMountain;       // BLE Peripheral Device (命名板子的名字),一个对象
BLEService batteryService("180F"); // 创建一个电池服务,且UUID为(180F)

// BLE Battery Level Characteristic"
BLEUnsignedCharCharacteristic batteryLevelChar("2A19",  //16BIT的UUID
                                                   BLERead|BLENotify);   //如果这个特征值改变,远程客户端会得到通知

int g_oldBatteryLevel = 0;       //从A0读到的电池电量数据
long g_previousMillis = 0;       //最后一次检测电池电量的时间,单位:ms


void updataBatteryLevel() 
{
  /*读取A0口当先的输入电压 
  用来模拟电池的电量值
  */
  int battery = analogRead(A0);   //读取A0
  int batteryLevel = map(battery, 0, 1023, 0, 100);
 
  if (batteryLevel != g_oldBatteryLevel)     // 如果电量改变了
  {    
    // 打印这个值
    Serial.print("Battery Level % is now: ");  
    Serial.println(batteryLevel);
    
    // 更新电池电量,保存下一个比较值
    batteryLevelChar.setValue(batteryLevel);  
    g_oldBatteryLevel = batteryLevel;           
  }
}

void setup() 
{
  // put your setup code here, to run once:
  Serial.begin(9600);     //初始化串口通信
 

  //analogReference(DEFAULT);     //配置AD

  pinMode(LED_Pin,OUTPUT);      //配置LED为输出,蓝牙连接成功后亮
  
  /* 给蓝牙设备设置一个本地名
     这个名字会出现在广告的数据包中
     并且远程设备通过这个名字连接这个设备
     这个名字可以更改但可能会在通知包里被截断   */
  BlueMountain.setLocalName("BatteryMonitorSketch");                 //设置本地名字
  BlueMountain.setAdvertisedServiceUuid(batteryService.uuid());      //添加服务的UUID
  BlueMountain.addAttribute(batteryService);                         //添加电池服务
  BlueMountain.addAttribute(batteryLevelChar);                       //添加电池电量
  batteryLevelChar.setValue(g_oldBatteryLevel);                      //设定初始值

  /* 激活蓝牙,此时它会不断地发射BLE广告数据包,
  远程BLE中心设备可收到,直到它接收到一个新的连接*/
  BlueMountain.begin();                   //开始服务
  delay(1000);
  Serial.println("Bluetooth device active, waiting for connections...");
}

// put your main code here, to run repeatedly:
void loop() 
{
  // 检测BLE外部设备是否连接
  BLECentral central = BlueMountain.central();

  // 如果中心设备连接了外围设备
  if( central )
  { 
    Serial.print("Connected to central: ");
    //在串口上打印中心设备的MAC地址
    Serial.println(central.address());
    // 打开13号口的LED
    digitalWrite(LED_Pin, HIGH);

    while(central.connected())
    {
      long currentMillis = millis();
      //200ms,检测一次电池电量。
      if(currentMillis - g_previousMillis >= 200 )
      {
        g_previousMillis = currentMillis;
        updataBatteryLevel();
      }
    }

    //当连接中断,关闭13号口LED
    digitalWrite(LED_Pin, LOW);
    Serial.print("Disconnected from central: ");
    Serial.println(central.address());
  }
}

转载于:https://www.cnblogs.com/BlueMountain-HaggenDazs/p/6056827.html

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/KEVINZHAO124517/article/details/102137118

智能推荐

分享作为程序猿的快乐_weixin_30952103的博客-程序员秘密

做为资深程序猿最大的快乐,就是苦中作乐。相信每个人在工作中总会碰到各种无语的场景,请大家在文章评论中留下最搞笑的瞬间,笑一笑十年少,笑多了,不怀孕。 1. 当客户要求兼容各大主流浏览器 2. 当我的代码终于编译成功时: 3. 当一个Bug出现在周五晚上时~~~ 4. 当组长问:你是否测试时: 5. 当你没测试代码就上传,结果完美运行时: 6. 凌...

uni-app导航跳转初始_小菜鸟学代码··的博客-程序员秘密

uni-app导航跳转导航(navigator)是个标签&lt;navigator url="路径"&gt;&lt;/navigator&gt; //普通跳转只能调到普通页面&lt;navigator url="/" open-type="switchTab"&gt;&lt;/navigator&gt; //加上open-type="switchTab" 跳转到tabbar页面&lt;navigator url="/" open-type="redirect"&gt;&lt;/navigator&g

关于 黑马程序员android全套60G视频教程免费分享(要的留下邮箱) (请版主关注)..._weixin_34262482的博客-程序员秘密

============问题描述============ 大家不要在发,站内信啊,或者留言啊,或者QQ了,根本就没有,并且是需要RMB的,我举报好多次了,不知道为什么版主没有管理。从我回帖到现在我最少收到100人的EMAILQQ等信息要这套东西,希望大家不要再受骗了,谢谢!~~~~~如果大家需要学习视频可以下载传智播客...

android AGC增益调整_GDWAVE Grp.的博客-程序员秘密

因为应用的agc没有特别增强,但是本机自带录音播放还是比较大的,为此想增大webrtc的增益,我这里AGC模式采用kAgcFixedDigital或kAgcAdaptiveDigital,int32_t WebRtcAgc_CalculateGainTable(int32_t *gainTable, int16_tdigCompGaindB, int16_ttargetLevelDbfs, uint8_t limiterEnable, int16_tanalogTarget)最终调节最近参数如下,...

Java通过浏览器请求头(User-Agent)获取 浏览器类型,操作系统类型,手机机型_操作系统类型浏览器可以拿到吗_山鸡的春天的博客-程序员秘密

User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。一些网站常常通过判断 UA 来给不同的操作系统、不同的浏览器发送不同的页面,因此可能造成某些页面无法在某个浏览器中正常显示,但通过伪装 UA 可以绕过检测。一:获得浏览器请求头中的User-Agent?1Strin

java jieba分词导入自定义txt字典_qq_fzx的博客-程序员秘密

WordDictionary.getInstance().loadUserDict(Paths.get("你的txt格式词典文件的路径:比如src/main/web/python/vocab.txt")) ;

随便推点

STM32开发C语言基础知识---关键字volatile_volatile stm32_leoche2012的博客-程序员秘密

1:关键字volatile:【一个定义为Volatile的变量可以随时被意想不到的改变。】这个说法有点抽象,怎么理解呢?使用的实际例子:1:设备的硬件寄存器2:多线程任务中被共享的变量3:中断服务子程序被访问到的非自动变量1)一个参数既可以是const还可以是volatile吗?解释为什么。 2); 一个指针可以是volatile 吗?解释为什么

eclipse 安装 Ibator 插件_DJPLH的博客-程序员秘密

1、Help-&amp;gt;Install New Software...2、在Work with 处输入http://ibatis.apache.org/tools/ibator/,点击add3、勾选Ibator Version 1.2。 Next 安装即可。

切换浏览示意图_weixin_30376509的博客-程序员秘密

一:布局&lt;?xml version="1.0" encoding="utf-8"?&gt;&lt;FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_heigh...

程序员幽默:当程序员当了爸爸_mazegong的博客-程序员秘密

程序员是一个随着第三次工业革命诞生的职业群体,拥有专业技能、爱代码、爱编程、爱生活,为互联网的飞速发展作出了卓越贡献~~人们口中的他们是这样的:干得比驴累,吃得比猪差;起得比鸡早,睡得比狗晚;看上去比谁都好,五年后比谁都老。所以,有一个这样的程序员爸爸,到底是种什么样的体验。01、跟爸爸说长大以后我也要当程序员,然后他是这样回答我的。儿子:爸,我想当程序员。爸爸:哦,那你先买40公斤面粉来!儿子:...

关于职业规划:程序员的出路问题一_qizhanfeng的博客-程序员秘密

【原创】下面四千字的东西,打了三个小时,又花了两小时修改,体会来自于自己的经历。既为楼主也为自己,也希望能给他人带来一点帮助,因为自己也曾苦于出路这个问题许久,徘徊于技术与销售之间。其实,最重要的是,想清楚自己要的到底是什么,而实现的方法有很多,选择其中的一个,然后耐心去做,注意做的过程中,要多方面发展。不断提高自己的综合能力才是硬道理——这才是出路之所在!!!。 【出路】 在职...

poi导出Excel,打开时提示“发现“…“中的部分内容有问题。是否让我们尽量尝试修复?如果您信任此工作簿的源,清单击“是“”怎么办?_是否让我们尽量尝试恢复,信任此工作簿_Counter-Strike大牛的博客-程序员秘密

这几天在弄Excel导出的事情。导出Excel之后,点击打开会提示:“发现"…"中的部分内容有问题。是否让我们尽量尝试修复?如果您信任此工作簿的源,清单击"是"”先说最后是怎么解决的,再说复杂的经过。着急的就不用往后看了。我的项目报这个错误是因为设置表格内容的时候传错了workbook。因为有一个读取原表格的workbook_1,还有一个写新表格的workbook_2。结果往新表格写数据的时候,使用了workbook_1,数据是能正常写进去没有问题,但是Excel肯定是察觉到了哪里不对,所以提示需要

推荐文章

热门文章

相关标签