Qwiic Pressure Sensor (BMP581) Hookup Guide

Pages
Contributors: El Duderino
Favorited Favorite 0

Arduino Examples

With the Arduino library installed, it's time to upload some code to use the BMP581. In this section we take a closer look at several of the examples included with the library.

Example 1 - Basic Readings (I2C)

The first example initializes the BMP581 to communicate over I2C with default settings. Open the example by navigating to File Examples > SparkFun BMP581 Arduino Library > Example_1_Basic_ReadingsI2C. Select your Board and Port and click upload. Open the serial monitor after the upload completes with the baud set to 115200 to watch pressure data (in Pascals) print out.

If you have switched to the alternate address, comment/uncomment the line with the correct value:

language:c
uint8_t i2cAddress = BMP581_I2C_ADDRESS_DEFAULT; // 0x47
//uint8_t i2cAddress = BMP581_I2C_ADDRESS_SECONDARY; // 0x46

The code attempts to initialize the sensor with default settings in I2C at the specified address and prints out an error message if it cannot initialize properly:

language:c
while(pressureSensor.beginI2C(i2cAddress) != BMP5_OK)
{
    // Not connected, inform user
    Serial.println("Error: BMP581 not connected, check wiring and I2C address!");

    // Wait a bit to see if connection is established
    delay(1000);
}

After initializing, the main loop polls the BMP581 for pressure and temperature data every second. If polling for data fails, the code will print out an error code for debugging. Try moving the sensor up and down and you should see noticeable differences in pressure readings with just a few inches of movement.

language:c
void loop()
{
    // Get measurements from the sensor
    bmp5_sensor_data data = {0};
    int8_t err = pressureSensor.getSensorData(&data);

    // Check whether data was acquired successfully
    if(err == BMP5_OK)
    {
        // Acquisistion succeeded, print temperature and pressure
        Serial.print("Temperature (C): ");
        Serial.print(data.temperature);
        Serial.print("\t\t");
        Serial.print("Pressure (Pa): ");
        Serial.println(data.pressure);
    }
    else
    {
        // Acquisition failed, most likely a communication error (code -2)
        Serial.print("Error getting data from sensor! Error code: ");
        Serial.println(err);
    }

    // Only print every second
    delay(1000);
}

Example 3 - Interrupts

Example 3 shows how to set up and use the out-of-range (OOR) interrupt condition on the BME581 to trigger interrupt routines on an attached microcontroller. If you're not familiar with processor interrupts, this tutorial gives a good primer on using them with Arduino.

When assembling the interrupt circuit, make sure to connect the INT pin on the breakout to a pin capable of accepting external interrupts. The code sets up D2 as the interrupt pin so adjust this line if your microcontroller does not support external interrupts on that pin:

language:c
// Pin used for interrupt detection
int interruptPin = 2;

The code creates a flag to know when an interrupt condition occurs and sets the out-of-range condition specifications to ±50 Pa with a center value of 84000 Pa:

language:c    
// Flag to know when interrupts occur
volatile bool interruptOccurred = false;

// OOR range specification
uint32_t oorCenter = 84000;
uint8_t oorWindow = 50;

Example 7 - Non-Volatile Memory

As we covered in the Hardware Overview section, the BMP581 includes 6 bytes of non-volatile memory (NVM) you can write to and read from. Example 7 demonstrates how to interact with the NVM.

Along with the other standard definitions and calls, we need to set the data to write to the NVM. You can store any 6 bytes of data but in this example we'll store some characters:

language:c
char dataToWrite[] = "Hello!";

After initializing the sensor in the BMP581 and verifying it is connected, the code attempts to write the data declared above to the NVM. If this is successful, the code then prints out the stored data:

language:c
Serial.println("Writing data to NVM: ");
Serial.println(dataToWrite);

// The BMP581 contains non-volatile memory (NVM) that is primarily used for
// calibration data internally by the sensor. However 6 bytes are user programmable,
// stored in 3 2-byte locations (0x20 - 0x22).
uint16_t dataIndex = 0;
for(uint8_t addr = BMP5_NVM_START_ADDR; addr <= BMP5_NVM_END_ADDR; addr++)
{
    uint16_t data = dataToWrite[dataIndex] | (dataToWrite[dataIndex+1] << 8);
    dataIndex += 2;

    pressureSensor.writeNVM(addr, data);
}

Serial.println("Data read back from NVM: ");

// Now we can read back the data and display it
for(uint8_t addr = BMP5_NVM_START_ADDR; addr <= BMP5_NVM_END_ADDR; addr++)
{
    uint16_t data = 0;
    pressureSensor.readNVM(addr, &data);
    char first = data & 0xFF;
    char second = (data >> 8) & 0xFF;
    Serial.print(first);
    Serial.print(second);
}

Example 8 - Low Power

Example 8 is a demo of how to reduce power in a circuit with the BMP581 using the Deep Standby and Forced modes along with the BMP581's interrupt pin. The interrupt pin can be used to wake a microcontroller whenever the BMP581 takes a reading and fires the interrupt. The code uses D5 as the interrupt pin so adjust this line of code if your microcontroller does not support external interrupts on that pin:

language:c
int interruptPin = 5;

The code initializes the sensor on the I2C bus, sets it into Deep Standby mode and enables the interrupt pin to fire whenever data is ready (when the sensor is put into Forced Mode):

language:c
err = pressureSensor.setMode(BMP5_POWERMODE_DEEP_STANDBY);
if(err != BMP5_OK)
{
    // Interrupt settings failed, most likely a communication error (code -2)
    Serial.print("Set mode failed! Error code: ");
    Serial.println(err);
}

The main loop includes a one second delay before transitioning the sensor from Deep Standby to Forced Mode. The delay can be replaced with a power sequence setting the microcontroller into a low power mode.

After transitioning to Forced Mode, the code performs a series of checks in case the measurement ready condition timed out and if the interrupt is ready or the get status call failed. Once the checks have passed, the code checks if the interrupt status matches the Data Ready state, pulls temperature and pressure data from the BMP581 and prints it over serial:

language:c
if(interruptStatus & BMP5_INT_ASSERTED_DRDY)
{
    // Get measurements from the sensor
    bmp5_sensor_data data = {0};
    int8_t err = pressureSensor.getSensorData(&data);

    // Check whether data was acquired successfully
    if(err == BMP5_OK)
    {
        // Acquisistion succeeded, print temperature and pressure
        Serial.print("Temperature (C): ");
        Serial.print(data.temperature);
        Serial.print("\t\t");
        Serial.print("Pressure (Pa): ");
        Serial.println(data.pressure);
    }
    else
    {
        // Acquisition failed, most likely a communication error (code -2)
        Serial.print("Error getting data from sensor! Error code: ");
        Serial.println(err);
    }
}
else
{
    Serial.println("Wrong interrupt condition!");
}

Example 9 - Fast Measurements

The final example demonstrates how to use continuous mode for max speed measurements. This example uses Continuous Mode where the sensor performs measurements as soon as the previous measurement finishes. This example is a bit different from the other examples as it only reports the number of measurements taken during a one second interval and does not print the actual data measured by the sensor.

The code sets the oversampling ratio to 1x so the sensor can perform measurements at up to 500Hz in Continuous Mode and configures the Interrupt pin to trigger an interrupt every time a measurement is performed:

language:c
err = pressureSensor.setMode(BMP5_POWERMODE_CONTINOUS);
if(err != BMP5_OK)
{
    // Interrupt settings failed, most likely a communication error (code -2)
    Serial.print("Set mode failed! Error code: ");
    Serial.println(err);
}

// Configure the BMP581 to trigger interrupts whenever a measurement is performed
BMP581_InterruptConfig interruptConfig =
{
    .enable   = BMP5_INTR_ENABLE,    // Enable interrupts
    .drive    = BMP5_INTR_PUSH_PULL, // Push-pull or open-drain
    .polarity = BMP5_ACTIVE_HIGH,    // Active low or high
    .mode     = BMP5_PULSED,         // Latch or pulse signal
    .sources  =
    {
        .drdy_en = BMP5_ENABLE,        // Trigger interrupts when data is ready
        .fifo_full_en = BMP5_DISABLE,  // Trigger interrupts when FIFO is full
        .fifo_thres_en = BMP5_DISABLE, // Trigger interrupts when FIFO threshold is reached
        .oor_press_en = BMP5_DISABLE   // Trigger interrupts when pressure goes out of range
    }
};

The main loop checks if it is time to print (one second) and then prints the number of measurements taken during the print period:

language:c
if(millis() > lastPrintTime + printPeriod)
    {
        // Print out number of measurements this period
        Serial.print("Number of measurements in ");
        Serial.print(printPeriod);
        Serial.print("ms: ");
        Serial.println(measurementsThisPeriod);

        // Reset number of measurements for next period
        measurementsThisPeriod = 0;

        // Increment last print time
        lastPrintTime += printPeriod;
    }