SparkFun NanoBeacon Board - IN100 Hookup Guide
BMA400 Qwiic Example
Now that we know the IN100 is working and advertising, let's use a custom config file to send acceleration data from the SparkFun Triple Axis Accelerometer Breakout - BMA400 (Qwiic) to a RedBoard IoT running code to convert the values into a serial printout.
Required Libraries & Board Tools
This example assumes the use of the SparkFun IoT RedBoard board file as well as several libraries that do not come pre-installed with Arduino. Make sure to install both the board files and libraries prior to using this example. The SparkFun IoT RedBoard uses the ESP32 Dev Module board definition included in the "esp32" boards package. For detailed information on installing and using the IoT RedBoard, check out this section of our Hookup Guide for the board. Install the libraries used in this example with the Arduino Library Manager tool by searching for "ESP32 BLE Arduino".
Qwiic BMA400 Config File
With the board files and libraries installed we can move on to loading the Qwiic BMA400 config file from the Examples folder in the GitHub repository. This also contains the Arduino code so go ahead and download both (or the whole repository).
This config file contains all of the I2C commands as well as custom advertising data settings to name the NanoBeacon "BMA400_Data" and have it send voltage and I2C data. You can modify this if necessary but for a quick personal test, these settings should be just fine. You can view the I2C commands in the "I2C" window as shown below:
After loading the config file and adjusting anything you see fit, click the "Burn/Program" button. Reminder, this is a one-time use button and there is no confirmation prompt. Any settings here are saved permanently to the IN100 so if you do change anything here, make sure it works before clicking this button.
Arduino Code
With just the config file loaded on the NanoBeacon, you can open up a scanner app and watch the acceleration data print out in hex but that isn't very human-readable. To convert this hex data to a serial print, we wrote a quick Arduino sketch that connects to a NanoBeacon board running the config file we just uploaded and then parses the hex data into a serial print to easily ready acceleration data from all three of the BMA400's axes.
Open the sketch file or copy the code below into a blank Arduino sketch. Select your board (in our case "ESP32 Dev Module") and Port and click the upload button.
language:c
#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>
#include <BLEEddystoneURL.h>
#include <BLEEddystoneTLM.h>
#include <BLEBeacon.h>
int scanTime = 1;
BLEScan *pBLEScan;
// This class is used for the onResult() callback function
class MyAdvertisedDeviceCallbacks : public BLEAdvertisedDeviceCallbacks
{
// This function is called each time a new BLE device is found during a scan
void onResult(BLEAdvertisedDevice advertisedDevice)
{
// Some BLE devices don't have names, so we'll ignore the ones that don't
if (advertisedDevice.haveName())
{
// Check if the name of this device matches our beacon
const char* deviceName = advertisedDevice.getName().c_str();
if(strncmp(deviceName, "BMA400_Data", strlen(deviceName)) == 0)
{
// This is our beacon! Print out the received signal strength
Serial.printf("RSSI: %i\n", advertisedDevice.getRSSI());
// Copy the manufacturer data into a buffer
uint8_t manufacturerData[32];
std::string manufacturerDataString = advertisedDevice.getManufacturerData();
manufacturerDataString.copy((char*) manufacturerData, manufacturerDataString.length(), 0);
// The first 2 bytes are the manufaturer ID, print those out
uint16_t manufacturerID = (manufacturerData[0] << 8 ) | manufacturerData[1];
Serial.printf("Manufacturer ID: %04X\n", manufacturerID);
// The next byte is the battery voltage, units are 31.25mV/LSB
uint16_t voltageRaw = manufacturerData[2];
float voltage = voltageRaw * 0.03125;
Serial.printf("Voltage: %.2f\n", voltage);
// Last 6 bytes are the raw acceleration data for the x/y/z axes, as specified in the BMA400 datasheet
int16_t xRaw = ((uint16_t) manufacturerData[4] << 8) | manufacturerData[3];
int16_t yRaw = ((uint16_t) manufacturerData[6] << 8) | manufacturerData[5];
int16_t zRaw = ((uint16_t) manufacturerData[8] << 8) | manufacturerData[7];
// The raw values are 12-bit signed values, so we need to make sure negative values are correctly signed
if(xRaw > 2047) xRaw -= 4096;
if(yRaw > 2047) yRaw -= 4096;
if(zRaw > 2047) zRaw -= 4096;
// Convert the raw values to acceleration in g's
// BMA400 defaults to +/- 4g over the whole 12-bit range
float xAcc = xRaw * 4.0 / pow(2, 11);
float yAcc = yRaw * 4.0 / pow(2, 11);
float zAcc = zRaw * 4.0 / pow(2, 11);
// Now print out the x/y/z acceleration values
Serial.printf("X: %.2f Y: %.2f Z: %.2f\n\n", xAcc, yAcc, zAcc);
// Now that we've found our beacon and logged everything, we can stop the scan
pBLEScan->stop();
}
}
}
};
void setup()
{
// Set up serial
Serial.begin(115200);
Serial.println("BLE scan sketch begin!");
// Create new BLE scan object
BLEDevice::init("");
pBLEScan = BLEDevice::getScan();
// Set callback for when new devices are found in the scan
pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
// Enable active scanning. It uses more power, but is faster
pBLEScan->setActiveScan(true);
// Set the scan interval and window in milliseconds
pBLEScan->setInterval(100);
pBLEScan->setWindow(99);
}
void loop()
{
// Start new scan. This blocks until finished
BLEScanResults foundDevices = pBLEScan->start(scanTime, false);
// Scan finished, delete results to release memory
pBLEScan->clearResults();
}
After uploading, open the serial monitor with the baud set to 115200. The code will start to scan for the matching NanoBeacon device (BMA400_Data) and when it succeeds, prints out the data sent by the beacon including Manufacturer ID, voltage measured on Vcc and the acceleration data of the x/y/z axes.
Additional Config Tests
For those who want to go beyond this example or prefer to send I2C data from different devices, InPlay has a growing list of other config tests for other sensors, like the BME280 atmospheric sensor, available from the GitHub repository below: