2018-03-19 14:48:09 hello_json 阅读数 5519
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3507 人正在学习 去看看 许英俊

前言

最近在使用蓝牙4.0做单导联心电监测产品时遇到了一个问题。某些机型在蓝牙4.0传递数据的过程中出现丢包(比如最新华为mate10),导致无法展示正确的心电图。后来经过实测,原来是每秒数据量过大(大概975byte/s),但并不是所有的安卓设备都会丢包,这引起了我的注意。赶紧找硬件开发的同事一起分析,最终得出,mate10的蓝牙4.0通讯默认间隙时间较长,通讯频率降低,导致数据丢失。

1、BLE通讯 Connection paramter

Connection paramter有三种状态:

1.BluetoothGatt.CONNECTION_PRIORITY_BALANCED = 0
使用Bluetooth SIG推荐的连接参数, 如果没有请求连接参数更新,这是默认值。

2.BluetoothGatt.CONNECTION_PRIORITY_HIGH = 1
高优先级,低延迟连接。

3.BluetoothGatt.CONNECTION_PRIORITY_LOW_POWER = 2
低功耗,降低数据速率连接参数

随后,就以上模式进行了针对性的资料查找,蓝牙协议分析 给了我很大的帮助。

2、Android设置BLE连接参数

在BluetoothGattCallback抽象类中,处了有我们熟悉的onConnectionStateChange方法:
/**
* Callback indicating when GATT client has connected/disconnected to/from a remote
* GATT server.
*
* @param gatt GATT client
* @param status Status of the connect or disconnect operation.
* {@link BluetoothGatt#GATT_SUCCESS} if the operation succeeds.
* @param newState Returns the new connection state. Can be one of
* {@link BluetoothProfile#STATE_DISCONNECTED} or
* {@link BluetoothProfile#STATE_CONNECTED}
*/
public void onConnectionStateChange(BluetoothGatt gatt, int status,
int newState) {
}

还有一个当蓝牙连接参数改变的监听onConnectionUpdated
/**
* Callback indicating the connection parameters were updated.
*
* @param gatt GATT client involved
* @param interval Connection interval used on this connection, 1.25ms unit. Valid
* range is from 6 (7.5ms) to 3200 (4000ms).
* @param latency Slave latency for the connection in number of connection events. Valid
* range is from 0 to 499
* @param timeout Supervision timeout for this connection, in 10ms unit. Valid range is
* from 10 (0.1s) to 3200 (32s)
* @param status {@link BluetoothGatt#GATT_SUCCESS} if the connection has been updated
* successfully
* @hide
*/
public void onConnectionUpdated(BluetoothGatt gatt, int interval, int latency, int timeout,
int status) {
}

也就是说,通过此回调函数,我们可以判断出当前BLE工作的状态。
那么,如何去设置呢?

楼主发现目前处了Android O其他的默认为CONNECTION_PRIORITY_HIGH 。由此可以按照正常的步骤来操作:

if (Build.VERSION.SDK_INT >=Build.VERSION_CODES.O) {
                   requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
                    mConnectionPriorityOperationInProgress = true;
                }
@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
 public void requestConnectionPriority(int priority){
        if (mBluetoothGatt != null) {
            boolean requestConnectionPriority = mBluetoothGatt.requestConnectionPriority(priority);
            Log.w("wsh"," requestConnectionPriority : "+ requestConnectionPriority);
        }
    }

核心方法还是使用系统BluetoothGatt的requestConnectionPriority方法。

3、注意点

在蓝牙设备建立连接之后,系统会默认设定一些连接参数,这样就会多次执行onConnectionUpdated回调,我们一定要通过一些同步机制或延时设置的方式来确保设置参数成功。假如我们设置后,系统又设置了一次,就会出现参数被覆盖的情况。

2019-07-19 17:18:42 qq_39306385 阅读数 172
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3507 人正在学习 去看看 许英俊

使用nordic官网的串口蓝牙时,若传输大量数据,会使单片机复位,从而蓝牙断开。

原因:在串口服务函数里发送蓝牙的数据,导致中断响应不及时,系统复位。

解决方法:串口服务函数不要发送蓝牙数据,只接受串口数据,使用定时器发送数据。

为了防止不同的数据帧粘在同一包,串口传输时定义通信协议,再使用fifo缓存将要发送的数据。fifo尽量大,5K没有问题。

定义了一个简单的协议:

  Head        Length        Data 
  2字节        2字节      不定长度

0x11 0x22   0xxx

Head  数据包头
Length Data长度
Data  具体数据

具体代码如下:

uint8_t uart_readF = 0;  //命令接收标志
uint16_t uart_len = 0;   //命令总长度
uint16_t uart_cnt = 0;   //命令已接收长度


void uart_event_handle(app_uart_evt_t * p_event)
{
	uint8_t  dat;
    switch (p_event->evt_type)
    {
        case APP_UART_DATA_READY:
            UNUSED_VARIABLE(app_uart_get(&dat));
			switch(uart_readF){
				case 0:
					if(dat == 0x11){
						uart_readF = 1;
					}
					break;
				case 1:
					if(dat == 0x22){
						uart_readF = 2;
					}
					break;
				case 2:
					uart_len = dat << 8;
					uart_readF = 3;
					break;
				case 3:
					uart_len += dat;
					if(uart_len > Fifo_Empty_Size(ffs)){
						uart_readF = 0;                  //fifo不足以写入本次数据帧,抛弃该数据帧
					}else{
						Fifo_Push(ffs,uart_len>>8);
						Fifo_Push(ffs,(uint8_t)uart_len);//将本次数据帧长度写入fifo
						uart_readF = 4;
						uart_cnt = 0;
					}
					break;
				case 4:
					Fifo_Push(ffs,dat); //将数据写入fifo
					if(++uart_cnt == uart_len){
						uart_readF = 0;
					}
					break;
			}
            break;

        case APP_UART_COMMUNICATION_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_communication);
            break;

        case APP_UART_FIFO_ERROR:
            APP_ERROR_HANDLER(p_event->data.error_code);
            break;

        default:
            break;
    }
}

在定时器每隔10ms(这个时间根据实际情况修改,测试10ms传输数据没有问题)去读取fifo里面的数据,通过蓝牙发送出去。发送数据时,一帧数据大于20个字节(蓝牙一包最多可以发送20个字节的用户数据),每一包都要发足20个字节,最后一包可以不用发足20字节。这是为了防止,写上位机软件的人员老是认为每一包数据都是有20个字节的,没有严格按照通信协议解析数据,造成通信存在问题(经常遇到这样的人,对接起来真累)。


uint8_t CMDDat[250] = {0};
uint16_t CMDLen = 0;
uint16_t CMDOff = 0;
static void TIME_update(void) 
{
	uint8_t dat = 0;
	uint16_t len = 0;
	
	if(CMDF==0){
		if(Fifo_GetLen(ffs) > 1){  //协议中,一帧数据的长度为两个字节
			Fifo_Pop(ffs,&dat);
			CMDLen = dat << 8;
			Fifo_Pop(ffs,&dat);
			CMDLen += dat;          //获取一帧数据的长度
			CMDF = 1;
		}
	}
	if(CMDF==1){
		if(Fifo_GetLen(ffs) >= CMDLen){
			Fifo_Pop_More(ffs,CMDDat,CMDLen); //获取一帧数据
			CMDOff = 0;
			CMDF = 2;
		}
	}
	if(CMDF==2){
		len = 20 < CMDLen ? 20 : CMDLen;     //长度多余20个字节,每次发送20个字节
//		uart_send(CMDDat+CMDOff,len);
		ble_nus_string_send(&m_nus, CMDDat+CMDOff, len);
		CMDLen -= len;
		CMDOff += len;
		if(CMDLen == 0){
			CMDF = 0;
		}
	}
}

 

2013-09-11 15:43:28 szrfstar11 阅读数 1796
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3507 人正在学习 去看看 许英俊


    信驰达蓝牙4.0跑步机设计方案,是基于TI低功耗蓝牙片上系统CC2540F256的近距离无线传输跑步机控制器的设计,将嵌入式技术和无线通信技术有机结合起来,利用蓝牙4.0技术自动将跑步机设备上的测量数据传输到iPod touch5、iPhone4S/5, ipad3等支持蓝牙4.0的设备上显示,并自动地进行智能化的人体运动时各项身体指标参数的管理。

应用该方案的跑步机以CC2540增强型内核C8051为信息处理单元,并以CC2540无线收发端为无线通信单元,主要由跑步机上的各项身体指标测量传感器数据采集模块(包括血压、心率、计步、血氧、血糖等参数)、输入输出控制电路、无线传输模块等部分组成,其结构如图所示:

 

一、信驰达蓝牙4.0跑步机方案特色 

 

二、方案操作演示


三、系统支持

 

四、方案应用


本文来源深圳信驰达科技www.szrfstar.com,转载请注明出处。

2017-12-05 18:09:28 qdh186 阅读数 2039
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3507 人正在学习 去看看 许英俊

最近要做Android手机通过蓝牙跟硬件通过互通数据,实现操控硬件的效果。

1.蓝牙权限的打开

//用于蓝牙之间传输数据的权限
 <uses-permission android:name="android.permission.BLUETOOTH"/>
 //设备被检测到
    <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>

还有一个点要注意:要使用蓝牙4.0,必须要求手机 API 18以上。
2.开始查找设备

你买的硬件的蓝牙模块在默认情况下是处于被检测的状态,所以手机直接连接就好。

手机端查找蓝牙设备的方式有两种:

(1)通过给bluetoothAdapter.startLeScanBluet方法设置LeScanCallback回调来进行(我就是用的这种方式,感觉这种方式最靠谱)

//获取BluetoothManager 
final BluetoothManager bluetoothManager =(BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);

 //获取adapter
   BluetoothAdapter   mBluetoothAdapter = bluetoothManager.getAdapter();

   //这种可以实现不弹对话框打开蓝牙
if (!mBluetoothAdapter.isEnabled()) {  
       //若没打开则打开蓝牙  
       mBluetoothAdapter.enable();  
}    

//该方法为查找设备的方法
 private void scanLeDevice(final boolean enable) {
        if (enable) {
            // Stops scanning after a pre-defined scan period.
            mHandler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    mScanning = false;                mBluetoothAdapter.stopLeScan(mLeScanCallback);
                    invalidateOptionsMenu();
                }
            }, SCAN_PERIOD);

            mScanning = true;
            mBluetoothAdapter.startLeScan(mLeScanCallback);
        } else {
            mScanning = false;
            mBluetoothAdapter.stopLeScan(mLeScanCallback);
        }
    }
//查找到设备后的回调
  // Device scan callback.
    private BluetoothAdapter.LeScanCallback mLeScanCallback =new BluetoothAdapter.LeScanCallback() {
        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                //这里我用一个list来存储所搜索到的设备
                    mLeDeviceListAdapter.addDevice(device);                    mLeDeviceListAdapter.notifyDataSetChanged();
                }
            });
        }
    };

(2)通过startDiscovery+BroadcastReceiver来实现(这种方式有时候搜索不到)

这种方式需要 Build.VERSION.SDK_INT >= 23 并且添加相应的权限

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
// 寻找蓝牙设备,android会将查找到的设备以广播形式发出去      
adapter.startDiscovery(); 
//广播接收
private BroadcastReceiver receiver = new BroadcastReceiver() {     
   @Override     
  public void onReceive(Context context, Intent intent) {     
       String action = intent.getAction();     
        if (BluetoothDevice.ACTION_FOUND.equals(action)) {     
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);     
            System.out.println(device.getName());     
       }     
   }     
}  

3.开始连接设备并实现相互通信

这里我用了一个service+broadcast来实现的。service的主要作用是去连接蓝牙并实现数据的交互。broadcast主要用于更新UI。
代码比较长我就贴主要的,全部代码在demo里面

//连接设备的方法
 public boolean connect(final String address) {
        if (mBluetoothAdapter == null || address == null) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }

        // Previously connected device.  Try to reconnect.
        if (mBluetoothDeviceAddress != null && address.equals(mBluetoothDeviceAddress)
                && mBluetoothGatt != null) {
            Log.d(TAG, "Trying to use an existing mBluetoothGatt for connection.");
            if (mBluetoothGatt.connect()) {
                mConnectionState = STATE_CONNECTING;
                return true;
            } else {
                return false;
            }
        }

        final BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(address);
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        // We want to directly connect to the device, so we are setting the autoConnect
        // parameter to false.
        mBluetoothGatt = device.connectGatt(this, false, mGattCallback);
        Log.d(TAG, "Trying to create a new connection.");
        mBluetoothDeviceAddress = address;
        mConnectionState = STATE_CONNECTING;
        return true;
    }

//设备状态的接口回调
 private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {
            String intentAction;
            if (newState == BluetoothProfile.STATE_CONNECTED) {
                intentAction = ACTION_GATT_CONNECTED;
                mConnectionState = STATE_CONNECTED;
                broadcastUpdate(intentAction);
                Log.i(TAG, "Connected to GATT server.");
                // Attempts to discover services after successful connection.
                Log.i(TAG, "Attempting to start service discovery:" +
                        mBluetoothGatt.discoverServices());

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                intentAction = ACTION_GATT_DISCONNECTED;
                mConnectionState = STATE_DISCONNECTED;
                Log.i(TAG, "Disconnected from GATT server.");
                broadcastUpdate(intentAction);
            }
        }

Demo下载地址

2016-07-14 18:57:03 cyinclude 阅读数 3879
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3507 人正在学习 去看看 许英俊
最近一直被这个蓝牙4.0数据传输问题的困扰,安卓版本这么多,发现一样的数据传输代码在不同手机上效果截然不同。
目前发现在5.1的系统上,蓝牙4.0每次发送256byte数据可行,但是在4.4的系统上每次传输数据最多为20byte。

下次传输时还未到BLE的数据可接收的时间,今天被这个小问题困扰了一下午。所以解决方法就是每次发送完,
sleep()一定时间,时间间隔根据实际情况而定,要是想保证发送正确率,时间可以长一点,要想保证速度,
可以短一点,但是可能会出现丢包现象。

没有更多推荐了,返回首页