-
-
Thx!
If you didn't have that, you could set Bangle.js to just do a read every so often to get the latest data (rather than having it 'pushed')
My "use case" (actually only proof of concept) is to run inference (using Tensorflow Lite) on the Nicla-device and push the results to Bangle, perhaps also pushing some sensor data. To save power on both devices, I'm thinking of starting the Bluetooth-connection every 5 minutes or so. This is something I haven't looked into yet how to do, using setInterval perhaps?
Anyhow, so far this use case is more of a solution searching for a problem instead of a clear requirement, so not sure yet what I'm going to do, need to brainstorm a bit :-) -
Ok, success! Not that I know why it did not work in the first place, but by getting rid of the cccd-handle altogether, I'm now able to receive data from 6 sensors to Bangle + calculating altitude from the barometer.
31.54c co2:554 IAQ:56 Hum:25 1001.64 pa Gas:34170 Alt:-0.17m
For the benefit of others, here's what I did:
On Bangle side:
Nothing, i.e. no need to handle_cccd = ...,On Arduino side:
Changed to:
BLEShortCharacteristic temperatureCharacteristic(BLE_SENSE_UUID("2001"), BLERead | BLENotify);
from:
BLEShortCharacteristic temperatureCharacteristic(BLE_SENSE_UUID("2001"), BLERead);
...and put this in the
loop
function:void loop(){ while (BLE.connected()){ static auto printTime = millis(); BHY2.update(); nicla::leds.setColor(blue); if (millis() - printTime >= 1000) { printTime = millis(); float temperatureValue = temperature.value(); temperatureCharacteristic.writeValue(temperatureValue * 100); Serial.println(temperatureValue); uint32_t co2 = bsec.co2_eq(); co2Characteristic.writeValue(co2); float airQuality = float(bsec.iaq()); bsecCharacteristic.writeValue(airQuality); float pressureValue = pressure.value(); pressureCharacteristic.writeValue((pressureValue - 800) * 100); Serial.println(pressureValue); float humidityValue = humidity.value(); humidityCharacteristic.writeValue(humidityValue); unsigned int g = gas.value(); gasCharacteristic.writeValue(g); }
-
Sorry, but I'm again a bit stuck with BLE, my issue is actually same/similar as this one, but that's 2 years old and perhaps for another device than Bangle.
As posted here, I've been able to connect and transmit data from an Arduino-device (Nicla Sense ME), but the Arduino-program crashes with an ambigous message "Out of memory" when I want to transmit data from more sensors, this even if only approx. 50% of the memory is used. As this is for me very challenging to troubleshoot, I thought I'd instead use this Arduino-code, that is transmitting to a WebBLE dashboard. The web dashboard works fine.
However, when trying to connect from Bangle, a connection is established, but I initially got
CCCD Handle not found
. The Arduino advertising code is using thisBLEFloatCharacteristic temperatureCharacteristic("19b10000-2001-537e-4f6c-d104768a1214", BLERead);
where I've from BLEProperty.h found out thatBLERead = 0x02
. Thus I tried using the same on the Bangle side:ch.handle_cccd = 0x02; return ch.startNotifications();
but I'm still not receiving any data. nRFConnect is very seldom able to connect to the Nicla-device, but the few times it has been, I've not seen anything related to this cccd-handle.
To further troubleshoot, I've tried to replace BLERead with 0x00 on the Arduino-side and use same cccd-handle on Bangle, did not help, a connection is established but no data is flowing.
I also dived in the WebBLE-dashboard JS-code to understand how that works, and on line 11 below (line 450 in the dashboard code) this same BLERead property is used. But as said, when I'm using the same concept in the Bangle-code, I'm not getting anywhere.
I've also tried many other permutations, too many to list here, but either I get "CCCD handle not found" or no data.// Set up the characteristics for (const sensor of sensors) { msg('characteristic ' + sensor + "..."); NiclaSenseME[sensor].characteristic = await service.getCharacteristic(NiclaSenseME[sensor].uuid); // Set up notification if (NiclaSenseME[sensor].properties.includes("BLENotify")) { NiclaSenseME[sensor].characteristic.addEventListener('characteristicvaluechanged', function (event) { handleIncoming(NiclaSenseME[sensor], event.target.value); }); await NiclaSenseME[sensor].characteristic.startNotifications(); } // Set up polling for read if (NiclaSenseME[sensor].properties.includes("BLERead")) { NiclaSenseME[sensor].polling = setInterval(function () { NiclaSenseME[sensor].characteristic.readValue().then(function (data) { handleIncoming(NiclaSenseME[sensor], data); }) } , 500); }
-
Yes, this works! It makes sense now when I added it and see the whole code.
Thx a lot @fanoush !
Posting the whole code here so others may benefit from itNRF.connect("F5:CB:47:42:E3:BB public").then(function(g) { gatt = g; return gatt.getPrimaryService("07e1f0e2-b68f-4f71-8bfc-19b3b0427b68"); }).then(function(service) { return service.getCharacteristic("5d75d722-fce9-471b-93e2-6c625ef6d634"); }).then(function(characteristic) { characteristic.on('characteristicvaluechanged', function(temperature) { temp = temperature.target.value.buffer; temp = (temp[1] * 256 + temp[0]) / 100; console.log("Temp: ", temp); }); return characteristic.startNotifications(); }).then(function(){ return gatt.getPrimaryService("07e1f0e2-b68f-4f71-8bfc-19b3b0427b68"); }).then(function(service) { return service.getCharacteristic("5d75d723-fce9-471b-93e2-6c625ef6d634"); }).then(function(characteristic) { characteristic.on('characteristicvaluechanged', function(co2) { co2 = co2.target.value.buffer; co2 = (co2[1] * 256 + co2[0]); console.log("co2 : ", co2); }); return characteristic.startNotifications(); }).then(function() { console.log("Done!"); }).catch(function(e) { E.showMessage(e.toString(), "ERROR"); console.log(e); });
-
-
Slight progress as I was able to chain two characteristics, but only the second one showing co2 values is doing something. The first one is supposed to show temperature, but seems it is not reached as I only see co2 values. I've read up on JS promises but haven't found out how to receive and show several values.
NRF.connect("F5:CB:47:42:E3:BB public").then(function(g) { gatt = g; return gatt.getPrimaryService("07e1f0e2-b68f-4f71-8bfc-19b3b0427b68"); }).then(function(service) { return service.getCharacteristic("5d75d722-fce9-471b-93e2-6c625ef6d634"); }).then(function(characteristic) { characteristic.on('characteristicvaluechanged', function(temperature) { temp = temperature.target.value.buffer; temp = (temp[1] * 256 + temp[0]) / 100; console.log("Temp: ", temp); }); //return characteristic.startNotifications(); return gatt.getPrimaryService("07e1f0e2-b68f-4f71-8bfc-19b3b0427b68"); }).then(function(service) { return service.getCharacteristic("5d75d723-fce9-471b-93e2-6c625ef6d634"); }).then(function(characteristic) { characteristic.on('characteristicvaluechanged', function(co2) { co2 = co2.target.value.buffer; co2 = (co2[1] * 256 + co2[0]); console.log("co2 : ", co2); }); return characteristic.startNotifications(); }).then(function() { console.log("Done!"); }).catch(function(e) { E.showMessage(e.toString(), "ERROR"); console.log(e); });
-
-
-
-
one thing that puzzles me is this line g.drawString(" Batt:" + data, 1, g.getWidth()/2); which should display Batt:nnn where nnn is the value without leading zeros. On the Bangle 2 display is though instead shown b:nnn, so instead of " Batt:" is " b:" shown (lowercase b).
No problems when using the vector font though
-
Not a problem, I learned something while searching for info about MAC-addresses.
Especially for other Bluetooth- and JS-newbies like me, below skeleton JS-code can either show the value received, or a simple graph. Just remove/add comments at the
show_data
- orgraph
-lines. And here's the Arduino-code I'm using.On the JS-side there's for sure room for improvement, one thing that puzzles me is this line
g.drawString(" Batt:" + data, 1, g.getHeigth()/2);
which should displayBatt:nnn
where nnn is the value without leading zeros. On the Bangle 2 display is though instead shownb:nnn
, so instead of " Batt:" is " b:" shown (lowercase b). The value itself is shown correctly.var gatt; var history = new Float32Array(64); g.clear(); // Load fonts require("Font7x11Numeric7Seg").add(Graphics); function graph(data) { // quickly move all elements of history back one history.set(new Float32Array(history.buffer,4)); history[history.length-1] = data; // g.clear(); // Draw Graph var r = require("graph").drawLine(g, history, { miny: 26, axes : true, gridy : 10, title: "Battery" }); // Label last reading g.setFontAlign(1,-1); g.drawString(Math.round(data), r.x+r.w, r.gety(data)+2); // Update the screen g.flip(); } function show_data(data) { var on = true; g.clear(); g.setFont("7x11Numeric7Seg",3); g.drawString(" Batt:" + data, 1, g.getHeigth()/2); } NRF.connect("MA:C-:AD:DR:ES:S! public").then(function(g) { gatt = g; return gatt.getPrimaryService(0x180F); }).then(function(service) { return service.getCharacteristic(0x2A19); }).then(function(characteristic) { characteristic.on('characteristicvaluechanged', function(event) { console.log("battery: "+JSON.stringify(event.target.value.buffer)); show_data(event.target.value.buffer); //graph(event.target.value.buffer); }); return characteristic.startNotifications(); }).then(function() { console.log("Done!"); });
-
Theoretically, it is possible to make a device with affordable means that will help, say, paralyzed people or people with injured hands.
Yes, it has been done, at least with professional/clinical EEG-devices, not sure about consumer-based devices, but haven't researched it. I'll try to improve the ML-model with more data and "better" data through some bio-feedback mechanism, and once that's done I'll see what I'll invent :-)But long before that I'll try to sneak in BJS communicating with a Arduino device through Bluetooth, AI will play a part as well.
-
Thx @Gordon!
It was a pain in the... to find out the MAC address of Wio Terminal's Bluetooth chip, but I eventually found out that manufacturers often just increase the WiFi address with 1, which indeed worked here.
Now at least I'm seeing the dummy value in the console, so at least have a starting point. -
Ok, so now I've been able to transmit a value from Wio Terminal through Arduino with this code.
Using nRF Connect I've verified that the value is updated frequently (see attached screenshot).I've tried to get my head around Bluetooth communication through this, this, and other BT-tutorials found at Espruino.com, but I'm still at loss how to connect from Bangle.js2 and read this simple value, so would appreciate any help.
I purchased 3 Pucks around 6 years ago, and if I remember correctly it was very easy to connect them together through Bluetooth, but can't find that code now. Of course the current use case is not identical, so don't know how much it would help anyway.
Edit: Can't delete an attachment (the huge picture), sorry for that
-
Thx @Gordon! Looking at this this tutorial I understand Web Bluetooth is supported. Until the device is delivered, I'll try communicating between a Wio Terminal (using Arduino) and Bangle.js2 to understand a bit more.
-
@Serj you might've seen the newest AI-related video in my YouTube channel? I try to keep you entertained :-D
Next AI project might involve a Bangle.js in case I'm able to communicate through Bluetooth with Nicla Sense ME as asked about here. I'm still a complete newbie in this area, so don't know how easy or difficult it is, but as soon as the Nicla arrives I'll start looking into it more.
-
I'm expecting to receive a Nicla Sense ME within a couple of weeks, and thought that I'd try to send data from it to Bangle.js2 through Bluetooth, probably showing some dashboard or graphs on the watch. Here's the datasheet btw.
Has anyone done something similar with any Espruino and Arduino device and be willing to share the code, especially the Arduino code?
I'm aware of the tutorials, e.g. this one, and it seems quite easy to communicate between Espruino devices, might be easy on the Arduino side as well. -
-
-
Thanks @Serj! I've added the previous video to my YouTube channel, somehow it had escaped me to do it earlier.
Your project idea sounds interesting! Moving the mouse cursor might very well work better without ML, just by using accelerometer data. I have a vague memory that someone has done something similar. Simulating mouse button(s) might be trickier without ML, so a blended approach for this might be best.
I'm next spring teaching basics in Machine Learning at university level, and this project might be something to at least partially include in the curriculum. My university purchased 10 Bangles for teaching purposes, so I could ask some students to use the watches for collecting data. In addition we have 10 Arduino ML kits + other miscellaneous hardware to use. -
You wanted more :-)
While I've not been able (or even tried) to add any Espruino device to what I've been working on, this was published yesterday. In the video
and tutorial I'm showing and explaining how to use an EEG-headset and ML (Machine Learning) to control a very simplistic Pong-game. Next related projects are already under work, so if interested, stay tuned :-) -
Thx @Gordon !
Yes, the machine learning part is completely done with Edge Impulse, and I agree, it's an impressive platform, and for many use cases the time limit of 20 minutes (for the free tier) is more than enough. You can also do inference on a mobile, e.g. with camera/images, audio, or accelerometer.
I also tried to learn Tensorflow some years back, but got stuck on too many details here and there in Python, so Edge Impulse and other platforms hiding the inner parts of the engine help bringing ML "to the crowds".
For ML nerds: Other platforms I've found are Google's Teachable Machine (browser based) and Microsoft's Lobe.Ai (client), those are a bit quicker to get started with if you are only interested in ML with images or audio. -
Ok, then I understand your train of thought!
If I would use a very old (but very reliable) IBM keyboard I would probably need more force, compared with my current not so great MS Surface Pro 4 keyboard where keys move only 1 mm or so. With my way of typing, I'm however doubting the accuracy would be much better than randomly right, of course the Bangle/Bangles would need to be very tight to reduce any slipping.
Interesting idea anyway, I'll put it behind my ear.PS Similar solutions can be found by searching for
make any surface a keyboard
, e.g.:
https://www.youtube.com/watch?v=cQqgm7PGSXA&ab_channel=Akshay
https://mashable.com/article/wearable-surface-keyboard
Partly related to this, I spent some time a couple of months ago in prototyping an app which recognizes different activities. This is using Edge Impulse and thus TensorFlow. The tutorial was now published and can be found here.
Disclaimer: While the app works pretty well for me, it's still only a prototype and the code is partly a mess. I tried to use ChatGPT to clean it up, but I got in an endless loop of it breaking existing functionality, and run out of time.