Puck Controlling Other Puck Using NRF
In this coding sample I will show you how to code your puck to control other pucks using Bluetooth connection. In a nutshell the puck is connecting via Bluetooth LE (or to be more percise the nRF51/52 chip). During the connection (as peripheral) the Puck will get both services and characteristics (or Generic Attrivute Profile also known as GATT) depends on the peripheral, it might broadcast a name (the pucks do) or it will send a URL. Knowing this information we can start design the code.
Here is what I wanted to achieve:
- Run only with button click - I didn't want to keep connected to the other pucks. From the creator's documentation the puck will draw 200μa if stay connected. I will use setWatch on BTN for events
- Run battery level function - same function on all the pucks to indicate and visually show (by using LED1,LED2,LED3) battery level
- Retry option - Because the NRF / bluetooth might fail because of connection option, I wanted to implement retry option with in the code.
In order to achieve these 3 goals i came up with the code as follow
function showBatteryLevel() {
if(digitalRead(LED1) == 1 || digitalRead(LED2) == 1 || digitalRead(LED3) == 1) {
LED1.reset();
LED2.reset();
LED3.reset();
return;
}
let level = Puck.getBatteryPercentage(); //Turn green light
if(level>75) LED2.set(); //Turn blue light
else if(level > 40) LED3.set(); //Turn red light
else LED1.set();
}
function execute(devices, index) {
if(index < devices.length) {
console.log(devices[index]);
console.log('index:' + index);
console.log(devices[index].name);
if(devices[index].hasOwnProperty('name') && startWith(devices[index].name, 'Puck.js')) {
let gatt = null;
devices[index].gatt.connect().then(function(g) {
console.log('connect');
gatt = g;
console.log(g);
let ps = null;
try {
ps = gatt.getPrimaryService("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
console.log(ps);
return ps;
} catch(e) {
console.log('error' + e);
execute(devices,index); // in case we fail do the retry
}
}).then(function(service) {
console.log('Service');
return service.getCharacteristic("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
}).then(function(characteristic) {
console.log('characteristic');
characteristic.writeValue("showBatteryLevel()\n");
}).then(function() {
if(gatt !== null) {
gatt.disconnect();
}
console.log("Done!:" + devices[index].name);
execute(devices,index+1);
});
} else {
execute(devices,index+1);
return;
}
} else {
console.log('Done!');
return;
}
}
function startWith(str, substr) {
for(let index in substr) {
if(substr[index] !== str[index]) {
return false;
}
}
return true;
}
function broadcast() {
showBatteryLevel();
let devices;
NRF.findDevices(function(d) {
devices = d;
console.log('length:' + devices.length);
execute(devices,0); // execute will be a recursive function
}, 2000);
}
setWatch(function() { broadcast(); }, BTN, { repeat: true, edge: 'falling' });If you need a guide on how to start with puck check out my first Puck video In the decscription i also included links to the documentation.
You can download the javascript code
