Adding IMU and BLE Libraries
MCU needs to provide posture position inference. I've decided to use BLE due to low power consumption. Arduino provides a ready to use BLE library, which supports Arduino Nano 33 IoT radio.
My project requires to calculate position of the device from built-in accelerometer. Arduino provides a ready to use library for LSM6D53.
Both libraries come with easy to use examples.
Adding IMU and BLE Libraries
Edge Impulse support Arduino Nano 33 BLE and provides examples of using it with BLE and IMU. So I've decided to use this example to accelerate development instead of improving my previous Arduino sketch. I've imported Edge Impulse Arduino Nano 33 BLE accelerometer example.
I've modified code to include LSM6D53 header instead one that comes with the example. As well I've applied the same modifications to the code as I've dome in my previous sketch.
Transitioning from phone to Arduino IMU
I've build and deployed my new code. Than I've started testing and my test results where wrong. I've realized that the phone and its accelerometer orientation during the data collection is not necessary the same as during my testing with MCU.
After some exploration I've adjusted the code to account for this difference. In the line 1 I've changed the order of first two parameters and in line 4 I've added minus sign.
IMU.readAcceleration(buffer[ix + 1], buffer[ix], buffer[ix + 2]); buffer[ix + 0] *= CONVERT_G_TO_MS2; buffer[ix + 1] *= CONVERT_G_TO_MS2; buffer[ix + 2] *= -CONVERT_G_TO_MS2;
After this modification my tests start generating correct results.
Publishing data over BLE
I've created my custom BLE posture service and characteristic. So the posture state can be read by a phone.
// Custom BLE Posture Service BLEService postureService("b7469627-3ad1-4b96-8684-14d6cb73014a"); // Custom BLE Posture Position Characteristic BLEUnsignedCharCharacteristic postureChar("b7469627-3ad1-4b96-8684-14d6cb73014a", // custom 128-bit characteristic UUID BLERead | BLENotify); // remote clients will be able to get notifications if this characteristic changes
And I've initialized BLE in the setup() function:
// Set advertised local name and services UUID BLE.setDeviceName("Arduino Nano 33 IoT"); BLE.setLocalName("Trakcore"); BLE.setAdvertisedService(postureService); // add the service UUID postureService.addCharacteristic(postureChar); // add the posture position characteristic BLE.addService(postureService); // Add the posture service postureChar.writeValue(oldPosture); // set initial value for this characteristic /* Start advertising BLE. It will start continuously transmitting BLE advertising packets and will be visible to remote BLE central devices until it receives a new connection */ // start advertising BLE.advertise();
And than I've modified the loop() function to publish posture readings:
void loop() { // wait for a BLE central BLEDevice central = BLE.central(); // if a central is connected to the peripheral: if (central) { Serial.print("Connected to central: "); // print the central's BT address: Serial.println(central.address()); // check the position every 2000ms // while the central is connected: while (central.connected()) { updatePosture(); Serial.print("Disconnected from central: "); Serial.println(central.address()); ei_printf("\nStarting inferencing in 2 seconds...\n"); delay(2000); } } }
I'm only publishing posture data (line 2) when it changes. As well I've added LED indication as it simpler to find out test results.
if (posture != oldPosture) { // if the posture has changed postureChar.writeValue(posture); // and update the battery level characteristic if (posture == EI_STRAIGHT) digitalWrite(LED_BUILTIN, LOW); else digitalWrite(LED_BUILTIN, HIGH); oldPosture = posture; // save the level for next comparison }
Testing BLE functionality on the phone
I've installed nRF Connect for mobile from Nordic on my phone. I've started it and was able to see my device as Trakcore on the scanner screen.
I've select my device and on the client screen I've expanded my custom service.
Now I was able to select my custom characteristic of the posture service.
And I was able to read the posture state as a value (0-curved, 1-straight) of my characteristic:
Summary and next steps
I'm quite happy with the development progress. The next step for me is to build an app which will read data from MCU and will raise alerts if posture is curved.
Thank you for reading my project blog post!
References
https://www.element14.com/community/docs/DOC-95660/l/the-learning-circuit-79-how-accelerometers-work
https://www.arduino.cc/en/Reference/ArduinoBLE
https://www.bluetooth.com/specifications/assigned-numbers/
https://www.novelbits.io/uuid-for-custom-services-and-characteristics/