Add support for BMP280/BME280 sensor

Change Serial and I2C pins mamangement to use default ones if not defined in configuration.h
Fix some typo
This commit is contained in:
Luc 2020-08-25 22:03:24 +02:00
parent 2a4dffcea5
commit fe168f7224
28 changed files with 2308 additions and 32 deletions

View File

@ -79,8 +79,6 @@
#if defined (DISPLAY_DEVICE)
//for ILI9143 edit User_Setup.h of TFT_eSPI library
#if (DISPLAY_DEVICE == OLED_I2C_SSD1306) || (DISPLAY_DEVICE == OLED_I2C_SSDSH1106)
#define DISPLAY_I2C_PIN_SDA 4
#define DISPLAY_I2C_PIN_SCL 15
#define DISPLAY_I2C_PIN_RST 16 //comment if not applicable
#define DISPLAY_I2C_ADDR 0x3c
#endif //(DISPLAY_DEVICE == OLED_I2C_SSD1306) || (DISPLAY_DEVICE == OLED_I2C_SSDSH1106)
@ -101,7 +99,7 @@
//ANALOG_DEVICE 3
//BMP280_DEVICE 4
//BME280_DEVICE 5
#define SENSOR_DEVICE DHT22_DEVICE
#define SENSOR_DEVICE BMP280_DEVICE
#ifdef BUZZER_DEVICE
#define ESP3D_BUZZER_PIN 15
@ -110,6 +108,7 @@
#ifdef SENSOR_DEVICE
//pin
#define ESP3D_SENSOR_PIN 22
#define SENSOR_ADDR 0x76
//Conversion coefficient
#define SENSOR_CONVERTER(v) v*0.588
//Unit to use, if not applicaple for sensor will use default one

View File

@ -22,8 +22,21 @@
//-1 means use default pins of your board what ever the serial you choose
// * UART 0 possible options are (1, 3), (2, 3) or (15, 13)
// * UART 1 allows only TX on 2 if UART 0 is not (2, 3)
#ifndef ESP_RX_PIN
#define ESP_RX_PIN -1
#endif //~ESP_RX_PIN
#ifndef ESP_TX_PIN
#define ESP_TX_PIN -1
#endif //~ESP_TX_PIN
//I2C Pins
#ifndef ESP_SDA_PIN
#define ESP_SDA_PIN SDA
#endif //~ESP_SDA_PIN
#ifndef ESP_SCL_PIN
#define ESP_SCL_PIN SCL
#endif //~ESP_SCL_PIN
//Pins for the support of connected camera
#if CAMERA_DEVICE == CAMERA_MODEL_CUSTOM

View File

@ -22,7 +22,7 @@
#define _VERSION_ESP3D_H
//version and sources location
#define FW_VERSION "3.0.0.a51"
#define FW_VERSION "3.0.0.a52"
#define REPOSITORY "https://github.com/luc-github/ESP3D/tree/3.0"
#endif //_VERSION_ESP3D_H

View File

@ -51,12 +51,12 @@ static bool bSnapshot;
#include "Wire.h"
#if DISPLAY_DEVICE == OLED_I2C_SSD1306
#include <SSD1306Wire.h>
SSD1306Wire esp3d_screen(DISPLAY_I2C_ADDR, DISPLAY_I2C_PIN_SDA, DISPLAY_I2C_PIN_SCL);
SSD1306Wire esp3d_screen(DISPLAY_I2C_ADDR, ESP_SDA_PIN, ESP_SCL_PIN);
#include "advanced_SSD1306.h"
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306
#if DISPLAY_DEVICE == OLED_I2C_SSDSH1106
#include <SH1106Wire.h>
SH1106Wire esp3d_screen(DISPLAY_I2C_ADDR, (DISPLAY_I2C_PIN_SDA==-1)?SDA:DISPLAY_I2C_PIN_SDA, (DISPLAY_I2C_PIN_SCL==-1)?SCL:DISPLAY_I2C_PIN_SCL);
SH1106Wire esp3d_screen(DISPLAY_I2C_ADDR, ESP_SDA_PIN, ESP_SCL_PIN);
#include "advanced_SSDSH1106.h"
#endif //DISPLAY_DEVICE == OLED_I2C_SSDSH1106
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106

View File

@ -30,12 +30,12 @@
#include "esp3d_logo.h"
#if DISPLAY_DEVICE == OLED_I2C_SSD1306
#include <SSD1306Wire.h>
SSD1306Wire esp3d_screen(DISPLAY_I2C_ADDR, DISPLAY_I2C_PIN_SDA, DISPLAY_I2C_PIN_SCL);
SSD1306Wire esp3d_screen(DISPLAY_I2C_ADDR, ESP_SDA_PIN, ESP_SCL_PIN);
#include "basic_SSD1306.h"
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306
#if DISPLAY_DEVICE == OLED_I2C_SSDSH1106
#include <SH1106Wire.h>
SH1106Wire esp3d_screen(DISPLAY_I2C_ADDR, (DISPLAY_I2C_PIN_SDA==-1)?SDA:DISPLAY_I2C_PIN_SDA, (DISPLAY_I2C_PIN_SCL==-1)?SCL:DISPLAY_I2C_PIN_SCL);
SH1106Wire esp3d_screen(DISPLAY_I2C_ADDR, ESP_SDA_PIN, ESP_SCL_PIN);
#include "basic_SSDSH1106.h"
#endif //DISPLAY_DEVICE == OLED_I2C_SSDSH1106
#endif //DISPLAY_DEVICE == OLED_I2C_SSD1306 || DISPLAY_DEVICE == OLED_I2C_SSDSH1106

View File

@ -0,0 +1,194 @@
/*
bmx280.cpp - sensor functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
This code is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This code is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with This code; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*/
#include "../../include/esp3d_config.h"
#ifdef SENSOR_DEVICE
#if SENSOR_DEVICE==BMP280_DEVICE || SENSOR_DEVICE==BME280_DEVICE
#include "bmx280.h"
#include "../../core/settings_esp3d.h"
#include "../../core/esp3doutput.h"
#include <BMx280I2C.h>
#include <Wire.h>
#define NB_TYPE_SENSOR 2
const char * SENSOR_NAME[NB_TYPE_SENSOR] = {"BMP280", "BME280"};
const uint8_t SENSOR_ID[NB_TYPE_SENSOR] = {BMP280_DEVICE, BME280_DEVICE};
BMx280I2C * bmx280_device;
BMX280SensorDevice::BMX280SensorDevice()
{
bmx280_device = nullptr;
}
BMX280SensorDevice::~BMX280SensorDevice()
{
end();
}
bool BMX280SensorDevice::begin()
{
end();
uint8_t sensortype= Settings_ESP3D::read_byte(ESP_SENSOR_TYPE);
if (sensortype == 0) {
log_esp3d("No Sensor active");
return true;
}
if (!isModelValid(sensortype)) {
log_esp3d("No valid id ");
return false;
}
//Setup Wire pins first as lib does setup wire
Wire.begin(ESP_SDA_PIN,ESP_SCL_PIN);
log_esp3d("Starting wire SDA:%d SCL:%d", ESP_SDA_PIN,ESP_SCL_PIN);
bmx280_device = new BMx280I2C(SENSOR_ADDR);
if (!bmx280_device) {
log_esp3d("Cannot instanciate sensor");
return false;
}
if (!bmx280_device->begin()) {
log_esp3d("No valid sensor status");
return false;
}
//reset sensor to default parameters.
bmx280_device->resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280_device->writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280_device->writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280_device->isBME280()) {
bmx280_device->writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
return true;
}
void BMX280SensorDevice::end()
{
if (bmx280_device) {
delete bmx280_device;
}
bmx280_device = nullptr;
}
bool BMX280SensorDevice::isModelValid(uint8_t model)
{
for (uint8_t i = 0; i < NB_TYPE_SENSOR; i++) {
if (model == SENSOR_ID[i]) {
return true;
}
}
return false;
}
uint8_t BMX280SensorDevice::getIDFromString(const char *s)
{
for (uint8_t i = 0; i < NB_TYPE_SENSOR; i++) {
log_esp3d("checking %s with %s",s, SENSOR_NAME[i]);
if (strcmp(s, SENSOR_NAME[i])==0) {
log_esp3d("found %d",SENSOR_ID[i]);
return SENSOR_ID[i];
}
}
return 0;
}
uint8_t BMX280SensorDevice::nbType()
{
return NB_TYPE_SENSOR;
}
uint8_t BMX280SensorDevice::GetModel(uint8_t i)
{
if (i <NB_TYPE_SENSOR) {
return SENSOR_ID[i];
}
return 0;
}
const char * BMX280SensorDevice::GetModelString(uint8_t i)
{
if (i <NB_TYPE_SENSOR) {
return SENSOR_NAME[i];
}
return "NONE";
}
//helper function
float toFahrenheit(float fromCelcius)
{
return 1.8 * fromCelcius + 32.0;
};
const char * BMX280SensorDevice::GetData()
{
static String s;
if (bmx280_device) {
if (!bmx280_device->measure()) {
s="BUSY";
log_esp3d("sensor is busy");
} else {
uint8_t nbtry = 0;
do {
log_esp3d("try sensor %d",nbtry);
Hal::wait(100);
nbtry ++;
} while (!bmx280_device->hasValue() && nbtry < 3);
if (bmx280_device->hasValue()) {
float temperature = bmx280_device->getTemperature();
float pressure = bmx280_device->getPressure();
float humidity=0;
if (bmx280_device->isBME280()) {
humidity = bmx280_device->getHumidity();
}
log_esp3d("T %f P %f H %f",temperature, pressure, humidity);
if ( String(temperature,1)!="nan") {
if (strcmp(SENSOR__UNIT,"F")==0) {
temperature = toFahrenheit(temperature);
}
s= String(temperature,1);
s+= SENSOR__UNIT;
s+= " " +String(pressure,1);
s+= "Pa";
if (bmx280_device->isBME280()) {
s+=" " + String(humidity,1) + "%";
}
} else {
s="DISCONNECTED";
log_esp3d("No valid data");
}
} else {
s="DISCONNECTED";
log_esp3d("No valid data");
}
}
} else {
s="DISCONNECTED";
log_esp3d("No device");
}
return s.c_str();
}
#endif //BMP280_DEVICE || BME280_DEVICE
#endif //SENSOR_DEVICE

View File

@ -1,5 +1,5 @@
/*
dht.h - dht functions class
bmx280.h - sensor functions class
Copyright (c) 2014 Luc Lebosse. All rights reserved.
@ -20,31 +20,24 @@
#ifndef _DHT_H
#define _DHT_H
#ifndef _BMX280_SENSOR_H
#define _BMX280_SENSOR_H
#include "sensor.h"
class DHT
class BMX280SensorDevice : ESP3DSensorDevice
{
public:
DHT();
~DHT();
BMX280SensorDevice();
~BMX280SensorDevice();
bool begin();
void end();
uint8_t GetModel();
const char *GetModelString();
const char *GetData();
float getHumidity();
float getTemperature();
bool started();
bool isCelsiusUnit();
void setCelsiusUnit(bool set);
private:
bool _started;
bool _usecelsius;
float _temperature;
float _humidity;
bool isModelValid(uint8_t model);
uint8_t getIDFromString(const char *);
uint8_t nbType();
uint8_t GetModel(uint8_t i=0);
const char *GetModelString(uint8_t i=0);
const char * GetData();
};
#endif //_DHT_H
#endif //_BMX280_SENSOR_H

View File

@ -20,8 +20,8 @@
#ifndef _ANALOG_SENSOR_H
#define _ANALOG_SENSOR_H
#ifndef _DHT_SENSOR_H
#define _DHT_SENSOR_H
#include "sensor.h"
@ -40,5 +40,5 @@ public:
const char * GetData();
};
#endif //_ANALOG_SENSOR_H
#endif //_DHT_SENSOR_H

View File

@ -30,6 +30,10 @@
#if SENSOR_DEVICE==ANALOG_DEVICE
#include "analogsensor.h"
#endif //ANALOG_DEVICE
#if SENSOR_DEVICE==BMP280_DEVICE || SENSOR_DEVICE==BME280_DEVICE
#include "bmx280.h"
#endif //BMP280_DEVICE || BME280_DEVICE
#if defined (WIFI_FEATURE) || defined(ETH_FEATURE)
#include "../websocket/websocket_server.h"
#endif // WIFI_FEATURE || ETH_FEATURE
@ -59,6 +63,9 @@ bool ESP3DSensor::begin()
#endif //ANALOG_DEVICE
#if SENSOR_DEVICE==DHT11_DEVICE || SENSOR_DEVICE==DHT22_DEVICE
_device = (ESP3DSensorDevice * )new DHTSensorDevice();
#endif //DHT11_DEVICE || DHT22_DEVICE
#if SENSOR_DEVICE==BMP280_DEVICE || SENSOR_DEVICE==BME280_DEVICE
_device = (ESP3DSensorDevice * )new BMX280SensorDevice();
#endif //DHT11_DEVICE || DHT22_DEVICE
if (!_device) {
log_esp3d("No device created");
@ -152,6 +159,9 @@ const char * ESP3DSensor::GetData()
void ESP3DSensor::handle()
{
if (_interval == 0) {
return;
}
if (_started && _device) {
if ((millis() - _lastReadTime) > _interval) {
String data = _device->GetData();

View File

@ -0,0 +1,38 @@
# Yet Another Arduino BME280 and BMP280 Digital Pressure Sensor Library
home: https://bitbucket.org/christandlg/bmx280mi
sensors: https://www.bosch-sensortec.com/bst/products/all_products/bmp280 / https://www.bosch-sensortec.com/bst/products/all_products/bme280
## Features:
- Supports I2C (via the Wire library) and SPI (via the SPI library) interfaces
- Supports other I2C and SPI libraries via inheritance
- Supports 64 bit pressure calculation
- Never blocks or delays (except for convenience functions)
## Changelog:
- 1.2.0
- fixed a bug #3 where getPressure(), getPressure64() and getHumitiy would depend on getTemperature() to be called immediately before (since last time hasValue() returned true) in order to return correct values.
- 1.1.2
- updated documentation on function hasValue()
- updated examples
- 1.1.1
- fixed an error in 64 bit pressure calculation
- 1.1.0
- added 64 bit pressure calculation
- 1.0.0
- added new classes BMx280TwoWire and BMx280SPIClass for TwoWire and SPIClass interfaces
-moved BMx280I2C and BMx280SPI classes into their own respecitve source files, further separating data processing from communications
- when updating from an earlier version and using the BMx280I2C or BMx280SPI classes, change ```#include <BMx280MI.h>``` to ```#include <BMx280I2C.h>``` or ```#include <BMx280SPI.h>```, respectively
- simplified function BMx280MI::measure()
- 0.0.2
- humidity measurement implemented
- 0.0.1
- initial release

View File

@ -0,0 +1,95 @@
// BMx280_I2C.ino
//
// shows how to use the BMP280 / BMx280 library with the sensor connected using I2C.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - BMP280 / BME280
// 3.3V ---- VCC
// GND ----- GND
// SDA ----- SDA
// SCL ----- SCL
// some BMP280/BME280 modules break out the CSB and SDO pins as well:
// 5V ------ CSB (enables the I2C interface)
// GND ----- SDO (I2C Address 0x76)
// 5V ------ SDO (I2C Address 0x77)
// other pins can be left unconnected.
#include <Arduino.h>
#include <Wire.h>
#include <BMx280I2C.h>
#define I2C_ADDRESS 0x76
//create a BMx280I2C object using the I2C interface with I2C Address 0x76
BMx280I2C bmx280(I2C_ADDRESS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
Wire.begin();
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and I2C Address.");
while (1);
}
if (bmx280.isBME280())
Serial.println("sensor is a BME280");
else
Serial.println("sensor is a BMP280");
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish
do
{
delay(100);
} while (!bmx280.hasValue());
Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
if (bmx280.isBME280())
{
Serial.print("Humidity: ");
Serial.println(bmx280.getHumidity());
}
}

View File

@ -0,0 +1,88 @@
// BMx280_SPI.ino
//
// shows how to use the BMx280 library with the sensor connected using SPI.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - AS3935
// 5V ------ VCC
// GND ----- GND
// MOSI ---- SDA
// SCK ----- SCL
// MISO ---- SDO
// D4 ------ CSB
// note: CSB _must_ be pulled low during BMx280 startup to enable the SPI interface.
#include <Arduino.h>
#include <SPI.h>
#include <BMx280SPI.h>
#define PIN_CS 4
//create an BMx280SPI object using pin 4 as chip select pin
BMx280SPI bmx280(PIN_CS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
SPI.begin();
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and chip select pin.");
while (1);
}
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish
do
{
delay(100);
} while (!bmx280.hasValue());
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
if (bmx280.isBME280())
{
Serial.print("Humidity: ");
Serial.println(bmx280.getHumidity());
}
}

View File

@ -0,0 +1,88 @@
// BMx280_SPI.ino
//
// shows how to use the BMx280 library with the sensor connected using SPI.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - AS3935
// 5V ------ VCC
// GND ----- GND
// MOSI ---- SDA
// SCK ----- SCL
// MISO ---- SDO
// D4 ------ CSB
// note: CSB _must_ be pulled low during BMx280 startup to enable the SPI interface.
#include <Arduino.h>
#include <SPI.h>
#include <BMx280SPIClass.h>
#define PIN_CS 4
//create an BMx280SPI object using pin 4 as chip select pin
BMx280SPIClass bmx280(&SPI, PIN_CS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
SPI.begin();
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and chip select pin.");
while (1);
}
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish
do
{
delay(100);
} while (!bmx280.hasValue());
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
if (bmx280.isBME280())
{
Serial.print("Humidity: ");
Serial.println(bmx280.getHumidity());
}
}

View File

@ -0,0 +1,95 @@
// BMx280_I2C.ino
//
// shows how to use the BMP280 / BMx280 library with the sensor connected using I2C.
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the AS3935 to the Arduino like this:
//
// Arduino - BMP280 / BME280
// 3.3V ---- VCC
// GND ----- GND
// SDA ----- SDA
// SCL ----- SCL
// some BMP280/BME280 modules break out the CSB and SDO pins as well:
// 5V ------ CSB (enables the I2C interface)
// GND ----- SDO (I2C Address 0x76)
// 5V ------ SDO (I2C Address 0x77)
// other pins can be left unconnected.
#include <Arduino.h>
#include <Wire.h>
#include <BMx280TwoWire.h>
#define I2C_ADDRESS 0x76
//create a BMx280I2C object using the I2C interface with I2C Address 0x76
BMx280TwoWire bmx280(&Wire, I2C_ADDRESS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
Wire.begin();
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and I2C Address.");
while (1);
}
if (bmx280.isBME280())
Serial.println("sensor is a BME280");
else
Serial.println("sensor is a BMP280");
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish.
do
{
delay(100);
} while (!bmx280.hasValue());
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
if (bmx280.isBME280())
{
Serial.print("Humidity: ");
Serial.println(bmx280.getHumidity());
}
}

View File

@ -0,0 +1,179 @@
// BMx280_otherInterfaces.ino
//
// shows how to use the BMx280 library with interfaces other than the native I2C or SPI interfaces.
// here, the second I2C port of an Arduino Due is used (Wire1)
//
// Copyright (c) 2018 Gregor Christandl
//
// connect the BMx280 to the Arduino Due like this:
//
// Arduino - BMx280
// 3.3V ---- VCC
// GND ----- GND
// SDA1 ---- SDA/SDI
// SCL1 ---- SKC/SCL
// some BMP280/BME280 modules break out the CSB and SDO pins as well:
// 5V ------ CSB (enables the I2C interface)
// GND ----- SDO (I2C Address 0x76)
// 5V ------ SDO (I2C Address 0x77)
// other pins can be left unconnected.
#include <Arduino.h>
#include <Wire.h>
#include <BMx280MI.h>
#define I2C_ADDRESS 0x76
//class derived from BMx280MI that implements communication via an interface other than native I2C or SPI.
class BMx280Wire1 : public BMx280MI
{
public:
//constructor of the derived class.
//@param address i2c address of the sensor.
BMx280Wire1(uint8_t i2c_address):
address_(i2c_address) //initialize the BMx280Wire1 classes private member address_ to the i2c address provided
{
//nothing else to do here...
}
private:
//this function must be implemented by derived classes. it is used to initialize the interface or check the sensor for example.
//@return true on success, false otherwise.
bool beginInterface()
{
return true;
}
//this function must be implemented by derived classes. this function is responsible for reading data from the sensor.
//@param reg register to read.
//@return read data (1 byte).
uint8_t readRegister(uint8_t reg)
{
#if defined(ARDUINO_SAM_DUE)
//workaround for Arduino Due. The Due seems not to send a repeated start with the code above, so this
//undocumented feature of Wire::requestFrom() is used. can be used on other Arduinos too (tested on Mega2560)
//see this thread for more info: https://forum.arduino.cc/index.php?topic=385377.0
Wire1.requestFrom(address_, 1, reg, 1, true);
#else
Wire1.beginTransmission(address_);
Wire1.write(reg);
Wire1.endTransmission(false);
Wire1.requestFrom(address_, static_cast<uint8_t>(1));
#endif
return Wire1.read();
}
//this function can be implemented by derived classes. implementing this function is optional, but readings may be incorrect if
//it is not (see BMP280 / BME280 datasheet).
//@param reg register to read.
//@param length number of registers to read (max: 4)
//@return read data. LSB = last register read.
uint32_t readRegisterBurst(uint8_t reg, uint8_t length)
{
if (length > 4)
return 0L;
uint32_t data = 0L;
#if defined(ARDUINO_SAM_DUE)
//workaround for Arduino Due. The Due seems not to send a repeated start with the code below, so this
//undocumented feature of Wire::requestFrom() is used. can be used on other Arduinos too (tested on Mega2560)
//see this thread for more info: https://forum.arduino.cc/index.php?topic=385377.0
Wire1.requestFrom(address_, length, data, length, true);
#else
Wire1.beginTransmission(address_);
Wire1.write(reg);
Wire1.endTransmission(false);
Wire1.requestFrom(address_, static_cast<uint8_t>(length));
for (uint8_t i = 0; i < length; i++)
{
data <<= 8;
data |= Wire1.read();
}
#endif
return data;
}
//this function must be implemented by derived classes. this function is responsible for sending data to the sensor.
//@param reg register to write to.
//@param data data to write to register.
void writeRegister(uint8_t reg, uint8_t data)
{
Wire1.beginTransmission(address_);
Wire1.write(reg);
Wire1.write(data);
Wire1.endTransmission();
}
uint8_t address_; //i2c address of sensor
};
//create an BMx280 object using the I2C interface, I2C address 0x01 and IRQ pin number 2
BMx280Wire1 bmx280(I2C_ADDRESS);
void setup() {
// put your setup code here, to run once:
Serial.begin(9600);
//wait for serial connection to open (only necessary on some boards)
while (!Serial);
Wire1.begin();
//begin() checks the Interface, reads the sensor ID (to differentiate between BMP280 and BME280)
//and reads compensation parameters.
if (!bmx280.begin())
{
Serial.println("begin() failed. check your BMx280 Interface and I2C Address.");
while (1);
}
//reset sensor to default parameters.
bmx280.resetToDefaults();
//by default sensing is disabled and must be enabled by setting a non-zero
//oversampling setting.
//set an oversampling setting for pressure and temperature measurements.
bmx280.writeOversamplingPressure(BMx280MI::OSRS_P_x16);
bmx280.writeOversamplingTemperature(BMx280MI::OSRS_T_x16);
//if sensor is a BME280, set an oversampling setting for humidity measurements.
if (bmx280.isBME280())
bmx280.writeOversamplingHumidity(BMx280MI::OSRS_H_x16);
}
void loop() {
// put your main code here, to run repeatedly:
delay(1000);
//start a measurement
if (!bmx280.measure())
{
Serial.println("could not start measurement, is a measurement already running?");
return;
}
//wait for the measurement to finish
do
{
delay(100);
} while (!bmx280.hasValue());
//important: measurement data is read from the sensor in function hasValue() only.
//make sure to call get*() functions only after hasValue() has returned true.
Serial.print("Pressure: "); Serial.println(bmx280.getPressure());
Serial.print("Pressure (64 bit): "); Serial.println(bmx280.getPressure64());
Serial.print("Temperature: "); Serial.println(bmx280.getTemperature());
if (bmx280.isBME280())
{
Serial.print("Humidity: ");
Serial.println(bmx280.getHumidity());
}
}

View File

@ -0,0 +1,116 @@
#######################################
# Syntax Coloring Map For ExampleLibrary
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
BMx280MI KEYWORD1
BMx280I2C KEYWORD1
BMx280SPI KEYWORD1
BMx280CompParams KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
begin KEYWORD2
measure KEYWORD2
hasValue KEYWORD2
getHumidity KEYWORD2
getPressure KEYWORD2
getPressure64 KEYWORD2
getTemperature KEYWORD2
readHumidity KEYWORD2
readTemperature KEYWORD2
readPressure KEYWORD2
readID KEYWORD2
readCompensationParameters KEYWORD2
isBME280 KEYWORD2
resetToDefaults KEYWORD2
readOversamplingHumidity KEYWORD2
writeOversamplingHumidity KEYWORD2
readOversamplingPressure KEYWORD2
writeOversamplingPressure KEYWORD2
readOversamplingTemperature KEYWORD2
writeOversamplingTemperature KEYWORD2
readFilterSetting KEYWORD2
writeFilterSetting KEYWORD2
readPowerMode KEYWORD2
writePowerMode KEYWORD2
readStandbyTime KEYWORD2
writeStandbyTime KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
FILTER_OFF LITERAL1
FILTER_x02 LITERAL1
FILTER_x04 LITERAL1
FILTER_x08 LITERAL1
FILTER_x16 LITERAL1
OSRS_H_x00 LITERAL1
OSRS_H_x01 LITERAL1
OSRS_H_x02 LITERAL1
OSRS_H_x04 LITERAL1
OSRS_H_x08 LITERAL1
OSRS_H_x16 LITERAL1
OSRS_P_x00 LITERAL1
OSRS_P_x01 LITERAL1
OSRS_P_x02 LITERAL1
OSRS_P_x04 LITERAL1
OSRS_P_x08 LITERAL1
OSRS_P_x16 LITERAL1
OSRS_T_x00 LITERAL1
OSRS_T_x01 LITERAL1
OSRS_T_x02 LITERAL1
OSRS_T_x04 LITERAL1
OSRS_T_x08 LITERAL1
OSRS_T_x16 LITERAL1
BMx280_MODE_SLEEP LITERAL1
BMx280_MODE_FORCED LITERAL1
BMx280_MODE_NORMAL LITERAL1
T_SB_0 LITERAL1
T_SB_1 LITERAL1
T_SB_2 LITERAL1
T_SB_3 LITERAL1
T_SB_4 LITERAL1
T_SB_5 LITERAL1
T_SB_6 LITERAL1
T_SB_7 LITERAL1
BME280_ID LITERAL1
BMP280_ID LITERAL1
dig_T1_ LITERAL1
dig_T2_ LITERAL1
dig_T3_ LITERAL1
dig_P1_ LITERAL1
dig_P2_ LITERAL1
dig_P3_ LITERAL1
dig_P4_ LITERAL1
dig_P5_ LITERAL1
dig_P6_ LITERAL1
dig_P7_ LITERAL1
dig_P8_ LITERAL1
dig_P9_ LITERAL1
dig_H1_ LITERAL1
dig_H2_ LITERAL1
dig_H3_ LITERAL1
dig_H4_ LITERAL1
dig_H5_ LITERAL1
dig_H6_ LITERAL1
#######################################

View File

@ -0,0 +1,19 @@
{
"name": "BMx280MI",
"version": "1.2.0",
"keywords": "BMP280, BME280, BMx280",
"description": "A library for the Bosch Sensortec BME280 and BMP280 Digital Pressure Sensors. The library supports both the SPI (via the SPI Library) and I2C (via the Wire Library) interfaces. Use of other I2C / SPI libraries (e.g. software I2C) is supported by inheritance. Supports 64 bit pressure calculation. ",
"authors":
{
"name": "Gregor Christandl",
"email": "christandlg@yahoo.com",
"url": "https://bitbucket.org/christandlg/bmx280mi"
},
"repository":
{
"type": "git",
"url": "https://bitbucket.org/christandlg/bmx280mi.git"
},
"frameworks": "arduino",
"platforms": "*"
}

View File

@ -0,0 +1,9 @@
name=BMx280MI
version=1.2.0
author=Gregor Christandl <christandlg@yahoo.com>
maintainer=Gregor Christandl <christandlg@yahoo.com>
sentence=A library for the Bosch Sensortec BME280 and BMP280 Digital Pressure Sensors.
paragraph=The library supports both the SPI (via the SPI Library) and I2C (via the Wire Library) interfaces. Use of other I2C / SPI libraries (e.g. software I2C) is supported by inheritance. Supports 64 bit pressure calculation.
category=Sensors
url=https://bitbucket.org/christandlg/bmx280mi
architectures=*

View File

@ -0,0 +1,31 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "BMx280I2C.h"
BMx280I2C::BMx280I2C(uint8_t address) :
BMx280TwoWire(&Wire, address)
{
//nothing to do here...
}
BMx280I2C::~BMx280I2C()
{
//nothing to do here...
}

View File

@ -0,0 +1,34 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BMX280I2C_H_
#define BMX280I2C_H_
#include "BMx280TwoWire.h"
class BMx280I2C :
public BMx280TwoWire
{
public:
BMx280I2C(uint8_t address);
virtual ~BMx280I2C();
};
#endif /* BMX280I2C_H_ */

View File

@ -0,0 +1,492 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "BMx280MI.h"
BMx280MI::BMx280MI() :
id_(BMP280_ID), //assume BMP280 by default
temp_fine_(0L),
uh_(0L),
up_(0L),
ut_(0L)
{
comp_params_ = {
0, //dig_T1
0, //dig_T2
0, //dig_T3
0, //dig_P1
0, //dig_P2
0, //dig_P3
0, //dig_P4
0, //dig_P5
0, //dig_P6
0, //dig_P7
0, //dig_P8
0, //dig_P9
0, //dig_H1
0, //dig_H2
0, //dig_H3
0, //dig_H4
0, //dig_H5
0 //dig_H6
};
}
BMx280MI::~BMx280MI()
{
//nothing to do here...
}
bool BMx280MI::begin()
{
//return false if the interface could not be initialized.
if (!beginInterface())
return false;
//update sensor ID.
id_ = readID();
//check sensor ID. return false if sensor ID does not match BME280 or BMP280 sensors.
if ((id_ != BMx280MI::BMP280_ID) && (id_ != BMx280MI::BME280_ID))
return false;
//wait until the sensor has finished transferring calibration data
while (static_cast<bool>(readRegisterValue(BMx280_REG_STATUS, BMx280_MASK_STATUS_IM_UPDATE)))
delay(100);
//read compensation parameters
comp_params_ = readCompensationParameters();
return true;
}
bool BMx280MI::measure()
{
uint8_t mode = readRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_MODE);
//start a measurement if the sensor is currently in sleep moode. any other mode indicates that
//measurements are performed automatically or a forced measurement is currently being performed.
if (mode == BMx280_MODE_SLEEP)
writeRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_MODE, BMx280_MODE_FORCED);
return true;
}
bool BMx280MI::hasValue()
{
bool has_value = !static_cast<bool>(readRegisterValue(BMx280_REG_STATUS, BMx280_MASK_STATUS_MEASURING));
if (has_value)
{
ut_ = readRegisterValueBurst(BMx280_REG_TEMP, BMx280_MASK_TEMP, 3);
up_ = readRegisterValueBurst(BMx280_REG_PRESS, BMx280_MASK_PRESS, 3);
if (isBME280())
uh_ = readRegisterValueBurst(BME280_REG_HUM, BME280_MASK_HUM, 2);
}
return has_value;
}
float BMx280MI::getHumidity()
{
//return NAN if the sensor is not a BME280.
if (!isBME280())
return NAN;
//return NAN if humidity measurements are disabled (humidity value == 0x8000)
if (uh_ == 0x8000)
return NAN;
updateTempFine();
int32_t v_x1_u32r;
//code adapted from BME280 data sheet section 4.2.3 and Bosch API
v_x1_u32r = temp_fine_ - 76800L;
v_x1_u32r = ((((static_cast<int32_t>(uh_) << 14) - (static_cast<int32_t>(comp_params_.dig_H4_) << 20) - (static_cast<int32_t>(comp_params_.dig_H5_) * v_x1_u32r)) + 16384L) >> 15) *
(((((((v_x1_u32r * static_cast<int32_t>(comp_params_.dig_H6_)) >> 10) * (((v_x1_u32r * static_cast<int32_t>(comp_params_.dig_H3_)) >> 11) + 32768L)) >> 10) + 2097152L) *
static_cast<int32_t>(comp_params_.dig_H2_) + 8192L) >> 14);
v_x1_u32r = v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * static_cast<int32_t>(comp_params_.dig_H1_)) >> 4);
v_x1_u32r = constrain(v_x1_u32r, 0L, 419430400L);
return static_cast<float>(v_x1_u32r >> 12) / 1024.0f;
}
float BMx280MI::getPressure()
{
//return NAN if pressure measurements are disabled.
if (up_ == 0x80000)
return NAN;
updateTempFine();
int32_t var1, var2;
uint32_t p;
//code adapted from BME280 data sheet section 8.2 and Bosch API
var1 = (static_cast<int32_t>(temp_fine_) >> 1) - 64000L;
var2 = (((var1 >> 2) * (var1 >> 2)) >> 11) * (static_cast<int32_t>(comp_params_.dig_P6_));
var2 = var2 + ((var1*(static_cast<int32_t>(comp_params_.dig_P5_))) << 1);
var2 = (var2 >> 2) + ((static_cast<int32_t>(comp_params_.dig_P4_)) << 16);
var1 = (((comp_params_.dig_P3_ * (((var1 >> 2) * (var1 >> 2)) >> 13)) >> 3) + (((static_cast<int32_t>(comp_params_.dig_P2_)) * var1) >> 1)) >> 18;
var1 = ((32768L + var1) * static_cast<int32_t>(comp_params_.dig_P1_)) >> 15;
if (var1 == 0)
return NAN; // avoid exception caused by division by zero
p = ((static_cast<uint32_t>(1048576L - up_)) - (var2 >> 12)) * 3125;
if (p < 0x80000000)
p = (p << 1) / static_cast<uint32_t>(var1);
else
p = p / static_cast<uint32_t>(var1) * 2;
var1 = (static_cast<int32_t>(comp_params_.dig_P9_) * static_cast<int32_t>(((p >> 3) * (p >> 3)) >> 13)) >> 12;
var2 = (static_cast<int32_t>(p >> 2) * static_cast<int32_t>(comp_params_.dig_P8_)) >> 13;
p = static_cast<uint32_t>(static_cast<int32_t>(p) + ((var1 + var2 + comp_params_.dig_P7_) >> 4));
return static_cast<float>(p);
}
double BMx280MI::getPressure64()
{
//return NAN if pressure measurements are disabled.
if (up_ == 0x80000)
return NAN;
updateTempFine();
int64_t var1, var2, p;
//code adapted from BME280 data sheet section 4.2.3 and Bosch API
var1 = static_cast<int64_t>(temp_fine_) - 128000L;
var2 = var1 * var1 * static_cast<int64_t>(comp_params_.dig_P6_);
var2 = var2 + ((var1 * static_cast<int64_t>(comp_params_.dig_P5_)) << 17);
var2 = var2 + (static_cast<int64_t>(comp_params_.dig_P4_) << 35);
var1 = ((var1 * var1 * static_cast<int64_t>(comp_params_.dig_P3_)) >> 8) + ((var1 * static_cast<int64_t>(comp_params_.dig_P2_)) << 12);
var1 = (((static_cast<int64_t>(1) << 47) + var1) * static_cast<int64_t>(comp_params_.dig_P1_)) >> 33;
if (var1 == 0)
return NAN; // avoid exception caused by division by zero
p = static_cast<int64_t>(1048576L - up_);
p = ((p << 31) - var2) * 3125 / var1;
var1 = (static_cast<int64_t>(comp_params_.dig_P9_) * (p >> 13) * (p >> 13)) >> 25;
var2 = (static_cast<int64_t>(comp_params_.dig_P8_) * p) >> 19;
p = ((p + var1 + var2) >> 8) + (static_cast<int64_t>(comp_params_.dig_P7_) << 4);
return static_cast<double>(p) / 256.0;
}
float BMx280MI::getTemperature()
{
//return NAN if temperature measurements are disabled.
if (ut_ == 0x80000)
return NAN;
updateTempFine();
int32_t T = (temp_fine_ * 5 + 128) >> 8;
return static_cast<float>(T) / 100.0f;
}
float BMx280MI::readHumidity()
{
if (!isBME280())
return NAN;
if (!measure())
return NAN;
do
{
delay(100);
} while (!hasValue());
return getHumidity();
}
float BMx280MI::readTemperature()
{
if (!measure())
return NAN;
do
{
delay(100);
} while (!hasValue());
return getTemperature();
}
float BMx280MI::readPressure()
{
if (!measure())
return NAN;
do
{
delay(100);
} while (!hasValue());
return getPressure();
}
uint8_t BMx280MI::readID()
{
return readRegisterValue(BMx280_REG_ID, BMx280_MASK_ID);
}
BMx280MI::BMx280CompParams BMx280MI::readCompensationParameters()
{
BMx280CompParams comp_params = {
0, //dig_T1
0, //dig_T2
0, //dig_T3
0, //dig_P1
0, //dig_P2
0, //dig_P3
0, //dig_P4
0, //dig_P5
0, //dig_P6
0, //dig_P7
0, //dig_P8
0, //dig_P9
0, //dig_H1
0, //dig_H2
0, //dig_H3
0, //dig_H4
0, //dig_H5
0 //dig_H6
};
//read compensation parameters
comp_params.dig_T1_ = static_cast<uint16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_T1, BMx280_MASK_DIG_T1, 2)));
comp_params.dig_T2_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_T2, BMx280_MASK_DIG_T2, 2)));
comp_params.dig_T3_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_T3, BMx280_MASK_DIG_T3, 2)));
comp_params.dig_P1_ = static_cast<uint16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P1, BMx280_MASK_DIG_P1, 2)));
comp_params.dig_P2_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P2, BMx280_MASK_DIG_P2, 2)));
comp_params.dig_P3_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P3, BMx280_MASK_DIG_P3, 2)));
comp_params.dig_P4_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P4, BMx280_MASK_DIG_P4, 2)));
comp_params.dig_P5_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P5, BMx280_MASK_DIG_P5, 2)));
comp_params.dig_P6_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P6, BMx280_MASK_DIG_P6, 2)));
comp_params.dig_P7_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P7, BMx280_MASK_DIG_P7, 2)));
comp_params.dig_P8_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P8, BMx280_MASK_DIG_P8, 2)));
comp_params.dig_P9_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BMx280_REG_DIG_P9, BMx280_MASK_DIG_P9, 2)));
//reda humidity compensation parameters if the sensor is of the BME280 family
if (isBME280())
{
comp_params.dig_H1_ = static_cast<uint8_t>(readRegisterValue(BME280_REG_DIG_H1, BME280_MASK_DIG_H1));
comp_params.dig_H2_ = static_cast<int16_t>(swapByteOrder(readRegisterValueBurst(BME280_REG_DIG_H2, BME280_MASK_DIG_H2, 2)));
comp_params.dig_H3_ = static_cast<uint8_t>((readRegisterValue(BME280_REG_DIG_H3, BME280_MASK_DIG_H3)));
uint8_t buf_msb = static_cast<uint8_t>((readRegisterValue(BME280_REG_DIG_H4_MSB, BME280_MASK_DIG_H4_MSB)));
uint8_t buf_lsb = static_cast<uint8_t>((readRegisterValue(BME280_REG_DIG_H4_LSB, BME280_MASK_DIG_H4_LSB)));
comp_params.dig_H4_ = (static_cast<uint16_t>(buf_msb) << 4) | buf_lsb;
buf_msb = static_cast<uint8_t>((readRegisterValue(BME280_REG_DIG_H5_MSB, BME280_MASK_DIG_H5_MSB)));
buf_lsb = static_cast<uint8_t>((readRegisterValue(BME280_REG_DIG_H5_LSB, BME280_MASK_DIG_H5_LSB)));
comp_params.dig_H5_ = (static_cast<uint16_t>(buf_msb) << 4) | buf_lsb;
comp_params.dig_H6_ = static_cast<int8_t>(readRegisterValue(BME280_REG_DIG_H6, BME280_MASK_DIG_H6));
}
return comp_params;
}
bool BMx280MI::isBME280(bool update_id)
{
if (update_id)
id_ = readID();
return (id_ == BMx280MI::BME280_ID);
}
void BMx280MI::resetToDefaults()
{
writeRegisterValue(BMx280_REG_RESET, BMP280_MASK_RESET, BMx280_CMD_RESET);
}
uint8_t BMx280MI::readOversamplingHumidity()
{
return readRegisterValue(BME280_REG_CTRL_HUM, BMx280_MASK_OSRS_H);
}
bool BMx280MI::writeOversamplingHumidity(uint8_t value)
{
if (!isBME280())
return false;
if (value > 0b111)
return false;
writeRegisterValue(BME280_REG_CTRL_HUM, BMx280_MASK_OSRS_H, value);
return true;
}
uint8_t BMx280MI::readOversamplingPressure()
{
return readRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_OSRS_P);
}
bool BMx280MI::writeOversamplingPressure(uint8_t value)
{
if (value > 0b111)
return false;
writeRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_OSRS_P, value);
return true;
}
uint8_t BMx280MI::readOversamplingTemperature()
{
return readRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_OSRS_T);
}
bool BMx280MI::writeOversamplingTemperature(uint8_t value)
{
if (value > 0b111)
return false;
writeRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_OSRS_T, value);
return true;
}
uint8_t BMx280MI::readFilterSetting()
{
return readRegisterValue(BMx280_REG_CONFIG, BMx280_MASK_FILTER);
}
bool BMx280MI::writeFilterSetting(uint8_t value)
{
if (value > 0b111)
return false;
writeRegisterValue(BMx280_REG_CONFIG, BMx280_MASK_FILTER, value);
return true;
}
uint8_t BMx280MI::readPowerMode()
{
return readRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_MODE);
}
bool BMx280MI::writePowerMode(uint8_t mode)
{
if (mode > 0x03)
return false;
writeRegisterValue(BMx280_REG_CTRL_MEAS, BMx280_MASK_MODE, mode);
return true;
}
uint8_t BMx280MI::readStandbyTime()
{
return readRegisterValue(BMx280_REG_CONFIG, BMx280_MASK_T_SB);
}
bool BMx280MI::writeStandbyTime(uint8_t standby_time)
{
if (standby_time > 0x07)
return false;
writeRegisterValue(BMx280_REG_CONFIG, BMx280_MASK_T_SB, standby_time);
return true;
}
void BMx280MI::updateTempFine() {
int32_t var1, var2;
//code adapted from BME280 data sheet section 8.2 and Bosch API
var1 = ((static_cast<int32_t>(ut_) >> 3) - (static_cast<int32_t>(comp_params_.dig_T1_) << 1));
var1 = (var1 * static_cast<int32_t>(comp_params_.dig_T2_)) >> 11;
var2 = (static_cast<int32_t>(ut_) >> 4) - static_cast<int32_t>(comp_params_.dig_T1_);
var2 = ((var2 * var2) >> 12) * static_cast<int32_t>(comp_params_.dig_T3_);
var2 = var2 >> 14;
temp_fine_ = var1 + var2;
}
uint16_t BMx280MI::swapByteOrder(uint16_t data)
{
//move LSB to MSB and MSB to LSB
return (data << 8) | (data >> 8);
}
uint8_t BMx280MI::setMaskedBits(uint8_t reg, uint8_t mask, uint8_t value)
{
//clear mask bits in register
reg &= (~mask);
//set masked bits in register according to value
return ((value << getMaskShift(mask)) & mask) | reg;
}
uint8_t BMx280MI::readRegisterValue(uint8_t reg, uint8_t mask)
{
return getMaskedBits(readRegister(reg), mask);
}
void BMx280MI::writeRegisterValue(uint8_t reg, uint8_t mask, uint8_t value)
{
uint8_t reg_val = readRegister(reg);
writeRegister(reg, setMaskedBits(reg_val, mask, value));
}
uint32_t BMx280MI::readRegisterValueBurst(uint8_t reg, uint32_t mask, uint8_t length)
{
return getMaskedBits(readRegisterBurst(reg, length), mask);
}
uint32_t BMx280MI::readRegisterBurst(uint8_t reg, uint8_t length)
{
if (length > 4)
return 0L;
uint32_t data = 0L;
for (uint8_t i = 0; i < length; i++)
{
data <<= 8;
data |= static_cast<uint32_t>(readRegister(reg));
}
return data;
}

View File

@ -0,0 +1,428 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BMX280MI_H_
#define BMX280MI_H_
#include <Arduino.h>
class BMx280MI
{
public:
enum filter_setting_t : uint8_t
{
FILTER_OFF = 0b000,
FILTER_x02 = 0b001,
FILTER_x04 = 0b010,
FILTER_x08 = 0b011,
FILTER_x16 = 0b100,
};
//humidity measurement oversampling register settings
//Note for BME280: when using filter, resolution is always 20 bit.
enum osrs_h : uint8_t
{
OSRS_H_x00 = 0b000, //deactivated
OSRS_H_x01 = 0b001,
OSRS_H_x02 = 0b010,
OSRS_H_x04 = 0b011,
OSRS_H_x08 = 0b100,
OSRS_H_x16 = 0b101
};
//pressure measurement oversampling register settings
//Note for BME280: when using filter, resolution is always 20 bit.
enum osrs_p : uint8_t
{
OSRS_P_x00 = 0b000, //deactivated
OSRS_P_x01 = 0b001,
OSRS_P_x02 = 0b010,
OSRS_P_x04 = 0b011,
OSRS_P_x08 = 0b100,
OSRS_P_x16 = 0b101
};
//temperature measurement oversampling register settings
//Note for BME280: when using filter, resolution is always 20 bit.
enum osrs_t : uint8_t
{
OSRS_T_x00 = 0b000, //deactivated
OSRS_T_x01 = 0b001, //16 bits
OSRS_T_x02 = 0b010, //17 bits
OSRS_T_x04 = 0b011, //18 bits
OSRS_T_x08 = 0b100, //19 bits
OSRS_T_x16 = 0b101 //20 bits
};
enum power_mode_t : uint8_t
{
BMx280_MODE_SLEEP = 0b00, //device in sleep mode.
BMx280_MODE_FORCED = 0b01, //measurements are performed on demand.
BMx280_MODE_FORCED_ALT = 0b10, //alternative value for BMx280_MODE_FORCED.
BMx280_MODE_NORMAL = 0b11 //measurements are performed periodically.
};
enum standby_time_t : uint8_t
{
T_SB_0 = 0b000, //0.5 ms
T_SB_1 = 0b001, //62.5 ms
T_SB_2 = 0b010, //125 ms
T_SB_3 = 0b011, //250 ms
T_SB_4 = 0b100, //500 ms
T_SB_5 = 0b101, //1000 ms
T_SB_6 = 0b110, //2000 ms (BMP280), 10ms (BME280)
T_SB_7 = 0b111, //4000 ms (BMP280), 20ms (BME280)
};
//compensation parameters
struct BMx280CompParams {
uint16_t dig_T1_;
int16_t dig_T2_;
int16_t dig_T3_;
uint16_t dig_P1_;
int16_t dig_P2_;
int16_t dig_P3_;
int16_t dig_P4_;
int16_t dig_P5_;
int16_t dig_P6_;
int16_t dig_P7_;
int16_t dig_P8_;
int16_t dig_P9_;
uint8_t dig_H1_;
int16_t dig_H2_;
uint8_t dig_H3_;
int16_t dig_H4_;
int16_t dig_H5_;
int8_t dig_H6_;
};
static const uint8_t BMP280_ID = 0x58;
static const uint8_t BME280_ID = 0x60;
BMx280MI();
virtual ~BMx280MI();
//initializes the sensor.
//@return true on success, false otherwise.
bool begin();
//starts a measurement. return true if automatic measurements are enabled (normal mode) or a forced measurement
//is currently running.
//@return true on success, false otherwise.
bool measure();
//@return true if a measurement was completed, false otherwise.
//checks if a measurement is currently running. if no measurement is running, reads measurement data from the sensor.
//important: values returned by get*() functions will not change unless hasValue() was called and returned true.
//if automatic measurements are enabled calling this function may cause the values returned by getHumidity(),
//getPressure() and getTemperature() to change.
bool hasValue();
//@return the last measured humidity value, in %RH. uses the calculation code taken from the datasheet.
float getHumidity();
//@return the last measured pressure, in Pa. uses the 32bit calculation code taken from the datasheet.
float getPressure();
//@return the last measured pressure, in Pa. uses the 64bit calculcation code taken from the datasheet.
double getPressure64();
//@return the last measured temperature, in deg C. uses the 32bit calculation code taken from the datasheet.
float getTemperature();
//triggers a measurement and returns the measured humidity. do not use in
//event loops, as it blocks.
//@return humidtity in %RH or NAN if the measurement failed (or the sensor is not a BME280).
float readHumidity();
//triggers a measurement and returns the measured temperature. do not use in
//event loops, as it blocks.
//@return temperature in deg C or NAN if the measurement failed.
float readTemperature();
//triggers a measurement and returns the measured pressure. do not use in
//event loops, as it blocks.
//@return pressure in Pa or NAN if the measurement failed.
float readPressure();
//@return the ID of the BMP280. the sensor will always return 0x58 (BMP280) or 0x60 (BME280), so this function
//can be used as a communication check.
uint8_t readID();
//reads the compensation parameters from the sensor.
//@return sensors compensation parameters as BMx280CompParams struct.
BMx280CompParams readCompensationParameters();
//checks if the sensor ID matches that of a BME280 sensor.
//@param (optional) update_id if true the internally kept sensor ID is updated.
//@return true if the sensor is a BME280, false otherwise.
bool isBME280(bool update_id = false);
/*
resets all registers to default values. */
void resetToDefaults();
//@return pressure oversampling setting
uint8_t readOversamplingHumidity();
//@param value to set
//@return true on success, false otherwise.
bool writeOversamplingHumidity(uint8_t value);
//@return pressure oversampling setting
uint8_t readOversamplingPressure();
//@param value to set
//@return true on success, false otherwise.
bool writeOversamplingPressure(uint8_t value);
//@return pressure oversampling setting
uint8_t readOversamplingTemperature();
//@param value to set
//@return true on success, false otherwise.
bool writeOversamplingTemperature(uint8_t value);
//@return filter setting as filter_setting_t.
uint8_t readFilterSetting();
//@param filter setting as filter_setting_t.
//@return true on success, false otherwise.
bool writeFilterSetting(uint8_t setting);
//@return sensors power mode as power_mode_t.
uint8_t readPowerMode();
//sets the sensors power mode.
//@param power mode as power_mode_t
//@return true on success, false otherwise.
bool writePowerMode(uint8_t mode);
//@return standby time as standby_time_t.
uint8_t readStandbyTime();
//sets the sensors standby time. only has an effect if measurements are done in 'normal' (automatic) mode.
//@param standby time as standby_time_t.
//@return true on success, false otherwise.
bool writeStandbyTime(uint8_t standby_time);
private:
enum bmx280_register_t : uint8_t
{
BMx280_REG_ID = 0xD0, //contains 0x58 after power on
BMx280_REG_RESET = 0xE0, //write 0xB6 to reset
BMx280_REG_STATUS = 0xF3, //bit 0: im_update, bit 3: measuring
BMx280_REG_CTRL_MEAS = 0xF4, //sets data acquisition options of device
BMx280_REG_CONFIG = 0xF5, //sets the rate, filter and interface options of the device.
BMx280_REG_PRESS = 0xF7, //raw pressure measurement output data up[19:0] in registers 0xF7...0xF9
BMx280_REG_TEMP = 0xFA, //raw temperature measurement output data ut[19:0] in registers 0xFA...0xFC
BMx280_REG_DIG_T1 = 0x88, //dig_T1, unsigned short
BMx280_REG_DIG_T2 = 0x8A, //dig_T2, signed short
BMx280_REG_DIG_T3 = 0x8C, //dig_T3, signed short
BMx280_REG_DIG_P1 = 0x8E, //dig_P1, unsigned short
BMx280_REG_DIG_P2 = 0x90, //dig_P2, signed short
BMx280_REG_DIG_P3 = 0x92, //dig_P3, signed short
BMx280_REG_DIG_P4 = 0x94, //dig_P4, signed short
BMx280_REG_DIG_P5 = 0x96, //dig_P5, signed short
BMx280_REG_DIG_P6 = 0x98, //dig_P6, signed short
BMx280_REG_DIG_P7 = 0x9A, //dig_P7, signed short
BMx280_REG_DIG_P8 = 0x9C, //dig_P8, signed short
BMx280_REG_DIG_P9 = 0x9E, //dig_P9, signed short
BME280_REG_DIG_H1 = 0xA1, //dig_H1, unsigned char
BME280_REG_DIG_H2 = 0xE1, //dig_H2, signed short
BME280_REG_DIG_H3 = 0xE3, //dig_H3, unsigned char
BME280_REG_DIG_H4_MSB = 0xE4, //dig_H4_MSB, byte
BME280_REG_DIG_H4_LSB = 0xE5, //dig_H4_LSB, byte
BME280_REG_DIG_H5_MSB = 0xE6, //dig_H5_MSB, byte
BME280_REG_DIG_H5_LSB = 0xE5, //dig_H5_LSB, byte
BME280_REG_DIG_H6 = 0xE7, //dig_H6, signed char
BME280_REG_CTRL_HUM = 0xF2, //Controls oversampling of humidity data.
BME280_REG_HUM = 0xFD //raw humidity measurement output data uh[15:0]
};
enum bmx280_mask_t : uint8_t
{
BMx280_MASK_ID = 0b11111111,
BMP280_MASK_RESET = 0b11111111,
BMx280_MASK_OSRS_H = 0b00000111,
//register 0xF3
BMx280_MASK_STATUS_IM_UPDATE = 0b00000001,
BMx280_MASK_STATUS_MEASURING = 0b00001000,
//register 0xF4
BMx280_MASK_MODE = 0b00000011,
BMx280_MASK_OSRS_P = 0b00011100,
BMx280_MASK_OSRS_T = 0b11100000,
//register 0xF5
//BMx280_MASK_SPI3W_EN = 0b00000001, //SPI 3 Wire is not supported.
BMx280_MASK_FILTER = 0b00011100,
BMx280_MASK_T_SB = 0b11100000,
};
//32 bit masks for burst reading.
enum bmx280_mask_32bit_t : uint32_t
{
BMx280_MASK_DIG_T1 = 0x0000FFFF, //dig_T1, unsigned short
BMx280_MASK_DIG_T2 = 0x0000FFFF, //dig_T2, signed short
BMx280_MASK_DIG_T3 = 0x0000FFFF, //dig_T3, signed short
BMx280_MASK_DIG_P1 = 0x0000FFFF, //dig_P1, unsigned short
BMx280_MASK_DIG_P2 = 0x0000FFFF, //dig_P2, signed short
BMx280_MASK_DIG_P3 = 0x0000FFFF, //dig_P3, signed short
BMx280_MASK_DIG_P4 = 0x0000FFFF, //dig_P4, signed short
BMx280_MASK_DIG_P5 = 0x0000FFFF, //dig_P5, signed short
BMx280_MASK_DIG_P6 = 0x0000FFFF, //dig_P6, signed short
BMx280_MASK_DIG_P7 = 0x0000FFFF, //dig_P7, signed short
BMx280_MASK_DIG_P8 = 0x0000FFFF, //dig_P8, signed short
BMx280_MASK_DIG_P9 = 0x0000FFFF, //dig_P9, signed short
BME280_MASK_DIG_H1 = 0x000000FF, //dig_H1, unsigned char
BME280_MASK_DIG_H2 = 0x0000FFFF, //dig_H2, signed short
BME280_MASK_DIG_H3 = 0x000000FF, //dig_H3, unsigned char
BME280_MASK_DIG_H4_MSB = 0x000000FF, //dig_H4_MSB, byte
BME280_MASK_DIG_H4_LSB = 0x0000000F, //dig_H4_LSB, byte
BME280_MASK_DIG_H5_MSB = 0x000000FF, //dig_H5_MSB, byte
BME280_MASK_DIG_H5_LSB = 0x000000F0, //dig_H5_LSB, byte
BME280_MASK_DIG_H6 = 0x000000FF, //dig_H6, signed char
BME280_MASK_HUM = 0x0000FFFF, //humidity data (16 bits)
BMx280_MASK_PRESS = 0x00FFFFF0, //pressure data (20 bits)
BMx280_MASK_TEMP = 0x00FFFFF0 //temperature data (20 bits)
};
static const uint8_t BMx280_CMD_RESET = 0xB6;
virtual bool beginInterface() = 0;
/*
updates the value of private class member variable temp_fine_, which must be up to date
for temperature, pressure and humidity calculations.
*/
void updateTempFine();
/*
@param mask
@return number of bits to shift value so it fits into mask. */
template <class T> uint8_t getMaskShift(T mask)
{
uint8_t return_value = 0;
//count how many times the mask must be shifted right until the lowest bit is set
if (mask != 0)
{
while (!(mask & 1))
{
return_value++;
mask >>= 1;
}
}
return return_value;
};
/*
@param register value of register.
@param mask mask of value in register
@return value of masked bits. */
template <class T> T getMaskedBits(T reg, T mask)
{
//extract masked bits
return ((reg & mask) >> getMaskShift(mask));
};
/*
swaps the byte order (MSB -> LSB and LSB -> MSB) of a given uint16_t variable.
@param data
@return data*/
uint16_t swapByteOrder(uint16_t data);
/*
@param register value of register
@param mask mask of value in register
@param value value to write into masked area
@param register value with masked bits set to value. */
uint8_t setMaskedBits(uint8_t reg, uint8_t mask, uint8_t value);
/*
reads the masked value from the register.
@param reg register to read.
@param mask mask of value.
@return masked value in register. */
uint8_t readRegisterValue(uint8_t reg, uint8_t mask);
/*
sets values in a register.
@param reg register to set values in
@param mask bits of register to set value in
@param value value to set */
void writeRegisterValue(uint8_t reg, uint8_t mask, uint8_t value);
/*
reads the masked values from multiple registers. maximum read length is 4 bytes.
@param reg register to read.
@param mask mask of value.
@param length number of bytes to read
@return register content */
uint32_t readRegisterValueBurst(uint8_t reg, uint32_t mask, uint8_t length);
/*
reads a register from the sensor. must be overwritten by derived classes.
@param reg register to read.
@return register content*/
virtual uint8_t readRegister(uint8_t reg) = 0;
/*
reads a series of registers from the sensor. can be overwritten by derived classes.
if this function is not overwritten, the registers will be read using single-byte reads.
@param reg register to read.
@param length number of bytes to read. maximum length is 4 bytes.
@return register content. LSB = last byte read. e.g., if start register = 0xE0 and length = 4,
the returned value will contain the register data like this: (MSB) [0xE0 0xE1 0xE2 0xE3] (LSB)*/
virtual uint32_t readRegisterBurst(uint8_t reg, uint8_t length);
/*
writes a register to the sensor. must be overwritten by derived classes.
this function is also used to send direct commands.
@param reg register to write to.
@param value value writeRegister write to register. */
virtual void writeRegister(uint8_t reg, uint8_t value) = 0;
uint8_t id_; //the sensors ID. necessary to differentiate between BMP280 and BME280.
int32_t temp_fine_;
uint16_t uh_;
uint32_t up_;
uint32_t ut_;
BMx280CompParams comp_params_;
};
#endif /* BMX280MI_H_ */

View File

@ -0,0 +1,29 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "BMx280SPI.h"
BMx280SPI::BMx280SPI(uint8_t cs_) :
BMx280SPIClass(&SPI, cs_)
{
}
BMx280SPI::~BMx280SPI()
{
}

View File

@ -0,0 +1,34 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BMX280SPI_H_
#define BMX280SPI_H_
#include "BMx280SPIClass.h"
class BMx280SPI :
public BMx280SPIClass
{
public:
BMx280SPI(uint8_t cs_);
virtual ~BMx280SPI();
};
#endif /* BMX280SPI_H_ */

View File

@ -0,0 +1,93 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "BMx280SPIClass.h"
SPISettings BMx280SPIClass::spi_settings_ = SPISettings(2000000, MSBFIRST, SPI_MODE1);
BMx280SPIClass::BMx280SPIClass(SPIClass *spi, uint8_t chip_select) :
cs_(chip_select)
{
//nothing to do here...
}
BMx280SPIClass::~BMx280SPIClass()
{
//nothing to do here...
}
bool BMx280SPIClass::beginInterface()
{
pinMode(cs_, OUTPUT);
digitalWrite(cs_, HIGH); //deselect
return true;
}
uint8_t BMx280SPIClass::readRegister(uint8_t reg)
{
uint8_t return_value = 0;
SPI.beginTransaction(spi_settings_);
digitalWrite(cs_, LOW); //select sensor
SPI.transfer((reg & 0x3F) | 0x40); //select register and set pin 7 (indicates read)
return_value = SPI.transfer(0);
digitalWrite(cs_, HIGH); //deselect sensor
return return_value;
}
uint32_t BMx280SPIClass::readRegisterBurst(uint8_t reg, uint8_t length)
{
if (length > 4)
return 0L;
uint32_t data = 0;
SPI.beginTransaction(spi_settings_);
digitalWrite(cs_, LOW); //select sensor
SPI.transfer((reg & 0x3F) | 0x40); //select register and set pin 7 (indicates read)
for (uint8_t i = 0; i < length; i++)
{
data <<= 8;
data |= SPI.transfer(0);
}
digitalWrite(cs_, HIGH); //deselect sensor
return data;
}
void BMx280SPIClass::writeRegister(uint8_t reg, uint8_t value)
{
SPI.beginTransaction(spi_settings_);
digitalWrite(cs_, LOW); //select sensor
SPI.transfer((reg & 0x3F)); //select regsiter
SPI.transfer(value);
digitalWrite(cs_, HIGH); //deselect sensor
}

View File

@ -0,0 +1,51 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BMX280SPICLASS_H_
#define BMX280SPICLASS_H_
#include "BMx280MI.h"
#include <SPI.h>
class BMx280SPIClass :
public BMx280MI
{
public:
BMx280SPIClass(SPIClass *spi, uint8_t chip_select);
virtual ~BMx280SPIClass();
protected:
SPIClass *spi_;
uint8_t cs_;
static SPISettings spi_settings_; //spi settings object. is the same for all BMx280 sensors
private:
bool beginInterface();
uint8_t readRegister(uint8_t reg);
uint32_t readRegisterBurst(uint8_t reg, uint8_t length);
void writeRegister(uint8_t reg, uint8_t value);
};
#endif /* BMX280SPICLASS_H_ */

View File

@ -0,0 +1,98 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#include "BMx280TwoWire.h"
BMx280TwoWire::BMx280TwoWire(TwoWire *wire, uint8_t i2c_address) :
wire_(wire),
address_(i2c_address)
{
//nothing to do here...
}
BMx280TwoWire::~BMx280TwoWire()
{
wire_ = nullptr;
}
bool BMx280TwoWire::beginInterface()
{
return true;
}
uint8_t BMx280TwoWire::readRegister(uint8_t reg)
{
if (!wire_)
return 0;
#if defined(ARDUINO_SAM_DUE)
//workaround for Arduino Due. The Due seems not to send a repeated start with the code above, so this
//undocumented feature of Wire::requestFrom() is used. can be used on other Arduinos too (tested on Mega2560)
//see this thread for more info: https://forum.arduino.cc/index.php?topic=385377.0
wire_->requestFrom(address_, 1, reg, 1, true);
#else
wire_->beginTransmission(address_);
wire_->write(reg);
wire_->endTransmission(false);
wire_->requestFrom(address_, static_cast<uint8_t>(1));
#endif
return wire_->read();
}
uint32_t BMx280TwoWire::readRegisterBurst(uint8_t reg, uint8_t length)
{
if (!wire_)
return 0;
if (length > 4)
return 0L;
uint32_t data = 0L;
#if defined(ARDUINO_SAM_DUE)
//workaround for Arduino Due. The Due seems not to send a repeated start with the code below, so this
//undocumented feature of Wire::requestFrom() is used. can be used on other Arduinos too (tested on Mega2560)
//see this thread for more info: https://forum.arduino.cc/index.php?topic=385377.0
wire_->requestFrom(address_, length, data, length, true);
#else
wire_->beginTransmission(address_);
wire_->write(reg);
wire_->endTransmission(false);
wire_->requestFrom(address_, static_cast<uint8_t>(length));
for (uint8_t i = 0; i < length; i++)
{
data <<= 8;
data |= wire_->read();
}
#endif
return data;
}
void BMx280TwoWire::writeRegister(uint8_t reg, uint8_t value)
{
if (!wire_)
return;
wire_->beginTransmission(address_);
wire_->write(reg);
wire_->write(value);
wire_->endTransmission();
}

View File

@ -0,0 +1,50 @@
//Multi interface Bosch Sensortec BMP280 / BME280 pressure sensor library
// Copyright (c) 2018-2019 Gregor Christandl <christandlg@yahoo.com>
// home: https://bitbucket.org/christandlg/bmp280mi
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License, or (at your option) any later version.
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
// You should have received a copy of the GNU Lesser General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#ifndef BMX280TWOWIRE_H_
#define BMX280TWOWIRE_H_
#include <BMx280MI.h>
#include <Wire.h>
class BMx280TwoWire :
public BMx280MI
{
public:
BMx280TwoWire(TwoWire *wire, uint8_t i2c_address);
virtual ~BMx280TwoWire();
protected:
TwoWire *wire_;
uint8_t address_;
private:
bool beginInterface();
uint8_t readRegister(uint8_t reg);
uint32_t readRegisterBurst(uint8_t reg, uint8_t length);
void writeRegister(uint8_t reg, uint8_t value);
};
#endif /* BMX280TWOWIRE_H_ */