一、BLE技术简介

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

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

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

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

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

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

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()

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());
}
}

Arduino101学习笔记(十一)—— 蓝牙BLE的更多相关文章

  1. python3.4学习笔记(十一) 列表、数组实例

    python3.4学习笔记(十一) 列表.数组实例 #python列表,数组类型要相同,python不需要指定数据类型,可以把各种类型打包进去#python列表可以包含整数,浮点数,字符串,对象#创建 ...

  2. Go语言学习笔记十一: 切片(slice)

    Go语言学习笔记十一: 切片(slice) 切片这个概念我是从python语言中学到的,当时感觉这个东西真的比较好用.不像java语言写起来就比较繁琐.不过我觉得未来java语法也会支持的. 定义切片 ...

  3. JavaScript权威设计--JavaScript函数(简要学习笔记十一)

    1.函数调用的四种方式 第三种:构造函数调用 如果构造函数调用在圆括号内包含一组实参列表,先计算这些实参表达式,然后传入函数内.这和函数调用和方法调用是一致的.但如果构造函数没有形参,JavaScri ...

  4. SharpGL学习笔记(十一) 光源创建的综合例子:光源参数可调节的测试场景

    灯光的测试例子:光源参数可以调节的测试场景 先看一下测试场景和效果. 场景中可以切换视图, 以方便观察三维体和灯光的位置.环境光,漫射光,镜面反射光都可以在四种颜色间切换. 灯光位置和摄像机位置(Lo ...

  5. Android学习笔记之蓝牙通信...

    PS:最近同学问我蓝牙的事,因此自己也就脑补了一下蓝牙... 学习内容: 1.如何实现蓝牙通信技术...   蓝牙通信其实是手机里很常用的一种通信方式,现在的手机中是必然存在蓝牙的,蓝牙通信也是有一部 ...

  6. java jvm学习笔记十一(访问控制器)

     欢迎装载请说明出处: http://blog.csdn.net/yfqnihao/article/details/8271665 这一节,我们要学习的是访问控制器,在阅读本节之前,如果没有前面几节的 ...

  7. Oracle学习笔记十一 游标

    游标的简介 游标的概念 游标是从数据表中提取出来的数据,以临时表的形式存放在内存中,在游标中有一个数据指针,在初始状态下指向的是首记录,利用fetch语句可以移动该指针,从而对游标中的数据进行各种操作 ...

  8. Arduino101学习笔记(三)—— 101简介

    一.板子图示--摘自中文社区 二.技术规格 主控器 Intel Curie 工作电压 3.3V (I/O兼容5V) 输入电压 (推荐) 7-12V 输入电压 (极限) 6-20V 数字 I/O 14 ...

  9. Java基础学习笔记十一 Eclipse开发工具

    Eclipse是功能强大Java集成开发工具.它可以极大地提升我们的开发效率.可以自动编译,检查错误.在公司中,使用的就是Eclipse进行开发. Eclipse的下载.安装.卸载 下载 http:/ ...

随机推荐

  1. The Imitation Game

    <The Imitation Game>是一部非常好的电影,讲述了人工智能之父——阿兰图灵的传奇一生. 重点讲述了他通过破译德国的通讯密码缩短了二战的持续时间,因而拯救了无数生命的伟大事迹 ...

  2. UESTC 250

    windy数 基本的数位DP,需要判断当前位是否为起始位. #include <cstdio> #include <cmath> #include <cstring> ...

  3. iOS 利用不等的constraint实现布局间隔调整

    以前也写过一篇文章,说的也是如何利用constraint调整布局间隔,今天说另一种方法,实现简单,但有一定局限. 先看图 这里只截取了一部分,这个页面在4寸是可以显示的,但是如果不把控件间的间距缩小, ...

  4. 24. javacript高级程序设计-最佳实践

    1. 最佳实践 l 来自其他语言的代码约定可以用于决定何时进行注释,以及如何进行缩进,不过JavaScript需要针对其松散类型的性质创造一些特殊的约定 l javascript应该定义行为,html ...

  5. Java中的try,catch(Exception e),finally及return执行顺序

    结论: ①就算之前return,finally也会执行 ②finally的计算结果不影响之前的return值 ③finally的return值一定是最后的返回结果,因此将return放入finally ...

  6. windows配置nginx实现负载均衡集群

    windows配置nginx实现负载均衡集群2014-08-20 09:44:40   来源:www.abcde.cn   评论:0 点击:617 网上大部分关于nginx负载均衡集群的教程都是lin ...

  7. C#关于new的用法

    1.运算符就是在实例化一个类的时候(运算符的用法) A a=new A(); 2.new 约束指定泛型类声明中的任何类型参数都必须有公共无参数构造函数.当泛型类创建类型的新实例时,将此约束应用于类型参 ...

  8. Android Canvas绘图详解(图文)

    编辑推荐:稀土掘金,这是一个针对技术开发者的一个应用,你可以在掘金上获取最新最优质的技术干货,不仅仅是Android知识.前端.后端以至于产品和设计都有涉猎,想成为全栈工程师的朋友不要错过! Andr ...

  9. 用户登录流程详解 +volley(StringRequest)

    在实习期间由于要求使用volley,所以第一次开始接触volley,从一开始的迷茫陌生,到疯狂的查找各种资料,通过在项目中用到的实际问题,我想做一些总结,所以写了这篇文章.下面我将介绍我理解的用户登录 ...

  10. 仿知乎程序 fragment的切换以及toolbar在不同页面下显示的menu不同

           我们在看知乎的时候,你会发现,首页,发现,关注,收藏,草稿这五项,你在点击之后进入到相应页面之后,侧滑菜单还在,你左侧滑一下,这个侧滑菜单还在,而提问,左滑屏幕,这个页面就没有,有点像返 ...