diff --git a/examples/Example_01_BasicReadings/Example_01_BasicReadings.ino b/examples/Example_01_BasicReadings/Example_01_BasicReadings.ino index c9d7214..9d8daa3 100644 --- a/examples/Example_01_BasicReadings/Example_01_BasicReadings.ino +++ b/examples/Example_01_BasicReadings/Example_01_BasicReadings.ino @@ -10,7 +10,7 @@ SparkFun Electronics Date: September, 2024 SparkFun code, firmware, and software is released under the MIT License. - Please see LICENSE.md for further details. + Please see LICENSE.md for further details. Hardware Connections: IoT RedBoard --> BMV080 @@ -21,22 +21,30 @@ Serial.print it out at 115200 baud to serial monitor. Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/????? + https://www.sparkfun.com/products/26554 */ -#include #include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 +#include -Bmv080 bmv080; // Create an instance of the BMV080 class +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class #define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 -i2c_device_t i2c_device = {}; // I2C device struct instance for Bosch API +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif void setup() { Serial.begin(115200); - while(!Serial) delay(10); // Wait for Serial to become available. + while (!Serial) + delay(10); // Wait for Serial to become available. // Necessary for boards with native USB (like the SAMD51 Thing+). // For a final version of a project that does not need serial debug (or a USB cable plugged in), // Comment out this while loop, or it will prevent the remaining code from running. @@ -44,25 +52,24 @@ void setup() Serial.println(); Serial.println("BMV080 Example 1 - Basic Readings"); - Wire.begin(); + wirePort.begin(); - if (bmv080.begin(BMV080_ADDR, Wire) == false) { - Serial.println("BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); + if (bmv080.begin(BMV080_ADDR, wirePort) == false) + { + Serial.println( + "BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); while (1) - ; + ; } Serial.println("BMV080 found!"); - // Wire.setClock(400000); //Increase I2C data rate to 400kHz - - /* Communication interface initialization */ - i2c_init(&i2c_device); + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz /* Initialize the Sensor (read driver, open, reset, id etc.)*/ - bmv080.init(&i2c_device); + bmv080.init(); /* Set the sensor mode to continuous mode */ - if(bmv080.setMode(SFE_BMV080_MODE_CONTINUOUS) == true) + if (bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) { Serial.println("BMV080 set to continuous mode"); } @@ -74,13 +81,22 @@ void setup() void loop() { - if(bmv080.dataAvailable()) + if (bmv080.readSensor()) { - float pm25 = bmv080.getPM25(); - + float pm10 = bmv080.PM10(); + float pm25 = bmv080.PM25(); + float pm1 = bmv080.PM1(); + + Serial.print("PM10: "); + Serial.print(pm10); + Serial.print("\t"); + Serial.print("PM2.5: "); Serial.print(pm25); + Serial.print("\t"); + Serial.print("PM1: "); + Serial.print(pm1); - if(bmv080.getIsObstructed() == true) + if (bmv080.isObstructed() == true) { Serial.print("\tObstructed"); } diff --git a/examples/Example_02_DutyCycle/Example_02_DutyCycle.ino b/examples/Example_02_DutyCycle/Example_02_DutyCycle.ino index 2cc2623..2128fbf 100644 --- a/examples/Example_02_DutyCycle/Example_02_DutyCycle.ino +++ b/examples/Example_02_DutyCycle/Example_02_DutyCycle.ino @@ -21,16 +21,23 @@ Serial.print it out at 115200 baud to serial monitor. Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/????? + https://www.sparkfun.com/products/26554 */ #include #include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 -Bmv080 bmv080; // Create an instance of the BMV080 class +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class #define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 -i2c_device_t i2c_device = {}; // I2C device struct instance for Bosch API +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif void setup() { @@ -44,22 +51,19 @@ void setup() Serial.println(); Serial.println("BMV080 Example 2 - Duty Cycle"); - Wire.begin(); + wirePort.begin(); - if (bmv080.begin(BMV080_ADDR, Wire) == false) { + if (bmv080.begin(BMV080_ADDR, wirePort) == false) { Serial.println("BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); while (1) ; } Serial.println("BMV080 found!"); - // Wire.setClock(400000); //Increase I2C data rate to 400kHz - - /* Communication interface initialization */ - i2c_init(&i2c_device); + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz /* Initialize the Sensor (read driver, open, reset, id etc.)*/ - bmv080.init(&i2c_device); + bmv080.init(); /* Set the sensor Duty Cycling Period (seconds)*/ uint16_t duty_cycling_period = 20; @@ -73,7 +77,7 @@ void setup() } /* Set the sensor mode to Duty Cycle mode */ - if(bmv080.setMode(SFE_BMV080_MODE_DUTY_CYCLE) == true) + if(bmv080.setMode(SF_BMV080_MODE_DUTY_CYCLE) == true) { Serial.println("BMV080 set to Duty Cycle mode"); } @@ -85,13 +89,13 @@ void setup() void loop() { - if(bmv080.dataAvailable()) + if(bmv080.readSensor()) { - float pm25 = bmv080.getPM25(); + float pm25 = bmv080.PM25(); Serial.print(pm25); - if(bmv080.getIsObstructed() == true) + if(bmv080.isObstructed() == true) { Serial.print("\tObstructed"); } diff --git a/examples/Example_03_Interrupt/Example_03_Interrupt.ino b/examples/Example_03_Interrupt/Example_03_Interrupt.ino index 26281df..3e62d70 100644 --- a/examples/Example_03_Interrupt/Example_03_Interrupt.ino +++ b/examples/Example_03_Interrupt/Example_03_Interrupt.ino @@ -25,20 +25,27 @@ Serial.print it out at 115200 baud to serial monitor. Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/????? + https://www.sparkfun.com/products/26554 */ #include #include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 -Bmv080 bmv080; // Create an instance of the BMV080 class +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class #define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 #define IRQ_Pin 14 -i2c_device_t i2c_device = {}; // I2C device struct instance for Bosch API - bool int_flag = false; +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif + void setup() { Serial.begin(115200); @@ -51,27 +58,24 @@ void setup() Serial.println(); Serial.println("BMV080 Example 3 - Interrupt"); - Wire.begin(); + wirePort.begin(); - if (bmv080.begin(BMV080_ADDR, Wire) == false) { + if (bmv080.begin(BMV080_ADDR, wirePort) == false) { Serial.println("BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); while (1) ; } Serial.println("BMV080 found!"); - // Wire.setClock(400000); //Increase I2C data rate to 400kHz - - /* Communication interface initialization */ - i2c_init(&i2c_device); + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz /* Initialize the Sensor (read driver, open, reset, id etc.)*/ - bmv080.init(&i2c_device); + bmv080.init(); /* Set the sensor mode to continuous mode */ // The hardware interrupt of the BMV080 sensor unit cannot be used as trigger // in duty cycling mode. - if(bmv080.setMode(SFE_BMV080_MODE_CONTINUOUS) == true) + if(bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) { Serial.println("BMV080 set to continuous mode"); } @@ -91,11 +95,11 @@ void loop() int_flag = false; // Reset the flag do{ Serial.println("Reading BMV080"); - if(bmv080.dataAvailable()) + if(bmv080.readSensor()) { - float pm25 = bmv080.getPM25(); + float pm25 = bmv080.PM25(); Serial.print(pm25); - if(bmv080.getIsObstructed() == true) + if(bmv080.isObstructed() == true) { Serial.print("\tObstructed"); } diff --git a/examples/Example_04_SPI/Example_04_SPI.ino b/examples/Example_04_SPI/Example_04_SPI.ino index 10fc214..41673a3 100644 --- a/examples/Example_04_SPI/Example_04_SPI.ino +++ b/examples/Example_04_SPI/Example_04_SPI.ino @@ -29,15 +29,14 @@ Serial.print it out at 115200 baud to serial monitor. Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/????? + https://www.sparkfun.com/products/26554 */ #include #include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 -Bmv080 bmv080; // Create an instance of the BMV080 class - -spi_device_t spi_device = {}; // SPI device struct instance for Bosch API +SparkFunBMV080SPI bmv080; // Create an instance of the BMV080 class +#define CS_PIN 5 // Define the chip select pin void setup() { @@ -48,21 +47,28 @@ void setup() // For a final version of a project that does not need serial debug (or a USB cable plugged in), // Comment out this while loop, or it will prevent the remaining code from running. + pinMode(CS_PIN, OUTPUT); + pinMode(MOSI, OUTPUT); + pinMode(SCK, OUTPUT); + pinMode(MISO, INPUT); + digitalWrite(CS_PIN, HIGH); + Serial.println(); Serial.println("BMV080 Example 4 - SPI"); - /* Communication interface initialization */ - spi_init(&spi_device); - - if (bmv080.initSPI(&spi_device) == false) { + if (bmv080.begin(CS_PIN, SPI) == false) { Serial.println("SPI init failure. Check your jumpers and the hookup guide. Freezing..."); while (1) ; } Serial.println("BMV080 SPI init successful"); + + /* Initialize the Sensor (read driver, open, reset, id etc.)*/ + bmv080.init(); + /* Set the sensor mode to continuous mode */ - if(bmv080.setMode(SFE_BMV080_MODE_CONTINUOUS) == true) + if(bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) { Serial.println("BMV080 set to continuous mode"); } @@ -74,13 +80,13 @@ void setup() void loop() { - if(bmv080.dataAvailable()) + if(bmv080.readSensor()) { - float pm25 = bmv080.getPM25(); + float pm25 = bmv080.PM25(); Serial.print(pm25); - if(bmv080.getIsObstructed() == true) + if(bmv080.isObstructed() == true) { Serial.print("\tObstructed"); } diff --git a/examples/Example_05_Parameters/Example_05_Parameters.ino b/examples/Example_05_Parameters/Example_05_Parameters.ino index 6078de3..34cf918 100644 --- a/examples/Example_05_Parameters/Example_05_Parameters.ino +++ b/examples/Example_05_Parameters/Example_05_Parameters.ino @@ -9,6 +9,7 @@ distribution_id do_obstruction_detection do_vibration_filtering + measurement_algorithm After these parameters are read and set, This example shows how to use the sensor in "continuous mode" to get particulate matter readings once every @@ -31,16 +32,23 @@ Serial.print it out at 115200 baud to serial monitor. Feel like supporting our work? Buy a board from SparkFun! - https://www.sparkfun.com/products/????? + https://www.sparkfun.com/products/26554 */ #include #include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 -Bmv080 bmv080; // Create an instance of the BMV080 class +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class #define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 -i2c_device_t i2c_device = {}; // I2C device struct instance for Bosch API +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif void setup() { @@ -54,27 +62,24 @@ void setup() Serial.println(); Serial.println("BMV080 Example 5 - Get and Set Parameters"); - Wire.begin(); + wirePort.begin(); - if (bmv080.begin(BMV080_ADDR, Wire) == false) { + if (bmv080.begin(BMV080_ADDR, wirePort) == false) { Serial.println("BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); while (1) ; } Serial.println("BMV080 found!"); - // Wire.setClock(400000); //Increase I2C data rate to 400kHz - - /* Communication interface initialization */ - i2c_init(&i2c_device); + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz /* Initialize the Sensor (read driver, open, reset, id etc.)*/ - bmv080.init(&i2c_device); + bmv080.init(); getSetParameters(); // Get and set parameters /* Set the sensor mode to continuous mode */ - if(bmv080.setMode(SFE_BMV080_MODE_CONTINUOUS) == true) + if(bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) { Serial.println("BMV080 set to continuous mode"); } @@ -86,13 +91,22 @@ void setup() void loop() { - if(bmv080.dataAvailable()) + if(bmv080.readSensor()) { - float pm25 = bmv080.getPM25(); - + float pm10 = bmv080.PM10(); + float pm25 = bmv080.PM25(); + float pm1 = bmv080.PM1(); + + Serial.print("PM10: "); + Serial.print(pm10); + Serial.print("\t"); + Serial.print("PM2.5: "); Serial.print(pm25); + Serial.print("\t"); + Serial.print("PM1: "); + Serial.print(pm1); - if(bmv080.getIsObstructed() == true) + if (bmv080.isObstructed() == true) { Serial.print("\tObstructed"); } @@ -113,6 +127,7 @@ void getSetParameters(void) uint32_t distribution_id = 0; bool do_obstruction_detection = false; bool do_vibration_filtering = false; + uint8_t measurementAlgorithm = E_BMV080_MEASUREMENT_ALGORITHM_BALANCED; /*************************************************************************** * @@ -122,22 +137,22 @@ void getSetParameters(void) /* Get default parameter "volumetric_mass_density" */ - volumetric_mass_density = bmv080.getVolumetricMassDensity(); + volumetric_mass_density = bmv080.volumetricMassDensity(); Serial.print("BMV080 parameter 'volumetric_mass_density' READ: "); Serial.println(volumetric_mass_density); /* Get default parameter "integration_time" */ - integration_time = bmv080.getIntegrationTime(); + integration_time = bmv080.integrationTime(); Serial.print("BMV080 parameter 'integration_time' READ: "); Serial.println(integration_time); /* Get default parameter "distribution_id" */ - distribution_id = bmv080.getDistributionId(); + distribution_id = bmv080.distributionId(); Serial.print("BMV080 parameter 'distribution_id' READ: "); Serial.println(distribution_id); /* Get default parameter "do_obstruction_detection" */ - do_obstruction_detection = bmv080.getDoObstructionDetection(); + do_obstruction_detection = bmv080.doObstructionDetection(); Serial.print("BMV080 parameter 'do_obstruction_detection' READ: "); if(do_obstruction_detection == true) { @@ -149,7 +164,7 @@ void getSetParameters(void) } /* Get default parameter "do_vibration_filtering" */ - do_vibration_filtering = bmv080.getDoVibrationFiltering(); + do_vibration_filtering = bmv080.doVibrationFiltering(); Serial.print("BMV080 parameter 'do_vibration_filtering' READ: "); if(do_vibration_filtering == true) { @@ -160,6 +175,25 @@ void getSetParameters(void) Serial.println("false"); } + /* Get default parameter "measurement_algorithm" */ + measurementAlgorithm = bmv080.measurementAlgorithm(); + Serial.print("BMV080 parameter 'measurement_algorithm' READ: "); + switch (measurementAlgorithm) + { + case E_BMV080_MEASUREMENT_ALGORITHM_FAST_RESPONSE: + Serial.println("Fast Response"); + break; + case E_BMV080_MEASUREMENT_ALGORITHM_BALANCED: + Serial.println("Balanced"); + break; + case E_BMV080_MEASUREMENT_ALGORITHM_HIGH_PRECISION: + Serial.println("High Precision"); + break; + default: + Serial.println("Unknown"); + break; + } + /*************************************************************************** * @@ -174,6 +208,7 @@ void getSetParameters(void) // distribution_id = 3; // do_obstruction_detection = true; // do_vibration_filtering = false; + // measurementAlgorithm = E_BMV080_MEASUREMENT_ALGORITHM_BALANCED; /* Set custom parameter "volumetric_mass_density" */ if(bmv080.setVolumetricMassDensity(volumetric_mass_density) == true) @@ -244,5 +279,30 @@ void getSetParameters(void) Serial.println("Error setting BMV080 parameter 'do_vibration_filtering'"); } + /* Set custom parameter "measurement_algorithm" */ + if(bmv080.setMeasurementAlgorithm(measurementAlgorithm) == true) + { + Serial.print("BMV080 parameter 'measurement_algorithm' SET TO: "); + switch (measurementAlgorithm) + { + case E_BMV080_MEASUREMENT_ALGORITHM_FAST_RESPONSE: + Serial.println("Fast Response"); + break; + case E_BMV080_MEASUREMENT_ALGORITHM_BALANCED: + Serial.println("Balanced"); + break; + case E_BMV080_MEASUREMENT_ALGORITHM_HIGH_PRECISION: + Serial.println("High Precision"); + break; + default: + Serial.println("Unknown"); + break; + } + } + else + { + Serial.println("Error setting BMV080 parameter 'measurement_algorithm'"); + } + Serial.println(); } \ No newline at end of file diff --git a/examples/Example_06_TwoSensors/Example_06_TwoSensors.ino b/examples/Example_06_TwoSensors/Example_06_TwoSensors.ino new file mode 100644 index 0000000..b3966b1 --- /dev/null +++ b/examples/Example_06_TwoSensors/Example_06_TwoSensors.ino @@ -0,0 +1,173 @@ +/* + Using the BMV080 Particulate Matter PM2.5 Sensor + + This example shows how to use two BMV080 sensors on the same I2C bus. + + One sensor must have its AB0 Jumper changed to "0". + + The sensors will be in "continuous mode" to get + particulate matter readings once every second. + + It uses polling of the devices to check if new data is available. + + By: Pete Lewis + SparkFun Electronics + Date: September, 2024 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + Hardware Connections: + IoT RedBoard --> BMV080 + QWIIC --> QWIIC + + BMV080 "mode" jumper set to I2C (default) + + Serial.print it out at 115200 baud to serial monitor. + + Open a plotter to see the PM2.5 values from both sensors. + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/26554 +*/ + +#include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 +#include + +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class +#define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 + +SparkFunBMV080 bmv080_2; // Create an instance of the BMV080 class +#define BMV080_ADDR2 0x56 // AB0 Jumper set to 0 + +bool newDataAvailable = false; // Flag to indicate new data is available +bool newDataAvailable2 = false; // Flag to indicate new data is available + +float pm25 = 0.0; // Variable to store PM2.5 value +float pm25_2 = 0.0; // Variable to store PM2.5 value + +bool isObstructed = false; // Flag to indicate sensor is obstructed +bool isObstructed2 = false; // Flag to indicate sensor is obstructed + +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif + +void setup() +{ + Serial.begin(115200); + + while (!Serial) + delay(10); // Wait for Serial to become available. + // Necessary for boards with native USB (like the SAMD51 Thing+). + // For a final version of a project that does not need serial debug (or a USB cable plugged in), + // Comment out this while loop, or it will prevent the remaining code from running. + + Serial.println(); + Serial.println("BMV080 Example 6 - Two Sensors"); + + wirePort.begin(); + + if (bmv080.begin(BMV080_ADDR, wirePort) == false) + { + Serial.println( + "BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); + while (1) + ; + } + Serial.println("BMV080 at 0x57 found!"); + + if (bmv080_2.begin(BMV080_ADDR2, wirePort) == false) + { + Serial.println( + "BMV080 not detected at 0x56 I2C address. Check your jumpers and the hookup guide. Freezing..."); + while (1) + ; + } + Serial.println("BMV080 at 0x56 found!"); + + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz + + /* Initialize the Sensor (read driver, open, reset, id etc.)*/ + bmv080.init(); + + /* Set the sensor mode to continuous mode */ + if (bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) + { + Serial.println("BMV080 set to continuous mode"); + } + else + { + Serial.println("Error setting BMV080 mode"); + } + + delay(500); + + bmv080_2.init(); + + if (bmv080_2.setMode(SF_BMV080_MODE_CONTINUOUS) == true) + { + Serial.println("BMV080_2 set to continuous mode"); + } + else + { + Serial.println("Error setting BMV080_2 mode"); + } +} + +void loop() +{ + if (bmv080.readSensor()) + { + pm25 = bmv080.PM25(); + isObstructed = bmv080.isObstructed(); + newDataAvailable = true; + //Serial.println("Sensor 1 data available"); + } + delay(200); // needs a ~200ms delay in between talking to each sensor + + if (bmv080_2.readSensor()) + { + pm25_2 = bmv080_2.PM25(); + isObstructed2 = bmv080_2.isObstructed(); + newDataAvailable2 = true; + //Serial.println("Sensor 2 data available"); + } + + delay(200); // needs a ~200ms delay in between talking to each sensor + + if (newDataAvailable && newDataAvailable2) + { + //Serial.print("Sensor 1: "); + + Serial.print(pm25); + + if (isObstructed == true) + { + Serial.print(-1); + } + + //Serial.print("\tSensor 2: "); + + Serial.print(","); + + Serial.print(pm25_2); + + if (isObstructed2 == true) + { + Serial.print("-1"); + } + + Serial.println(); + + // reset variables + newDataAvailable = false; + newDataAvailable2 = false; + isObstructed = false; + isObstructed2 = false; + } +} diff --git a/examples/Example_07_Demo_Alphanumeric/Example_07_Demo_Alphanumeric.ino b/examples/Example_07_Demo_Alphanumeric/Example_07_Demo_Alphanumeric.ino new file mode 100644 index 0000000..21b0f1f --- /dev/null +++ b/examples/Example_07_Demo_Alphanumeric/Example_07_Demo_Alphanumeric.ino @@ -0,0 +1,119 @@ +/* + Using the BMV080 Particulate Matter PM2.5 Sensor + + This example shows how display the Pm2.5 readings on a SparkFun Qwiic + Alphanumeric display. + + It uses the sensor in "continuous mode" to get + particulate matter readings once every second. + + It uses polling of the device to check if new data is available. + + By: Pete Lewis + SparkFun Electronics + Date: September, 2024 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + Hardware Connections: + IoT RedBoard --> BMV080 + QWIIC --> QWIIC + + BMV080 "mode" jumper set to I2C (default) + + Serial.print it out at 115200 baud to serial monitor. + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/26554 +*/ + +#include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 +#include + +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class +#define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 + +#include //Click here to get the library: http://librarymanager/All#SparkFun_Qwiic_Alphanumeric_Display by SparkFun +HT16K33 display; +#define DISPLAY_ADDRESS 0x70 // Default I2C address when A0, A1 are floating + +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif + +void setup() +{ + Serial.begin(115200); + + while (!Serial) + delay(10); // Wait for Serial to become available. + // Necessary for boards with native USB (like the SAMD51 Thing+). + // For a final version of a project that does not need serial debug (or a USB cable plugged in), + // Comment out this while loop, or it will prevent the remaining code from running. + + Serial.println(); + Serial.println("BMV080 Example 7 - Alphanumeric Display"); + + wirePort.begin(); + + if (bmv080.begin(BMV080_ADDR, wirePort) == false) + { + Serial.println( + "BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); + while (1) + ; + } + Serial.println("BMV080 found!"); + + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz + + /* Initialize the Sensor (read driver, open, reset, id etc.)*/ + bmv080.init(); + + /* Set the sensor mode to continuous mode */ + if (bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) + { + Serial.println("BMV080 set to continuous mode"); + } + else + { + Serial.println("Error setting BMV080 mode"); + } + + if (display.begin(DISPLAY_ADDRESS, DEFAULT_NOTHING_ATTACHED, DEFAULT_NOTHING_ATTACHED, DEFAULT_NOTHING_ATTACHED, wirePort) == false) + { + Serial.println("Qwiic Alphanumeric Device did not acknowledge! Freezing."); + while (1); + } + Serial.println("Qwiic Alphanumeric Display acknowledged."); + + display.setBrightness(5); // Set brightness to 5/16 full brightness + + display.print("PM2.5"); + +} + +void loop() +{ + if (bmv080.readSensor()) + { + float pm25 = bmv080.PM25(); + + Serial.print(pm25); + display.print(int(pm25)); + + if (bmv080.isObstructed() == true) + { + Serial.print("\tObstructed"); + display.print("Obst"); + } + + Serial.println(); + } + delay(100); +} diff --git a/examples/Example_08_Demo_Oled/Example_08_Demo_Oled.ino b/examples/Example_08_Demo_Oled/Example_08_Demo_Oled.ino new file mode 100644 index 0000000..604b8d0 --- /dev/null +++ b/examples/Example_08_Demo_Oled/Example_08_Demo_Oled.ino @@ -0,0 +1,442 @@ +/* + Using the BMV080 Particulate Matter PM2.5 Sensor + + This example shows how display the PM1 and Pm2.5 readings on a SparkFun Qwiic + OLED Display, 1.3" wide. + + It uses the sensor in "continuous mode" to get + particulate matter readings once every second. + + It uses polling of the device to check if new data is available. + + By: Pete Lewis + SparkFun Electronics + Date: September, 2024 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + Hardware Connections: + IoT RedBoard --> QWIIC + QWIIC --> BMV080 + QWIIC --> QWIIC OLED Display + + BMV080 "mode" jumper set to I2C (default) + + Serial.print it out at 115200 baud to serial monitor. + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/26554 +*/ + +#define StatLedPin 13 + +// BMV080 Specifics +#include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 +#include + +SparkFunBMV080 bmv080; // Create an instance of the BMV080 class +#define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 + +float pm1Value = 0.0; // PM1 value - global so we can update it in the loop and +float pm25Value = 0.0; // PM2.5 value - global so we can update it in the loop + +// OLED Specifics +#include //http://librarymanager/All#SparkFun_Qwiic_OLED + +// The Library supports four different types of SparkFun boards. The demo uses the following +// defines to determine which device is being used. Uncomment the device being used for this demo. + +//QwiicMicroOLED myOLED; +//QwiicTransparentOLED myOLED; +//QwiicNarrowOLED myOLED; +Qwiic1in3OLED myOLED; + +#include "res/qw_bmp_sparkfun.h" + +// Fonts +#include +#include +#include +#include +#include + +// An array of fonts to loop over +QwiicFont *demoFonts[] = { + &QW_FONT_5X7, + &QW_FONT_8X16, + &QW_FONT_31X48, + &QW_FONT_LARGENUM, + &QW_FONT_7SEGMENT}; +int nFONTS = sizeof(demoFonts) / sizeof(demoFonts[0]); +int iFont = 0; + +// Some vars for the title. +String strTitle = "<>"; +QwiicFont *pFntTitle = &QW_FONT_5X7; + +QwiicFont *pFntLabel = &QW_FONT_5X7; +QwiicFont *pFntValue = &QW_FONT_LARGENUM; + +int width; +int height; + +// x position of the PM2.5 label, this will be set in the +// writeStaticDisplayItems() function +int xPosPM25; + +// Fuel Guage Specifics +#include // Click here to get the library: http://librarymanager/All#SparkFun_MAX1704x_Fuel_Gauge_Arduino_Library +SFE_MAX1704X lipo(MAX1704X_MAX17048); // Create a MAX17048 +double soc = 0; // Variable to keep track of LiPo state-of-charge (SOC) + + +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif + +void setup() +{ + pinMode(StatLedPin, OUTPUT); + digitalWrite(StatLedPin, LOW); + + lipo.disableDebugging(); // disable debugging for the MAX1704X fuel gauge + + Serial.begin(115200); + + while (!Serial) + delay(10); // Wait for Serial to become available. + // Necessary for boards with native USB (like the SAMD51 Thing+). + // For a final version of a project that does not need serial debug (or a USB cable plugged in), + // Comment out this while loop, or it will prevent the remaining code from running. + + Serial.println(); + Serial.println("BMV080 Example 8 - OLED Display"); + + wirePort.begin(); + + // Initalize the OLED device and related graphics system + if (myOLED.begin(wirePort) == false) + { + Serial.println("OLED Device begin failed. Freezing..."); + writeCenteredStringToDisplay("OLED Failure", true); + while (true) + ; + } + Serial.println("OLED Begin success"); + + // save device dims for the test routines + width = myOLED.getWidth(); + height = myOLED.getHeight(); + + showSplash(); + + myOLED.setFont(demoFonts[1]); + + if (bmv080.begin(BMV080_ADDR, wirePort) == false) + { + Serial.println( + "BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); + writeCenteredStringToDisplay("BMV080 Failure", true); + while (1) + ; + } + Serial.println("BMV080 found!"); + writeCenteredStringToDisplay("BMV080 Found", true); + + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz + + /* Initialize the Sensor (read driver, open, reset, id etc.)*/ + bmv080.init(); + + /* Set the sensor mode to continuous mode */ + if (bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) + { + Serial.println("BMV080 set to continuous mode"); + writeCenteredStringToDisplay("Continuous Mode Set", true); + } + else + { + Serial.println("Error setting BMV080 mode"); + writeCenteredStringToDisplay("BMV080 Mode Error", true); + } + + // Set up the MAX17048 LiPo fuel gauge: + if (lipo.begin() == false) // Connect to the MAX17043 using the default wire port + { + Serial.println(F("MAX17048 not detected. Please check wiring. Freezing.")); + writeCenteredStringToDisplay("MAX17048 Failure", true); + while (1) + ; + } + Serial.println("MAX17048 found!"); + + // Quick start restarts the MAX17043 in hopes of getting a more accurate + // guess for the SOC. + lipo.quickStart(); +} + +void loop() +{ + if (bmv080.readSensor()) + { + pm25Value = bmv080.PM25(); + pm1Value = bmv080.PM1(); + + Serial.print(pm1Value); + Serial.print("\t"); + Serial.print(pm25Value); + writeStaticDisplayItems(); + writeValuesToDisplay(); + // lipo.getSOC() returns the estimated state of charge (e.g. 79%) + soc = lipo.getSOC(); + Serial.print("\tBatt: "); + Serial.print(soc); // Print the battery state of charge + Serial.print(" %"); + writeBatteryLevelToDisplay(); + myOLED.display(); // actually command the display to show the scene + + if (bmv080.isObstructed() == true) + { + Serial.print("\tObstructed"); + writeObstructedBoarder(); + writeCenteredStringToDisplay("Obstructed", false); // don't clear the screen + // so the obstructed message is displayed on top of the PM values + } + + Serial.println(); + toggleHeartbeat(); + } + delay(100); +} + +void showSplash() +{ + int x0 = (width - QW_BMP_SPARKFUN.width) / 2; + if (x0 < 0) + x0 = 0; + + int y0 = (height - QW_BMP_SPARKFUN.height) / 2; + if (y0 < 0) + y0 = 0; + + myOLED.erase(); + myOLED.bitmap(x0, y0, QW_BMP_SPARKFUN); + myOLED.display(); + delay(2000); + + // Clear the screen + myOLED.erase(); + myOLED.display(); +} + +// Write the static display items to the screen +void writeStaticDisplayItems() +{ + // clear the screen + myOLED.erase(); + + myOLED.setFont(&QW_FONT_8X16); + + // draw the PM1 static text label + // calculate the x position of the PM1 label + // this is 1/4 the screen width minus 1/2 the width of the label + int xPosPM1Text = myOLED.getWidth() / 4 - myOLED.getStringWidth("PM1") / 2; + myOLED.text(xPosPM1Text, 0, "PM1", 1); + + // draw the PM2.5 static text label + // calculate the x position of the PM2.5 label + // this is 3/4 the screen width minus 1/2 the width of the label + int xPosPM25Text = (myOLED.getWidth() / 4) * 3 - myOLED.getStringWidth("PM2.5") / 2; + myOLED.text(xPosPM25Text, 0, "PM2.5", 1); + + // // draw the vertical separator line + // myOLED.line(myOLED.getWidth() / 2, 0, myOLED.getWidth() / 2, myOLED.getHeight(), 1); + // // draw a second line to make it more visible + // myOLED.line(myOLED.getWidth() / 2 + 1, 0, myOLED.getWidth() / 2 + 1, myOLED.getHeight(), 1); + +} + +// Write the PM1 and PM2.5 values to the display +void writeValuesToDisplay() +{ + // set the font to the large number font + myOLED.setFont(&QW_FONT_LARGENUM); + + // draw the PM1 value + String toPrint = "blank"; + toPrint = String(int(pm1Value)); + + // calculate the x position of the PM1 value + // we want it to be centered in the left half of the screen + int xPosPM1Value = (myOLED.getWidth() / 4) - (myOLED.getStringWidth(toPrint) / 2); + + // calculate the y start position of the PM1 value + // we want the bottom of the text to align with the bottom of the screen + int yPosPM1Value = myOLED.getHeight() - myOLED.getStringHeight(toPrint); + myOLED.text(xPosPM1Value, yPosPM1Value, toPrint, 1); + + // draw the PM2.5 value + // calculate the x position of the PM2.5 value + // we want it to be centered in the right half of the screen + int xPosPM25Value = (myOLED.getWidth() / 4) * 3 - (myOLED.getStringWidth(toPrint) / 2); + toPrint = String(int(pm25Value)); + myOLED.text(xPosPM25Value, yPosPM1Value, toPrint, 1); // same y position as the PM1 value +} + +// Write a string to the display that is centered horizontally and vertically +void writeCenteredStringToDisplay(String toPrint, bool clearScreen) +{ + // clear the screen + if(clearScreen) + { + myOLED.erase(); + } + + // set the font to the 8x16 font + myOLED.setFont(&QW_FONT_5X7); + + // calculate the x position of the toPrint text + // we want it to be centered in the screen horizontally + // and vertically + int xPosToPrint = (myOLED.getWidth() / 2) - (myOLED.getStringWidth(toPrint) / 2); + int yPosToPrint = (myOLED.getHeight() / 2) - (myOLED.getStringHeight(toPrint) / 2); + + // draw the string as text + myOLED.text(xPosToPrint, yPosToPrint, toPrint, 1); + myOLED.display(); +} + +// blink the status LED +void blinkStatLed() +{ + digitalWrite(StatLedPin, HIGH); + delay(10); + digitalWrite(StatLedPin, LOW); +} + +// toggle "heartbeat" rectangle in the upper right corner of the screen +void toggleHeartbeat() +{ + static bool bHeartbeat = false; + + // heartbeat rectangle is 3x3 pixels + uint8_t rectWidth = 3; + uint8_t rectHeight = 3; + + // heartbeat rectangle is in the upper right corner of the screen + uint8_t rectStartX = myOLED.getWidth() - rectWidth; + uint8_t rectStartY = 0; + + // draw the rectangle + myOLED.rectangleFill(rectStartX, rectStartY, rectWidth, rectHeight, 1); + + // toggle the heartbeat + bHeartbeat = !bHeartbeat; + + // if the heartbeat is off, erase the rectangle + if (!bHeartbeat) + { + myOLED.rectangleFill(rectStartX, rectStartY, rectWidth, rectHeight, 0); + } + + myOLED.display(); +} + +// Write the battery level to the display +// Create a rectangular battery level indicator on the bottom right side of the screen +// fill in the rectangle with a percentage of the battery level +// each section of the rectangle represents 25% of the battery level +void writeBatteryLevelToDisplay() +{ + // calculate the x position of the battery level indicator + // this is the right side of the screen minus 14 pixels + int xPosBatteryLevelIndicator = (myOLED.getWidth()- 14); + + // draw the battery level indicator outline + // this rectangle is an outline of the battery level indicator + // it looks like a small battery + // it is 6 pixels tall and 12 pixels wide + // the inside of the rectangle is not filled in + // the rectangle is drawn in white + // the inside of the rectangle will be filled in with the battery level + myOLED.rectangle(xPosBatteryLevelIndicator, myOLED.getHeight() - 6, 12, 6, 1); + + // draw the end shape of the battery level indicator + // this makes it look like a traditional battery level indicator + // like the end of a AA battery + // draw a filled in rectangle that will be the end shape of the battery level indicator + // it is 2 pixels tall and 2 pixels wide + // it is drawn in white + myOLED.rectangle(xPosBatteryLevelIndicator + 12, myOLED.getHeight() - 4, 2, 2, 1); + + // draw the inner sections of the battery level indicator + // There are 3 blocks inside the battery level indicator + // each block represents 33% of the battery level + // the left most block represents 0-33% of the battery level + // the middle block represents 34-66% of the battery level + // the right most block represents 67-100% of the battery level + // the blocks are filled in with white + // the blocks are 2 pixels tall and 2 pixels wide + // there is a 1 pixel gap between each block + + // calculate the y position of the battery level indicator blocks + // this is the bottom of the screen minus 4 pixels + int yPosBatteryLevelBlocks = myOLED.getHeight() - 4; + + // calculate the x position of the left most block + // this is the right side of the screen minus 12 pixels + int xPosLeftBlock = (myOLED.getWidth() - 12); + + // calculate the x position of the middle block + // this is the right side of the screen minus 9 pixels + int xPosMiddleBlock = (myOLED.getWidth() - 9); + + // calculate the x position of the right most block + // this is the right side of the screen minus 6 pixels + int xPosRightBlock = (myOLED.getWidth() - 6); + + // write all 3 battery block indicators as black rectangles + myOLED.rectangle(xPosLeftBlock, yPosBatteryLevelBlocks, 2, 2, 0); + myOLED.rectangle(xPosMiddleBlock, yPosBatteryLevelBlocks, 2, 2, 0); + myOLED.rectangle(xPosRightBlock, yPosBatteryLevelBlocks, 2, 2, 0); + + // if the battery level is at least 33% + // fill in the left most block + if (soc > 32) + { + myOLED.rectangle(xPosLeftBlock, yPosBatteryLevelBlocks, 2, 2, 1); + } + + // if the battery level is between 34% and 66% + // fill in the middle block + if (soc > 33) + { + myOLED.rectangle(xPosMiddleBlock, yPosBatteryLevelBlocks, 2, 2, 1); + } + + // if the battery level is greater than 66% + // fill in the right most block + if (soc > 66) + { + myOLED.rectangle(xPosRightBlock, yPosBatteryLevelBlocks, 2, 2, 1); + } +} + +void writeObstructedBoarder() +{ + // set fort to 5x7 + myOLED.setFont(&QW_FONT_5X7); + + int xPosObstructed = (myOLED.getWidth() / 2) - (myOLED.getStringWidth("Obstructed") / 2) - 2; + int yPosObstructed = (myOLED.getHeight() / 2) - (myOLED.getStringHeight("Obstructed") / 2) - 2; + int widthObstructed = myOLED.getStringWidth("Obstructed") + 4; + int heightObstructed = myOLED.getStringHeight("Obstructed") + 4; + + // draw the black filled rectangle + myOLED.rectangleFill(xPosObstructed, yPosObstructed, widthObstructed, heightObstructed, 0); +} \ No newline at end of file diff --git a/examples/Example_09_OpenClose/Example_09_OpenClose.ino b/examples/Example_09_OpenClose/Example_09_OpenClose.ino new file mode 100644 index 0000000..0fab106 --- /dev/null +++ b/examples/Example_09_OpenClose/Example_09_OpenClose.ino @@ -0,0 +1,188 @@ +/* + Using the BMV080 Particulate Matter PM2.5 Sensor + + This example shows how to open an instance of the object, take 5 readings, + then close the object. + + It then repeats this process every 5 seconds. + + This example shows how to use the sensor in "continuous mode" to get + particulate matter readings once every second. + + It uses polling of the device to check if new data is available. + + By: Pete Lewis + SparkFun Electronics + Date: September, 2024 + SparkFun code, firmware, and software is released under the MIT License. + Please see LICENSE.md for further details. + + Hardware Connections: + IoT RedBoard --> BMV080 + QWIIC --> QWIIC + + BMV080 "mode" jumper set to I2C (default) + + Serial.print it out at 115200 baud to serial monitor. + + Feel like supporting our work? Buy a board from SparkFun! + https://www.sparkfun.com/products/26554 +*/ + +#include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080 +#include + + +#define BMV080_ADDR 0x57 // SparkFun BMV080 Breakout defaults to 0x57 + +// Some Dev boards have their QWIIC connector on Wire or Wire1 +// This #ifdef will help this sketch work across more products + +#ifdef ARDUINO_SPARKFUN_THINGPLUS_RP2040 +#define wirePort Wire1 +#else +#define wirePort Wire +#endif + +int testTimes = 0; // Test times + +void setup() +{ + Serial.begin(115200); + + while (!Serial) + delay(10); // Wait for Serial to become available. + // Necessary for boards with native USB (like the SAMD51 Thing+). + // For a final version of a project that does not need serial debug (or a USB cable plugged in), + // Comment out this while loop, or it will prevent the remaining code from running. + + Serial.println(); + Serial.println("BMV080 Example 09 - Open and Close"); +} + +void loop() +{ + Serial.print("Test times: "); + Serial.println(testTimes); + testOnce(); + testTimes++; + delay(5000); +} + + +void testOnce() +{ + Serial.println(); + Serial.println("BMV080 Begin testing readings"); + + SparkFunBMV080 bmv080; // Create an instance of the BMV080 class + + wirePort.begin(); + + if (bmv080.begin(BMV080_ADDR, wirePort) == false) + { + Serial.println( + "BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing..."); + while (1) + ; + } + Serial.println("BMV080 found!"); + + // wirePort.setClock(400000); //Increase I2C data rate to 400kHz + + /* Initialize the Sensor (read driver, open, reset, id etc.)*/ + // Do what init() does, but check each call to each function individually + // to see if there are any issues with the sensor + + uint16_t major, minor, patch; + if (bmv080.driverVersion(major, minor, patch) == true) + { + Serial.print("BMV080 Driver Version: "); + Serial.print(major); + Serial.print("."); + Serial.print(minor); + Serial.print("."); + Serial.println(patch); + } + else + { + Serial.println("Error getting BMV080 driver version"); + } + + if (bmv080.open() == true) + { + Serial.println("BMV080 Opened"); + } + else + { + Serial.println("Error opening BMV080"); + } + + if (bmv080.reset() == true) + { + Serial.println("BMV080 Reset"); + } + else + { + Serial.println("Error resetting BMV080"); + } + + char idOut[13]; + if (bmv080.ID(idOut) == true) + { + Serial.print("BMV080 ID: "); + Serial.println(idOut); + } + else + { + Serial.println("Error getting BMV080 ID"); + } + + /* Set the sensor mode to continuous mode */ + if (bmv080.setMode(SF_BMV080_MODE_CONTINUOUS) == true) + { + Serial.println("BMV080 set to continuous mode"); + } + else + { + Serial.println("Error setting BMV080 mode"); + } + + // Take 5 readings + + // Poll the sensor 50 times, once every 100ms + // The sensor is setup to report readings once per second + // So this will result in 5 readings. + for(int i = 0 ; i < 50 ; i++) + { + if (bmv080.readSensor()) + { + float pm10 = bmv080.PM10(); + float pm25 = bmv080.PM25(); + float pm1 = bmv080.PM1(); + + Serial.print("PM10: "); + Serial.print(pm10); + Serial.print("\t"); + Serial.print("PM2.5: "); + Serial.print(pm25); + Serial.print("\t"); + Serial.print("PM1: "); + Serial.print(pm1); + + if (bmv080.isObstructed() == true) + { + Serial.print("\tObstructed"); + } + + Serial.println(); + } + delay(100); + } + + Serial.println("BMV080 End testing readings"); + + bmv080.close(); + + wirePort.end(); +} \ No newline at end of file diff --git a/keywords.txt b/keywords.txt index a0b329e..4373fb4 100644 --- a/keywords.txt +++ b/keywords.txt @@ -4,7 +4,8 @@ # Class ######################################################### -Bmv080 KEYWORD1 +SparkFunBMV080 KEYWORD1 +SparkFunBMV080SPI KEYWORD1 ######################################################### # Methods and Functions @@ -12,11 +13,9 @@ Bmv080 KEYWORD1 begin KEYWORD2 init KEYWORD2 -initSPI KEYWORD2 isConnected KEYWORD2 getDriverVersion KEYWORD2 open KEYWORD2 -openSPI KEYWORD2 reset KEYWORD2 getID KEYWORD2 setMode KEYWORD2 diff --git a/library.properties b/library.properties index d6a9f0c..fee6da7 100644 --- a/library.properties +++ b/library.properties @@ -5,7 +5,8 @@ maintainer=SparkFun Electronics sentence=Library for SparkFun BMV080 PM 2.5 Sensor paragraph=A very fast and efficient Arduino library for the BMV080 category=Sensor -url=https://github.com/sparkfun/SparkFun_Qwiic_OLED_Arduino_Library -architectures=esp32,esp32s2,esp32s3,cortex-m33 +url=https://github.com/sparkfun/SparkFun_BMV080_Arduino_Library +architectures=esp32,esp32s2,esp32s3,cortex-m33,cortex-m0plus,cortex-m4f precompiled=true -ldflags=-lbmv080 +depends=SparkFun Toolkit (>=1.0.0) +ldflags=-lbmv080 -lpostProcessor diff --git a/src/SparkFun_BMV080_Arduino_Library.h b/src/SparkFun_BMV080_Arduino_Library.h index 23bd364..d318499 100644 --- a/src/SparkFun_BMV080_Arduino_Library.h +++ b/src/SparkFun_BMV080_Arduino_Library.h @@ -1,66 +1,114 @@ /****************************************************************************** - SparkFun_BMV080_Arduino_Library.h - SparkFun BMV080 Library header file - - by Pete Lewis @SparkFun Electronics - September 2024 - - Based on original source code written by - Fischer Moseley @ SparkFun Electronics - Original Creation Date: July 24, 2019 - - This file implements the BMV080 class, prototyped in SparkFun_BMV080_Arduino_Library.h - - Development environment specifics: - IDE: Arduino 2.3.3 - Hardware Platform: SparkFun IoT Redboard ESP32 - BMV080 Breakout HW Version: v01 - - SPDX-License-Identifier: MIT - - Copyright (c) 2024 SparkFun Electronics - - Distributed as-is; no warranty is given. -******************************************************************************/ + * @file SparkFun_BMV080_Arduino_Library.h + * @brief SparkFun BMV080 Library header file + * + * This file implements the SparkFunBMV080 and SparkFunBMV080SPI classes, + * for use with the SparkFun BMV080 sensor qwiic breakout board, HW version v01. + * + * @author Pete Lewis + * @date Sprint 2025 + * @version 1.0 + * @copyright (c) 2024 SparkFun Electronics Inc. This project is released under the MIT License. + * + * SPDX-License-Identifier: MIT + * + ******************************************************************************/ #pragma once -// TODO: Add includes as needed (e.g. #include , #include ) -#include "sfeBmv080.h" +// helps to keep the Toolkit header before the tk calls +// clang-format off #include - -// #include "Arduino.h" -#include -#include -#include "combridge.h" +#include "sfTk/sfDevBMV080.h" +// clang-format on // The BMV080 Bosch API requires a larger than usual stack size // In particular, bmv080_serve_interrupt is the culprit. -SET_LOOP_TASK_STACK_SIZE(60 * 1024); // 60KB +// If we are an ESP32 architecture, then we need to increase the loop stack size +// to 60KB. This is because the ESP32 has a 32KB stack size by default. +#if defined(ESP32) +SET_LOOP_TASK_STACK_SIZE(60 * 1024); // 60KB +#endif -class Bmv080 : public sfeBmv080 +/** + * @brief Class for interfacing with the BMV080 sensor using I2C communication + * + * This class provides methods to initialize and communicate with the BMV080 sensor + * over an I2C bus. It inherits from the sfDevBMV080 class and uses the SparkFun + * Toolkit for I2C communication. + * + * @see sfDevBMV080 + */ +class SparkFunBMV080 : public sfDevBMV080 { public: - /// @brief Begins the Device - /// @param address I2C device address to use for the sensor - /// @param wirePort Wire port to use for I2C communication - /// @return True if successful, false otherwise - bool begin(const uint8_t address = SFE_BMV080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire) + /** + * @brief Begins the Device with I2C as the communication bus + * + * This method initializes the I2C bus and sets up communication with the BMV080 sensor. + * + * @param address I2C device address to use for the sensor + * @param wirePort Wire port to use for I2C communication + * @return True if successful, false otherwise + */ + bool begin(const uint8_t address = SF_BMV080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire) { - // Setup Arudino I2C bus + // Setup Arduino I2C bus _theI2CBus.init(wirePort, address); + _theI2CBus.setByteOrder(SFTK_MSBFIRST); // Begin the sensor - return sfeBmv080::begin(&_theI2CBus) == kSTkErrOk; + sfTkError_t rc = sfDevBMV080::begin(&_theI2CBus); + + return rc == ksfTkErrOk ? isConnected() : false; } /// @brief Checks if the Device is connected /// @return True if the sensor is connected, false otherwise bool isConnected() { - return sfeBmv080::isConnected() == kSTkErrOk; + return _theI2CBus.ping() == ksfTkErrOk; } private: - sfeTkArdI2C _theI2CBus; + sfTkArdI2C _theI2CBus; }; + +/** + * @brief Class for interfacing with the BMV080 sensor using SPI communication + * + * This class provides methods to initialize and communicate with the BMV080 sensor + * over an SPI bus. It inherits from the sfDevBMV080 class and uses the SparkFun + * Toolkit for SPI communication. + * + * @see sfDevBMV080 + */ +class SparkFunBMV080SPI : public sfDevBMV080 +{ + public: + /** + * @brief Begins the Device with SPI as the communication bus + * + * This method initializes the SPI bus and sets up communication with the BMV080 sensor. + * + * @param csPin The chip select pin for the sensor + * @param spiPort The SPI port to use for communication + * @param spiSettings The SPI settings to use for communication + * @return True if successful, false otherwise + */ + bool begin(uint8_t csPin, SPIClass &spiPort = SPI, + SPISettings spiSettings = SPISettings(100000, MSBFIRST, SPI_MODE0)) + { + + // Setup Arduino SPI bus + _theSPIBus.init(spiPort, spiSettings, csPin, true); + + // Begin the sensor + sfTkError_t rc = sfDevBMV080::begin(&_theSPIBus); + + return rc == ksfTkErrOk ? true : false; + } + + private: + sfTkArdSPI _theSPIBus; +}; \ No newline at end of file diff --git a/src/combridge.cpp b/src/combridge.cpp deleted file mode 100644 index 704aef2..0000000 --- a/src/combridge.cpp +++ /dev/null @@ -1,240 +0,0 @@ -/** - * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - * @file combridge.cpp - * - * @brief This file contains the serial communication interface (e.g. SPI and I2C) functions. - * Messages can be read and written. In addition, there is a waiting mechanism that waits for a defined time. - */ - - -/* Includes ------------------------------------------------------------------*/ -#include -#include "combridge.h" - -/* Private define ------------------------------------------------------------*/ -#define SPI_CLK_FREQ ((uint32_t)(1e6)) - -#define I2C_CLK_FREQ ((uint32_t)(100e3)) - -/* BMV080 I2C address - * note that the BMV080 pins are connected such that I2C Address Bit 0 = 0 and I2C Address Bit 1 = 0 - */ -#define BMV080_I2C_ADDRESS 0x57 - - -/* Exported functions --------------------------------------------------------*/ -void spi_init(spi_device_t *spi_device) -{ - SPISettings spi_settings(SPI_CLK_FREQ, MSBFIRST, SPI_MODE0); - spi_device->instance = &SPI; - spi_device->settings = spi_settings; - - pinMode(SS, OUTPUT); - pinMode(MOSI, OUTPUT); - pinMode(SCK, OUTPUT); - pinMode(MISO, INPUT); - digitalWrite(SS, HIGH); - spi_device->instance->begin(); -} - - -void i2c_init(i2c_device_t *i2c_device) -{ - i2c_device->instance = &Wire; - i2c_device->instance->begin(); - i2c_device->instance->setClock(I2C_CLK_FREQ); - i2c_device->instance->setBufferSize(512); -} - - -int8_t combridge_spi_read_16bit(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, uint16_t payload_length) -{ - int8_t return_value = E_COMBRIDGE_OK; - spi_device_t *spi_device = (spi_device_t *)handle; - - digitalWrite(SS, LOW); - spi_device->instance->beginTransaction(spi_device->settings); - spi_device->instance->transfer16(header); - - uint16_t payload_index = 0; - for (; payload_index < payload_length; payload_index++) - { - payload[payload_index] = spi_device->instance->transfer16(0); - } - spi_device->instance->endTransaction(); - digitalWrite(SS, HIGH); - - return return_value; -} - - -int8_t combridge_spi_write_16bit(bmv080_sercom_handle_t handle, uint16_t header, const uint16_t *payload, uint16_t payload_length) -{ - int8_t return_value = E_COMBRIDGE_OK; - spi_device_t *spi_device = (spi_device_t *)handle; - - digitalWrite(SS, LOW); - spi_device->instance->beginTransaction(spi_device->settings); - spi_device->instance->transfer16(header); - - uint16_t payload_index = 0; - for (; payload_index < payload_length; payload_index++) - { - spi_device->instance->transfer16(payload[payload_index]); - } - spi_device->instance->endTransaction(); - digitalWrite(SS, HIGH); - - return E_COMBRIDGE_OK; -} - - -int8_t combridge_i2c_read_16bit(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, uint16_t payload_length) -{ - int8_t return_value = E_COMBRIDGE_OK; - i2c_device_t *i2c_device = (i2c_device_t *)handle; - uint8_t * payload_byte = (uint8_t*)payload; - - /* 16-bit header left shifted by 1, since the R/W bit (most significant bit) is passed along with the 7-bit device address */ - uint16_t header_adjusted = header << 1; - - i2c_device->instance->beginTransmission(BMV080_I2C_ADDRESS); - i2c_device->instance->write((header_adjusted >> 8) & 0xFF); - i2c_device->instance->write(header_adjusted & 0xFF); - - if(i2c_device->instance->endTransmission(true) != 0) - { - return_value = E_COMBRIDGE_ERROR_WRITE_HEADER; - return return_value; - } - - i2c_device->instance->requestFrom(BMV080_I2C_ADDRESS, payload_length * 2); - - uint16_t payload_index = 0; - while(i2c_device->instance->available() && (payload_index < (payload_length * 2) )) - { - payload_byte[payload_index++] = i2c_device->instance->read(); - //Serial.print("."); - } - //Serial.print("payload_length"); - //Serial.println(payload_length); - - if(payload_index != (payload_length * 2)) - { - return_value = E_COMBRIDGE_ERROR_READ; - } - - /* Conversion of payload from big endian to little endian */ - for (payload_index = 0; payload_index < payload_length; payload_index++) - { - uint16_t swapped_word = ((payload[payload_index] << 8) | (payload[payload_index] >> 8)) & 0xffff; - payload[payload_index] = swapped_word; - } - - return return_value; -} - - -int8_t combridge_i2c_write_16bit(bmv080_sercom_handle_t handle, uint16_t header, const uint16_t *payload, uint16_t payload_length) -{ - int8_t return_value = E_COMBRIDGE_OK; - - i2c_device_t *i2c_device = (i2c_device_t *)handle; - uint8_t * payload_byte = (uint8_t*)payload; - - /* 16-bit header left shifted by 1, since the R/W bit (most significant bit) is passed along with the 7-bit device address */ - uint16_t header_adjusted = header << 1; - - /* Conversion of payload from little endian to big endian (dynamic allocation is used) */ - uint16_t *payload_swapped = (uint16_t *)calloc(payload_length, sizeof(uint16_t)); - if(payload_swapped) - { - for (uint16_t payload_index = 0; payload_index < payload_length; payload_index++) - { - payload_swapped[payload_index] = ((payload[payload_index] << 8) | (payload[payload_index] >> 8)) & 0xffff; - } - } - else - { - return_value = E_COMBRIDGE_ERROR_WRITE_HEADER; - return return_value; - } - - i2c_device->instance->beginTransmission(BMV080_I2C_ADDRESS); - i2c_device->instance->write((header_adjusted >> 8) & 0xFF); - i2c_device->instance->write(header_adjusted & 0xFF); - i2c_device->instance->write((uint8_t *)payload_swapped, payload_length * 2); - - if(i2c_device->instance->endTransmission(true) != 0) - { - return_value = E_COMBRIDGE_ERROR_WRITE; - } - - free(payload_swapped); - - return return_value; -} - - -int8_t combridge_delay(uint32_t period) -{ - delay(period); - - return E_COMBRIDGE_OK; -} diff --git a/src/combridge.h b/src/combridge.h deleted file mode 100644 index 318b28a..0000000 --- a/src/combridge.h +++ /dev/null @@ -1,136 +0,0 @@ -/** - * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - * @file combridge.h - * - * @brief Header for the serial communication interface functions in combridge.c. - */ - -#ifndef COMBRIDGE_H_ -#define COMBRIDGE_H_ - -/* Includes ------------------------------------------------------------------*/ -#include "bmv080.h" -#include -#include -#include - - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/* Exported types ------------------------------------------------------------*/ - -/*! -* @brief SPI device structure -*/ -typedef struct -{ - /*! Instance of arduino SPI protocol instance */ - SPIClass *instance; - /*! Instance of arduino SPI settings to be applied before every transmission */ - SPISettings settings; -} spi_device_t; - -/*! -* @brief I2C device structure -*/ -typedef struct -{ - /*! Instance of arduino I2C protocol instance */ - TwoWire *instance; -} i2c_device_t; - -/* Exported constants --------------------------------------------------------*/ -/*! 0: Status codes returned when there is no warning or error */ -#define E_COMBRIDGE_OK ((int8_t)0) -/*! -1: Status codes returned when memory allocation fails */ -#define E_COMBRIDGE_ERROR_MEMORY_ALLOCATION ((int8_t)-1) -/*! -2: Status codes returned when the read operation fails */ -#define E_COMBRIDGE_ERROR_READ ((int8_t)-2) -/*! -3: Status codes returned when the write operation fails */ -#define E_COMBRIDGE_ERROR_WRITE ((int8_t)-3) -/*! -4: Status codes returned when writing the header fails */ -#define E_COMBRIDGE_ERROR_WRITE_HEADER ((int8_t)-4) -/*! -5: Status codes returned when a reference is null */ -#define E_COMBRIDGE_ERROR_NULLPTR ((int8_t)-5) - -/* Exported functions prototypes ---------------------------------------------*/ - -/* Initialization functions */ -void spi_init(spi_device_t *spi_device); -void i2c_init(i2c_device_t *i2c_device); - -/* SPI read and write functions */ -int8_t combridge_spi_read_16bit(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, uint16_t payload_length); -int8_t combridge_spi_write_16bit(bmv080_sercom_handle_t handle, uint16_t header, const uint16_t *payload, uint16_t payload_length); - -/* I2C read and write functions */ -int8_t combridge_i2c_read_16bit(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, uint16_t payload_length); -int8_t combridge_i2c_write_16bit(bmv080_sercom_handle_t handle, uint16_t header, const uint16_t *payload, uint16_t payload_length); - -/* Delay function */ -int8_t combridge_delay(uint32_t period); - - -#ifdef __cplusplus -} -#endif - -#endif /* COMBRIDGE_H_ */ diff --git a/src/cortex-m0plus/libbmv080.a b/src/cortex-m0plus/libbmv080.a new file mode 100644 index 0000000..d4cd725 Binary files /dev/null and b/src/cortex-m0plus/libbmv080.a differ diff --git a/src/cortex-m0plus/libpostProcessor.a b/src/cortex-m0plus/libpostProcessor.a new file mode 100644 index 0000000..7db919c Binary files /dev/null and b/src/cortex-m0plus/libpostProcessor.a differ diff --git a/src/cortex-m33/libbmv080.a b/src/cortex-m33/libbmv080.a new file mode 100644 index 0000000..61f68b6 Binary files /dev/null and b/src/cortex-m33/libbmv080.a differ diff --git a/src/cortex-m33/libpostProcessor.a b/src/cortex-m33/libpostProcessor.a new file mode 100644 index 0000000..1957e49 Binary files /dev/null and b/src/cortex-m33/libpostProcessor.a differ diff --git a/src/cortex-m4/libbmv080.a b/src/cortex-m4/libbmv080.a new file mode 100644 index 0000000..187bed9 Binary files /dev/null and b/src/cortex-m4/libbmv080.a differ diff --git a/src/cortex-m4/libpostProcessor.a b/src/cortex-m4/libpostProcessor.a new file mode 100644 index 0000000..39a8b6b Binary files /dev/null and b/src/cortex-m4/libpostProcessor.a differ diff --git a/src/cortex-m4f/libbmv080.a b/src/cortex-m4f/libbmv080.a new file mode 100644 index 0000000..8f46eeb Binary files /dev/null and b/src/cortex-m4f/libbmv080.a differ diff --git a/src/cortex-m4f/libpostProcessor.a b/src/cortex-m4f/libpostProcessor.a new file mode 100644 index 0000000..017701d Binary files /dev/null and b/src/cortex-m4f/libpostProcessor.a differ diff --git a/src/esp32/libbmv080.a b/src/esp32/libbmv080.a index 8941dec..c24085d 100644 Binary files a/src/esp32/libbmv080.a and b/src/esp32/libbmv080.a differ diff --git a/src/esp32/libpostProcessor.a b/src/esp32/libpostProcessor.a index 8d07ae4..cb28556 100644 Binary files a/src/esp32/libpostProcessor.a and b/src/esp32/libpostProcessor.a differ diff --git a/src/esp32s2/libbmv080.a b/src/esp32s2/libbmv080.a new file mode 100644 index 0000000..7e44310 Binary files /dev/null and b/src/esp32s2/libbmv080.a differ diff --git a/src/esp32s2/libpostProcessor.a b/src/esp32s2/libpostProcessor.a new file mode 100644 index 0000000..6a39c47 Binary files /dev/null and b/src/esp32s2/libpostProcessor.a differ diff --git a/src/esp32s3/libbmv080.a b/src/esp32s3/libbmv080.a new file mode 100644 index 0000000..c24085d Binary files /dev/null and b/src/esp32s3/libbmv080.a differ diff --git a/src/esp32s3/libpostProcessor.a b/src/esp32s3/libpostProcessor.a new file mode 100644 index 0000000..cb28556 Binary files /dev/null and b/src/esp32s3/libpostProcessor.a differ diff --git a/src/bmv080.h b/src/sfTk/bmv080.h similarity index 91% rename from src/bmv080.h rename to src/sfTk/bmv080.h index 81e4d0f..f2fe237 100644 --- a/src/bmv080.h +++ b/src/sfTk/bmv080.h @@ -1,310 +1,314 @@ -/** - * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - * @file bmv080.h - * - * @brief BMV080 sensor driver functions - * - * - */ - -#ifndef BMV080_H_ -#define BMV080_H_ - -#include - -#include "bmv080_defs.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -/********************************************************************************************************************* -* Sensor driver functions -*********************************************************************************************************************/ - -/*! -* @brief Open a sensor unit by initializing a new handle. -* -* @pre Must be called first in order to create the _handle_ required by other functions. -* @post The _handle_ must be destroyed via _bmv080_close_. -* -* @param[out] handle : Unique handle for a sensor unit. -* @param[in] sercom_handle : Unique handle for a serial communication interface. -* @param[in] read : Function pointer for reading from an endpoint. -* @param[in] write : Function pointer for writing to an endpoint. -* @param[in] delay_ms : Function pointer for a delay in milliseconds. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_open(bmv080_handle_t* handle, const bmv080_sercom_handle_t sercom_handle, - const bmv080_callback_read_t read, const bmv080_callback_write_t write, const bmv080_callback_delay_t delay_ms); - -/*! -* @brief Get the version information of this sensor driver. -* -* @details The version numbers follow semantic versioning. -* -* @pre No preconditions apply, i.e. no connected sensor unit or sensor driver _handle_ is required. -* -* @param[out] major : Major version number. -* @param[out] minor : Minor version number. -* @param[out] patch : Patch version number. -* @param[out] git_hash : Character array of 13 elements, for internal use only. -* @param[out] num_commits_ahead : For internal use only. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_get_driver_version(uint16_t* major, uint16_t* minor, uint16_t* patch, char git_hash[12], int32_t* num_commits_ahead); - -/*! -* @brief Reset a sensor unit including both hardware and software. -* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* @post Any parameter changed through _bmv080_set_parameter_ is reverted back to its default. -* -* @param[in] handle : Unique handle for a sensor unit. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_reset(const bmv080_handle_t handle); - -/*! -* @brief Get a parameter. -* -* @details Table \ref parameter lists the available parameters with their keys and the expected types. -* This function can be called multiple times and is optional. -* -* -* -*
Table parameter : Available parameters
Key Type Unit Default Details -*
"error_logging" bool false Set if error log files are created. -*
Disabled if _false_, enabled if _true_. -*
"meta_data_logging" bool false Set if meta data log files are created. -*
Disabled if _false_, enabled if _true_. -*
"path" char* "" (empty) Path to directory where log files are written. -*
The maximum allowed length is 256 characters, which must be pre-allocated. -*
File logging is not available on embedded platforms (e.g. ARM Cortex-M). -*
This is applicable to all parameters with the suffix "_logging" in its name. -*
"pm_logging" bool false Set if particulate matter output log files are created. -*
Disabled if _false_, enabled if _true_. -*
"volumetric_mass_density" float kg / m^3 1.6 For internal use only. -*
"integration_time" float s 10 Measurement window. -*
In duty cycling mode, this measurement window is also the sensor ON time. -*
"duty_cycling_period" uint16_t s 30 Duty cycling period (sum of integration time and sensor OFF / sleep time). -*
This must be greater than integration time by at least 2 seconds. -*
"distribution_id" uint32_t 3 For internal use only. -*
"do_obstruction_detection" bool true Set if obstruction detection feature is enabled. -*
"do_vibration_filtering" bool false Set if vibration filter is enabled. -*
-* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* -* @param[in] handle : Unique handle for a sensor unit. -* @param[in] key : Key of the parameter to get. Valid keys are listed in table \ref parameter. -* @param[out] value : Value of the parameter to get of the in table \ref parameter listed type casted as void-pointer. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_get_parameter(const bmv080_handle_t handle, const char* key, void* value); - -/*! -* @brief Set a parameter. -* -* @details Table \ref parameter lists the available parameters with their keys and the expected types. -* This function can be called multiple times and is optional. -* -* -* -*
Table parameter : Available parameters
Key Type Unit Default Details -*
"error_logging" bool false Set if error log files are created. -*
Disabled if _false_, enabled if _true_. -*
"meta_data_logging" bool false Set if meta data log files are created. -*
Disabled if _false_, enabled if _true_. -*
"path" char* "" (empty) Path to directory where log files are written. -*
The path length must be less than 256 characters. -*
Relative and absolute paths with separators ( / ) or ( \\ ) are supported. -*
( . ) indicates the working directory and ( .. ) the parent directory. -*
File logging is not available on embedded platforms (e.g. ARM Cortex-M). -*
This is applicable to all parameters with the suffix "_logging" in its name. -*
"pm_logging" bool false Set if particulate matter output log files are created. -*
Disabled if _false_, enabled if _true_. -*
"volumetric_mass_density" float kg / m^3 1.6 For internal use only. -*
"integration_time" float s 10 Measurement window. -*
In duty cycling mode, this measurement window is also the sensor ON time. -*
"duty_cycling_period" uint16_t s 30 Duty cycling period (sum of integration time and sensor OFF / sleep time). -*
This must be greater than integration time by at least 2 seconds. -*
"distribution_id" uint32_t 3 For internal use only. -*
"do_obstruction_detection" bool true Set if obstruction detection feature is enabled. -*
"do_vibration_filtering" bool false Set if vibration filter is enabled. -*
s -* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* @pre This function must be called before _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_ -* in order to apply the parameter in the configuration of particle measurement. -* -* @param[in] handle : Unique handle for a sensor unit. -* @param[in] key : Key of the parameter to set. Valid keys are listed in table \ref parameter. -* @param[in] value : Value of the parameter to set of the in table \ref parameter listed type casted as void-pointer. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_set_parameter(const bmv080_handle_t handle, const char* key, const void* value); - -/*! -* @brief Get the sensor ID of a sensor unit. -* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* @pre The char array _id_ must have been allocated by the application with a size of 13 elements. -* -* @param[in] handle : Unique handle for a sensor unit. -* @param[out] id : Character array of 13 elements. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_get_sensor_id(const bmv080_handle_t handle, char id[13]); - -/*! -* @brief Start particle measurement in continuous mode. -* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* @pre Optionally, parameters can be set by preceding _bmv080_set_parameter_ calls. -* @post The measurement mode increases energy consumption. -* @post The sensor unit stays in measurement mode until _bmv080_stop_measurement_ is called. -* @post In measurement mode, _bmv080_serve_interrupt_ should be called regularly. -* -* @param[in] handle : Unique handle for a sensor unit. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_start_continuous_measurement(const bmv080_handle_t handle); - -/*! -* @brief Start particle measurement in duty cycling mode -* -* @pre A valid _handle_ generated by _bmv080_open_ is required. -* @pre Optionally, duty cycling parameters (integration_time and duty_cycling_period) can be set by preceding _bmv080_set_parameter_ calls. -* @post The sensor unit stays in duty cycling mode until _bmv080_stop_measurement_ is called. -* @post In measurement mode, _bmv080_serve_interrupt_ should be called regularly. -* -* @param[in] handle : Unique handle for a sensor unit. -* @param[in] get_tick_ms : Function pointer that provides a tick value in milliseconds (based on the host system clock). -* @param[in] duty_cycling_mode : Mode of performing the duty cycling measurement. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_start_duty_cycling_measurement(const bmv080_handle_t handle, const bmv080_callback_tick_t get_tick_ms, - bmv080_duty_cycling_mode_t duty_cycling_mode); - -/*! -* @brief Serve an interrupt using a callback function. -* -* @pre A valid _handle_ generated by _bmv080_open_ is required and -* the sensor unit entered measurement mode via _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_. -* @pre The application can call this function every time the sensor or the application triggers an interrupt. -* This interrupt may be a type of a software timeout (e.g. at least once per second) or a hardware interrupt (e.g. FIFO watermark exceeded). -* @pre This function tolerates very frequent or random calls to a certain extent. -* However, not calling _bmv080_serve_interrupt_ over longer periods might impair the measurement mode since events might be missed. -* @pre In continuous mode, new sensor output is available every second -* Hence, _data_ready_ is called once every second of the sensor unit's uptime. -* For example, if _bmv080_serve_interrupt_ is called 5 seconds after _bmv080_start_continuous_measurement_, -* the callback function _data_ready_ would subsequently be called 5 times to report the collected sensor output of each period. -* @pre In duty cycling mode, new sensor output is available every duty cycling period. -* Hence, _data_ready_ is called at the end of the integration time, once every duty cycling period. -* Note, _bmv080_serve_interrupt_ must be called at least once per second. -* @pre The recommendation is to call this function based on hardware interrupts. -* @pre The callback function _bmv080_callback_data_ready_t_ and the according _callback_parameter_ are provided by the caller application. -* @post Interrupt condition is served, e.g. FIFO is fetched or ASIC condition is solved -* -* @param[in] handle : Unique handle for a sensor unit. -* @param[in] data_ready : User defined callback function which is called when sensor output is available. -* @param[in] callback_parameters : User defined parameters to be passed to the callback function. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_serve_interrupt(const bmv080_handle_t handle, bmv080_callback_data_ready_t data_ready, void* callback_parameters); - -/*! -* @brief Stop particle measurement. -* -* @pre A valid _handle_ generated by _bmv080_open_ is required and -* the sensor unit entered measurement mode via _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_. -* @pre Must be called at the end of a data acquisition cycle to ensure that the sensor unit is ready for the next measurement cycle. -* -* @param[in] handle : Unique handle for a sensor unit. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_stop_measurement(const bmv080_handle_t handle); - -/*! -* @brief Close the sensor unit. -* -* @pre Must be called last in order to destroy the _handle_ created by _bmv080_open_. -* -* @param[in] handle : Unique handle for a sensor unit. -* -* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. -*/ -bmv080_status_code_t bmv080_close(bmv080_handle_t* handle); - -#ifdef __cplusplus -} -#endif /* __cplusplus */ - -#endif /* BMV080_H_ */ +/** + * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. + * + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. They may only be used + * within the parameters of the respective valid product data sheet. Bosch Sensortec products are + * provided with the express understanding that there is no warranty of fitness for a particular purpose. + * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, + * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. + * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The + * examination of fitness for the intended use is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for + * incidental, or consequential damages, arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch + * Sensortec for all costs in connection with such claims. + * + * The purchaser must monitor the market for the purchased products, particularly with regard to + * product safety and inform Bosch Sensortec without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid + * technical specifications of the product series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal client testing. The testing of an + * engineering sample may in no way replace the testing of a product series. Bosch Sensortec + * assumes no liability for the use of engineering samples. By accepting the engineering samples, the + * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information on application-sheets + * (hereinafter called "Information") is provided free of charge for the sole purpose to support your + * application work. The Software and Information is subject to the following terms and conditions: + * + * The Software is specifically designed for the exclusive use for Bosch Sensortec products by + * personnel who have special experience and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed or implied warranties, + * including without limitation, the implied warranties of merchantability and fitness for a particular + * purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment + * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their + * representatives and agents shall not be liable for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no + * responsibility for the consequences of use of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. No license is granted by implication or + * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + * + * It is not allowed to deliver the source code of the Software to any third party without permission of + * Bosch Sensortec. + * + * @file bmv080.h + * + * @brief BMV080 sensor driver functions + * + * + */ + +#ifndef BMV080_H_ +#define BMV080_H_ + +#include + +#include "bmv080_defs.h" + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/********************************************************************************************************************* +* Sensor driver functions +*********************************************************************************************************************/ + +/*! +* @brief Open a sensor unit by initializing a new handle. +* +* @pre Must be called first in order to create the _handle_ required by other functions. +* @post The _handle_ must be destroyed via _bmv080_close_. +* +* @param[out] handle : Unique handle for a sensor unit. +* @param[in] sercom_handle : Unique handle for a serial communication interface. +* @param[in] read : Function pointer for reading from an endpoint. +* @param[in] write : Function pointer for writing to an endpoint. +* @param[in] delay_ms : Function pointer for a delay in milliseconds. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_open(bmv080_handle_t* handle, const bmv080_sercom_handle_t sercom_handle, + const bmv080_callback_read_t read, const bmv080_callback_write_t write, const bmv080_callback_delay_t delay_ms); + +/*! +* @brief Get the version information of this sensor driver. +* +* @details The version numbers follow semantic versioning. +* +* @pre No preconditions apply, i.e. no connected sensor unit or sensor driver _handle_ is required. +* +* @param[out] major : Major version number. +* @param[out] minor : Minor version number. +* @param[out] patch : Patch version number. +* @param[out] git_hash : Character array of 13 elements, for internal use only. +* @param[out] num_commits_ahead : For internal use only. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_get_driver_version(uint16_t* major, uint16_t* minor, uint16_t* patch, char git_hash[12], int32_t* num_commits_ahead); + +/*! +* @brief Reset a sensor unit including both hardware and software. +* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* @post Any parameter changed through _bmv080_set_parameter_ is reverted back to its default. +* +* @param[in] handle : Unique handle for a sensor unit. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_reset(const bmv080_handle_t handle); + +/*! +* @brief Get a parameter. +* +* @details Table \ref parameter lists the available parameters with their keys and the expected types. +* This function can be called multiple times and is optional. +* +* +* +*
Table parameter : Available parameters
Key Type Unit Default Details +*
"error_logging" bool false Set if error log files are created. +*
Disabled if _false_, enabled if _true_. +*
"meta_data_logging" bool false Set if meta data log files are created. +*
Disabled if _false_, enabled if _true_. +*
"path" char* "" (empty) Path to directory where log files are written. +*
The maximum allowed length is 256 characters, which must be pre-allocated. +*
File logging is not available on embedded platforms (e.g. ARM Cortex-M). +*
This is applicable to all parameters with the suffix "_logging" in its name. +*
"pm_logging" bool false Set if particulate matter output log files are created. +*
Disabled if _false_, enabled if _true_. +*
"integration_time" float s 10 Measurement window. +*
In duty cycling mode, this measurement window is also the sensor ON time. +*
"duty_cycling_period" uint16_t s 30 Duty cycling period (sum of integration time and sensor OFF / sleep time). +*
This must be greater than integration time by at least 2 seconds. +*
"do_obstruction_detection" bool true Set if obstruction detection feature is enabled. +*
"do_vibration_filtering" bool false Set if vibration filter is enabled. +*
"measurement_algorithm" bmv080_measurement_algorithm_t E_BMV080_MEASUREMENT_ALGORITHM_HIGH_PRECISION (3) Selection of measurement algorithm based on the +*
use case, as defined by the type bmv080_measurement_algorithm_t, +*
in bmv080_defs.h. For a duty cycling measurement, this parameter is +*
fixed to E_BMV080_MEASUREMENT_ALGORITHM_FAST_RESPONSE. +*
+* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* +* @param[in] handle : Unique handle for a sensor unit. +* @param[in] key : Key of the parameter to get. Valid keys are listed in table \ref parameter. +* @param[out] value : Value of the parameter to get of the in table \ref parameter listed type casted as void-pointer. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_get_parameter(const bmv080_handle_t handle, const char* key, void* value); + +/*! +* @brief Set a parameter. +* +* @details Table \ref parameter lists the available parameters with their keys and the expected types. +* This function can be called multiple times and is optional. +* +* +* +*
Table parameter : Available parameters
Key Type Unit Default Details +*
"error_logging" bool false Set if error log files are created. +*
Disabled if _false_, enabled if _true_. +*
"meta_data_logging" bool false Set if meta data log files are created. +*
Disabled if _false_, enabled if _true_. +*
"path" char* "" (empty) Path to directory where log files are written. +*
The path length must be less than 256 characters. +*
Relative and absolute paths with separators ( / ) or ( \\ ) are supported. +*
( . ) indicates the working directory and ( .. ) the parent directory. +*
File logging is not available on embedded platforms (e.g. ARM Cortex-M). +*
This is applicable to all parameters with the suffix "_logging" in its name. +*
"pm_logging" bool false Set if particulate matter output log files are created. +*
Disabled if _false_, enabled if _true_. +*
"integration_time" float s 10 Measurement window. +*
In duty cycling mode, this measurement window is also the sensor ON time. +*
"duty_cycling_period" uint16_t s 30 Duty cycling period (sum of integration time and sensor OFF / sleep time). +*
This must be greater than integration time by at least 2 seconds. +*
"do_obstruction_detection" bool true Set if obstruction detection feature is enabled. +*
"do_vibration_filtering" bool false Set if vibration filter is enabled. +*
"measurement_algorithm" bmv080_measurement_algorithm_t E_BMV080_MEASUREMENT_ALGORITHM_HIGH_PRECISION (3) Selection of measurement algorithm based on the +*
use case, as defined by the type bmv080_measurement_algorithm_t, +*
in bmv080_defs.h. For a duty cycling measurement, this parameter is +*
fixed to E_BMV080_MEASUREMENT_ALGORITHM_FAST_RESPONSE. +*
+* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* @pre This function must be called before _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_ +* in order to apply the parameter in the configuration of particle measurement. +* +* @param[in] handle : Unique handle for a sensor unit. +* @param[in] key : Key of the parameter to set. Valid keys are listed in table \ref parameter. +* @param[in] value : Value of the parameter to set of the in table \ref parameter listed type casted as void-pointer. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_set_parameter(const bmv080_handle_t handle, const char* key, const void* value); + +/*! +* @brief Get the sensor ID of a sensor unit. +* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* @pre The char array _id_ must have been allocated by the application with a size of 13 elements. +* +* @param[in] handle : Unique handle for a sensor unit. +* @param[out] id : Character array of 13 elements. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_get_sensor_id(const bmv080_handle_t handle, char id[13]); + +/*! +* @brief Start particle measurement in continuous mode. +* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* @pre Optionally, parameters can be set by preceding _bmv080_set_parameter_ calls. +* @post The measurement mode increases energy consumption. +* @post The sensor unit stays in measurement mode until _bmv080_stop_measurement_ is called. +* @post In measurement mode, _bmv080_serve_interrupt_ should be called regularly. +* +* @param[in] handle : Unique handle for a sensor unit. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_start_continuous_measurement(const bmv080_handle_t handle); + +/*! +* @brief Start particle measurement in duty cycling mode +* +* @pre A valid _handle_ generated by _bmv080_open_ is required. +* @pre Optionally, duty cycling parameters (integration_time and duty_cycling_period) can be set by preceding _bmv080_set_parameter_ calls. +* @post The sensor unit stays in duty cycling mode until _bmv080_stop_measurement_ is called. +* @post In measurement mode, _bmv080_serve_interrupt_ should be called regularly. +* +* @param[in] handle : Unique handle for a sensor unit. +* @param[in] get_tick_ms : Function pointer that provides a tick value in milliseconds (based on the host system clock). +* @param[in] duty_cycling_mode : Mode of performing the duty cycling measurement. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_start_duty_cycling_measurement(const bmv080_handle_t handle, const bmv080_callback_tick_t get_tick_ms, + bmv080_duty_cycling_mode_t duty_cycling_mode); + +/*! +* @brief Serve an interrupt using a callback function. +* +* @pre A valid _handle_ generated by _bmv080_open_ is required and +* the sensor unit entered measurement mode via _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_. +* @pre The application can call this function every time the sensor or the application triggers an interrupt. +* This interrupt may be a type of a software timeout (e.g. at least once per second) or a hardware interrupt (e.g. FIFO watermark exceeded). +* @pre This function tolerates very frequent or random calls to a certain extent. +* However, not calling _bmv080_serve_interrupt_ over longer periods might impair the measurement mode since events might be missed. +* @pre In continuous mode, new sensor output is available every second +* Hence, _data_ready_ is called once every second of the sensor unit's uptime. +* For example, if _bmv080_serve_interrupt_ is called 5 seconds after _bmv080_start_continuous_measurement_, +* the callback function _data_ready_ would subsequently be called 5 times to report the collected sensor output of each period. +* @pre In duty cycling mode, new sensor output is available every duty cycling period. +* Hence, _data_ready_ is called at the end of the integration time, once every duty cycling period. +* Note, _bmv080_serve_interrupt_ must be called at least once per second. +* @pre The recommendation is to call this function based on hardware interrupts. +* @pre The callback function _bmv080_callback_data_ready_t_ and the according _callback_parameter_ are provided by the caller application. +* @post Interrupt condition is served, e.g. FIFO is fetched or ASIC condition is solved +* +* @param[in] handle : Unique handle for a sensor unit. +* @param[in] data_ready : User defined callback function which is called when sensor output is available. +* @param[in] callback_parameters : User defined parameters to be passed to the callback function. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_serve_interrupt(const bmv080_handle_t handle, bmv080_callback_data_ready_t data_ready, void* callback_parameters); + +/*! +* @brief Stop particle measurement. +* +* @pre A valid _handle_ generated by _bmv080_open_ is required and +* the sensor unit entered measurement mode via _bmv080_start_continuous_measurement_ or _bmv080_start_duty_cycling_measurement_. +* @pre Must be called at the end of a data acquisition cycle to ensure that the sensor unit is ready for the next measurement cycle. +* +* @param[in] handle : Unique handle for a sensor unit. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_stop_measurement(const bmv080_handle_t handle); + +/*! +* @brief Close the sensor unit. +* +* @pre Must be called last in order to destroy the _handle_ created by _bmv080_open_. +* +* @param[in] handle : Unique handle for a sensor unit. +* +* @return E_BMV080_OK if successful, otherwise the return value is a BMV080 status code. +*/ +bmv080_status_code_t bmv080_close(bmv080_handle_t* handle); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* BMV080_H_ */ diff --git a/src/bmv080_defs.h b/src/sfTk/bmv080_defs.h similarity index 93% rename from src/bmv080_defs.h rename to src/sfTk/bmv080_defs.h index be08636..e349468 100644 --- a/src/bmv080_defs.h +++ b/src/sfTk/bmv080_defs.h @@ -1,471 +1,488 @@ -/** - * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. - * - * Disclaimer - * - * Common: - * Bosch Sensortec products are developed for the consumer goods industry. They may only be used - * within the parameters of the respective valid product data sheet. Bosch Sensortec products are - * provided with the express understanding that there is no warranty of fitness for a particular purpose. - * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device - * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, - * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. - * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The - * examination of fitness for the intended use is the sole responsibility of the Purchaser. - * - * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for - * incidental, or consequential damages, arising from any product use not covered by the parameters of - * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch - * Sensortec for all costs in connection with such claims. - * - * The purchaser must monitor the market for the purchased products, particularly with regard to - * product safety and inform Bosch Sensortec without delay of all security relevant incidents. - * - * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid - * technical specifications of the product series. They are therefore not intended or fit for resale to third - * parties or for use in end products. Their sole purpose is internal client testing. The testing of an - * engineering sample may in no way replace the testing of a product series. Bosch Sensortec - * assumes no liability for the use of engineering samples. By accepting the engineering samples, the - * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering - * samples. - * - * Special: - * This software module (hereinafter called "Software") and any information on application-sheets - * (hereinafter called "Information") is provided free of charge for the sole purpose to support your - * application work. The Software and Information is subject to the following terms and conditions: - * - * The Software is specifically designed for the exclusive use for Bosch Sensortec products by - * personnel who have special experience and training. Do not use this Software if you do not have the - * proper experience or training. - * - * This Software package is provided `` as is `` and without any expressed or implied warranties, - * including without limitation, the implied warranties of merchantability and fitness for a particular - * purpose. - * - * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment - * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their - * representatives and agents shall not be liable for any direct or indirect damages or injury, except as - * otherwise stipulated in mandatory applicable law. - * - * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no - * responsibility for the consequences of use of such Information nor for any infringement of patents or - * other rights of third parties which may result from its use. No license is granted by implication or - * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are - * subject to change without notice. - * - * It is not allowed to deliver the source code of the Software to any third party without permission of - * Bosch Sensortec. - * - * @file bmv080_defs.h - * - * @brief BMV080 sensor driver definitions - * - * - */ - -#ifndef BMV080_DEFS_H_ -#define BMV080_DEFS_H_ - -#include -#include - -/********************************************************************************************************************* -* Type definitions -*********************************************************************************************************************/ - -/*! -* @brief Status codes returned by the BMV080 sensor driver. -*/ -typedef enum -{ - /* Ok ***********************************************************************************************************/ - - /*! 0: Default result on success or if there is no warning / error. */ - E_BMV080_OK = 0, - - /* Warnings *****************************************************************************************************/ - - /*! 1: Misuse detected in BMV080 API integration. */ - E_BMV080_WARNING_INVALID_REG_READ = 1, - /*! 2: Misuse detected in BMV080 API integration. */ - E_BMV080_WARNING_INVALID_REG_WRITE = 2, - - /*! 3: Misuse detected in BMV080 API integration. - * Hint: Please review SPI / I2C implementation, specifically multi-word reads. - */ - E_BMV080_WARNING_FIFO_READ = 3, - - /*! 4: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. - * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, - * or remove potential obstructions from field of view. - */ - E_BMV080_WARNING_FIFO_EVENTS_OVERFLOW = 4, - - /*! 208: Misuse detected in BMV080 API integration. */ - E_BMV080_WARNING_FIFO_SW_BUFFER_SIZE = 208, - /*! 209: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. - * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, - * or remove potential obstructions from field of view. - */ - E_BMV080_WARNING_FIFO_HW_BUFFER_SIZE = 209, - - /* Errors *******************************************************************************************************/ - - /*! 100: Misuse detected in BMV080 API integration. A reference points to an invalid / null address. - * Hint: Please check the pointer arguments of the API e.g. device handle. - */ - E_BMV080_ERROR_NULLPTR = 100, - - /*! 101: Misuse detected in BMV080 API integration. */ - E_BMV080_ERROR_REG_ADDR = 101, - - /*! 179: The sensor parameter is locked during measurement. - * Hint: Please configure BMV080 file logging (e.g. path) before starting a measurement. - * This is valid for general purpose platforms. - */ - E_BMV080_ERROR_PARAM_LOCKED = 179, - /*! 115: The parameter key is invalid. - * Hint: Invalid key provided to bmv080_set_parameters or bmv080_get_parameters APIs. - */ - E_BMV080_ERROR_PARAM_INVALID = 115, - /*! 102: Misuse detected in BMV080 API integration */ - E_BMV080_ERROR_PARAM_INVALID_CHANNEL = 102, - /*! 123: The parameter's value is invalid. - * Hint: Please provide correct value to bmv080_set_parameters API (e.g. duty_cycling_period) - * as specified in the API documentation. - */ - E_BMV080_ERROR_PARAM_INVALID_VALUE = 123, - /*! 104: Misuse detected in BMV080 API integration. */ - E_BMV080_ERROR_PARAM_INVALID_INTERNAL_CONFIG = 104, - - /*! 180: An API call is invalid because a precondition is still unsatisfied. - * Hint: Please ensure correct 'API calling sequence' or handle previously occurred errors. - */ - E_BMV080_ERROR_PRECONDITION_UNSATISFIED = 180, - - /*! 105: Reading via the provided hardware communication interface failed. - * Hint: Please review communication or implementation of SPI / I2C read function. - */ - E_BMV080_ERROR_HW_READ = 105, - /*! 106: Writing via the provided hardware communication interface failed. - * Hint: Please review communication or implementation of SPI / I2C write function. - */ - E_BMV080_ERROR_HW_WRITE = 106, - - /*! 107: The immutable "chip id" changed. - * Hint: Please review communication or implementation of SPI / I2C interface. - */ - E_BMV080_ERROR_MISMATCH_CHIP_ID = 107, - /*! 160: Misuse detected in BMV080 API integration. */ - E_BMV080_ERROR_MISMATCH_REG_VALUE = 160, - - /*! 116: The requested operation mode is invalid. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_OPERATION_MODE_INVALID = 116, - /*! 113: Changing to the requested operation mode failed. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_OPERATION_MODE_CHANGE = 113, - /*! 114: The operation modes of different channels are out of sync. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_OPERATION_MODE_CHANNELS_OUT_OF_SYNC = 114, - /*! 157: Misuse detected in BMV080 API integration. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_ASIC_NOT_CONFIGURED = 157, - - /*! 133: Memory read failed. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_MEM_READ = 133, - /*! 135: Misuse detected in BMV080 API integration. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_ADDRESS = 135, - /*! 136: Memory command failed. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_MEM_CMD = 136, - /*! 137: Memory access timeout. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_MEM_TIMEOUT = 137, - /*! 138: Misuse detected in BMV080 API integration. */ - E_BMV080_ERROR_MEM_INVALID = 138, - /*! 139: Misuse detected in BMV080 API integration. */ - E_BMV080_ERROR_MEM_OBSOLETE = 139, - /*! 140: Changing to the requested operation mode failed. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_MEM_OPERATION_MODE = 140, - /*! 153: Memory data integrity check failed. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_DATA_INTEGRITY = 153, - /*! 154: Memory data integrity check for internal test 1 region failed. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_DATA_INTEGRITY_INTERNAL_TEST_1 = 154, - /*! 156: Memory check for internal test 1 region failed. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_INTERNAL_TEST_1 = 156, - /*! 159: Memory data integrity check for internal test 2 region failed. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_DATA_INTEGRITY_INTERNAL_TEST_2 = 159, - /*! 161: Memory check for internal test 2 region failed. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_MEM_INTERNAL_TEST_2 = 161, - - /*! 210: Misuse detected in BMV080 API integration. - * Hint: Please review SPI / I2C implementation. - */ - E_BMV080_ERROR_FIFO_FORMAT = 210, - /*! 213: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. - * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, - * or remove potential obstructions from field of view. - */ - E_BMV080_ERROR_FIFO_EVENTS_COUNT_SATURATED = 213, - /*! 174: Misuse detected in BMV080 API integration. - * Hint: Please review SPI / I2C implementation and check that power provided to BMV080 is sufficient & stable. - */ - E_BMV080_ERROR_FIFO_UNAVAILABLE = 174, - /*! 214: Misuse detected in BMV080 API integration. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_FIFO_EVENTS_COUNT_DIFF = 214, - - /*! 161: An error occurred regarding the communication synchronization. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_SYNC_COMM = 161, - /*! 162: An error occurred regarding the control synchronization. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_SYNC_CTRL = 162, - /*! 163: An error occurred regarding the measurement synchronization. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_SYNC_MEAS = 163, - /*! 164: An error occurred regarding a locked synchronization. - * Hint: Please check that power provided to BMV080 is sufficient & stable. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_SYNC_LOCKED = 164, - /*! 165: An error occurred regarding the DC cancellation range. - * Hint: Please check thermal integration and/or remove potential obstructions from field of view. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_DC_CANCEL_RANGE = 165, - /*! 166: An error occurred regarding the DC estimation range. - * Hint: Please check thermal integration and/or remove potential obstructions from field of view. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_DC_ESTIM_RANGE = 166, - /*! 167: Misuse detected in BMV080 API integration. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_LPWR_T = 167, - /*! 168: An error occurred regarding LPWR range. - * Hint: Please check thermal integration sensor wear-out, humidity, - * and/or remove potential obstructions from field of view. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_LPWR_RANGE = 168, - /*! 169: An error occurred regarding the power domain. - * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL, VDDA or VSS). - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_POWER_DOMAIN = 169, - /*! 170: An error occurred regarding the headroom detection. - * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_HEADROOM_VDDL = 170, - /*! 171: An error occurred regarding the headroom LDV output. - * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_HEADROOM_LDV_OUTPUT = 171, - /*! 172: An error occurred regarding the headroom LDV reference. - * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_HEADROOM_LDV_REF = 172, - /*! 173: An error occurred regarding the user headroom detection. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_HEADROOM_INTERNAL = 173, - /*! 120: An error occurred due to a safety precaution mechanism. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_SAFETY_PRECAUTION = 120, - /*! 211: Possible communication issue on SPI/I2C - * or too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. - * Hint: Please review communication or implementation of SPI / I2C interface. - */ - E_BMV080_ERROR_TIMESTAMP_DIFFERENCE = 211, - /*! 212: The timestamp is smaller than the previous timestamp. - * Hint: Please review communication or implementation of SPI / I2C interface. - */ - E_BMV080_ERROR_TIMESTAMP_OVERFLOW = 212, - - /*! 300: BMV080 libraries are incompatible with each other. - * Hint: Please use compatible API libraries from the same SW package. - */ - E_BMV080_ERROR_LIB_VERSION_INCOMPATIBLE = 300, - /*! 301: Hint: Please contact BST customer support team. */ - E_BMV080_ERROR_INTERNAL_PARAMETER_VERSION_INVALID = 301, - /*! 302: Hint: Please contact BST customer support team. */ - E_BMV080_ERROR_INTERNAL_PARAMETER_INDEX_INVALID = 302, - - /*! 403: FIFO level invalid leading to memory allocation issue. - * Hint: Please review communication or implementation of SPI / I2C read function. - * If the problem is not resolved, please contact BST customer support team. - */ - E_BMV080_ERROR_MEMORY_ALLOCATION = 403, - - /*! 303: A linked delay callback function produced an error. - * Hint: callback function of type bmv080_callback_delay_t does not return 0, - * when it is called internally to perform a delay operation. - * Please check implementation of the delay function. - */ - E_BMV080_ERROR_CALLBACK_DELAY = 303, - - /*! 418: Sensor driver is not compatible with the used sensor HW sample. - * Hint: Please contact BST customer support team. - */ - E_BMV080_ERROR_INCOMPATIBLE_SENSOR_HW = 418 -}bmv080_status_code_t; - -/*! -* @brief Unique handle for a sensor unit. -*/ -typedef void* bmv080_handle_t; - -/*! -* @brief Unique handle for a serial communication, i.e. the hardware connection to the sensor unit. -*/ -typedef void* bmv080_sercom_handle_t; - -/*! -* @brief Modes of performing a duty cycling measurement. -*/ -typedef enum -{ - /*! 0: Mode with fixed duty cycle, ON time = integration_time and OFF time = sleep time */ - E_BMV080_DUTY_CYCLING_MODE_0 = 0 -} bmv080_duty_cycling_mode_t; - -/*! -* @brief Placeholder structure for extended sensor output information. -*/ -struct bmv080_extended_info_s; - -/*! -* @brief Output structure which is updated by bmv080_serve_interrupt when sensor output is available. -*/ -typedef struct -{ - /*! reserved_0: for internal use only */ - float reserved_0; - /*! reserved_1: for internal use only */ - float reserved_1; - /*! reserved_2: for internal use only */ - float reserved_2; - /*! pm2_5: PM2.5 value in ug/m3 */ - float pm2_5; - /*! runtime_in_sec: estimate of the time passed since the start of the measurement, in seconds */ - float runtime_in_sec; - /*! is_obstructed: flag to indicate whether the sensor is obstructed and cannot perform a valid measurement */ - bool is_obstructed; - /*! is_outside_detection_limits: flag to indicate whether the PM2.5 concentration is outside the detection limits - * and a valid measurement cannot be performed - */ - bool is_outside_detection_limits; - /*! extended_info: for internal use only */ - struct bmv080_extended_info_s *extended_info; -}bmv080_output_t; - - -/********************************************************************************************************************* -* Callback definitions -*********************************************************************************************************************/ - -/*! -* @brief Function pointer for reading an array of _payload_length_ words of 16 bit _payload_. -* -* @details All data, _header_ and _payload_, is transferred as MSB first. -* -* @pre Both _header_ and _payload_ words are 16 bit and combined. -* A _payload_ is only transferred on a complete transmission of 16 bits. -* @pre Burst transfers, i.e. reading a _header_ followed by several _payload_ elements, must be supported. -* -* @param[in] sercom_handle : Handle for a serial communication interface to a specific sensor unit. -* @param[in] header : Header information for the following _payload_. -* @param[out] payload : Payload to be read consisting of 16 bit words. -* @param[in] payload_length : Number of _payload_ elements to be read. -* -* @return Zero if successful, otherwise the return value is an externally defined error code. -*/ -typedef int8_t(*bmv080_callback_read_t)(bmv080_sercom_handle_t sercom_handle, uint16_t header, uint16_t* payload, - uint16_t payload_length); - -/*! -* @brief Function pointer for writing an array of _payload_length_ words of 16 bit _payload_. -* -* @details All data, _header_ and _payload_, is transferred as MSB first. -* -* @pre Both _header_ and _payload_ words are 16 bit. -* A _payload_ is only transferred on a complete transmission of 16 bits. -* @pre Burst transfers, i.e. writing a _header_ followed by several _payload_ elements, must be supported. -* -* @param[in] sercom_handle : Handle for a serial communication interface to a specific sensor unit. -* @param[in] header : Header information for the following _payload_. -* @param[in] payload : Payload to be written consisting of 16 bit words. -* @param[in] payload_length : Number of _payload_ elements to be written. -* -* @return Zero if successful, otherwise the return value is an externally defined error code. -*/ -typedef int8_t(*bmv080_callback_write_t)(bmv080_sercom_handle_t sercom_handle, uint16_t header, const uint16_t* payload, - uint16_t payload_length); - -/*! -* @brief Function pointer for executing a software delay operation. -* -* @param[in] duration_in_ms : Duration of the delay in milliseconds. -* -* @return Zero if successful, otherwise the return value is an externally defined error code. -*/ -typedef int8_t(*bmv080_callback_delay_t)(uint32_t duration_in_ms); - -/*! -* @brief Function pointer for getting a tick value in milliseconds (based on the host system clock). -* -* @details This serves as a measure of the elapsed time since start up, -* .e.g uint32_t HAL_GetTick(void) of the STM32 HAL Framework or uint32_t GetTickCount(void) of the Windows API. -* -* @return Tick value in milliseconds -*/ -typedef uint32_t(*bmv080_callback_tick_t)(void); - -/*! -* @brief Function pointer for handling the sensor's output information. -* -* @param[in] bmv080_output : Structure containing sensor output. -* @param[inout] callback_parameters : user defined parameters to be passed to the callback function. -*/ -typedef void(*bmv080_callback_data_ready_t)(bmv080_output_t bmv080_output, void* callback_parameters); - - -/* Function pointer to facilitate printing output / status information to the console */ -typedef int (*print_function_t)(const char *const _format, ...); - -#endif /* BMV080_DEFS_H_ */ +/** + * Copyright (C) Bosch Sensortec GmbH. All Rights Reserved. Confidential. + * + * Disclaimer + * + * Common: + * Bosch Sensortec products are developed for the consumer goods industry. They may only be used + * within the parameters of the respective valid product data sheet. Bosch Sensortec products are + * provided with the express understanding that there is no warranty of fitness for a particular purpose. + * They are not fit for use in life-sustaining, safety or security sensitive systems or any system or device + * that may lead to bodily harm or property damage if the system or device malfunctions. In addition, + * Bosch Sensortec products are not fit for use in products which interact with motor vehicle systems. + * The resale and/or use of products are at the purchaser's own risk and his own responsibility. The + * examination of fitness for the intended use is the sole responsibility of the Purchaser. + * + * The purchaser shall indemnify Bosch Sensortec from all third party claims, including any claims for + * incidental, or consequential damages, arising from any product use not covered by the parameters of + * the respective valid product data sheet or not approved by Bosch Sensortec and reimburse Bosch + * Sensortec for all costs in connection with such claims. + * + * The purchaser must monitor the market for the purchased products, particularly with regard to + * product safety and inform Bosch Sensortec without delay of all security relevant incidents. + * + * Engineering Samples are marked with an asterisk (*) or (e). Samples may vary from the valid + * technical specifications of the product series. They are therefore not intended or fit for resale to third + * parties or for use in end products. Their sole purpose is internal client testing. The testing of an + * engineering sample may in no way replace the testing of a product series. Bosch Sensortec + * assumes no liability for the use of engineering samples. By accepting the engineering samples, the + * Purchaser agrees to indemnify Bosch Sensortec from all claims arising from the use of engineering + * samples. + * + * Special: + * This software module (hereinafter called "Software") and any information on application-sheets + * (hereinafter called "Information") is provided free of charge for the sole purpose to support your + * application work. The Software and Information is subject to the following terms and conditions: + * + * The Software is specifically designed for the exclusive use for Bosch Sensortec products by + * personnel who have special experience and training. Do not use this Software if you do not have the + * proper experience or training. + * + * This Software package is provided `` as is `` and without any expressed or implied warranties, + * including without limitation, the implied warranties of merchantability and fitness for a particular + * purpose. + * + * Bosch Sensortec and their representatives and agents deny any liability for the functional impairment + * of this Software in terms of fitness, performance and safety. Bosch Sensortec and their + * representatives and agents shall not be liable for any direct or indirect damages or injury, except as + * otherwise stipulated in mandatory applicable law. + * + * The Information provided is believed to be accurate and reliable. Bosch Sensortec assumes no + * responsibility for the consequences of use of such Information nor for any infringement of patents or + * other rights of third parties which may result from its use. No license is granted by implication or + * otherwise under any patent or patent rights of Bosch. Specifications mentioned in the Information are + * subject to change without notice. + * + * It is not allowed to deliver the source code of the Software to any third party without permission of + * Bosch Sensortec. + * + * @file bmv080_defs.h + * + * @brief BMV080 sensor driver definitions + * + * + */ + +#ifndef BMV080_DEFS_H_ +#define BMV080_DEFS_H_ + +#include +#include + +/********************************************************************************************************************* +* Type definitions +*********************************************************************************************************************/ + +/*! +* @brief Status codes returned by the BMV080 sensor driver. +*/ +typedef enum +{ + /* Ok ***********************************************************************************************************/ + + /*! 0: Default result on success or if there is no warning / error. */ + E_BMV080_OK = 0, + + /* Warnings *****************************************************************************************************/ + + /*! 1: Misuse detected in BMV080 API integration. */ + E_BMV080_WARNING_INVALID_REG_READ = 1, + /*! 2: Misuse detected in BMV080 API integration. */ + E_BMV080_WARNING_INVALID_REG_WRITE = 2, + + /*! 3: Misuse detected in BMV080 API integration. + * Hint: Please review SPI / I2C implementation, specifically multi-word reads. + */ + E_BMV080_WARNING_FIFO_READ = 3, + + /*! 4: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. + * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, + * or remove potential obstructions from field of view. + */ + E_BMV080_WARNING_FIFO_EVENTS_OVERFLOW = 4, + + /*! 208: Misuse detected in BMV080 API integration. */ + E_BMV080_WARNING_FIFO_SW_BUFFER_SIZE = 208, + /*! 209: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. + * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, + * or remove potential obstructions from field of view. + */ + E_BMV080_WARNING_FIFO_HW_BUFFER_SIZE = 209, + + /* Errors *******************************************************************************************************/ + + /*! 100: Misuse detected in BMV080 API integration. A reference points to an invalid / null address. + * Hint: Please check the pointer arguments of the API e.g. device handle. + */ + E_BMV080_ERROR_NULLPTR = 100, + + /*! 101: Misuse detected in BMV080 API integration. */ + E_BMV080_ERROR_REG_ADDR = 101, + + /*! 179: The sensor parameter is locked during measurement. + * Hint: Please configure BMV080 file logging (e.g. path) before starting a measurement. + * This is valid for general purpose platforms. + */ + E_BMV080_ERROR_PARAM_LOCKED = 179, + /*! 115: The parameter key is invalid. + * Hint: Invalid key provided to bmv080_set_parameters or bmv080_get_parameters APIs. + */ + E_BMV080_ERROR_PARAM_INVALID = 115, + /*! 102: Misuse detected in BMV080 API integration */ + E_BMV080_ERROR_PARAM_INVALID_CHANNEL = 102, + /*! 123: The parameter's value is invalid. + * Hint: Please provide correct value to bmv080_set_parameters API (e.g. duty_cycling_period) + * as specified in the API documentation. + */ + E_BMV080_ERROR_PARAM_INVALID_VALUE = 123, + /*! 104: Misuse detected in BMV080 API integration. */ + E_BMV080_ERROR_PARAM_INVALID_INTERNAL_CONFIG = 104, + + /*! 180: An API call is invalid because a precondition is still unsatisfied. + * Hint: Please ensure correct 'API calling sequence' or handle previously occurred errors. + */ + E_BMV080_ERROR_PRECONDITION_UNSATISFIED = 180, + + /*! 105: Reading via the provided hardware communication interface failed. + * Hint: Please review communication or implementation of SPI / I2C read function. + */ + E_BMV080_ERROR_HW_READ = 105, + /*! 106: Writing via the provided hardware communication interface failed. + * Hint: Please review communication or implementation of SPI / I2C write function. + */ + E_BMV080_ERROR_HW_WRITE = 106, + + /*! 107: The immutable "chip id" changed. + * Hint: Please review communication or implementation of SPI / I2C interface. + */ + E_BMV080_ERROR_MISMATCH_CHIP_ID = 107, + /*! 160: Misuse detected in BMV080 API integration. */ + E_BMV080_ERROR_MISMATCH_REG_VALUE = 160, + + /*! 116: The requested operation mode is invalid. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_OPERATION_MODE_INVALID = 116, + /*! 113: Changing to the requested operation mode failed. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_OPERATION_MODE_CHANGE = 113, + /*! 114: The operation modes of different channels are out of sync. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_OPERATION_MODE_CHANNELS_OUT_OF_SYNC = 114, + /*! 157: Misuse detected in BMV080 API integration. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_ASIC_NOT_CONFIGURED = 157, + + /*! 133: Memory read failed. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_MEM_READ = 133, + /*! 135: Misuse detected in BMV080 API integration. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_ADDRESS = 135, + /*! 136: Memory command failed. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_MEM_CMD = 136, + /*! 137: Memory access timeout. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_MEM_TIMEOUT = 137, + /*! 138: Misuse detected in BMV080 API integration. */ + E_BMV080_ERROR_MEM_INVALID = 138, + /*! 139: Misuse detected in BMV080 API integration. */ + E_BMV080_ERROR_MEM_OBSOLETE = 139, + /*! 140: Changing to the requested operation mode failed. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_MEM_OPERATION_MODE = 140, + /*! 153: Memory data integrity check failed. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_DATA_INTEGRITY = 153, + /*! 154: Memory data integrity check for internal test 1 region failed. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_DATA_INTEGRITY_INTERNAL_TEST_1 = 154, + /*! 156: Memory check for internal test 1 region failed. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_INTERNAL_TEST_1 = 156, + /*! 159: Memory data integrity check for internal test 2 region failed. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_DATA_INTEGRITY_INTERNAL_TEST_2 = 159, + /*! 161: Memory check for internal test 2 region failed. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_MEM_INTERNAL_TEST_2 = 161, + + /*! 210: Misuse detected in BMV080 API integration. + * Hint: Please review SPI / I2C implementation. + */ + E_BMV080_ERROR_FIFO_FORMAT = 210, + /*! 213: Too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. + * Hint: Call bmv080_serve_interrupt more frequently, or switch from polling to interrupt based use, + * or remove potential obstructions from field of view. + */ + E_BMV080_ERROR_FIFO_EVENTS_COUNT_SATURATED = 213, + /*! 174: Misuse detected in BMV080 API integration. + * Hint: Please review SPI / I2C implementation and check that power provided to BMV080 is sufficient & stable. + */ + E_BMV080_ERROR_FIFO_UNAVAILABLE = 174, + /*! 214: Misuse detected in BMV080 API integration. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_FIFO_EVENTS_COUNT_DIFF = 214, + + /*! 161: An error occurred regarding the communication synchronization. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_SYNC_COMM = 161, + /*! 162: An error occurred regarding the control synchronization. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_SYNC_CTRL = 162, + /*! 163: An error occurred regarding the measurement synchronization. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_SYNC_MEAS = 163, + /*! 164: An error occurred regarding a locked synchronization. + * Hint: Please check that power provided to BMV080 is sufficient & stable. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_SYNC_LOCKED = 164, + /*! 165: An error occurred regarding the DC cancellation range. + * Hint: Please check thermal integration and/or remove potential obstructions from field of view. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_DC_CANCEL_RANGE = 165, + /*! 166: An error occurred regarding the DC estimation range. + * Hint: Please check thermal integration and/or remove potential obstructions from field of view. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_DC_ESTIM_RANGE = 166, + /*! 167: Misuse detected in BMV080 API integration. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_LPWR_T = 167, + /*! 168: An error occurred regarding LPWR range. + * Hint: Please check thermal integration sensor wear-out, humidity, + * and/or remove potential obstructions from field of view. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_LPWR_RANGE = 168, + /*! 169: An error occurred regarding the power domain. + * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL, VDDA or VSS). + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_POWER_DOMAIN = 169, + /*! 170: An error occurred regarding the headroom detection. + * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_HEADROOM_VDDL = 170, + /*! 171: An error occurred regarding the headroom LDV output. + * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_HEADROOM_LDV_OUTPUT = 171, + /*! 172: An error occurred regarding the headroom LDV reference. + * Hint: Please check that power provided to BMV080 is sufficient & stable (VDDL). + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_HEADROOM_LDV_REF = 172, + /*! 173: An error occurred regarding the user headroom detection. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_HEADROOM_INTERNAL = 173, + /*! 120: An error occurred due to a safety precaution mechanism. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_SAFETY_PRECAUTION = 120, + /*! 211: Possible communication issue on SPI/I2C + * or too many particle / obstruction events detected than can be processed by bmv080_serve_interrupt API. + * Hint: Please review communication or implementation of SPI / I2C interface. + */ + E_BMV080_ERROR_TIMESTAMP_DIFFERENCE = 211, + /*! 212: The timestamp is smaller than the previous timestamp. + * Hint: Please review communication or implementation of SPI / I2C interface. + */ + E_BMV080_ERROR_TIMESTAMP_OVERFLOW = 212, + + /*! 300: BMV080 libraries are incompatible with each other. + * Hint: Please use compatible API libraries from the same SW package. + */ + E_BMV080_ERROR_LIB_VERSION_INCOMPATIBLE = 300, + /*! 301: Hint: Please contact BST customer support team. */ + E_BMV080_ERROR_INTERNAL_PARAMETER_VERSION_INVALID = 301, + /*! 302: Hint: Please contact BST customer support team. */ + E_BMV080_ERROR_INTERNAL_PARAMETER_INDEX_INVALID = 302, + + /*! 403: FIFO level invalid leading to memory allocation issue. + * Hint: Please review communication or implementation of SPI / I2C read function. + * If the problem is not resolved, please contact BST customer support team. + */ + E_BMV080_ERROR_MEMORY_ALLOCATION = 403, + + /*! 303: A linked delay callback function produced an error. + * Hint: callback function of type bmv080_callback_delay_t does not return 0, + * when it is called internally to perform a delay operation. + * Please check implementation of the delay function. + */ + E_BMV080_ERROR_CALLBACK_DELAY = 303, + + /*! 418: Sensor driver is not compatible with the used sensor HW sample. + * Hint: Please contact BST customer support team. + */ + E_BMV080_ERROR_INCOMPATIBLE_SENSOR_HW = 418 +}bmv080_status_code_t; + +/*! +* @brief Unique handle for a sensor unit. +*/ +typedef void* bmv080_handle_t; + +/*! +* @brief Unique handle for a serial communication, i.e. the hardware connection to the sensor unit. +*/ +typedef void* bmv080_sercom_handle_t; + +/*! +* @brief Modes of performing a duty cycling measurement. +*/ +typedef enum +{ + /*! 0: Mode with fixed duty cycle, ON time = integration_time and OFF time = sleep time */ + E_BMV080_DUTY_CYCLING_MODE_0 = 0 +} bmv080_duty_cycling_mode_t; + +/*! +* @brief Measurement algorithm choices. +*/ +typedef enum +{ + E_BMV080_MEASUREMENT_ALGORITHM_FAST_RESPONSE = 1, + E_BMV080_MEASUREMENT_ALGORITHM_BALANCED = 2, + E_BMV080_MEASUREMENT_ALGORITHM_HIGH_PRECISION = 3 +} bmv080_measurement_algorithm_t; + +/*! +* @brief Placeholder structure for extended sensor output information. +*/ +struct bmv080_extended_info_s; + +/*! +* @brief Output structure which is updated by bmv080_serve_interrupt when sensor output is available. +*/ +typedef struct +{ + /*! runtime_in_sec: estimate of the time passed since the start of the measurement, in seconds */ + float runtime_in_sec; + /*! pm2_5_mass_concentration: PM2.5 value in ug/m3 */ + float pm2_5_mass_concentration; + /*! pm1_mass_concentration: PM1 value in ug/m3 */ + float pm1_mass_concentration; + /*! pm10_mass_concentration: PM10 value in ug/m3 */ + float pm10_mass_concentration; + + /*! pm2_5_number_concentration: PM2.5 value in particles/cm3 */ + float pm2_5_number_concentration; + /*! pm1_number_concentration: PM1 value in particles/cm3 */ + float pm1_number_concentration; + /*! pm10_number_concentration: PM10 value in particles/cm3 */ + float pm10_number_concentration; + + /*! is_obstructed: flag to indicate whether the sensor is obstructed and cannot perform a valid measurement */ + bool is_obstructed; + /*! is_outside_measurement_range: flag to indicate whether the PM2.5 concentration is + * outside the specified measurement range (0..1000 ug/m3) + */ + bool is_outside_measurement_range; + /*! reserved_0: for internal use only */ + float reserved_0; + /*! reserved_1: for internal use only */ + float reserved_1; + /*! reserved_2: for internal use only */ + float reserved_2; + /*! extended_info: for internal use only */ + struct bmv080_extended_info_s *extended_info; +}bmv080_output_t; + +/********************************************************************************************************************* +* Callback definitions +*********************************************************************************************************************/ + +/*! +* @brief Function pointer for reading an array of _payload_length_ words of 16 bit _payload_. +* +* @details All data, _header_ and _payload_, is transferred as MSB first. +* +* @pre Both _header_ and _payload_ words are 16 bit and combined. +* A _payload_ is only transferred on a complete transmission of 16 bits. +* @pre Burst transfers, i.e. reading a _header_ followed by several _payload_ elements, must be supported. +* +* @param[in] sercom_handle : Handle for a serial communication interface to a specific sensor unit. +* @param[in] header : Header information for the following _payload_. +* @param[out] payload : Payload to be read consisting of 16 bit words. +* @param[in] payload_length : Number of _payload_ elements to be read. +* +* @return Zero if successful, otherwise the return value is an externally defined error code. +*/ +typedef int8_t(*bmv080_callback_read_t)(bmv080_sercom_handle_t sercom_handle, uint16_t header, uint16_t* payload, + uint16_t payload_length); + +/*! +* @brief Function pointer for writing an array of _payload_length_ words of 16 bit _payload_. +* +* @details All data, _header_ and _payload_, is transferred as MSB first. +* +* @pre Both _header_ and _payload_ words are 16 bit. +* A _payload_ is only transferred on a complete transmission of 16 bits. +* @pre Burst transfers, i.e. writing a _header_ followed by several _payload_ elements, must be supported. +* +* @param[in] sercom_handle : Handle for a serial communication interface to a specific sensor unit. +* @param[in] header : Header information for the following _payload_. +* @param[in] payload : Payload to be written consisting of 16 bit words. +* @param[in] payload_length : Number of _payload_ elements to be written. +* +* @return Zero if successful, otherwise the return value is an externally defined error code. +*/ +typedef int8_t(*bmv080_callback_write_t)(bmv080_sercom_handle_t sercom_handle, uint16_t header, const uint16_t* payload, + uint16_t payload_length); + +/*! +* @brief Function pointer for executing a software delay operation. +* +* @param[in] duration_in_ms : Duration of the delay in milliseconds. +* +* @return Zero if successful, otherwise the return value is an externally defined error code. +*/ +typedef int8_t(*bmv080_callback_delay_t)(uint32_t duration_in_ms); + +/*! +* @brief Function pointer for getting a tick value in milliseconds (based on the host system clock). +* +* @details This serves as a measure of the elapsed time since start up, +* .e.g uint32_t HAL_GetTick(void) of the STM32 HAL Framework or uint32_t GetTickCount(void) of the Windows API. +* +* @return Tick value in milliseconds +*/ +typedef uint32_t(*bmv080_callback_tick_t)(void); + +/*! +* @brief Function pointer for handling the sensor's output information. +* +* @param[in] bmv080_output : Structure containing sensor output. +* @param[inout] callback_parameters : user defined parameters to be passed to the callback function. +*/ +typedef void(*bmv080_callback_data_ready_t)(bmv080_output_t bmv080_output, void* callback_parameters); + +#endif /* BMV080_DEFS_H_ */ diff --git a/src/sfTk/sfDevBMV080.cpp b/src/sfTk/sfDevBMV080.cpp new file mode 100644 index 0000000..2cf4b1d --- /dev/null +++ b/src/sfTk/sfDevBMV080.cpp @@ -0,0 +1,431 @@ +/** + * @file sfDevBMV080.cpp + * @brief Implementation file for the SparkFun BMV080 Library + * + * This file contains the implementation of the sfDevBMV080 class, which provides + * an interface to the BMV080 sensor. It includes methods for initializing the sensor, + * reading sensor data, and configuring sensor settings. + * + * @author Pete Lewis + * @date 2025 + * @version 1.0 + * @copyright (c) 2025 SparkFun Electronics Inc. This project is released under the MIT License. + * + * SPDX-License-Identifier: MIT + * + * @see sfDevBMV080.h + */ + +#include "bmv080.h" +#include "bmv080_defs.h" +#include "sfDevBMV080.h" + +// need our bus I2C type for some I2C specific features +#include "sfTk/sfTkII2C.h" +#include "sfTk/sfToolkit.h" + +#include + +// Some communication functions used with the system. These are from the original code from +// Bosch - so keeping them the same. It is unclear if the library they provide depends on these +// specific values - it probably does - so leaving as is. + +#define E_COMBRIDGE_OK ((int8_t)0) +/*! -1: Status codes returned when memory allocation fails */ +#define E_COMBRIDGE_ERROR_MEMORY_ALLOCATION ((int8_t)-1) +/*! -2: Status codes returned when the read operation fails */ +#define E_COMBRIDGE_ERROR_READ ((int8_t)-2) +/*! -3: Status codes returned when the write operation fails */ +#define E_COMBRIDGE_ERROR_WRITE ((int8_t)-3) +/*! -4: Status codes returned when writing the header fails */ +#define E_COMBRIDGE_ERROR_WRITE_HEADER ((int8_t)-4) +/*! -5: Status codes returned when a reference is null */ +#define E_COMBRIDGE_ERROR_NULLPTR ((int8_t)-5) + +// C function used in this library only - so static + +/* Our bus read and write functions */ + +// -------------------------------------------------------------------------------------------- +// BOSCH API Callbacks +// -------------------------------------------------------------------------------------------- +// Callback for reading data-- called from the Bosch supplied library +// +// static int8_t device_read_16bit_CB(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, +int8_t sfDevBMV080::device_read_16bit_CB(bmv080_sercom_handle_t handle, uint16_t header, uint16_t *payload, + uint16_t payload_length) +{ + if (handle == nullptr) + return E_COMBRIDGE_ERROR_NULLPTR; + + // Our output var. + size_t nRead = 0; + + // Get our sparkfun toolkit bus object/interface + sfTkIBus *theBus = (sfTkIBus *)handle; + + if (theBus->type() == ksfTkBusTypeI2C) // I2C specific shift + header = header << 1; + + sfTkError_t rc = theBus->readRegister(header, payload, payload_length, nRead); + + if (rc != ksfTkErrOk || nRead != payload_length) + return E_COMBRIDGE_ERROR_READ; + + return E_COMBRIDGE_OK; +} + +// -------------------------------------------------------------------------------------------- +// Callback for reading data-- called from the Bosch supplied library +// +int8_t sfDevBMV080::device_write_16bit_CB(bmv080_sercom_handle_t handle, uint16_t header, const uint16_t *payload, + uint16_t payload_length) +{ + if (handle == nullptr) + return E_COMBRIDGE_ERROR_NULLPTR; + + sfTkIBus *theBus = (sfTkIBus *)handle; + + if (theBus->type() == ksfTkBusTypeI2C) // I2C specific shift + header = header << 1; + + sfTkError_t rc = theBus->writeRegister(header, payload, payload_length); + + // okay, not okay? + return rc == ksfTkErrOk ? E_COMBRIDGE_OK : E_COMBRIDGE_ERROR_WRITE; +} + +// -------------------------------------------------------------------------------------------- +// Delay callback function for the Bosch library +// +int8_t sfDevBMV080::device_delay_CB(uint32_t period) +{ + sftk_delay_ms(period); + // delay(period); + + return E_COMBRIDGE_OK; +} + +//--------------------------------------------------------------------- +// helpful class method/callback + +/* Custom function for consuming sensor readings */ +void sfDevBMV080::set_sensor_value(bmv080_output_t bmv080_output, void *callback_parameters) +{ + ((sfDevBMV080 *)callback_parameters)->setSensorValue(bmv080_output); +} + +//--------------------------------------------------------------------- +// End CB functions +//--------------------------------------------------------------------- +//--------------------------------------------------------------------- +// Core object implementation +//--------------------------------------------------------------------- +sfTkError_t sfDevBMV080::begin(sfTkIBus *theBus) +{ + // Nullptr check + if (theBus == nullptr) + return ksfTkErrFail; + + // Set bus pointer + _theBus = theBus; + + return ksfTkErrOk; +} + +//--------------------------------------------------------------------- +float sfDevBMV080::PM10() +{ + return _sensorValue.pm10_mass_concentration; +} + +//--------------------------------------------------------------------- +float sfDevBMV080::PM25() +{ + return _sensorValue.pm2_5_mass_concentration; +} + +//--------------------------------------------------------------------- +float sfDevBMV080::PM1() +{ + return _sensorValue.pm1_mass_concentration; +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::isObstructed() +{ + return _sensorValue.is_obstructed; +} + +//--------------------------------------------------------------------- +void sfDevBMV080::setSensorValue(bmv080_output_t bmv080_output) +{ + // TODO: should here be a mode where the library user can set register a callback function to handle the data? + // This way the end user can get all the sensor data at once - possible issue is stack/re-entrancy + _dataAvailable = true; + + // cache the latest sensor values - copy output to our class variable + _sensorValue = bmv080_output; +} + +//--------------------------------------------------------------------- +// Read the latest values from the sensor. +// +// Return the value if a struct is passed in. +bool sfDevBMV080::readSensor(bmv080_output_t *bmv080_output /* default is nullptr*/) +{ + _dataAvailable = false; + if (!sensorServiceRoutine()) + return false; + + if (_dataAvailable && bmv080_output != nullptr) + *bmv080_output = _sensorValue; + + return _dataAvailable; +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setMode(uint8_t mode) +{ + bmv080_status_code_t bmv080_current_status = + E_BMV080_ERROR_PARAM_INVALID_VALUE; // return status from the Bosch API function + + if (mode == SF_BMV080_MODE_CONTINUOUS) + { + bmv080_current_status = bmv080_start_continuous_measurement(_bmv080_handle_class); + } + else if (mode == SF_BMV080_MODE_DUTY_CYCLE) + { + bmv080_duty_cycling_mode_t duty_cycling_mode = E_BMV080_DUTY_CYCLING_MODE_0; + bmv080_current_status = bmv080_start_duty_cycling_measurement( + _bmv080_handle_class, (bmv080_callback_tick_t)sftk_ticks_ms(), duty_cycling_mode); + } + + // check if the mode was set correctly + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +// Called to pump the service routine of the BMV080 sensor driver +// + +bool sfDevBMV080::sensorServiceRoutine(void) +{ + if (_bmv080_handle_class == NULL) + return false; + /* The interrupt is served by the BMV080 sensor driver */ + bmv080_status_code_t bmv080_current_status = + bmv080_serve_interrupt(_bmv080_handle_class, (bmv080_callback_data_ready_t)set_sensor_value, (void *)this); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +// Our init method +bool sfDevBMV080::init() +{ + // Do we have a bus? + if (_theBus == nullptr) + return false; + + // Call various bosch API functions to initialize the sensor + uint16_t major, minor, patch; + char id[kBMV800IDLength]; + if (!driverVersion(major, minor, patch) || !open() || !reset() || !ID(id)) + return false; + + return true; +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::open() +{ + if (_theBus == nullptr) + return false; + + // Open the device - pass in the data read, data write and delay functions callbacks. Note - the "sercom_handle_t" + // is just a pointer to our Toolkit communication bus objects + + bmv080_status_code_t status = bmv080_open( + &_bmv080_handle_class, (bmv080_sercom_handle_t)_theBus, (bmv080_callback_read_t)device_read_16bit_CB, + (bmv080_callback_write_t)device_write_16bit_CB, (bmv080_callback_delay_t)device_delay_CB); + + return (status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::close() +{ + if (_theBus == nullptr) + return false; + + // Close the device + + bmv080_status_code_t status = bmv080_close(&_bmv080_handle_class); + + return (status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::reset() +{ + bmv080_status_code_t bmv080_current_status = bmv080_reset(_bmv080_handle_class); + + return (bmv080_current_status == E_BMV080_OK); +} +//--------------------------------------------------------------------- +bool sfDevBMV080::driverVersion(uint16_t &major, uint16_t &minor, uint16_t &patch) +{ + char git_hash[12]; + int32_t commits_ahead = 0; + + bmv080_status_code_t bmv080_current_status = + bmv080_get_driver_version(&major, &minor, &patch, git_hash, &commits_ahead); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +// Method to get the ID +bool sfDevBMV080::ID(char idOut[kBMV800IDLength]) +{ + memset(idOut, 0x00, kBMV800IDLength); + bmv080_status_code_t bmv080_current_status = bmv080_get_sensor_id(_bmv080_handle_class, idOut); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +uint16_t sfDevBMV080::dutyCyclingPeriod() +{ + uint16_t duty_cycling_period = 0; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "duty_cycling_period", (void *)&duty_cycling_period); + + return (bmv080_current_status == E_BMV080_OK ? duty_cycling_period : 0); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setDutyCyclingPeriod(uint16_t duty_cycling_period) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "duty_cycling_period", (void *)&duty_cycling_period); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +float sfDevBMV080::volumetricMassDensity() +{ + float volumetric_mass_density = 0.0; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "volumetric_mass_density", (void *)&volumetric_mass_density); + + return (bmv080_current_status == E_BMV080_OK ? volumetric_mass_density : 0.0); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setVolumetricMassDensity(float volumetric_mass_density) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "volumetric_mass_density", (void *)&volumetric_mass_density); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +float sfDevBMV080::integrationTime() +{ + float integration_time = 0.0; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "integration_time", (void *)&integration_time); + + return (bmv080_current_status == E_BMV080_OK ? integration_time : 0.0); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setIntegrationTime(float integration_time) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "integration_time", (void *)&integration_time); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +uint32_t sfDevBMV080::distributionId() +{ + uint32_t distribution_id = 0; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "distribution_id", (void *)&distribution_id); + + return (bmv080_current_status == E_BMV080_OK ? distribution_id : 0); +} + +//--------------------------------------------------------------------- + +bool sfDevBMV080::setDistributionId(uint32_t distribution_id) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "distribution_id", (void *)&distribution_id); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::doObstructionDetection() +{ + bool do_obstruction_detection = false; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "do_obstruction_detection", (void *)&do_obstruction_detection); + + return (bmv080_current_status == E_BMV080_OK ? do_obstruction_detection : false); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setDoObstructionDetection(bool do_obstruction_detection) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "do_obstruction_detection", (void *)&do_obstruction_detection); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::doVibrationFiltering() +{ + bool do_vibration_filtering = false; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "do_vibration_filtering", (void *)&do_vibration_filtering); + + return (bmv080_current_status == E_BMV080_OK ? do_vibration_filtering : false); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setDoVibrationFiltering(bool do_vibration_filtering) +{ + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "do_vibration_filtering", (void *)&do_vibration_filtering); + + return (bmv080_current_status == E_BMV080_OK); +} + +//--------------------------------------------------------------------- +uint8_t sfDevBMV080::measurementAlgorithm() +{ + bmv080_measurement_algorithm_t measurement_algorithm; + bmv080_status_code_t bmv080_current_status = + bmv080_get_parameter(_bmv080_handle_class, "measurement_algorithm", (void *)&measurement_algorithm); + + return (bmv080_current_status == E_BMV080_OK ? (uint8_t)measurement_algorithm : 0); +} + +//--------------------------------------------------------------------- +bool sfDevBMV080::setMeasurementAlgorithm(uint8_t measurement_algorithm) +{ + bmv080_measurement_algorithm_t bmv080_measurement_algorithm = (bmv080_measurement_algorithm_t)measurement_algorithm; + bmv080_status_code_t bmv080_current_status = + bmv080_set_parameter(_bmv080_handle_class, "measurement_algorithm", (void *)&bmv080_measurement_algorithm); + + return (bmv080_current_status == E_BMV080_OK); +} \ No newline at end of file diff --git a/src/sfTk/sfDevBMV080.h b/src/sfTk/sfDevBMV080.h new file mode 100644 index 0000000..7e25837 --- /dev/null +++ b/src/sfTk/sfDevBMV080.h @@ -0,0 +1,642 @@ +/** + * @file sfDevBMV080.h + * @brief Header file for the SparkFun BMV080 Library + * + * This file contains the header of the sfDevBMV080 class, which provides + * an interface to the BMV080 sensor. It includes methods for initializing the sensor, + * reading sensor data, and configuring sensor settings. + * + * @author Pete Lewis + * @date 2025 + * @version 1.0 + * @copyright (c) 2025 SparkFun Electronics Inc. This project is released under the MIT License. + * + * SPDX-License-Identifier: MIT + * + * @see sfDevBMV080.cpp + */ + +#pragma once + +#include "bmv080.h" +#include "bmv080_defs.h" + +// Include the platform independent layer of the SparkFun Toolkit +#include +#include +#include + +#define SF_BMV080_DEFAULT_ADDRESS 0x57 +#define SF_BMV080_DEFAULT_IRQ_PIN 14 + +#define SF_BMV080_MODE_CONTINUOUS 0 +#define SF_BMV080_MODE_DUTY_CYCLE 1 + +class sfDevBMV080 +{ + public: + /// @brief Default constructor + sfDevBMV080() : _theBus{nullptr} + { + } + + /** + * @brief Begins communication with the BMV080 sensor + * + * This method initializes the communication interface with the sensor. + * It must be called before init() and any other operations with the sensor. + * + * @param theBus SparkFun Toolkit bus interface to use for communication. + * + * @return sfTkError_t Status code: + * - 0: Success + * - Negative: Error occurred + * - Positive: Warning condition + * + * @see init() + * @see open() + */ + sfTkError_t begin(sfTkIBus *theBus = nullptr); + + /** + * @brief Initializes the BMV080 sensor + * + * This method performs complete initialization of the sensor by: + * - Opening communication with the sensor + * - Performing a soft reset + * - Getting driver version information + * - Reading the sensor ID + * + * It must be called after begin() and before attempting any other operations. + * + * @return true if initialization was successful + * @return false if any initialization step failed + * + * @see begin() + * @see open() + * @see reset() + * @see driverVersion() + * @see ID() + */ + bool init(void); + + /** + * @brief Gets the version information of the BMV080 sensor driver + * + * This method retrieves the vendor-supplied version information for the + * sensor driver software. The version follows semantic versioning format + * with major, minor, and patch numbers. + * + * @param[out] major Major version number indicating incompatible API changes + * @param[out] minor Minor version number indicating backwards-compatible functionality + * @param[out] patch Patch version number indicating backwards-compatible bug fixes + * + * @return true if the version information was successfully retrieved + * @return false if there was an error getting the version information + * + * @see init() + */ + bool driverVersion(uint16_t &major, uint16_t &minor, uint16_t &patch); + + /** + * @brief Opens and initializes communication with the BMV080 sensor + * + * This method initializes a new handle for communicating with the sensor. + * It must be called before attempting to configure or read from the sensor. + * + * @return true if the sensor was successfully opened and handle created + * @return false if the sensor could not be opened or handle creation failed + * + * @note This method is automatically called by init() + * + * @see init() + * @see begin() + */ + bool open(void); + + /** + * @brief Closes communication with the BMV080 sensor + * + * @return true if the sensor was successfully closed and handle created + * @return false if the sensor could not be closed or handle creation failed + * + * @see open() + */ + bool close(void); + + /** + * @brief Resets the BMV080 sensor to its default state + * + * This method performs a soft reset of the sensor, returning all settings + * to their default values. The sensor will need to be reconfigured after + * a reset. + * + * @return true if the reset was successful + * @return false if the reset failed + * + * @note After reset, you may need to reinitialize settings like operational mode + * and duty cycling period + * + * @see init() + * @see setMode() + */ + bool reset(void); + + /** + * @brief Length of the BMV080 sensor ID string buffer + * + * This constant defines the required buffer size for storing the sensor's + * unique identification string. The buffer must be at least this size + * when calling the ID() method. + * + * @see ID() + */ + static const size_t kBMV800IDLength = 13; + /** + * @brief Gets the unique identifier of the BMV080 sensor + * + * This method retrieves the sensor's unique identification string. + * The ID can be used to distinguish between different BMV080 sensors + * or verify the sensor's authenticity. + * + * @param[out] idOut Buffer to store the sensor's ID string. + * Must be at least kBMV800IDLength (13) bytes long. + * + * @return true if the ID was successfully retrieved + * @return false if there was an error reading the ID + * + * @note The buffer must be pre-allocated with at least kBMV800IDLength bytes + * + * @see kBMV800IDLength + */ + bool ID(char idOut[kBMV800IDLength]); + + /** + * @brief Sets the operational mode of the BMV080 sensor + * + * This method configures how the sensor takes measurements. It supports two modes: + * continuous measurement or duty-cycled measurement. + * + * @param mode The desired operational mode: + * - SFE_BMV080_MODE_CONTINUOUS: Sensor takes measurements continuously + * - SFE_BMV080_MODE_DUTY_CYCLE: Sensor takes measurements at specified intervals + * + * @return true if the mode was set successfully + * @return false if setting the mode failed + * + * @note When using duty cycle mode, the measurement interval can be configured + * using setDutyCyclingPeriod() + * + * @see setDutyCyclingPeriod() + * @see readSensor() + * @see bmv080_output_t + */ + bool setMode(uint8_t mode); + + /** + * @brief Gets the PM10 (particulate matter ≤10 µm) concentration + * + * This method returns the latest PM10 reading from the sensor's internal cache. + * The value represents the mass concentration of particles with a diameter + * of 10 micrometers or less. + * + * @return The PM10 concentration in micrograms per cubic meter (µg/m³) + * + * @note The PM10 value is updated when readSensor() is called + * + * @see readSensor() + * @see PM1() + * @see bmv080_output_t + */ + float PM10(void); + + /** + * @brief Gets the PM2.5 (particulate matter ≤2.5 µm) concentration + * + * This method returns the latest PM2.5 reading from the sensor's internal cache. + * The value represents the mass concentration of particles with a diameter + * of 2.5 micrometers or less. + * + * @return The PM2.5 concentration in micrograms per cubic meter (µg/m³) + * + * @note The PM2.5 value is updated when readSensor() is called + * + * @see readSensor() + * @see PM1() + * @see bmv080_output_t + */ + float PM25(void); + + /** + * @brief Gets the PM1 (particulate matter ≤1.0 µm) concentration + * + * This method returns the latest PM1 reading from the sensor's internal cache. + * The value represents the mass concentration of particles with a diameter + * of 1.0 micrometers or less. + * + * @return The PM1 concentration in micrograms per cubic meter (µg/m³) + * + * @note The PM1 value is updated when readSensor() is called + * + * @see readSensor() + * @see PM25() + * @see bmv080_output_t + */ + float PM1(void); + + /** + * @brief Checks if the BMV080 sensor is obstructed + * + * This method returns the obstruction status from the latest sensor reading. + * An obstruction could be caused by dust, debris, or other particles + * blocking the sensor's optical path. + * + * @return true if the sensor is obstructed + * @return false if the sensor is not obstructed + * + * @note The obstruction status is updated when readSensor() is called + * + * @see readSensor() + * @see bmv080_output_t + */ + bool isObstructed(); + + /** + * @brief Internal method to set sensor values from callback + * + * This method is called by the BMV080 driver callback to update internal sensor data. + * It stores the latest sensor readings and sets the data available flag. + * + * @param bmv080_output The sensor output structure containing the latest readings + * including PM2.5, PM1, and obstruction status + * + * @note This is primarily an internal method used as part of the callback mechanism + * from the Bosch BMV080 driver. It should not typically be called directly + * by library users. + * + * @see set_sensor_value() + * @see bmv080_output_t + */ + void setSensorValue(bmv080_output_t bmv080_output); + + /** + * @brief Reads the latest sensor values from the BMV080 + * + * This method triggers a sensor reading and updates the internal data cache. + * If a pointer to a bmv080_output_t struct is provided, it will be populated + * with the latest sensor values. + * + * @param[out] bmv080_output Optional pointer to a bmv080_output_t struct to store the sensor readings. + * If nullptr (default), the values are only stored internally. + * + * @return true if new data was successfully read from the sensor + * @return false if the sensor read failed or no new data is available + * + * @note This method clears the _dataAvailable flag before attempting to read new data + * + * @see sensorServiceRoutine() + * @see bmv080_output_t + */ + bool readSensor(bmv080_output_t *bmv080_output = nullptr); + + /** + * @brief Gets the current duty cycling period setting + * + * Returns the time interval between measurements when the sensor is in + * duty cycle mode. This setting has no effect when the sensor is in + * continuous measurement mode. + * + * @return The duty cycling period in seconds + * + * @note This setting only affects the sensor when in SFE_BMV080_MODE_DUTY_CYCLE mode + * + * @see setDutyCyclingPeriod() + * @see setMode() + */ + uint16_t dutyCyclingPeriod(); + + /** + * @brief Sets the time interval between measurements in duty cycle mode + * + * This method configures how frequently the sensor takes measurements when + * operating in duty cycle mode. A longer period reduces power consumption + * but provides less frequent updates. + * + * @param duty_cycling_period The time between measurements in seconds + * + * @return true if the period was successfully set + * @return false if setting the period failed + * + * @note This setting only takes effect when the sensor is in SFE_BMV080_MODE_DUTY_CYCLE mode + * + * @see dutyCyclingPeriod() + * @see setMode() + */ + bool setDutyCyclingPeriod(uint16_t duty_cycling_period); + + /** + * @brief Gets the volumetric mass density setting + * + * This method returns the current volumetric mass density setting used for + * particle concentration calculations. This value affects how the sensor + * converts between particle counts and mass concentrations. + * + * @return The volumetric mass density in grams per cubic centimeter (g/cm³) + * + * @see setVolumetricMassDensity() + * @see PM25() + * @see PM1() + */ + float volumetricMassDensity(); + + /** + * @brief Sets the volumetric mass density for particle concentration calculations + * + * This method configures the density value used to convert between particle + * counts and mass concentrations. This setting affects the accuracy of + * PM2.5 and PM1 measurements based on the expected particle density. + * + * @param volumetric_mass_density The particle density in grams per cubic centimeter (g/cm³) + * + * @return true if the density was successfully set + * @return false if setting the density failed + * + * @see volumetricMassDensity() + * @see PM25() + * @see PM1() + */ + bool setVolumetricMassDensity(float volumetric_mass_density); + + /** + * @brief Gets the sensor's integration time setting + * + * This method returns the current integration time setting used for + * particle measurements. The integration time affects the sensor's + * measurement accuracy and response time. + * + * @return The integration time in milliseconds (ms) + * + * @see setIntegrationTime() + * @see readSensor() + */ + float integrationTime(); + + /** + * @brief Sets the sensor's integration time for measurements + * + * This method configures the integration time used for particle measurements. + * Longer integration times can improve measurement accuracy but increase + * response time and power consumption. + * + * @param integration_time The measurement integration time in milliseconds (ms) + * + * @return true if the integration time was successfully set + * @return false if setting the integration time failed + * + * @see integrationTime() + * @see readSensor() + */ + bool setIntegrationTime(float integration_time); + + /** + * @brief Gets the current distribution ID setting + * + * This method returns the distribution ID used by the sensor for particle + * size classification. The distribution ID affects how particles are + * categorized into different size bins. + * + * @return The current distribution ID value + * + * @see setDistributionId() + * @see PM25() + * @see PM1() + */ + uint32_t distributionId(); + + /** + * @brief Sets the distribution ID for particle size classification + * + * This method configures which particle size distribution model the sensor + * uses for classifying particles. Different distribution IDs are optimized + * for different types of particles and environments. + * + * @param distribution_id The distribution ID to use for particle classification + * + * @return true if the distribution ID was successfully set + * @return false if setting the distribution ID failed + * + * @see distributionId() + * @see PM25() + * @see PM1() + */ + bool setDistributionId(uint32_t distribution_id); + + /** + * @brief Gets the obstruction detection setting + * + * This method returns whether the sensor's obstruction detection feature + * is enabled. When enabled, the sensor will monitor for any blockages + * in its optical path. + * + * @return true if obstruction detection is enabled + * @return false if obstruction detection is disabled + * + * @see setDoObstructionDetection() + * @see isObstructed() + */ + bool doObstructionDetection(); + + /** + * @brief Enables or disables the sensor's obstruction detection feature + * + * This method controls whether the sensor actively monitors for obstructions + * in its optical path. When enabled, the sensor will report blockages + * through the isObstructed() method. + * + * @param do_obstruction_detection true to enable obstruction detection, + * false to disable it + * + * @return true if the setting was successfully changed + * @return false if changing the setting failed + * + * @see doObstructionDetection() + * @see isObstructed() + */ + bool setDoObstructionDetection(bool do_obstruction_detection); + + /** + * @brief Gets the vibration filtering setting + * + * This method returns whether the sensor's vibration filtering feature + * is enabled. When enabled, the sensor applies algorithms to reduce + * measurement noise caused by mechanical vibrations. + * + * @return true if vibration filtering is enabled + * @return false if vibration filtering is disabled + * + * @see setDoVibrationFiltering() + * @see readSensor() + */ + bool doVibrationFiltering(); + + /** + * @brief Enables or disables vibration filtering + * + * This method controls whether the sensor applies vibration filtering + * algorithms to reduce measurement noise caused by mechanical vibrations. + * Enabling this feature can improve measurement accuracy in environments + * with significant vibration. + * + * @param do_vibration_filtering true to enable vibration filtering, + * false to disable it + * + * @return true if the setting was successfully changed + * @return false if changing the setting failed + * + * @see doVibrationFiltering() + * @see readSensor() + */ + bool setDoVibrationFiltering(bool do_vibration_filtering); + + /** + * @brief Gets the current measurement algorithm setting + * + * This method returns the measurement algorithm used by the sensor for + * particle analysis. Different algorithms can be optimized for specific + * measurement conditions or particle types. + * + * @return The current measurement algorithm identifier + * + * @see setMeasurementAlgorithm() + * @see readSensor() + */ + uint8_t measurementAlgorithm(); + + /** + * @brief Sets the measurement algorithm for particle analysis + * + * This method configures which algorithm the sensor uses for analyzing + * particle measurements. Different algorithms can be optimized for + * specific types of particles or measurement environments. + * + * @param measurement_algorithm The algorithm identifier to use for measurements + * + * @return true if the algorithm was successfully set + * @return false if setting the algorithm failed + * + * @see measurementAlgorithm() + * @see readSensor() + */ + bool setMeasurementAlgorithm(uint8_t measurement_algorithm); + + private: + // bosch bmv080 library callback functions (static methods to be used as callbacks) + /** + * @brief Callback function for reading 16-bit values from the BMV080 sensor + * + * This static method serves as a callback for the Bosch BMV080 driver to read + * 16-bit registers from the sensor over the communication bus. + * + * @param handle The SERCOM handle for communication with the sensor + * @param reg_addr The register address to read from + * @param[out] reg_data Pointer to store the read data + * @param len Number of 16-bit words to read + * + * @return int8_t Status code: + * - 0: Success + * - Negative: Error occurred + * + * @note This is an internal callback used by the Bosch BMV080 driver + * + * @see device_write_16bit_CB() + */ + static int8_t device_read_16bit_CB(bmv080_sercom_handle_t, uint16_t, uint16_t *, uint16_t); + + /** + * @brief Callback function for writing 16-bit values to the BMV080 sensor + * + * This static method serves as a callback for the Bosch BMV080 driver to write + * 16-bit registers to the sensor over the communication bus. + * + * @param handle The SERCOM handle for communication with the sensor + * @param reg_addr The register address to write to + * @param[in] reg_data Pointer to the data to write + * @param len Number of 16-bit words to write + * + * @return int8_t Status code: + * - 0: Success + * - Negative: Error occurred + * + * @note This is an internal callback used by the Bosch BMV080 driver + * + * @see device_read_16bit_CB() + */ + static int8_t device_write_16bit_CB(bmv080_sercom_handle_t, uint16_t, const uint16_t *, uint16_t); + + /** + * @brief Callback function for implementing delays in the BMV080 sensor driver + * + * This static method serves as a callback for the Bosch BMV080 driver to + * implement timing delays required by the sensor operations. + * + * @param delay_ms The delay duration in milliseconds + * + * @return int8_t Status code: + * - 0: Success + * - Negative: Error occurred + * + * @note This is an internal callback used by the Bosch BMV080 driver + * + * @see device_read_16bit_CB() + * @see device_write_16bit_CB() + */ + static int8_t device_delay_CB(uint32_t); + + /** + * @brief Static callback for updating sensor values from the BMV080 driver + * + * This static method serves as a callback function for the Bosch BMV080 driver + * to update sensor readings. It receives new measurement data and passes it + * to the appropriate instance through the void pointer to user data. + * + * @param bmv080_output The sensor output structure containing the latest readings + * @param[in] user_data Pointer to the sfDevBMV080 instance (cast from void*) + * + * @note This is an internal callback used by the Bosch BMV080 driver + * + * @see setSensorValue() + * @see bmv080_output_t + */ + static void set_sensor_value(bmv080_output_t, void *); + + /** + * @brief Services the BMV080 sensor driver + * + * This method pumps the service routine of the BMV080 sensor driver, + * allowing it to process measurements and update sensor values. + * It is called internally by readSensor() to maintain proper + * sensor operation. + * + * @return true if the service routine completed successfully + * @return false if an error occurred during servicing + * + * @note This is an internal method used by the driver + * + * @see readSensor() + * @see set_sensor_value() + */ + bool sensorServiceRoutine(void); + + // BMV080 sensor handle - used when referencing the sensor using the Bosch API + bmv080_handle_t _bmv080_handle_class = NULL; + + // Internal flag to track if new sensor data is available + bool _dataAvailable = false; + + // Internal cache for the latest sensor values + bmv080_output_t _sensorValue; + + protected: + // Pointer to the SparkFun Toolkit bus interface used for communication + sfTkIBus *_theBus; +}; \ No newline at end of file diff --git a/src/sfeBmv080.cpp b/src/sfeBmv080.cpp deleted file mode 100644 index 9f6cd3e..0000000 --- a/src/sfeBmv080.cpp +++ /dev/null @@ -1,475 +0,0 @@ -/****************************************************************************** - sfeQwiicBuzzer.h - SparkFun Qwiic Buzzer Library header file - - by Pete Lewis @SparkFun Electronics - January 2024 - - Based on original source code written by - Fischer Moseley @ SparkFun Electronics - Original Creation Date: July 24, 2019 - - Development environment specifics: - IDE: Arduino 2.2.1 - Hardware Platform: Arduino Uno/SparkFun Redboard - Qwiic Buzzer Version: v10 - - SPDX-License-Identifier: MIT - - Copyright (c) 2023 SparkFun Electronics - - Distributed as-is; no warranty is given. -******************************************************************************/ - -#include "sfeBmv080.h" -#include "bmv080_defs.h" -#include "bmv080.h" - -#ifdef __cplusplus -extern "C" { -#endif /* __cplusplus */ - -void bmv080_service_routine(const bmv080_handle_t handle, void* callback_parameters); -void use_sensor_output(bmv080_output_t bmv080_output, void* callback_parameters); - - -/* Custom function for consuming sensor readings */ -void use_sensor_output(bmv080_output_t bmv080_output, void* callback_parameters) -{ - //data_ready_callback_count += 1; - //print_function_t print = (print_function_t)callback_parameters; - - - ((sfeBmv080*)callback_parameters)->setSensorValue(bmv080_output); - - //Serial.println(bmv080_output.pm2_5); - - //Serial.println("u"); - - //sfeBmv080::_sensorValue.pm2_5 = bmv080_output.pm2_5; // update the class variable with the new PM2.5 value - //setSensorValue(bmv080_output.pm2_5); - //sensorValue.pm2_5 = bmv080_output.pm2_5; - // print("Runtime: %.2f s, PM2.5: %.0f ug/m^3, obstructed: %s, outside detection limits: %s\r\n", - // bmv080_output.runtime_in_sec, bmv080_output.pm2_5, (bmv080_output.is_obstructed ? "yes" : "no"), (bmv080_output.is_outside_detection_limits ? "yes" : "no")); -} - - -void bmv080_service_routine(const bmv080_handle_t handle, void* callback_parameters) -{ - /* The interrupt is served by the BMV080 sensor driver */ - bmv080_status_code_t bmv080_current_status = bmv080_serve_interrupt(handle, (bmv080_callback_data_ready_t)use_sensor_output, callback_parameters); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Fetching measurement data failed with BMV080 status %d\r\n", (int32_t)bmv080_current_status); - } -} - - -#ifdef __cplusplus -} -#endif - - -sfeTkError_t sfeBmv080::begin(sfeTkII2C *theBus) -{ - // Nullptr check - if (theBus == nullptr) - return kSTkErrFail; - - // Set bus pointer - _theBus = theBus; - - sfeTkError_t err; - err = isConnected(); - // Check whether the ping was successful - if (err != kSTkErrOk) - return err; - - // Done! - return kSTkErrOk; -} - -sfeTkError_t sfeBmv080::isConnected() -{ - // Just ping the device address - return _theBus->ping(); -} - -float sfeBmv080::getPM25() -{ - return _sensorValue.pm2_5; -} - -bool sfeBmv080::getIsObstructed() -{ - return _sensorValue.is_obstructed; -} - -void sfeBmv080::setSensorValue(bmv080_output_t bmv080_output) -{ - _dataAvailable = true; - _sensorValue.pm2_5 = bmv080_output.pm2_5; - _sensorValue.runtime_in_sec = bmv080_output.runtime_in_sec; - _sensorValue.is_obstructed = bmv080_output.is_obstructed; - _sensorValue.is_outside_detection_limits = bmv080_output.is_outside_detection_limits; -} - -bool sfeBmv080::setMode(uint8_t mode) -{ - bmv080_status_code_t bmv080_current_status; // return status from the Bosch API function - - if(mode == SFE_BMV080_MODE_CONTINUOUS) - { - bmv080_current_status = bmv080_start_continuous_measurement(bmv080_handle_class); - } - else if(mode == SFE_BMV080_MODE_DUTY_CYCLE) - { - bmv080_duty_cycling_mode_t duty_cycling_mode = E_BMV080_DUTY_CYCLING_MODE_0; - bmv080_current_status = bmv080_start_duty_cycling_measurement(bmv080_handle_class, (bmv080_callback_tick_t)millis, duty_cycling_mode); - } - - // check if the mode was set correctly - if (bmv080_current_status == E_BMV080_OK) - { - return true; - } - else - { - return false; - } -} - -bool sfeBmv080::dataAvailable() -{ - bmv080_service_routine(bmv080_handle_class, this); - if(_dataAvailable == true) - { - _dataAvailable = false; - return true; - } - else - return false; -} - -bool sfeBmv080::init(i2c_device_t *i2c_device) -{ - if(getDriverVersion() == false) - { - return false; - } - - if(open(i2c_device) == false) - { - return false; - } - - if(reset() == false) - { - return false; - } - - if(getID() == false) - { - return false; - } - - return true; -} - -bool sfeBmv080::open(i2c_device_t *i2c_device) -{ - bmv080_sercom_handle_t sercom_handle = (bmv080_sercom_handle_t)i2c_device; - bmv080_callback_read_t read = (const bmv080_callback_read_t)combridge_i2c_read_16bit; - bmv080_callback_write_t write = (const bmv080_callback_write_t)combridge_i2c_write_16bit; - bmv080_callback_delay_t delay_ms = (const bmv080_callback_delay_t)combridge_delay; - - bmv080_status_code_t bmv080_current_status = bmv080_open(&bmv080_handle_class, sercom_handle, read, write, delay_ms); - - if (bmv080_current_status != E_BMV080_OK) - { - Serial.println("BMV080 open failed"); - return false; - } - else - { - Serial.println("BMV080 open successfully"); - return true; - } -} - -bool sfeBmv080::initSPI(spi_device_t *spi_device) -{ - if(getDriverVersion() == false) - { - return false; - } - - if(openSPI(spi_device) == false) - { - return false; - } - - if(reset() == false) - { - return false; - } - - if(getID() == false) - { - return false; - } - - return true; -} - -bool sfeBmv080::openSPI(spi_device_t *spi_device) -{ - bmv080_sercom_handle_t sercom_handle = (bmv080_sercom_handle_t)spi_device; - bmv080_callback_read_t read = (const bmv080_callback_read_t)combridge_spi_read_16bit; - bmv080_callback_write_t write = (const bmv080_callback_write_t)combridge_spi_write_16bit; - bmv080_callback_delay_t delay_ms = (const bmv080_callback_delay_t)combridge_delay; - - bmv080_status_code_t bmv080_current_status = bmv080_open(&bmv080_handle_class, sercom_handle, read, write, delay_ms); - - if (bmv080_current_status != E_BMV080_OK) - { - Serial.println("BMV080 open failed"); - return false; - } - else - { - Serial.println("BMV080 open successfully"); - return true; - } -} - -bool sfeBmv080::reset() -{ - bmv080_status_code_t bmv080_current_status = bmv080_reset(bmv080_handle_class); - - if (bmv080_current_status != E_BMV080_OK) - { - Serial.println("BMV080 reset failed"); - return false; - } - else - { - Serial.println("BMV080 reset successfully"); - return true; - } -} - -bool sfeBmv080::getDriverVersion() -{ - uint16_t major = 0; - uint16_t minor = 0; - uint16_t patch = 0; - char git_hash[12]; - int32_t commits_ahead = 0; - - bmv080_status_code_t bmv080_current_status = bmv080_get_driver_version(&major, &minor, &patch, git_hash, &commits_ahead); - - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 driver version: %d\n", bmv080_current_status); - return false; - } - - printf("BMV080 driver version: %d.%d.%d\n", major, minor, patch); - return true; -} - -bool sfeBmv080::getID() -{ - char id[13]; - memset(id, 0x00, 13); - bmv080_status_code_t bmv080_current_status = bmv080_get_sensor_id(bmv080_handle_class, id); - - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 sensor ID: %d\n", bmv080_current_status); - return false; - } - else - { - printf("BMV080 sensor ID: %s\n", id); - return true; - } -} - -uint16_t sfeBmv080::getDutyCyclingPeriod() -{ - uint16_t duty_cycling_period = 0; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "duty_cycling_period", (void*)&duty_cycling_period); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Duty Cycling Period: %d\n", bmv080_current_status); - return 0; - } - else - { - printf("BMV080 Duty Cycling Period Read: %d\n", duty_cycling_period); - return duty_cycling_period; - } -} - -bool sfeBmv080::setDutyCyclingPeriod(uint16_t duty_cycling_period) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "duty_cycling_period", (void*)&duty_cycling_period); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Duty Cycling Period: %d\n", bmv080_current_status); - return false; - } - else - { - printf("BMV080 Duty Cycling Period Set: %d\n", duty_cycling_period); - return true; - } -} - -float sfeBmv080::getVolumetricMassDensity() -{ - float volumetric_mass_density = 0.0; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "volumetric_mass_density", (void*)&volumetric_mass_density); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Volumetric Mass Density: %d\n", bmv080_current_status); - return 0.0; - } - else - { - return volumetric_mass_density; - } -} - -bool sfeBmv080::setVolumetricMassDensity(float volumetric_mass_density) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "volumetric_mass_density", (void*)&volumetric_mass_density); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Volumetric Mass Density: %d\n", bmv080_current_status); - return false; - } - else - { - return true; - } -} - -float sfeBmv080::getIntegrationTime() -{ - float integration_time = 0.0; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "integration_time", (void*)&integration_time); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Integration Time: %d\n", bmv080_current_status); - return 0.0; - } - else - { - return integration_time; - } -} - -bool sfeBmv080::setIntegrationTime(float integration_time) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "integration_time", (void*)&integration_time); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Integration Time: %d\n", bmv080_current_status); - return false; - } - else - { - return true; - } -} - -uint32_t sfeBmv080::getDistributionId() -{ - uint32_t distribution_id = 0; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "distribution_id", (void*)&distribution_id); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Distribution ID: %d\n", bmv080_current_status); - return 0; - } - else - { - return distribution_id; - } -} - -bool sfeBmv080::setDistributionId(uint32_t distribution_id) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "distribution_id", (void*)&distribution_id); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Distribution ID: %d\n", bmv080_current_status); - return false; - } - else - { - return true; - } -} - -bool sfeBmv080::getDoObstructionDetection() -{ - bool do_obstruction_detection = false; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "do_obstruction_detection", (void*)&do_obstruction_detection); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Obstruction Detection: %d\n", bmv080_current_status); - return false; - } - else - { - return do_obstruction_detection; - } -} - -bool sfeBmv080::setDoObstructionDetection(bool do_obstruction_detection) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "do_obstruction_detection", (void*)&do_obstruction_detection); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Obstruction Detection: %d\n", bmv080_current_status); - return false; - } - else - { - return true; - } -} - -bool sfeBmv080::getDoVibrationFiltering() -{ - bool do_vibration_filtering = false; - bmv080_status_code_t bmv080_current_status = bmv080_get_parameter(bmv080_handle_class, "do_vibration_filtering", (void*)&do_vibration_filtering); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error getting BMV080 Vibration Filtering: %d\n", bmv080_current_status); - return false; - } - else - { - return do_vibration_filtering; - } -} - -bool sfeBmv080::setDoVibrationFiltering(bool do_vibration_filtering) -{ - bmv080_status_code_t bmv080_current_status = bmv080_set_parameter(bmv080_handle_class, "do_vibration_filtering", (void*)&do_vibration_filtering); - if (bmv080_current_status != E_BMV080_OK) - { - printf("Error setting BMV080 Vibration Filtering: %d\n", bmv080_current_status); - return false; - } - else - { - return true; - } -} - diff --git a/src/sfeBmv080.h b/src/sfeBmv080.h deleted file mode 100644 index f5a968e..0000000 --- a/src/sfeBmv080.h +++ /dev/null @@ -1,177 +0,0 @@ -/****************************************************************************** - sfeBmv080.h - SparkFun BMV080 Library header file - - by Pete Lewis @SparkFun Electronics - September 2024 - - This file implements the BMV080 class, prototyped in SparkFun_BMV080_Arduino_Library.h - - Development environment specifics: - IDE: Arduino 2.3.3 - Hardware Platform: SparkFun IoT Redboard ESP32 - BMV080 Breakout HW Version: v01 - - SPDX-License-Identifier: MIT - - Copyright (c) 2024 SparkFun Electronics - - Distributed as-is; no warranty is given. -******************************************************************************/ - -#pragma once - -#include "bmv080.h" -#include "bmv080_defs.h" -#include "combridge.h" - -#include -#include - -#define SFE_BMV080_DEFAULT_ADDRESS 0x57 -#define SFE_BMV080_DEFAULT_IRQ_PIN 14 - -#define SFE_BMV080_MODE_CONTINUOUS 0 -#define SFE_BMV080_MODE_DUTY_CYCLE 1 - - - -class sfeBmv080 -{ - public: - /// @brief Default constructor - sfeBmv080() : _theBus{nullptr} - { - } - - /// @brief Begins the Device - /// @param theBus I2C bus to use for communication - /// @return 0 for succuss, negative for errors, positive for warnings - sfeTkError_t begin(sfeTkII2C *theBus = nullptr); - - /// @brief Checks if the Device is connected - /// @return 0 for succuss, negative for errors, positive for warnings - sfeTkError_t isConnected(); - - /// @brief Initialize the sensor i2c - /// @details This function initializes the sensor and should be called - /// @details before any other functions. It calls Open, Reset, getDriverVersion, and getID. - /// @param i2c_device The I2C device to use - /// @return True if successful, false otherwise - bool init(i2c_device_t *i2c_device); - - /// @brief Initialize the sensor SPI - /// @details This function initializes the sensor and should be called - /// @details before any other functions. It calls Open, Reset, getDriverVersion, and getID. - /// @param spi_device The SPI device to use - /// @return True if successful, false otherwise - bool initSPI(spi_device_t *spi_device); - - /// @brief Get the version information of this sensor driver. - /// @return True if successful, false otherwise - bool getDriverVersion(); - - /// @brief Open a sensor unit by initializing a new handle. - /// @param i2c_device The I2C device to use - /// @return True if successful, false otherwise - bool open(i2c_device_t *i2c_device); - - /// @brief Open a sensor unit by initializing a new handle. - /// @param spi_device The SPI device to use - /// @return True if successful, false otherwise - bool openSPI(spi_device_t *spi_device); - - /// @brief Reset the sensor - /// @return True if successful, false otherwise - bool reset(); - - /// @brief Get the ID of the sensor - /// @return True if successful, false otherwise - bool getID(); - - /// @brief Set the mode of the sensor - /// @param mode SFE_BMV080_MODE_CONTINUOUS, SFE_BMV080_MODE_DUTY_CYCLE - /// @return True if successful, false otherwise - bool setMode(uint8_t mode); - - /// @brief Get the PM2.5 value - /// @return The PM2.5 value as a float in ug/m3 - float getPM25(); - - /// @brief Get the obstruction status - /// @return True if obstructed, false otherwise - bool getIsObstructed(); - - - void setSensorValue(bmv080_output_t bmv080_output); - - /// @brief Check if new data is available - /// @details This function should be called in the main loop to check if new data is available - /// @details If new data is available, the data can be read using getPM25 and getIsObstructed - /// @return True if new data is available, false otherwise - bool dataAvailable(); - - /// @brief Get the duty cycling period - /// @return The duty cycling period in seconds - uint16_t getDutyCyclingPeriod(); - - /// @brief Set the duty cycling period - /// @param period The duty cycling period in seconds - /// @return True if successful, false otherwise - bool setDutyCyclingPeriod(uint16_t duty_cycling_period); - - /// @brief Get a parameter: "volumetric_mass_density" - /// @return float volumetric_mass_density - float getVolumetricMassDensity(); - - /// @brief Set a parameter: "volumetric_mass_density" - /// @param volumetric_mass_density - /// @return True if successful, false otherwise - bool setVolumetricMassDensity(float volumetric_mass_density); - - /// @brief Get a parameter: "integration_time" - /// @return float integration_time - float getIntegrationTime(); - - /// @brief Set a parameter: "integration_time" - /// @param integration_time - /// @return True if successful, false otherwise - bool setIntegrationTime(float integration_time); - - /// @brief Get a parameter: "distribution_id" - /// @return uint32_t distribution_id - uint32_t getDistributionId(); - - /// @brief Set a parameter: "distribution_id" - /// @param distribution_id - /// @return True if successful, false otherwise - bool setDistributionId(uint32_t distribution_id); - - /// @brief Get a parameter: "do_obstruction_detection" - /// @return bool do_obstruction_detection - bool getDoObstructionDetection(); - - /// @brief Set a parameter: "do_obstruction_detection" - /// @param do_obstruction_detection - /// @return True if successful, false otherwise - bool setDoObstructionDetection(bool do_obstruction_detection); - - /// @brief Get a parameter: "do_vibration_filtering" - /// @return bool do_vibration_filtering - bool getDoVibrationFiltering(); - - /// @brief Set a parameter: "do_vibration_filtering" - /// @param do_vibration_filtering - /// @return True if successful, false otherwise - bool setDoVibrationFiltering(bool do_vibration_filtering); - - - - private: - bmv080_handle_t bmv080_handle_class = NULL; - bool _dataAvailable = false; - bmv080_output_t _sensorValue; - - protected: - sfeTkII2C *_theBus; -}; \ No newline at end of file