The Intel Curie based Arduino/Genuino 101 is a BLE capable board that has an impressive set of features. It has a built in IMU, a great Arduino library for interacting with Bluetooth Low Energy, loads of memory and power. Also it costs the same as a standard Arduino. Note these examples will also work with the yet to be released TinyTile. Which is essentially a small version of the Arduino 101.
NodeJS is a super rad language that lets you write server-side javascript. Which basically means you have some host machine run the code but its also cross platform. So the code here can even run on an Intel Edison or a Raspberry Pi. Think small computer controls dozens of bluetooth devices. #SwarmThePlanet
Prerequisites- Install NodeJS https://docs.npmjs.com/getting-started/installing-node
- Satisfy the pre-reqs here for bluetooth https://github.com/sandeepmistry/noble
- Install the latest Arduino IDE and add the board type https://www.arduino.cc/en/Guide/Arduino101#toc2
- Get your board plugged in!
- Pull down the example repo. https://github.com/virgilvox/curie-ble-example-js
- Inside /arduino_sketches you'll find the sketch that corresponds to each node example. Lets start with the simplest example, sensorNotify.ino
- Open the Arduino IDE, select the Arduino101 from boards
- Copy the sketch from step 2 into the IDE and upload it to the board.
1. Open up a terminal and navigate to the directory for the examples
cd <whatever-your-path-is>/curie-ble-example-js
2. Install the node.js dependancies
npm install
3. Enable bluetooth, then run the script corresponding to the firmware
node sensorNotify
Cool! In the console you should see some values spit out.
This example reads an analog pin and writes the value to a characteristic that can then be read by the node script.
Try out the other examples if you like, the rest of this guide covers whats going on in the code.
Deep-DiveBLE & Arduino LibraryBluetooth low energy has a very specific protocol that lets devices broadcast services and characteristics so that its easy to integrate and connect them with any device. These services and characteristics are typically UUIDs, randomly unique identifiers. The node example essentially scans to find a UUID of a device, connects to it and then works to discover its characteristics.
The Arduino sketch defines what those services/characteristics are and then at an interval writes a value that can be read to its characteristic.
In the sensorNotify example our devices has this structure.
- Service: 19B10000-E8F2-537E-4F6C-D104768A1216
- Characteristic: 5667f3b1-d6a2-4fb2-a917-4bee580a9c84
Which we define after loading in the library. Note we define that "BLERead | BLENotify" are allowed on that characteristic. Meaning the value can be read and changes subscribed to.
#include <CurieBLE.h>
BLEPeripheral blePeripheral;
BLEService customService("19B10000-E8F2-537E-4F6C-D104768A1216");
BLEUnsignedCharCharacteristic sensorCharacteristic("5667f3b1-d6a2-4fb2-a917-4bee580a9c84", BLERead | BLENotify);
Then in our setup we define a name for our new BLE device:
void setup() {
Serial.begin(9600);
blePeripheral.setLocalName("Curie");
blePeripheral.setAdvertisedServiceUuid(customService.uuid());
blePeripheral.addAttribute(customService);
blePeripheral.addAttribute(sensorCharacteristic);
sensorCharacteristic.setValue(0);
blePeripheral.begin();
}
In our loop we wait for someone to connect and then start writing a value to our characteristic:
void loop() {
BLECentral central = blePeripheral.central();
if (central) {
Serial.print("Connected to central: ");
Serial.println(central.address());
while (central.connected()) {
int sensorValue = analogRead(0);
sensorCharacteristic.setValue(sensorValue);
}
}
}
NodeJS - Noble BLE libraryWe first load in the library and define what we're searching for.
var noble = require('noble');
// Search only for the Service UUID of the device (remove dashes)
var serviceUuids = ['19B10000E8F2537E4F6CD104768A1216'];
// Search only for sensor charateristic
var characteristicUuids = ['5667f3b1d6a24fb2a9174bee580a9c84'];
Start scanning when bluetooth is ready:
// start scanning when bluetooth is powered on
noble.on('stateChange', function(state) {
if (state === 'poweredOn') {
noble.startScanning(serviceUuids);
} else {
noble.stopScanning();
}
});
We search for the device, discover its services, then the characteristics on that service:
// Search for BLE peripherals
noble.on('discover', function(peripheral) {
peripheral.connect(function(error) {
console.log('connected to peripheral: ' + peripheral.uuid);
// Only discover the service we specified above
peripheral.discoverServices(serviceUuids, function(error, services) {
var service = services[0];
console.log('discovered service');
service.discoverCharacteristics(characteristicUuids, function(error, characteristics) {
console.log('discovered characteristics');
......
...
What we get back is an array of characteristic javascript objects. In this case we pull out first and only one and then subscribe to it, which tells the board to notify us of changes and then we create an event handler for that data change.
// Assign Characteristic
var sensorCharacteristic = characteristics[0];
sensorCharacteristic.subscribe(function(error) {
if(error) console.log(error);
});
// Handle data events for characteristic
sensorCharacteristic.on('data', function(data, isNotification) {
console.log('Sensor Value', data.readUInt8(0))
});
});
});
});
});
Writing to a characteristicAt this point you should have a decent grasp on how this all works. The best way to figure out how to do this is the led example sketch and node script.
Happy Hacking!
BONUS TIPCheck out my example for using the curie with Web bluetooth. Thats right! Browsers now have access to bluetooth.
https://github.com/virgilvox/curie-web-ble
Add some IoT with the Octoblu Meshblu nodeJs library using my other guide!
https://www.hackster.io/virgilvox/meshblu-getting-iot-devices-to-talk-2f7c90
Comments
Please log in or sign up to comment.