Skip to main content

Read PM values

What this example shows​

Reading PM10, PM2.5 and PM1 from the BMV080 in continuous measurement mode, and checking whether something is blocking the sensor. The sensor delivers a new reading about once a second; the sketch asks for one every 100 ms and prints a line only when a new one has arrived.

The example code​

This is simpleReading.ino from the pinned library, without its header comment. The sketch itself is exactly as shipped. It uses the board's default address, 0x57.

Select Board
simpleReading.ino
#include "BMV080-SOLDERED.h"

BMV080 bmv080; // Create an instance of the BMV080 class
#define BMV080_ADDR 0x57 // BMV080 default address

void setup()
{
Serial.begin(115200);

while (!Serial)
delay(10); // Wait for Serial to become available.

Wire.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...");
while (1)
;
}

/* Initialize the Sensor (read driver, open, reset, id etc.)*/
bmv080.init();

/* Set the sensor mode to continuous mode */
if (bmv080.setMode(BMV080_MODE_CONTINUOUS) == true)
{
Serial.println("BMV080 set to continuous mode");
}
else
{
Serial.println("Error setting BMV080 mode");
}
}

void loop()
{
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);
}

Expected result, from a bench run on this board (the run did not record which controller it used):

Serial MonitorAutoscrollShow timestampNewline115200 baud
Message (Enter to send message to the board)
BMV080 set to continuous mode
PM10: 9.84 PM2.5: 7.12 PM1: 5.06
PM10: 10.27 PM2.5: 7.39 PM1: 5.21
PM10: 10.03 PM2.5: 7.25 PM1: 5.14
PM10: 9.71 PM2.5: 7.01 PM1: 4.98
PM10: 9.92 PM2.5: 7.18 PM1: 5.09

A new line appears about once a second, with each value in µg/m³, and ends with Obstructed when the sensor's view is blocked. Your numbers depend on the air around the sensor. If the sensor does not answer, the sketch prints BMV080 not detected at default I2C address. Check your jumpers and the hookup guide. Freezing... and stops.

Functions used​

BMV080()returns None

Creates the sensor object. It takes no arguments: the address and the Wire port are given to begin().

ReturnsConstructor; no return value.

begin(const uint8_t address = BMV080_DEFAULT_ADDRESS, TwoWire &wirePort = Wire)returns bool

Sets the I2C address and Wire port the library uses and checks that the sensor answers at that address. It does not start the I2C bus, so call Wire.begin() first, as the example does.

Returnstrue when the sensor answered at the address, false otherwise.

Parameters

NameTypeDescription
addressuint8_tThe sensor's I2C address. Defaults to BMV080_DEFAULT_ADDRESS, which is 0x57, the board's default.
wirePortTwoWire &The I2C port to use. Defaults to Wire.
init()returns bool

Prepares the sensor through the Bosch driver: reads the driver version, opens the sensor, performs a soft reset and reads the sensor's ID. Call it after begin() and before anything else.

Returnstrue when every step succeeded, false when one failed.

setMode(uint8_t mode)returns bool

Starts measuring in the mode you choose.

Returnstrue when the Bosch driver started the measurement, false otherwise.

Parameters

NameTypeDescription
modeuint8_tBMV080_MODE_CONTINUOUS for continuous measurement, or BMV080_MODE_DUTY_CYCLE for duty cycling.
readSensor(bmv080_output_t *bmv080_output = nullptr)returns bool

Lets the Bosch driver fetch and process data from the sensor once. When a new reading arrives, the library keeps it for PM10(), PM25(), PM1() and isObstructed(). Call it regularly, as the example does in loop().

Returnstrue when a new reading arrived during this call, false otherwise.

Parameters

NameTypeDescription
bmv080_outputbmv080_output_t *Optional. A Bosch output structure to copy the new reading into. The example leaves it out.
PM10()returns float

Returns the PM10 value of the latest reading: particles 10 µm across or smaller.

ReturnsPM10 mass concentration in µg/m³.

PM25()returns float

Returns the PM2.5 value of the latest reading: particles 2.5 µm across or smaller.

ReturnsPM2.5 mass concentration in µg/m³.

PM1()returns float

Returns the PM1 value of the latest reading: particles 1 µm across or smaller.

ReturnsPM1 mass concentration in µg/m³.

isObstructed()returns bool

Returns the obstruction flag of the latest reading. The sensor sets it when a fixed object sits in its optical path; brief obstructions, such as a hand waved past, are filtered out.

Returnstrue when the latest reading was obstructed, false otherwise.

Putting it together​

The order matters: Wire.begin(), then begin() with the address, then init(), then setMode(). After that, call readSensor() often and read the values only when it returns true. If you change the address with jumpers JP2 and JP3, change BMV080_ADDR to match.