Skip to content

Commit c4cb132

Browse files
committed
Central connection sample with Peripheral Texas Instruments Sensor Tag (CC2650). Connect, enable optical sensor, adjust measurement/transmission period.
http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide
1 parent a07fbec commit c4cb132

File tree

1 file changed

+302
-0
lines changed

1 file changed

+302
-0
lines changed
Lines changed: 302 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,302 @@
1+
/*********************************************************************
2+
This is an example for our nRF52 based Bluefruit LE modules
3+
4+
Pick one up today in the adafruit shop!
5+
6+
Adafruit invests time and resources providing this open source code,
7+
please support Adafruit and open-source hardware by purchasing
8+
products from Adafruit!
9+
10+
MIT license, check LICENSE for more information
11+
All text above, and the splash screen below must be included in
12+
any redistribution
13+
*********************************************************************/
14+
15+
/* This sketch shows how to use BLEClientService and BLEClientCharacteristic
16+
* to implement a custom client that is used to talk with Gatt server on
17+
* the TI SensorTag peripheral device.
18+
*
19+
* Online uuid/hex converters
20+
* https://yupana-engineering.com/online-uuid-to-c-array-converter
21+
* https://www.scadacore.com/tools/programming-calculators/online-hex-converter/
22+
* https://codebeautify.org/string-hex-converter
23+
*
24+
* Adafruit Bluefruit Feather nRF52
25+
* https://learn.adafruit.com/bluefruit-nrf52-feather-learning-guide/blescanner
26+
*
27+
* Sensor Tag
28+
* http://processors.wiki.ti.com/index.php/CC2650_SensorTag_User%27s_Guide#Optical_Sensor
29+
*
30+
* Scan Response (Extended Advertisement data retrieval)
31+
* https://devzone.nordicsemi.com/tutorials/b/bluetooth-low-energy/posts/ble-advertising-a-beginners-tutorial
32+
*
33+
*/
34+
35+
#include <bluefruit.h>
36+
37+
/* TI Sensor Tag UUID Definitions
38+
* Base SensorTag UUID pattern: F000-0000-0451-4000-B000-000000000000
39+
* Optical Service: 0xA070
40+
* Optical Characteristic: 0xAA71
41+
* Optical Data Collection Enabler: 0xAA72
42+
* Optical Measurement Period: 0xAA73
43+
* Local Name: "CC2650 SensorTag"
44+
*/
45+
46+
uint8_t SENSORTAG_OPTICAL_SERVICE_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x70,0xAA,0x00,0xF0};
47+
uint8_t SENSORTAG_OPTICAL_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x71,0xAA,0x00,0xF0};
48+
uint8_t SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x72,0xAA,0x00,0xF0};
49+
uint8_t SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xB0,0x00,0x40,0x51,0x04,0x73,0xAA,0x00,0xF0};
50+
uint8_t SENSORTAG_ADV_COMPLETE_LOCAL_NAME[] = {0x43,0x43,0x32,0x36,0x35,0x30,0x20,0x53,0x65,0x6e,0x73,0x6f,0x72,0x54,0x61,0x67};
51+
52+
BLEClientService sensorTagOpticalService(SENSORTAG_OPTICAL_SERVICE_UUID);
53+
BLEClientCharacteristic sensorTagOpticalCharacteristic(SENSORTAG_OPTICAL_CHARACTERISTIC_UUID);
54+
BLEClientCharacteristic opticalCharacteristicDataCollectionEnabler(SENSORTAG_OPTICAL_ENABLE_CHARACTERISTIC_UUID);
55+
BLEClientCharacteristic opticalCharacteristicPeriod(SENSORTAG_OPTICAL_PERIOD_CHARACTERISTIC_UUID);
56+
57+
58+
void setup()
59+
{
60+
Serial.begin(115200);
61+
62+
Serial.println("Bluefruit52 Central TI Sensor Tag Example");
63+
Serial.println("-----------------------------------------\n");
64+
65+
// Initialize Bluefruit with maximum connections as Peripheral = 0, Central = 1
66+
// SRAM usage required by SoftDevice will increase dramatically with number of connections
67+
Bluefruit.begin(0, 1);
68+
69+
Bluefruit.setName("Bluefruit52 TI SensorTag Central");
70+
71+
// Initialize Service
72+
sensorTagOpticalService.begin();
73+
74+
// set up callback for receiving measurement
75+
sensorTagOpticalCharacteristic.setNotifyCallback(sensortag_optical_notify_callback);
76+
sensorTagOpticalCharacteristic.begin();
77+
78+
// set up the characteristic to enable the optical component on the device
79+
opticalCharacteristicDataCollectionEnabler.begin();
80+
81+
// set up the characteristic to adjust the measurement period
82+
opticalCharacteristicPeriod.begin();
83+
84+
// Increase Blink rate to different from PrPh advertising mode
85+
Bluefruit.setConnLedInterval(250);
86+
87+
// Callbacks for Central
88+
Bluefruit.Central.setDisconnectCallback(disconnect_callback);
89+
Bluefruit.Central.setConnectCallback(connect_callback);
90+
91+
/* Start Central Scanning
92+
* - Enable auto scan if disconnected
93+
* - Interval = 100 ms, window = 80 ms
94+
* - No UUID Filter
95+
* - Use active scan
96+
* - Start(timeout) with timeout = 0 will scan forever (until connected)
97+
*/
98+
99+
Bluefruit.Scanner.setRxCallback(scan_callback);
100+
Bluefruit.Scanner.restartOnDisconnect(true);
101+
Bluefruit.Scanner.setInterval(160, 80); // in unit of 0.625 ms
102+
// Bluefruit.Scanner.filterUuid(); // do not not set anything here or Scan Response won't work
103+
Bluefruit.Scanner.useActiveScan(true); // required for SensorTag to reveal the Local Name in the advertisement.
104+
Bluefruit.Scanner.start(0); // 0 = Don't stop scanning after n seconds
105+
}
106+
107+
void loop()
108+
{
109+
// do nothing
110+
}
111+
112+
/**
113+
* Callback invoked when scanner pick up an advertising data
114+
* @param report Structural advertising data
115+
*/
116+
void scan_callback(ble_gap_evt_adv_report_t* report)
117+
{
118+
Serial.println("");
119+
Serial.println("Scan Callback");
120+
printReport( report );
121+
122+
/* Choose a peripheral to connect with by searching for an advertisement packet with a
123+
Complete Local Name matching our target device*/
124+
uint8_t buffer[BLE_GAP_ADV_MAX_SIZE] = { 0 };
125+
126+
Serial.print("Parsing report for Local Name ... ");
127+
if(Bluefruit.Scanner.parseReportByType(report, BLE_GAP_AD_TYPE_COMPLETE_LOCAL_NAME, buffer, sizeof(buffer)))
128+
{
129+
Serial.println("Found Local Name");
130+
Serial.printf("%14s %s\n", "Local Name:", buffer);
131+
132+
Serial.print(" Local Name data: ");
133+
printHexList(buffer, BLE_GAP_ADV_MAX_SIZE );
134+
135+
Serial.print("Determining Local Name Match ... ");
136+
if ( !memcmp( buffer, SENSORTAG_ADV_COMPLETE_LOCAL_NAME, sizeof(SENSORTAG_ADV_COMPLETE_LOCAL_NAME)) )
137+
{
138+
Serial.println("Local Name Match!");
139+
140+
Serial.println("Connecting to Peripheral ... ");
141+
Bluefruit.Central.connect(report);
142+
}
143+
else
144+
{
145+
Serial.println("No Match");
146+
}
147+
}
148+
else
149+
{
150+
Serial.println("Failed");
151+
}
152+
}
153+
154+
/**
155+
* Callback invoked when an connection is established
156+
* @param conn_handle
157+
*/
158+
void connect_callback(uint16_t conn_handle)
159+
{
160+
Serial.println("");
161+
Serial.print("Connect Callback, conn_handle: ");
162+
Serial.println( conn_handle );
163+
164+
/* Complete Local Name */
165+
uint8_t buffer[BLE_GAP_ADV_MAX_SIZE] = { 0 };
166+
167+
// If Service is not found, disconnect and return
168+
Serial.print("Discovering Optical Service ... ");
169+
if ( !sensorTagOpticalService.discover(conn_handle) )
170+
{
171+
Serial.println("No Service Found");
172+
173+
// disconect since we couldn't find service
174+
Bluefruit.Central.disconnect(conn_handle);
175+
176+
return;
177+
}
178+
Serial.println("Service Found");
179+
180+
// Once service is found, we continue to discover the primary characteristic
181+
Serial.print("Discovering Optical Characteristic ... ");
182+
if ( !sensorTagOpticalCharacteristic.discover() )
183+
{
184+
// Measurement chr is mandatory, if it is not found (valid), then disconnect
185+
Serial.println("No Characteristic Found. Characteristic is mandatory but not found. ");
186+
Bluefruit.Central.disconnect(conn_handle);
187+
return;
188+
}
189+
Serial.println("Characteristic Found");
190+
191+
// Data Collection Charactistic. Find and enable.
192+
// You enable data collection on the Characteristic before the peripheral will start measuring values.
193+
// This is different than setting the Notify descriptor, which is handled below.
194+
Serial.print("Discovering Data Collection Configuration Characteristic ... ");
195+
if ( !opticalCharacteristicDataCollectionEnabler.discover() )
196+
{
197+
Serial.println("No Characteristic Found. Characteristic is mandatory but not found.");
198+
Bluefruit.Central.disconnect(conn_handle);
199+
return;
200+
}
201+
Serial.println("Characteristic Found");
202+
// Found it, now write 0x01 to turn on optical data collection
203+
Serial.print("Enabling Data Collection, return value: ");
204+
Serial.println( opticalCharacteristicDataCollectionEnabler.write8( 0x01 ) );
205+
206+
// Measurement Period Characteristic. Find and adjust.
207+
Serial.print("Measurement Period Characteristic ... ");
208+
if ( !opticalCharacteristicPeriod.discover() )
209+
{
210+
Serial.println("No Characteristic Found, but not mandatory so not disconnecting");
211+
}
212+
Serial.println("Characteristic Found");
213+
// Found it, now adjust it:
214+
// Resolution 10 ms. Range 100 ms (0x0A) to 2.55 sec (0xFF). Default is 800 milliseconds (0x50).
215+
// 19 is 250
216+
Serial.print("Adjusting Measurement Period, return value: ");
217+
// Serial.println( opticalCharacteristicPeriod.write8( 0xFF ) ); // Slowest
218+
Serial.println( opticalCharacteristicPeriod.write8( 0x0A ) ); // Fastest
219+
220+
// Reaching here means we are ready to go, let's enable notification on measurement chr
221+
Serial.print("Enabling Notify on the Characteristic ... ");
222+
if ( sensorTagOpticalCharacteristic.enableNotify() )
223+
{
224+
Serial.println("enableNotify success, now ready to receive Characteristic values");
225+
}else
226+
{
227+
Serial.println("Couldn't enable notify for Characteristic. Increase DEBUG LEVEL for troubleshooting");
228+
}
229+
}
230+
231+
/**
232+
* Callback invoked when a connection is dropped
233+
* @param conn_handle
234+
* @param reason
235+
*/
236+
void disconnect_callback(uint16_t conn_handle, uint8_t reason)
237+
{
238+
(void) conn_handle;
239+
(void) reason;
240+
241+
Serial.println("Disconnected");
242+
}
243+
244+
/**
245+
* Hooked callback that triggered when a measurement value is sent from peripheral
246+
* @param chr Pointer client characteristic that even occurred,
247+
* in this example it should be sensorTagOpticalCharacteristic
248+
* @param data Pointer to received data
249+
* @param len Length of received data
250+
*/
251+
void sensortag_optical_notify_callback(BLEClientCharacteristic* chr, uint8_t* data, uint16_t len)
252+
{
253+
Serial.print("Optical data: ");
254+
uint16_t tData = (uint16_t) ( ( data[0] & 0xFF ) | ( data[1] & 0xFF ) << 8 );
255+
Serial.print( sensorOpt3001Convert( tData ) );
256+
Serial.println( " Lux" );
257+
}
258+
259+
/*
260+
* Conversion to Lux. Algorithm from the TI Sensor Tag Wiki documentation page
261+
*/
262+
float sensorOpt3001Convert(uint16_t rawData)
263+
{
264+
uint16_t e, m;
265+
266+
m = rawData & 0x0FFF;
267+
e = (rawData & 0xF000) >> 12;
268+
269+
/** e on 4 bits stored in a 16 bit unsigned => it can store 2 << (e - 1) with e < 16 */
270+
e = (e == 0) ? 1 : 2 << (e - 1);
271+
272+
return m * (0.01 * e);
273+
}
274+
275+
/* Prints a hex list to the Serial Monitor */
276+
void printHexList(uint8_t* buffer, uint8_t len)
277+
{
278+
// print forward order
279+
for(int i=0; i<len; i++)
280+
{
281+
Serial.printf("%02X-", buffer[i]);
282+
}
283+
Serial.println();
284+
}
285+
286+
void printReport( const ble_gap_evt_adv_report_t* report )
287+
{
288+
Serial.print( " rssi: " );
289+
Serial.println( report->rssi );
290+
Serial.print( " scan_rsp: " );
291+
Serial.println( report->scan_rsp );
292+
Serial.print( " type: " );
293+
Serial.println( report->type );
294+
Serial.print( " dlen: " );
295+
Serial.println( report->dlen );
296+
Serial.print( " data: " );
297+
for( int i = 0; i < report->dlen; i+= sizeof(uint8_t) )
298+
{
299+
Serial.printf( "%02X-", report->data[ i ] );
300+
}
301+
Serial.println("");
302+
}

0 commit comments

Comments
 (0)