Ultra-Compact Air Quality Monitor Using PandaByte Bosch BMV080 Particulate Matter Sensor

by pandabyte in Circuits > Arduino

74 Views, 0 Favorites, 0 Comments

Ultra-Compact Air Quality Monitor Using PandaByte Bosch BMV080 Particulate Matter Sensor

bmv080_landscape.jpg

The PandaByte BMV080 is a breakout sensor module built around Bosch’s BMV080, currently one of the world’s smallest particulate matter (PM) sensors, capable of measuring PM1, PM2.5, and PM10 in real time.

This tutorial shows how to:

  1. Understand the BMV080 sensor hardware
  2. Connect it safely to an ESP32 (we will use PandaByte xS3 ESP32-S3 for this tutorial)
  3. Install required library and Bosch SDK
  4. Read and display PM values using Arduino IDE
  5. Leverage native PandaByte board support via ESP32 Core v3.3.6

This guide is suitable for makers, IoT developers, and product designers building air quality monitoring solutions.

YouTube Link for a quick tutorial on our BMV080 PM sensor: https://youtu.be/z9ygY5GQSpk

Supplies

supplies_4.png

Hardware

  1. PandaByte BMV080 Air Quality Sensor
  2. PandaByte xS3 ESP32-S3 (16MB Flash) (recommended) OR
  3. Any other ESP32 or ESP32-S3 board with at least 16MB FLASH memory
  4. Grove cable (optional but recommended)
  5. Jumper wires (Dupont)
  6. USB-C cable

Software

  1. Arduino IDE
  2. ESP32 Arduino Core v3.3.6 or newer
  3. SparkFun BMV080 Arduino Library
  4. Bosch BMV080 SDK (Software Development Kit)

Understanding the BMV080 Module

Key Features

  1. Bosch BMV080 PM sensor
  2. Measures: PM1, PM2.5, PM10
  3. Interface: I²C and SPI
  4. Operating Voltage: 3.3V ONLY
  5. Onboard Grove connector + 2.54mm headers

⚠️ Important:

Do NOT connect this sensor to 5V power. It will permanently damage the module.

Board & Core Setup

PB board.jpeg

Since PandaByte boards are officially included in ESP32 Arduino Core v3.3.6, setup is easy:

Install ESP32 Core

In Arduino IDE: https://espressif.github.io/arduino-esp32/package_esp32_index.json

Select:

Tools → Board → PandaByte xS3 ESP32-S3

Tools → Flash Size → 16MB

PandaByte pin mappings are already defined in the official ESP32 core:

https://github.com/espressif/arduino-esp32/blob/master/variants/pandabyte_xs3/pins_arduino.h

This means:

  1. I2C pins are predefined
  2. No manual pin mapping needed
  3. Fully compatible with Arduino sketches

Wiring the Sensor

wiring1.png
wiring2.jpg

Option A – Using Grove (Recommended)

  1. Simply plug the Grove cable from:
  2. BMV080 → xS3 compatible Grove Shield (I2C port)

Option B – Using Jumper Wires

BMV080 PinPandaByte xS3

  1. GND → GND
  2. 3.3V → 3.3V
  3. SDA → SDA (GPIO 8)
  4. SCL → SCL (GPIO 9)

Install SparkFun BMV080 Library

In Arduino IDE:

  1. Library Manager → Search “BMV080” → Install SparkFun BMV080

Make sure to install all dependencies.

Example sketch path:

  1. File → Examples → SparkFun BMV080 → Example1_BasicReadings

Download Bosch BMV080 SDK

This step is mandatory or the program will NOT work.

  1. Search: Bosch BMV080 Sensor
  2. Go to Bosch Sensortec official page
  3. Download BMV080 SDK
  4. Accept license and submit form
  5. Download ZIP from email

Extract the zip file to a folder.

Copy Required Bosch Files

Copy below header files.

If using another ESP32 variant (ESP32, S2, C6), copy the last two files (lib_postProcessor.a and lib_bmv080.a) from matching folders accordingly.


Bosch SDK File → → → SparkFun BMV080 Arduino Library Directory

api/inc/bmv080.h → → → src/sfTk/bmv080.h

api/inc/bmv080_defs.h → → → src/sfTk/bmv080_defs.h

api/api/lib/xtensa_esp32s3/xtensa_esp32s3_elf_gcc/release/lib_postProcessor.a → → → src/esp32s3/lib_postProcessor.a

api/api/lib/xtensa_esp32s3/xtensa_esp32s3_elf_gcc/release/lib_bmv080.a → → → src/esp32s3/lib_bmv080.a

Arduino Example Code

#include "SparkFun_BMV080_Arduino_Library.h" // CTRL+Click here to get the library: http://librarymanager/All#SparkFun_BMV080
#include <Wire.h>

SparkFunBMV080 bmv080; // Create an instance of the BMV080 class
#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

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 1 - Basic Readings");

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");
}
}

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);
}

Upload & Monitor

BMV080_SerialMonitor.png
  1. Select board: PandaByte xS3 ESP32S3
  2. Flash size: 16MB
  3. Upload code
  4. Open Serial Monitor @115200 baud

You should see:

  1. PM1: xx µg/m³
  2. PM2.5: xx µg/m³
  3. PM10: xx µg/m³

Confirmed working values in your demo.