working encrypted OTA, added BMP280
This commit is contained in:
parent
e462fa5e47
commit
1adf9a477a
5
build.sh
5
build.sh
@ -4,11 +4,12 @@
|
||||
|
||||
idf.py -DROLE=SENDER build
|
||||
|
||||
cp build/wellhub.bin /var/www/esp_ota
|
||||
|
||||
ret_val=$?
|
||||
|
||||
if (($ret_val != 0)); then
|
||||
exit
|
||||
fi
|
||||
|
||||
image_enc/encrypt.py build/wellhub.bin build/wellhub.enc
|
||||
cp build/wellhub.bin /var/www/esp_ota
|
||||
|
||||
|
||||
311
components/BMP280_DEV/BMP280_DEV.cpp
Executable file
311
components/BMP280_DEV/BMP280_DEV.cpp
Executable file
@ -0,0 +1,311 @@
|
||||
/*
|
||||
BMP280_DEV is an I2C/SPI compatible library for the Bosch BMP280 barometer.
|
||||
|
||||
Copyright (C) Martin Lindupp 2019
|
||||
|
||||
V1.0.0 -- Initial release
|
||||
V1.0.1 -- Added ESP32 HSPI support and change library to unique name
|
||||
V1.0.2 -- Modification to allow external creation of HSPI object on ESP32
|
||||
V1.0.3 -- Changed library name in the library.properties file
|
||||
V1.0.5 -- Fixed bug in BMP280_DEV::getTemperature() function, thanks to Jon M.
|
||||
V1.0.6 -- Merged multiple instances and initialisation pull requests by sensslen
|
||||
V1.0.8 -- Used default arguments for begin() member function and
|
||||
added example using multiple BMP280 devices with SPI comms in NORMAL mode
|
||||
V1.0.9 -- Moved writeMask to Device class and improved measurement detection code
|
||||
V1.0.10 -- Modification to allow user-defined pins for I2C operation on the ESP8266
|
||||
V1.0.12 -- Allow sea level pressure calibration using setSeaLevelPressure() function
|
||||
V1.0.14 -- Fix uninitialised structures, thanks to David Jade investigating and
|
||||
flagging up this issue
|
||||
V1.0.16 -- Modification to allow user-defined pins for I2C operation on the ESP32
|
||||
V1.0.17 -- Added getCurrentTemperature(), getCurrentPressure(), getCurrentTempPres()
|
||||
getCurrentAltitude() and getCurrentMeasurements() functions,
|
||||
to allow the BMP280 to be read directly without checking the measuring bit
|
||||
V1.0.18 -- Initialise "device" constructor member variables in the same order they are declared
|
||||
V1.0.19 -- Allow for additional TwoWire instances
|
||||
V1.0.20 -- Removed default parameter causing ESP32 compilation error with user defined I2C pins
|
||||
V1.0.21 -- Fixed uninitialised "Wire" pointer for ESP8266/ESP32 with user defined I2C pins
|
||||
|
||||
The MIT License (MIT)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <BMP280_DEV.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Class Constructors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
BMP280_DEV::BMP280_DEV(TwoWire& twoWire) : Device(twoWire) { setI2CAddress(BMP280_I2C_ADDR); } // Constructor for I2C communications
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
BMP280_DEV::BMP280_DEV(uint8_t sda, uint8_t scl, TwoWire& twoWire) : // Constructor for I2C comms on ESP8266
|
||||
Device(sda, scl, twoWire) { setI2CAddress(BMP280_I2C_ADDR); }
|
||||
#endif
|
||||
BMP280_DEV::BMP280_DEV(uint8_t cs) : Device(cs) {} // Constructor for SPI communications
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
BMP280_DEV::BMP280_DEV(uint8_t sda, uint8_t scl, TwoWire& twoWire) : // Constructor for I2C comms on ESP32
|
||||
Device(sda, scl, twoWire) { setI2CAddress(BMP280_I2C_ADDR); }
|
||||
BMP280_DEV::BMP280_DEV(uint8_t cs, uint8_t spiPort, SPIClass& spiClass) : Device(cs, spiPort, spiClass) {} // Constructor for SPI communications on the ESP32
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Public Member Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t BMP280_DEV::begin(Mode mode, // Initialise BMP280 device settings
|
||||
Oversampling presOversampling,
|
||||
Oversampling tempOversampling,
|
||||
IIRFilter iirFilter,
|
||||
TimeStandby timeStandby)
|
||||
{
|
||||
initialise(); // Call the Device base class "initialise" function
|
||||
if (readByte(BMP280_DEVICE_ID) != DEVICE_ID) // Check the device ID
|
||||
{
|
||||
return 0; // If the ID is incorrect return 0
|
||||
}
|
||||
reset(); // Reset the BMP280 barometer
|
||||
readBytes(BMP280_TRIM_PARAMS, (uint8_t*)¶ms, sizeof(params)); // Read the trim parameters into the params structure
|
||||
setConfigRegister(iirFilter, timeStandby); // Initialise the BMP280 configuration register
|
||||
setCtrlMeasRegister(mode, presOversampling, tempOversampling); // Initialise the BMP280 control and measurement register
|
||||
return 1; // Report successful initialisation
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::begin(Mode mode, uint8_t addr) // Initialise BMP280 with default settings, but selected mode and
|
||||
{ // I2C address
|
||||
setI2CAddress(addr);
|
||||
return begin(mode);
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::begin(uint8_t addr) // Initialise BMP280 with default settings and selected I2C address
|
||||
{
|
||||
setI2CAddress(addr);
|
||||
return begin();
|
||||
}
|
||||
|
||||
void BMP280_DEV::reset() // Reset the BMP280 barometer
|
||||
{
|
||||
writeByte(BMP280_RESET, RESET_CODE);
|
||||
delay(10);
|
||||
}
|
||||
|
||||
void BMP280_DEV::startNormalConversion() { setMode(NORMAL_MODE); } // Start continuous measurement in NORMAL_MODE
|
||||
|
||||
void BMP280_DEV::startForcedConversion() // Start a one shot measurement in FORCED_MODE
|
||||
{
|
||||
ctrl_meas.reg = readByte(BMP280_CTRL_MEAS); // Read the control and measurement register
|
||||
if (ctrl_meas.bit.mode == SLEEP_MODE) // Only set FORCED_MODE if we're already in SLEEP_MODE
|
||||
{
|
||||
setMode(FORCED_MODE);
|
||||
}
|
||||
}
|
||||
|
||||
void BMP280_DEV::stopConversion() { setMode(SLEEP_MODE); } // Stop the conversion and return to SLEEP_MODE
|
||||
|
||||
void BMP280_DEV::setPresOversampling(Oversampling presOversampling) // Set the pressure oversampling rate
|
||||
{
|
||||
ctrl_meas.bit.osrs_p = presOversampling;
|
||||
writeByte(BMP280_CTRL_MEAS, ctrl_meas.reg);
|
||||
}
|
||||
|
||||
void BMP280_DEV::setTempOversampling(Oversampling tempOversampling) // Set the temperature oversampling rate
|
||||
{
|
||||
ctrl_meas.bit.osrs_t = tempOversampling;
|
||||
writeByte(BMP280_CTRL_MEAS, ctrl_meas.reg);
|
||||
}
|
||||
|
||||
void BMP280_DEV::setIIRFilter(IIRFilter iirFilter) // Set the IIR filter setting
|
||||
{
|
||||
config.bit.filter = iirFilter;
|
||||
writeByte(BMP280_CONFIG, config.reg);
|
||||
}
|
||||
|
||||
void BMP280_DEV::setTimeStandby(TimeStandby timeStandby) // Set the time standby measurement interval
|
||||
{
|
||||
config.bit.t_sb = timeStandby;
|
||||
writeByte(BMP280_CONFIG, config.reg);
|
||||
}
|
||||
|
||||
void BMP280_DEV::setSeaLevelPressure(float pressure) // Set the sea level pressure value
|
||||
{
|
||||
sea_level_pressure = pressure;
|
||||
}
|
||||
|
||||
void BMP280_DEV::getCurrentTemperature(float &temperature) // Get the current temperature without checking the measuring bit
|
||||
{
|
||||
uint8_t data[3]; // Create a data buffer
|
||||
readBytes(BMP280_TEMP_MSB, &data[0], 3); // Read the temperature and pressure data
|
||||
int32_t adcTemp = (int32_t)data[0] << 12 | (int32_t)data[1] << 4 | (int32_t)data[2] >> 4; // Copy the temperature and pressure data into the adc variables
|
||||
int32_t temp = bmp280_compensate_T_int32(adcTemp); // Temperature compensation (function from BMP280 datasheet)
|
||||
temperature = (float)temp / 100.0f; // Calculate the temperature in degrees Celsius
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::getTemperature(float &temperature) // Get the temperature with measurement check
|
||||
{
|
||||
if (!dataReady()) // Check if a measurement is ready
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
getCurrentTemperature(temperature); // Get the current temperature
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BMP280_DEV::getCurrentPressure(float &pressure) // Get the current pressure without checking the measuring bit
|
||||
{
|
||||
float temperature;
|
||||
getCurrentTempPres(temperature, pressure);
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::getPressure(float &pressure) // Get the pressure
|
||||
{
|
||||
float temperature;
|
||||
return getTempPres(temperature, pressure);
|
||||
}
|
||||
|
||||
void BMP280_DEV::getCurrentTempPres(float &temperature, float &pressure) // Get the current temperature and pressure without checking the measuring bit
|
||||
{
|
||||
uint8_t data[6]; // Create a data buffer
|
||||
readBytes(BMP280_PRES_MSB, &data[0], 6); // Read the temperature and pressure data
|
||||
int32_t adcTemp = (int32_t)data[3] << 12 | (int32_t)data[4] << 4 | (int32_t)data[5] >> 4; // Copy the temperature and pressure data into the adc variables
|
||||
int32_t adcPres = (int32_t)data[0] << 12 | (int32_t)data[1] << 4 | (int32_t)data[2] >> 4;
|
||||
int32_t temp = bmp280_compensate_T_int32(adcTemp); // Temperature compensation (function from BMP280 datasheet)
|
||||
uint32_t pres = bmp280_compensate_P_int64(adcPres); // Pressure compensation (function from BMP280 datasheet)
|
||||
temperature = (float)temp / 100.0f; // Calculate the temperature in degrees Celsius
|
||||
pressure = (float)pres / 256.0f / 100.0f; // Calculate the pressure in millibar
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::getTempPres(float &temperature, float &pressure) // Get the temperature and pressure
|
||||
{
|
||||
if (!dataReady()) // Check if a measurement is ready
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
getCurrentTempPres(temperature, pressure); // Get the current temperature and pressure
|
||||
return 1;
|
||||
}
|
||||
|
||||
void BMP280_DEV::getCurrentAltitude(float &altitude) // Get the current altitude without checking the measuring bit
|
||||
{
|
||||
float temperature, pressure;
|
||||
getCurrentMeasurements(temperature, pressure, altitude);
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::getAltitude(float &altitude) // Get the altitude
|
||||
{
|
||||
float temperature, pressure;
|
||||
return getMeasurements(temperature, pressure, altitude);
|
||||
}
|
||||
|
||||
void BMP280_DEV::getCurrentMeasurements(float &temperature, float &pressure, float &altitude) // Get all the measurements without checking the measuring bit
|
||||
{
|
||||
getCurrentTempPres(temperature, pressure);
|
||||
altitude = ((float)powf(sea_level_pressure / pressure, 0.190223f) - 1.0f) * (temperature + 273.15f) / 0.0065f; // Calculate the altitude in metres
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::getMeasurements(float &temperature, float &pressure, float &altitude) // Get all measurements temperature, pressue and altitude
|
||||
{
|
||||
if (getTempPres(temperature, pressure))
|
||||
{
|
||||
altitude = ((float)powf(sea_level_pressure / pressure, 0.190223f) - 1.0f) * (temperature + 273.15f) / 0.0065f; // Calculate the altitude in metres
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Private Member Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void BMP280_DEV::setMode(Mode mode) // Set the BMP280's mode
|
||||
{
|
||||
ctrl_meas.bit.mode = mode;
|
||||
writeByte(BMP280_CTRL_MEAS, ctrl_meas.reg);
|
||||
}
|
||||
|
||||
// Set the BMP280 control and measurement register
|
||||
void BMP280_DEV::setCtrlMeasRegister(Mode mode, Oversampling presOversampling, Oversampling tempOversampling)
|
||||
{
|
||||
ctrl_meas.reg = tempOversampling << 5 | presOversampling << 2 | mode;
|
||||
writeByte(BMP280_CTRL_MEAS, ctrl_meas.reg);
|
||||
}
|
||||
|
||||
// Set the BMP280 configuration register
|
||||
void BMP280_DEV::setConfigRegister(IIRFilter iirFilter, TimeStandby timeStandby)
|
||||
{
|
||||
config.reg = timeStandby << 5 | iirFilter << 2;
|
||||
writeByte(BMP280_CONFIG, config.reg);
|
||||
}
|
||||
|
||||
uint8_t BMP280_DEV::dataReady() // Check if a measurement is ready
|
||||
{
|
||||
if (ctrl_meas.bit.mode == SLEEP_MODE) // If we're in SLEEP_MODE return immediately
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
status.reg = readByte(BMP280_STATUS); // Read the status register
|
||||
if (status.bit.measuring ^ previous_measuring) // Edge detection: check if the measurement bit has been changed
|
||||
{
|
||||
previous_measuring = status.bit.measuring; // Update the previous measuring flag
|
||||
if (!status.bit.measuring) // Check if the measuring bit has been cleared
|
||||
{
|
||||
if (ctrl_meas.bit.mode == FORCED_MODE) // If we're in FORCED_MODE switch back to SLEEP_MODE
|
||||
{
|
||||
ctrl_meas.bit.mode = SLEEP_MODE;
|
||||
}
|
||||
return 1; // A measurement is ready
|
||||
}
|
||||
}
|
||||
return 0; // A measurement is still pending
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Bosch BMP280_DEV (Private) Member Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
// Returns temperature in DegC, resolution is 0.01 DegC. Output value of “5123” equals 51.23 DegC.
|
||||
// t_fine carries fine temperature as global value
|
||||
int32_t BMP280_DEV::bmp280_compensate_T_int32(int32_t adc_T)
|
||||
{
|
||||
int32_t var1, var2, T;
|
||||
var1 = ((((adc_T >> 3) - ((int32_t)params.dig_T1 << 1))) * ((int32_t)params.dig_T2)) >> 11;
|
||||
var2 = (((((adc_T >> 4) - ((int32_t)params.dig_T1)) * ((adc_T >> 4) - ((int32_t)params.dig_T1))) >> 12) *
|
||||
((int32_t)params.dig_T3)) >> 14;
|
||||
t_fine = var1 + var2;
|
||||
T = (t_fine * 5 + 128) >> 8;
|
||||
return T;
|
||||
}
|
||||
|
||||
// Returns pressure in Pa as unsigned 32 bit integer in Q24.8 format (24 integer bits and 8 fractional bits).
|
||||
// Output value of “24674867” represents 24674867/256 = 96386.2 Pa = 963.862 hPa
|
||||
uint32_t BMP280_DEV::bmp280_compensate_P_int64(int32_t adc_P)
|
||||
{
|
||||
int64_t var1, var2, p;
|
||||
var1 = ((int64_t)t_fine) - 128000;
|
||||
var2 = var1 * var1 * (int64_t)params.dig_P6;
|
||||
var2 = var2 + ((var1 * (int64_t)params.dig_P5) << 17);
|
||||
var2 = var2 + (((int64_t)params.dig_P4) << 35);
|
||||
var1 = ((var1 * var1 * (int64_t)params.dig_P3) >> 8) + ((var1 * (int64_t)params.dig_P2) << 12);
|
||||
var1 = (((((int64_t)1) << 47) + var1)) * ((int64_t)params.dig_P1) >> 33;
|
||||
if (var1 == 0)
|
||||
{
|
||||
return 0; // avoid exception caused by division by zero
|
||||
}
|
||||
p = 1048576 - adc_P;
|
||||
p = (((p << 31) - var2) * 3125) / var1;
|
||||
var1 = (((int64_t)params.dig_P9) * (p >> 13) * (p>>13)) >> 25;
|
||||
var2 = (((int64_t)params.dig_P8) * p) >> 19;
|
||||
p = ((p + var1 + var2) >> 8) + (((int64_t)params.dig_P7) << 4);
|
||||
return (uint32_t)p;
|
||||
}
|
||||
221
components/BMP280_DEV/BMP280_DEV.h
Executable file
221
components/BMP280_DEV/BMP280_DEV.h
Executable file
@ -0,0 +1,221 @@
|
||||
/*
|
||||
BMP280_DEV is an I2C/SPI compatible library for the Bosch BMP280 barometer.
|
||||
|
||||
Copyright (C) Martin Lindupp 2019
|
||||
|
||||
V1.0.0 -- Initial release
|
||||
V1.0.1 -- Added ESP32 HSPI support and change library to unique name
|
||||
V1.0.2 -- Modification to allow external creation of HSPI object on ESP32
|
||||
V1.0.3 -- Changed library name in the library.properties file
|
||||
V1.0.5 -- Fixed bug in BMP280_DEV::getTemperature() function, thanks to Jon M.
|
||||
V1.0.6 -- Merged multiple instances and initialisation pull requests by sensslen
|
||||
V1.0.8 -- Used default arguments for begin() member function and
|
||||
added example using multiple BMP280 devices with SPI comms in NORMAL mode
|
||||
V1.0.9 -- Moved writeMask to Device class and improved measurement detection code
|
||||
V1.0.10 -- Modification to allow user-defined pins for I2C operation on the ESP8266
|
||||
V1.0.12 -- Allow sea level pressure calibration using setSeaLevelPressure() function
|
||||
V1.0.14 -- Fix uninitialised structures, thanks to David Jade investigating and
|
||||
flagging up this issue
|
||||
V1.0.16 -- Modification to allow user-defined pins for I2C operation on the ESP32
|
||||
V1.0.17 -- Added getCurrentTemperature(), getCurrentPressure(), getCurrentTempPres()
|
||||
getCurrentAltitude() and getCurrentMeasurements() functions,
|
||||
to allow the BMP280 to be read directly without checking the measuring bit
|
||||
V1.0.18 -- Initialise "device" constructor member variables in the same order they are declared
|
||||
V1.0.19 -- Allow for additional TwoWire instances
|
||||
V1.0.20 -- Removed default parameter causing ESP32 compilation error with user defined I2C pins
|
||||
V1.0.21 -- Fixed uninitialised "Wire" pointer for ESP8266/ESP32 with user defined I2C pins
|
||||
|
||||
The MIT License (MIT)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef BMP280_DEV_h
|
||||
#define BMP280_DEV_h
|
||||
|
||||
#include <Device.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define BMP280_I2C_ADDR 0x77 // The BMP280 I2C address
|
||||
#define BMP280_I2C_ALT_ADDR 0x76 // The BMP280 I2C alternate address
|
||||
#define DEVICE_ID 0x58 // The BMP280 device ID
|
||||
#define RESET_CODE 0xB6 // The BMP280 reset code
|
||||
|
||||
enum SPIPort { BMP280_SPI0, BMP280_SPI1 };
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Registers
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum {
|
||||
BMP280_TRIM_PARAMS = 0x88, // Trim parameter registers' base sub-address
|
||||
BMP280_DEVICE_ID = 0xD0, // Device ID register sub-address
|
||||
BMP280_RESET = 0xE0, // Reset register sub-address
|
||||
BMP280_STATUS = 0xF3, // Status register sub-address
|
||||
BMP280_CTRL_MEAS = 0xF4, // Control and measurement register sub-address
|
||||
BMP280_CONFIG = 0xF5, // Configuration register sub-address
|
||||
BMP280_PRES_MSB = 0xF7, // Pressure Most Significant Byte (MSB) register sub-address
|
||||
BMP280_PRES_LSB = 0xF8, // Pressure Least Significant Byte (LSB) register sub-address
|
||||
BMP280_PRES_XLSB = 0xF9, // Pressure eXtended Least Significant Byte (XLSB) register sub-address
|
||||
BMP280_TEMP_MSB = 0xFA, // Pressure Most Significant Byte (MSB) register sub-address
|
||||
BMP280_TEMP_LSB = 0xFB, // Pressure Least Significant Byte (LSB) register sub-address
|
||||
BMP280_TEMP_XLSB = 0xFC // Pressure eXtended Least Significant Byte (XLSB) register sub-address
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Modes
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum Mode {
|
||||
SLEEP_MODE = 0x00, // Device mode bitfield in the control and measurement register
|
||||
FORCED_MODE = 0x01,
|
||||
NORMAL_MODE = 0x03
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Register bit field Definitions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
enum Oversampling {
|
||||
OVERSAMPLING_SKIP = 0x00, // Oversampling bit fields in the control and measurement register
|
||||
OVERSAMPLING_X1 = 0x01,
|
||||
OVERSAMPLING_X2 = 0x02,
|
||||
OVERSAMPLING_X4 = 0x03,
|
||||
OVERSAMPLING_X8 = 0x04,
|
||||
OVERSAMPLING_X16 = 0x05
|
||||
};
|
||||
|
||||
enum IIRFilter {
|
||||
IIR_FILTER_OFF = 0x00, // Infinite Impulse Response (IIR) filter bit field in the configuration register
|
||||
IIR_FILTER_2 = 0x01,
|
||||
IIR_FILTER_4 = 0x02,
|
||||
IIR_FILTER_8 = 0x03,
|
||||
IIR_FILTER_16 = 0x04
|
||||
};
|
||||
|
||||
enum TimeStandby {
|
||||
TIME_STANDBY_05MS = 0x00, // Time standby bit field in the configuration register
|
||||
TIME_STANDBY_62MS = 0x01,
|
||||
TIME_STANDBY_125MS = 0x02,
|
||||
TIME_STANDBY_250MS = 0x03,
|
||||
TIME_STANDBY_500MS = 0x04,
|
||||
TIME_STANDBY_1000MS = 0x05,
|
||||
TIME_STANDBY_2000MS = 0x06,
|
||||
TIME_STANDBY_4000MS = 0x07
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV Class definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class BMP280_DEV : public Device { // Derive the BMP280_DEV class from the Device class
|
||||
public:
|
||||
BMP280_DEV(TwoWire& twoWire = Wire); // BMP280_DEV object for I2C operation
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
BMP280_DEV(uint8_t sda, uint8_t scl, TwoWire& twoWire = Wire); // BMP280_DEV object for ESP8266 I2C operation with user-defined pins
|
||||
#endif
|
||||
BMP280_DEV(uint8_t cs); // BMP280_DEV object for SPI operation
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
BMP280_DEV(uint8_t sda, uint8_t scl, TwoWire& twoWire = Wire); // BMP280_DEV object for ESP32 I2C operation with user-defined pins
|
||||
BMP280_DEV(uint8_t cs, uint8_t spiPort, SPIClass& spiClass); // BMP280_DEV object for SPI1 with supplied SPIClass object
|
||||
#endif
|
||||
uint8_t begin(Mode mode = SLEEP_MODE, // Initialise the barometer with arguments
|
||||
Oversampling presOversampling = OVERSAMPLING_X16,
|
||||
Oversampling tempOversampling = OVERSAMPLING_X2,
|
||||
IIRFilter iirFilter = IIR_FILTER_OFF,
|
||||
TimeStandby timeStandby = TIME_STANDBY_05MS);
|
||||
uint8_t begin(Mode mode, uint8_t addr); // Initialise the barometer specifying start mode and I2C addrss
|
||||
uint8_t begin(uint8_t addr); // Initialise the barometer specifying I2C address with default initialisation
|
||||
void reset(); // Soft reset the barometer
|
||||
void startNormalConversion(); // Start continuous measurement in NORMAL_MODE
|
||||
void startForcedConversion(); // Start a one shot measurement in FORCED_MODE
|
||||
void stopConversion(); // Stop the conversion and return to SLEEP_MODE
|
||||
void setPresOversampling(Oversampling presOversampling); // Set the pressure oversampling: OFF, X1, X2, X4, X8, X16
|
||||
void setTempOversampling(Oversampling tempOversampling); // Set the temperature oversampling: OFF, X1, X2, X4, X8, X16
|
||||
void setIIRFilter(IIRFilter iirFilter); // Set the IIR filter setting: OFF, 2, 4, 8, 16
|
||||
void setTimeStandby(TimeStandby timeStandby); // Set the time standby measurement interval: 0.5, 62, 125, 250, 500ms, 1s, 2s, 4s
|
||||
void setSeaLevelPressure(float pressure = 1013.23f); // Set the sea level pressure value
|
||||
void getCurrentTemperature(float &temperature); // Get the current temperature measurement without checking the measuring bit
|
||||
uint8_t getTemperature(float &temperature); // Get a temperature measurement
|
||||
void getCurrentPressure(float &pressure); // Get the current pressure without checking the measuring bit
|
||||
uint8_t getPressure(float &pressure); // Get a pressure measurement
|
||||
void getCurrentTempPres(float &temperature, float &pressure); // Get the current temperature and pressure without checking the measuring bit
|
||||
uint8_t getTempPres(float &temperature, float &pressure); // Get a temperature and pressure measurement
|
||||
void getCurrentAltitude(float &altitude); // Get the current altitude without checking the measuring bit
|
||||
uint8_t getAltitude(float &altitude); // Get an altitude measurement
|
||||
void getCurrentMeasurements(float &temperature, float &pressure, float &altitude); // Get all measurements without checking the measuring bit
|
||||
uint8_t getMeasurements(float &temperature, float &pressure, float &altitude); // Get temperature, pressure and altitude measurements
|
||||
protected:
|
||||
private:
|
||||
void setMode(Mode mode); // Set the barometer mode
|
||||
void setCtrlMeasRegister(Mode mode, Oversampling presOversampling, Oversampling tempOversamping); // Set the BMP280 control and measurement register
|
||||
void setConfigRegister(IIRFilter iirFilter, TimeStandby timeStandby); // Set the BMP280 configuration register
|
||||
uint8_t dataReady(); // Checks if a measurement is ready
|
||||
|
||||
struct { // The BMP280 compensation trim parameters (coefficients)
|
||||
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;
|
||||
} params;
|
||||
|
||||
union { // Copy of the BMP280's configuration register
|
||||
struct {
|
||||
uint8_t spi3w_en : 1;
|
||||
uint8_t : 1;
|
||||
uint8_t filter : 3;
|
||||
uint8_t t_sb : 3;
|
||||
} bit;
|
||||
uint8_t reg;
|
||||
} config = { .reg = 0 };
|
||||
|
||||
union { // Copy of the BMP280's control and measurement register
|
||||
struct {
|
||||
uint8_t mode : 2;
|
||||
uint8_t osrs_p : 3;
|
||||
uint8_t osrs_t : 3;
|
||||
} bit;
|
||||
uint8_t reg;
|
||||
} ctrl_meas = { .reg = 0 };
|
||||
|
||||
union { // Copy of the BMP280's status register
|
||||
struct {
|
||||
uint8_t im_update : 1;
|
||||
uint8_t : 2;
|
||||
uint8_t measuring : 1;
|
||||
} bit;
|
||||
uint8_t reg;
|
||||
} status = { .reg = 0 };
|
||||
|
||||
int32_t t_fine; // Bosch t_fine variable
|
||||
int32_t bmp280_compensate_T_int32(int32_t adc_T); // Bosch temperature compensation function
|
||||
uint32_t bmp280_compensate_P_int64(int32_t adc_P); // Bosch pressure compensation function
|
||||
bool previous_measuring; // Previous measuring state
|
||||
float sea_level_pressure = 1013.23f; // Sea level pressure
|
||||
};
|
||||
|
||||
#endif
|
||||
16
components/BMP280_DEV/CMakeLists.txt
Executable file
16
components/BMP280_DEV/CMakeLists.txt
Executable file
@ -0,0 +1,16 @@
|
||||
set(COMPONENT_SRCDIRS
|
||||
"."
|
||||
)
|
||||
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
"."
|
||||
)
|
||||
|
||||
set(COMPONENT_REQUIRES
|
||||
"arduino"
|
||||
)
|
||||
|
||||
register_component()
|
||||
|
||||
target_compile_definitions(${COMPONENT_TARGET} PUBLIC -DESP32)
|
||||
#target_compile_options(${COMPONENT_TARGET} PRIVATE -fno-rtti)
|
||||
180
components/BMP280_DEV/Device.cpp
Executable file
180
components/BMP280_DEV/Device.cpp
Executable file
@ -0,0 +1,180 @@
|
||||
/*
|
||||
Device is an I2C/SPI compatible base class library.
|
||||
|
||||
Copyright (C) Martin Lindupp 2019
|
||||
|
||||
V1.0.0 -- Initial release
|
||||
V1.0.1 -- Added ESP32 HSPI support
|
||||
V1.0.2 -- Modification to allow external creation of HSPI object on ESP32
|
||||
V1.0.3 -- Addition of SPI write and read byte masks
|
||||
V1.0.4 -- Modification to allow user-defined pins for I2C operation on the ESP8266
|
||||
V1.0.5 -- Modification to allow user-defined pins for I2C operation on the ESP32
|
||||
V1.0.6 -- Initialise "device" constructor member variables in the same order they are declared
|
||||
V1.0.7 -- Allow for additional TwoWire instances
|
||||
V1.0.8 -- Fixed uninitialised "Wire" pointer for ESP8266/ESP32 with user defined I2C pins
|
||||
|
||||
The MIT License (MIT)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <Device.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Device Class Constructors
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Device::Device(TwoWire& twoWire) : comms(I2C_COMMS), i2c(&twoWire) {} // Initialise constructor for I2C communications
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
Device::Device(uint8_t sda, uint8_t scl, TwoWire& twoWire) : // Constructor for ESP8266 I2C with user-defined pins
|
||||
comms(I2C_COMMS_DEFINED_PINS), i2c(&twoWire), sda(sda), scl(scl) {}
|
||||
#endif
|
||||
Device::Device(uint8_t cs) : comms(SPI_COMMS), cs(cs), spiClockSpeed(1000000) {} // Constructor for SPI communications
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
Device::Device(uint8_t sda, uint8_t scl, TwoWire& twoWire) :
|
||||
comms(I2C_COMMS_DEFINED_PINS), i2c(&twoWire), sda(sda), scl(scl) {} // Constructor for ESP32 I2C with user-defined pins
|
||||
Device::Device(uint8_t cs, uint8_t spiPort, SPIClass& spiClass) // Constructor for ESP32 HSPI communications
|
||||
: comms(SPI_COMMS), cs(cs), spiPort(spiPort), spi(&spiClass), spiClockSpeed(1000000) {}
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Device Public Member Function
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Device::setClock(uint32_t clockSpeed) // Set the I2C or SPI clock speed
|
||||
{
|
||||
if (comms == I2C_COMMS)
|
||||
{
|
||||
i2c->setClock(clockSpeed);
|
||||
}
|
||||
else
|
||||
{
|
||||
spiClockSpeed = clockSpeed;
|
||||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Device I2C & SPI Wrapper (Protected) Member Functions
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void Device::initialise() // Initialise device communications
|
||||
{
|
||||
if (comms == I2C_COMMS) // Check with communications bus has been selected I2C or SPI
|
||||
{
|
||||
i2c->begin(); // Initialise I2C communication
|
||||
i2c->setClock(800000); // Set the SCL clock to default of 400kHz
|
||||
}
|
||||
#if defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32
|
||||
else if (comms == I2C_COMMS_DEFINED_PINS) // Check if the ESP8266 or ESP32 has specified user-defined I2C pins
|
||||
{
|
||||
i2c->begin(sda, scl); // Initialise I2C communication with user-defined pins
|
||||
i2c->setClock(800000); // Set the SCL clock to default of 400kHz
|
||||
comms = I2C_COMMS; // Set the communications to standard I2C
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
digitalWrite(cs, HIGH); // Pull the chip select (CS) pin high
|
||||
pinMode(cs, OUTPUT); // Set-up the SPI chip select pin
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
if (spiPort == HSPI) // Set-up spi pointer for VSPI or HSPI communications
|
||||
{
|
||||
spi->begin(14, 27, 13, 2); // Start HSPI on SCK 14, MOSI 13, MISO 24, SS CS (GPIO2 acts as dummy pin)
|
||||
}
|
||||
else
|
||||
{
|
||||
spi = &SPI; // Start VSPI on SCK 5, MOSI 18, MISO 19, SS CS
|
||||
spi->begin();
|
||||
}
|
||||
#else
|
||||
spi = &SPI; // Set-up spi pointer for SPI communications
|
||||
spi->begin();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void Device::setI2CAddress(uint8_t addr) // Set the Device's I2C address
|
||||
{
|
||||
address = addr;
|
||||
}
|
||||
|
||||
void Device::writeByte(uint8_t subAddress, uint8_t data)
|
||||
{
|
||||
if (comms == I2C_COMMS)
|
||||
{
|
||||
i2c->beginTransmission(address); // Write a byte to the sub-address using I2C
|
||||
i2c->write(subAddress);
|
||||
i2c->write(data);
|
||||
i2c->endTransmission();
|
||||
}
|
||||
else // if (comms == SPI_COMMS)
|
||||
{
|
||||
spi->beginTransaction(SPISettings(spiClockSpeed, MSBFIRST, SPI_MODE0)); // Write a byte to the sub-address using SPI
|
||||
digitalWrite(cs, LOW);
|
||||
spi->transfer(subAddress & WRITE_MASK);
|
||||
spi->transfer(data);
|
||||
digitalWrite(cs, HIGH);
|
||||
spi->endTransaction();
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Device::readByte(uint8_t subAddress) // Read a byte from the sub-address using I2C
|
||||
{
|
||||
uint8_t data = 0x00;
|
||||
if (comms == I2C_COMMS)
|
||||
{
|
||||
i2c->beginTransmission(address);
|
||||
i2c->write(subAddress);
|
||||
i2c->endTransmission(false);
|
||||
i2c->requestFrom(address, (uint8_t)1);
|
||||
data = i2c->read();
|
||||
}
|
||||
else // if (comms == SPI_COMMS)
|
||||
{
|
||||
spi->beginTransaction(SPISettings(spiClockSpeed, MSBFIRST, SPI_MODE0)); // Read a byte from the sub-address using SPI
|
||||
digitalWrite(cs, LOW);
|
||||
spi->transfer(subAddress | READ_MASK);
|
||||
data = spi->transfer(data);
|
||||
digitalWrite(cs, HIGH);
|
||||
spi->endTransaction();
|
||||
}
|
||||
return data; // Return data read from sub-address register
|
||||
}
|
||||
|
||||
void Device::readBytes(uint8_t subAddress, uint8_t* data, uint16_t count)
|
||||
{
|
||||
if (comms == I2C_COMMS) // Read "count" bytes into the "data" buffer using I2C
|
||||
{
|
||||
i2c->beginTransmission(address);
|
||||
i2c->write(subAddress);
|
||||
i2c->endTransmission(false);
|
||||
uint8_t i = 0;
|
||||
i2c->requestFrom(address, (uint8_t)count);
|
||||
while (i2c->available())
|
||||
{
|
||||
data[i++] = i2c->read();
|
||||
}
|
||||
}
|
||||
else // if (comms == SPI_COMMS)
|
||||
{
|
||||
spi->beginTransaction(SPISettings(spiClockSpeed, MSBFIRST, SPI_MODE0)); // Read "count" bytes into the "data" buffer using SPI
|
||||
digitalWrite(cs, LOW);
|
||||
spi->transfer(subAddress | READ_MASK);
|
||||
spi->transfer(data, count);
|
||||
digitalWrite(cs, HIGH);
|
||||
spi->endTransaction();
|
||||
}
|
||||
}
|
||||
89
components/BMP280_DEV/Device.h
Executable file
89
components/BMP280_DEV/Device.h
Executable file
@ -0,0 +1,89 @@
|
||||
/*
|
||||
Device is an I2C/SPI compatible base class library.
|
||||
|
||||
Copyright (C) Martin Lindupp 2019
|
||||
|
||||
V1.0.0 -- Initial release
|
||||
V1.0.1 -- Added ESP32 HSPI support
|
||||
V1.0.2 -- Modification to allow external creation of HSPI object on ESP32
|
||||
V1.0.3 -- Addition of SPI write and read byte masks
|
||||
V1.0.4 -- Modification to allow user-defined pins for I2C operation on the ESP8266
|
||||
V1.0.5 -- Modification to allow user-defined pins for I2C operation on the ESP32
|
||||
V1.0.6 -- Initialise "device" constructor member variables in the same order they are declared
|
||||
V1.0.7 -- Allow for additional TwoWire instances
|
||||
V1.0.8 -- Fixed uninitialised "Wire" pointer for ESP8266/ESP32 with user defined I2C pins
|
||||
|
||||
The MIT License (MIT)
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef Device_h
|
||||
#define Device_h
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <Wire.h>
|
||||
#include <SPI.h>
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Device Communications
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#if defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32
|
||||
enum Comms { I2C_COMMS, SPI_COMMS, I2C_COMMS_DEFINED_PINS };
|
||||
#else
|
||||
enum Comms { I2C_COMMS, SPI_COMMS };
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Device Class definition
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
class Device{
|
||||
public:
|
||||
Device(TwoWire& twoWire); // Device object for I2C operation
|
||||
#ifdef ARDUINO_ARCH_ESP8266
|
||||
Device(uint8_t sda, uint8_t scl, TwoWire& twoWire); // Device object for ESP8266 I2C operation with user-defined pins
|
||||
#endif
|
||||
Device(uint8_t cs); // Device object for SPI operation
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
Device(uint8_t sda, uint8_t scl, TwoWire& twoWire); // Device object for ESP32 I2C operation with user-defined pins
|
||||
Device(uint8_t cs, uint8_t spiPort, SPIClass& spiClass); // Device object for ESP32 HSPI operation with supplied SPI object
|
||||
#endif
|
||||
void setClock(uint32_t clockSpeed); // Set the I2C/SPI clock speed
|
||||
protected:
|
||||
void initialise(); // Initialise communications
|
||||
void setI2CAddress(uint8_t addr); // Set the Device I2C address
|
||||
void writeByte(uint8_t subAddress, uint8_t data); // I2C and SPI write byte wrapper function
|
||||
uint8_t readByte(uint8_t subAddress); // I2C and SPI read byte wrapper function
|
||||
void readBytes(uint8_t subAddress, uint8_t* dest, uint16_t count); // I2C and SPI read bytes wrapper function
|
||||
private:
|
||||
Comms comms; // Communications bus: I2C or SPI
|
||||
uint8_t address; // The device I2C address
|
||||
uint8_t cs; // The SPI chip select pin
|
||||
#ifdef ARDUINO_ARCH_ESP32
|
||||
uint8_t spiPort; // SPI port type VSPI or HSPI
|
||||
#endif
|
||||
TwoWire* i2c; // Pointer to the Wire class
|
||||
SPIClass* spi; // Pointer to the SPI class
|
||||
uint32_t spiClockSpeed; // The SPI clock speed
|
||||
const uint8_t WRITE_MASK = 0x7F; // Sub-address write mask for SPI communications
|
||||
const uint8_t READ_MASK = 0x80; // Sub-address read mask for SPI communications
|
||||
#if defined ARDUINO_ARCH_ESP8266 || defined ARDUINO_ARCH_ESP32
|
||||
uint8_t sda, scl; // Software I2C SDA and SCL pins
|
||||
#endif
|
||||
};
|
||||
#endif
|
||||
21
components/BMP280_DEV/LICENSE
Executable file
21
components/BMP280_DEV/LICENSE
Executable file
@ -0,0 +1,21 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2019 MartinL1
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
352
components/BMP280_DEV/README.md
Executable file
352
components/BMP280_DEV/README.md
Executable file
@ -0,0 +1,352 @@
|
||||
# BMP280_DEV
|
||||
An Arduino compatible, non-blocking, I2C/SPI library for the Bosch BMP280 barometer.
|
||||
|
||||

|
||||
|
||||
© Copyright, image courtesy of [Adafruit Industries](https://www.adafruit.com/product/2651) lisensed under the terms of the [Create Commons Attribution-ShareAlike 3.0 Unported](https://creativecommons.org/licenses/by-sa/3.0/legalcode).
|
||||
|
||||
This BMP280_DEV library offers the following features:
|
||||
|
||||
- Returns temperature in degrees celsius (**°C**), pressure in hectoPascals/millibar (**hPa**) and altitude in metres (**m**)
|
||||
- NORMAL or FORCED modes of operation
|
||||
- I2C or hardware SPI communications with configurable clock rates
|
||||
- Non-blocking operation
|
||||
- In NORMAL mode barometer returns results at the specified standby time interval
|
||||
- Highly configurable, allows for changes to pressure and temperature oversampling, IIR filter and standby time
|
||||
|
||||
---
|
||||
## __Contents__
|
||||
|
||||
1. [Version](#version)
|
||||
2. [Arduino Compatiblility](#arduino_compatibility)
|
||||
3. [Installation](#installation)
|
||||
3. [Usage](#usage)
|
||||
1. [BMP280_DEV Library](#bmp280_dev_library)
|
||||
2. [Device Initialisation](#device_intialisation)
|
||||
3. [Device Configuration](#device_configuration)
|
||||
4. [Modes Of Operation](#modes_of_operation)
|
||||
5. [Results Acquisition](#results_acquisition)
|
||||
6. [Code Implementation](#code_implementation)
|
||||
5. [Example Code](#example_code)
|
||||
|
||||
<a name="version"></a>
|
||||
## __Version__
|
||||
|
||||
- Version 1.0.21 -- Fixed uninitialised "Wire" pointer for ESP8266/ESP32 with user defined I2C pins
|
||||
- Version 1.0.20 -- Removed default parameter causing ESP32 compilation error with user defined I2C pins
|
||||
- Version 1.0.19 -- Allow for additional TwoWire instances
|
||||
- Version 1.0.18 -- Initialise "device" constructor member variables in the same order they are declared
|
||||
- Version 1.0.17 -- Added getCurrentTemperature(), getCurrentPressure(), getCurrentTempPres()
|
||||
getCurrentAltitude() and getCurrentMeasurements() functions,
|
||||
to allow the BMP280 to be read directly without checking the status register
|
||||
- Version 1.0.16 -- Modification to allow user-defined pins for I2C operation on the ESP32
|
||||
- Version 1.0.14 -- Fix uninitialised structures, thanks to David Jade investigating and flagging up this issue
|
||||
- Version 1.0.12 -- Allow sea level pressure calibration using setSeaLevelPressure() function
|
||||
- Version 1.0.10 -- Modification to allow user-defined pins for I2C operation on the ESP8266
|
||||
- Version 1.0.9 -- Moved writeMask to Device class and improved measurement detection code
|
||||
- Version 1.0.8 -- Use default arguments for begin() member function and
|
||||
add example using multiple BMP280 devices with SPI comms in NORMAL mode
|
||||
- Version 1.0.6 -- Merged multiple instances and initialisation pull requests by sensslen
|
||||
- Version 1.0.5 -- Fixed bug in BMP280_DEV::getTemperature() function, thanks to Jon M.
|
||||
- Version 1.0.3 -- Change library name in the library.properties file
|
||||
- Version 1.0.2 -- Modification to allow external creation of a HSPI object on the ESP32
|
||||
- Version 1.0.1 -- Added ESP32 HSPI support and changed library name for Arduino compatibility
|
||||
- Version 1.0.0 -- Intial version
|
||||
|
||||
<a name="arduino_compatibility"></a>
|
||||
## __Arduino Compatibility__
|
||||
|
||||
- All Arduino boards, but for 5V Arduino boards (such as the Uno, Nano, Mega, Leonardo, etc...), please check if the BMP280 breakout board requires a 5V to +3.3V voltage level shifter
|
||||
|
||||
<a name="installation"></a>
|
||||
## __Installation__
|
||||
|
||||
The BMP280_DEV library can be installed using the Arduino IDE's Library Manager. To access the Library Manager, in the Arduino IDE's menu select _Sketch->Include Library->Manage Libraries..._. In the Library Manager's search bar type BMP280 then select the "Install" button in the BMP280_DEV entry.
|
||||
|
||||
Alternatively simply download BMP280_DEV from this Github repository, un-zip or extract the files and place the BMP280_DEV directory in your _.../Arduino/libraries/..._ folder. The _.../Arduino/..._ folder is the one where your Arduino IDE sketches are usually located.
|
||||
|
||||
<a name="usage"></a>
|
||||
## __Usage__
|
||||
|
||||
<a name="bmp280_dev_library"></a>
|
||||
### __BMP280_DEV Library__
|
||||
|
||||
Simply include the BMP280_DEV.h file at the beginning of your sketch:
|
||||
|
||||
```
|
||||
#include <BMP280_DEV.h>
|
||||
```
|
||||
|
||||
For I2C communication the BMP280_DEV object is normally created (instantiated) without parameters:
|
||||
|
||||
```
|
||||
BMP280_DEV bmp280; // Set up I2C communications
|
||||
```
|
||||
|
||||
Alternatively an auxiliary or secondary I2C (Wire) port can be specified:
|
||||
|
||||
```
|
||||
BMP280_DEV bmp280(Wire1); // Set up I2C communications on a secondary port
|
||||
```
|
||||
|
||||
By default the library uses the BMP280's I2C address 0x77. (To use the alternate I2C address: 0x76, see the begin() function below.
|
||||
|
||||
The ESP8266 and ESP32 also offer the option of selecting the I2C SDA and SDA pins as parameters:
|
||||
|
||||
```
|
||||
BMP280_DEV bmp280(A6, A7); // Set up I2C communications on ESP32 pins A6 (SDA) and A7 (SCL): bmp280(SDA, SCL);
|
||||
```
|
||||
|
||||
If no parameters are selected, the ESP32 uses its default SDA and SCL pins.
|
||||
|
||||
For SPI communication the chip select (CS) Arduino digital output pin is specified as an argument, for example digital pin 10:
|
||||
|
||||
```
|
||||
BMP280_dev bmp280(10); // Set up SPI communications on digital pin D10
|
||||
```
|
||||
|
||||
The library also supports the ESP32 HSPI operation on pins: SCK 14, MOSI 13, MISO 27 and user defined SS (CS):
|
||||
|
||||
```
|
||||
SPIClass SPI1(HSPI); // Create the SPI1 HSPI object
|
||||
BMP280_DEV bmp(21, HSPI, SPI1); // Set up HSPI port communications on the ESP32
|
||||
```
|
||||
|
||||
By default the I2C runs in fast mode at 400kHz and SPI at 1MHz. However it is possible to change either the I2C or SPI clock speed using the set clock function:
|
||||
|
||||
```
|
||||
bmp280.setClock(4000000); // Set the SPI clock to 4MHz
|
||||
```
|
||||
|
||||
---
|
||||
### __Device Initialisation__
|
||||
|
||||
To initialise the bmp280 it is necessary to call the begin() function with or without parameters. The parameters specify the starting mode, pressure/temperature oversampling, IIR filter and standby time options respectively:
|
||||
|
||||
```
|
||||
bmp280.begin(SLEEP_MODE, OVERSAMPLING_X16, OVERSAMPLING_X2, IIR_FILTER_4, TIME_STANDBY_05MS);
|
||||
```
|
||||
|
||||
Alternatively simply call the begin function without any paremeters, this sets up the default configuration: SLEEP_MODE, pressure oversampling X16, temperature oversampling X2, IIR filter OFF and a standby time of 0.5ms:
|
||||
|
||||
```
|
||||
bmp280.begin(); // Initialise the BMP280 with default configuration
|
||||
```
|
||||
|
||||
Another alternative is to pass the BMP280's mode as an argument:
|
||||
|
||||
```
|
||||
bmp280.begin(NORMAL_MODE); // Initialise the BMP280 in NORMAL_MODE with default configuration
|
||||
```
|
||||
|
||||
Or, specifying mode and alternate I2C address:
|
||||
|
||||
```
|
||||
bmp280.begin(FORCED_MODE, BMP280_I2C_ALT_ADDR); // Initialise the BMP280 in FORCED_MODE with the alternate I2C address (0x76)
|
||||
```
|
||||
|
||||
Or even just the alternate I2C address, (BMP280 initialised in SLEEP_MODE by default):
|
||||
|
||||
```
|
||||
bmp280.begin(BMP280_I2C_ALT_ADDR); // Initialise the BMP280 with the alternate I2C address (0x76)
|
||||
```
|
||||
|
||||
Note that the begin functions return the value 1 upon successful initialisation, otherwise it returns 0 for failure.
|
||||
|
||||
---
|
||||
<a name="device_configuration"></a>
|
||||
### __Device Configuration__
|
||||
|
||||
After initialisation it is possible to change the BMP280 configuration with the following functions:
|
||||
|
||||
```
|
||||
bmp280.setPresOversamping(OVERSAMPING_X4); // Options are OVERSAMPLING_SKIP, _X1, _X2, _X4, _X8, _X16
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.setTempOversamping(OVERSAMPING_X4); // Options are OVERSAMPLING_SKIP, _X1, _X2, _X4, _X8, _X16
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.setIIRFilter(IIR_FILTER_16); // Options are IIR_FILTER_OFF, _2, _4, _8, _16
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Options are TIME_STANDBY_05MS, _62MS, _125MS, _250MS, _500MS, _1000MS, 2000MS, 4000MS
|
||||
```
|
||||
---
|
||||
<a name="modes_of_operation"></a>
|
||||
### __Modes Of Operation__
|
||||
|
||||
The BMP280 has 3 modes of operation: **SLEEP_MODE**, **NORMAL_MODE** and **FORCED_MODE**:
|
||||
|
||||
- **SLEEP_MODE**: puts the device into an inactive standby state
|
||||
|
||||
- **NORMAL_MODE**: performs continuous conversions, separated by the standby time
|
||||
|
||||
- **FORCED_MODE**: performs a single conversion, returning to **SLEEP_MODE** upon completion
|
||||
|
||||
To kick-off conversions in **NORMAL_MODE**:
|
||||
|
||||
```
|
||||
bmp280.startNormalConversion(); // Start continuous conversions, separated by the standby time
|
||||
```
|
||||
|
||||
To perform a single oneshot conversion in **FORCED_MODE**:
|
||||
|
||||
```
|
||||
bmp280.startForcedConversion(); // Start a single oneshot conversion
|
||||
```
|
||||
|
||||
To stop the conversion at anytime and return to **SLEEP_MODE**:
|
||||
|
||||
```
|
||||
bmp280.stopConversion(); // Stop conversion and return to SLEEP_MODE
|
||||
```
|
||||
---
|
||||
<a name="results_acquisition"></a>
|
||||
### __Results Acquisition__
|
||||
|
||||
The BMP280 barometer library acquires temperature in degrees celsius (**°C**), pressure in hectoPascals/millibar (**hPa**) and altitude in metres (**m**). The acquisition functions scan the BMP280's status register and return 1 if the barometer results are ready and have been successfully read, 0 if they are not; this allows for non-blocking code implementation. The temperature, pressure and altitude results themselves are _float_ variables by passed reference to the function and are updated upon a successful read.
|
||||
|
||||
Here are the results acquisition functions:
|
||||
|
||||
```
|
||||
bmp280.getMeasurements(temperature, pressure, altitude); // Acquire temperature, pressue and altitude measurements
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getTempPres(temperature, pressure); // Acquire both the temperature and pressure
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getTemperature(temperature); // Acquire the temperature only
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getPressure(pressure); // Acquire the pressure only, (also calculates temperature, but doesn't return it)
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getAltitude(altitude); // Acquire the altitude only
|
||||
```
|
||||
|
||||
However, these function only operate correctly and efficiently if your Arduino sketch's loop() time is fast enough (<35ms). If your loop() time is slow then these functions are unable to poll the BMP280's status register quickly enough. In this case, it is possible to simply read the barometer's latest results without checking the status register with the following functions:
|
||||
|
||||
```
|
||||
bmp280.getCurrentMeasurements(temperature, pressure, altitude); // Acquire the current temperature, pressue and altitude measurements
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getCurrentTempPres(temperature, pressure); // Acquire both the current temperature and pressure
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getCurrentTemperature(temperature); // Acquire the current temperature only
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getCurrentPressure(pressure); // Acquire the currentpressure only, (also calculates temperature, but doesn't return it)
|
||||
```
|
||||
|
||||
```
|
||||
bmp280.getCurrentAltitude(altitude); // Acquire the current altitude only
|
||||
```
|
||||
---
|
||||
<a name="code_implementation"></a>
|
||||
### __Code Implementation__
|
||||
|
||||
Here is an example sketch of how to use the BMP280 library for non-blocking I2C operation, default configuration with continuous conversion in NORMAL_MODE, but with a standby sampling time of 1 second:
|
||||
|
||||
```
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation (address 0x77)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280.setTimeStandby(TIME_STANDBY_1000MS); // Set the standby time to 1s
|
||||
bmp280.startNormalConversion(); // Start NORMAL conversion mode
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F(m"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
A second sketch example for I2C operation, default configuration in FORCED conversion mode:
|
||||
|
||||
```
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation (address 0x77)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
bmp280.startForcedConversion(); // Start a forced conversion (if in SLEEP_MODE)
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
The sketches for SPI operation are identical except that the line:
|
||||
|
||||
```
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation (address 0x77)
|
||||
```
|
||||
|
||||
...should be replaced with the line:
|
||||
|
||||
```
|
||||
BMP280_DEV bmp280(10); // Instantiate (create) a BMP280_DEV object and set-up for SPI operation with chip select on D10
|
||||
```
|
||||
|
||||
For more details see code examples provided in the _.../examples/..._ directory.
|
||||
|
||||
---
|
||||
<a name="example_code"></a>
|
||||
## __Example Code__
|
||||
|
||||
- __BMP280_I2C_Normal.ino__ : I2C Interface, Normal Mode, Standard I2C Address (0x77)
|
||||
|
||||
- __BMP280_I2C_Alt_Normal.ino__ : 2C Interface, Normal Mode, Alternative I2C Address (0x76)
|
||||
|
||||
- __BMP280_I2C_Forced.ino__ : I2C Interface, Forced Mode, Standard I2C Address (0x77)
|
||||
|
||||
- __BMP280_SPI_Normal.ino__ : SPI Interface, Normal Mode
|
||||
|
||||
- __BMP280_SPI_Forced.ino__ : SPI Interface, Forced Mode
|
||||
|
||||
- __BMP280_ESP32_HSPI_Normal.ino__ : ESP32 HSPI Interface, Normal Mode
|
||||
|
||||
- __BMP280_SPI_Normal_Multiple.ino__ : SPI Interface, Normal Mode, Multiple BMP280 Devices
|
||||
|
||||
- __BMP280_ESP8266_I2C_Normal_DefinedPins.ino__ : ESP8266 I2C Interface, Normal Mode, User-Defined Pins
|
||||
|
||||
- __BMP280_ESP32_I2C_Normal_DefinedPins.ino__ : ESP32 I2C Interface, Normal Mode, User-Defined Pins
|
||||
@ -0,0 +1,45 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - ESP32 HSPI Communications, Default Configuration, Normal Conversion
|
||||
//////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
//BMP280_DEV bmp280(21); // Create BMP280_DEV object and set-up for VSPI operation, SCK 5, MOSI 18, MISO 19, SS 21
|
||||
SPIClass SPI1(HSPI); // Create (instantiate) the SPI1 object for HSPI operation
|
||||
BMP280_DEV bmp280(21, HSPI, SPI1); // Create BMP280_DEV object and set-up for HSPI operation, SCK 14, MOSI 13, MISO 27, SS 21
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280.setTimeStandby(TIME_STANDBY_1000MS); // Set the standby time to 1 second (1000ms)
|
||||
bmp280.startNormalConversion(); // Start NORMAL continuous conversion
|
||||
|
||||
xTaskCreatePinnedToCore( // Kick-off "TaskOne" pinned to core 1
|
||||
taskOne,
|
||||
"TaskOne",
|
||||
10000,
|
||||
NULL,
|
||||
1,
|
||||
NULL,
|
||||
1);
|
||||
}
|
||||
|
||||
void taskOne(void* parameter)
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void loop() { delay(1000); } // Add 1 second delay
|
||||
@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - ESP32, I2C Communications, Default Configuration, Normal Conversion, User-Defined Pins
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280(A6, A7); // Instantiate (create) a BMP280 object and set-up for I2C operation on pins SDA: A6, SCL: A7
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,29 @@
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - ESP8266, I2C Communications, Default Configuration, Normal Conversion, User-Defined Pins
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280(6, 7); // Instantiate (create) a BMP280 object and set-up for I2C operation on pins SDA: 6, SCL: 7
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - I2C Communications (Alternative Address), Default Configuration, Normal Conversion
|
||||
/////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(BMP280_I2C_ALT_ADDR); // Default initialisation with alternative I2C address (0x76), place the BMP280 into SLEEP_MODE
|
||||
//bmp280.setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
//bmp280.setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
//bmp280.setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
31
components/BMP280_DEV/examples/BMP280_I2C_Forced/BMP280_I2C_Forced.ino
Executable file
31
components/BMP280_DEV/examples/BMP280_I2C_Forced/BMP280_I2C_Forced.ino
Executable file
@ -0,0 +1,31 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - I2C Communications, Default Configuration, Normal Conversion
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation (address 0x77)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
//bmp280.setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
//bmp280.setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
//bmp280.setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
bmp280.startForcedConversion(); // Start BMP280 forced conversion (if we're in SLEEP_MODE)
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
32
components/BMP280_DEV/examples/BMP280_I2C_Normal/BMP280_I2C_Normal.ino
Executable file
32
components/BMP280_DEV/examples/BMP280_I2C_Normal/BMP280_I2C_Normal.ino
Executable file
@ -0,0 +1,32 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - I2C Communications, Default Configuration, Normal Conversion
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280; // Instantiate (create) a BMP280_DEV object and set-up for I2C operation (address 0x77)
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
//bmp280.setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
//bmp280.setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
//bmp280.setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
31
components/BMP280_DEV/examples/BMP280_SPI_Forced/BMP280_SPI_Forced.ino
Executable file
31
components/BMP280_DEV/examples/BMP280_SPI_Forced/BMP280_SPI_Forced.ino
Executable file
@ -0,0 +1,31 @@
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - SPI Communications, Default Configuration, Forced Conversion
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280(10); // Instantiate (create) a BMP280_DEV object and set-up for SPI operation on digital pin D10
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
//bmp280.setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
//bmp280.setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
//bmp280.setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
bmp280.startForcedConversion(); // Start BMP280 forced conversion (if we're in SLEEP_MODE)
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
32
components/BMP280_DEV/examples/BMP280_SPI_Normal/BMP280_SPI_Normal.ino
Executable file
32
components/BMP280_DEV/examples/BMP280_SPI_Normal/BMP280_SPI_Normal.ino
Executable file
@ -0,0 +1,32 @@
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - SPI Communications, Default Configuration, Normal Conversion
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280(10); // Instantiate (create) a BMP280_DEV object and set-up for SPI operation on digital pin D10
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
//bmp280.setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
//bmp280.setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
//bmp280.setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
bmp280.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(temperature); // Display the results
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,44 @@
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// BMP280_DEV - SPI Communications, Default Configuration, Normal Conversion, Mulitple Devices
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <BMP280_DEV.h> // Include the BMP280_DEV.h library
|
||||
|
||||
float temperature, pressure, altitude; // Create the temperature, pressure and altitude variables
|
||||
BMP280_DEV bmp280_1(10); // Instantiate (create) a BMP280_DEV object and set-up for SPI operation on digital pin D10
|
||||
BMP280_DEV bmp280_2(9); // Instantiate (create) a BMP280_DEV object and set-up for SPI operation on digital pin D9
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(115200); // Initialise the serial port
|
||||
bmp280_1.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280_1.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280_1.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
bmp280_2.begin(); // Default initialisation, place the BMP280 into SLEEP_MODE
|
||||
bmp280_2.setTimeStandby(TIME_STANDBY_2000MS); // Set the standby time to 2 seconds
|
||||
bmp280_2.startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (bmp280_1.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(F("BMP280_1 ")); // Display the results
|
||||
Serial.print(temperature);
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
if (bmp280_2.getMeasurements(temperature, pressure, altitude)) // Check if the measurement is complete
|
||||
{
|
||||
Serial.print(F("BMP280_2 ")); // Display the results
|
||||
Serial.print(temperature);
|
||||
Serial.print(F("*C "));
|
||||
Serial.print(pressure);
|
||||
Serial.print(F("hPa "));
|
||||
Serial.print(altitude);
|
||||
Serial.println(F("m"));
|
||||
}
|
||||
}
|
||||
40
image_enc/encrypt.py
Executable file
40
image_enc/encrypt.py
Executable file
@ -0,0 +1,40 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
from Crypto import Random
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util import Counter
|
||||
|
||||
def main() -> None:
|
||||
IN_FILE = sys.argv[1]
|
||||
OUT_FILE = sys.argv[2]
|
||||
|
||||
# IN_FILE = "build/wellhub.bin"
|
||||
# OUT_FILE = "out.enc"
|
||||
|
||||
rand = Random.new()
|
||||
|
||||
with open(IN_FILE, "rb") as f_in, open(OUT_FILE, "wb") as f_out:
|
||||
inp = f_in.read(-1)
|
||||
|
||||
ran = rand.read(24)
|
||||
sig = b'wellhub0'
|
||||
|
||||
header = []
|
||||
header += (ran)
|
||||
header += (sig)
|
||||
header += inp
|
||||
|
||||
raw = bytearray(header)
|
||||
|
||||
key = b"thirty two bytes key sdf asdf 32"
|
||||
cipher = AES.new(key, AES.MODE_CBC)
|
||||
|
||||
ciphertext = cipher.encrypt(raw)
|
||||
|
||||
f_out.write(ciphertext)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
14
main/App.cpp
14
main/App.cpp
@ -5,6 +5,7 @@
|
||||
#include <Arduino.h>
|
||||
#include "Settings.h"
|
||||
#include "errors.h"
|
||||
#include <Wire.h>
|
||||
|
||||
#include "Ota.h"
|
||||
#include "ProvisionSoftAP.h"
|
||||
@ -26,6 +27,8 @@ void App::init()
|
||||
m_led = new Led(LED_PIN);
|
||||
m_wifi = new Wifi();
|
||||
|
||||
#if 1
|
||||
|
||||
bool needs_provision = true;
|
||||
|
||||
if(SETTINGS.wifi.num > 0)
|
||||
@ -68,6 +71,17 @@ void App::init()
|
||||
|
||||
m_ble = new Ble(*this);
|
||||
m_ble->start();
|
||||
|
||||
#endif
|
||||
#if 0
|
||||
m_bmp280 = new Bmp280(Wire);
|
||||
|
||||
while(true)
|
||||
{
|
||||
m_bmp280->test();
|
||||
delay(10);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void App::otaCheck()
|
||||
|
||||
@ -10,6 +10,7 @@
|
||||
#include "Wifi.h"
|
||||
#include "Mqtt.h"
|
||||
#include "Ble.h"
|
||||
#include "Bmp280.h"
|
||||
|
||||
class App
|
||||
{
|
||||
@ -17,6 +18,7 @@ protected:
|
||||
Wifi * m_wifi = nullptr;
|
||||
Mqtt * m_mqtt = nullptr;
|
||||
Ble * m_ble = nullptr;
|
||||
Bmp280 * m_bmp280 = nullptr;
|
||||
|
||||
public:
|
||||
Led * m_led = nullptr;
|
||||
|
||||
27
main/Bmp280.cpp
Normal file
27
main/Bmp280.cpp
Normal file
@ -0,0 +1,27 @@
|
||||
/// © MiroZ 2024
|
||||
|
||||
#include "Bmp280.h"
|
||||
|
||||
#include <esp_log.h>
|
||||
|
||||
static const char *TAG = "bme280";
|
||||
|
||||
Bmp280::Bmp280(TwoWire & wire) : m_wire(wire)
|
||||
{
|
||||
m_sensor = new BMP280_DEV(wire);
|
||||
m_sensor->begin(0x76);
|
||||
m_sensor->setPresOversampling(OVERSAMPLING_X4); // Set the pressure oversampling to X4
|
||||
m_sensor->setTempOversampling(OVERSAMPLING_X1); // Set the temperature oversampling to X1
|
||||
m_sensor->setIIRFilter(IIR_FILTER_4); // Set the IIR filter to setting 4
|
||||
m_sensor->setTimeStandby(TIME_STANDBY_62MS);
|
||||
m_sensor->startNormalConversion(); // Start BMP280 continuous conversion in NORMAL_MODE
|
||||
}
|
||||
|
||||
bool Bmp280::test()
|
||||
{
|
||||
float temp, pressure, alt;
|
||||
m_sensor->getCurrentMeasurements(temp, pressure, alt);
|
||||
ESP_LOGI(TAG, "temp: %0.3f, pressure: %0.3f, alt: %0.3f", temp*1.8+32, pressure, alt);
|
||||
|
||||
return true;
|
||||
}
|
||||
21
main/Bmp280.h
Normal file
21
main/Bmp280.h
Normal file
@ -0,0 +1,21 @@
|
||||
/// © MiroZ 2024
|
||||
|
||||
#ifndef __BMP280_H__
|
||||
#define __BMP280_H__
|
||||
|
||||
#include <Wire.h>
|
||||
#include <BMP280_DEV.h>
|
||||
|
||||
class Bmp280
|
||||
{
|
||||
protected:
|
||||
BMP280_DEV * m_sensor;
|
||||
TwoWire & m_wire;
|
||||
|
||||
public:
|
||||
Bmp280(TwoWire & wire);
|
||||
|
||||
bool test();
|
||||
};
|
||||
|
||||
#endif
|
||||
@ -1,5 +1,5 @@
|
||||
idf_component_register(SRCS main.cpp App.cpp Settings.cpp Led.cpp TaskMgr.cpp Wifi.cpp utilities.cpp
|
||||
ProvisionSoftAP.cpp ReaderWriter.cpp Ota.cpp Mqtt.cpp Ble.cpp
|
||||
ProvisionSoftAP.cpp ReaderWriter.cpp Ota.cpp Mqtt.cpp Ble.cpp Bmp280.cpp
|
||||
INCLUDE_DIRS "."
|
||||
EMBED_TXTFILES ../html/logo.png ../html/provision.html
|
||||
EMBED_TXTFILES ../certs/eventgrid.azure.pem ../certs/client1-authn-ID.key ../certs/client1-authn-ID.pem ../certs/bigfoot-inc.pem
|
||||
|
||||
36
main/Ota.cpp
36
main/Ota.cpp
@ -15,12 +15,14 @@
|
||||
#include "esp_flash_partitions.h"
|
||||
#include "esp_partition.h"
|
||||
#include "string.h"
|
||||
#include "mbedtls/aes.h"
|
||||
#include "utilities.h"
|
||||
|
||||
#include "Ota.h"
|
||||
|
||||
#include <HTTPClient.h>
|
||||
|
||||
#define OTA_URL "https://bigfoot-inc.com/fw/wellhub.bin"
|
||||
#define OTA_URL "https://bigfoot-inc.com/fw/wellhub.enc.bin"
|
||||
extern const uint8_t server_cert[] asm("_binary_bigfoot_inc_pem_start");
|
||||
|
||||
static const char *TAG = "OTA";
|
||||
@ -86,15 +88,41 @@ void Ota::start()
|
||||
update_partition = esp_ota_get_next_update_partition(NULL);
|
||||
ESP_LOGI(TAG, "Writing to partition subtype %d at offset 0x%x", update_partition->subtype,
|
||||
update_partition->address);
|
||||
|
||||
assert(update_partition != NULL);
|
||||
|
||||
int binary_file_length = 0;
|
||||
/*deal with all receive packet*/
|
||||
bool image_header_was_checked = false;
|
||||
|
||||
// ready header
|
||||
int data_read = stream->readBytes(otaWriteData, 32);
|
||||
if (data_read != 32)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
return;
|
||||
}
|
||||
|
||||
esp_aes_context m_dec_ctx;
|
||||
uint8_t m_dec_iv[16];
|
||||
|
||||
memset(m_dec_iv, 0, sizeof(m_dec_iv));
|
||||
esp_aes_init(&m_dec_ctx);
|
||||
esp_aes_setkey(&m_dec_ctx, (const uint8_t*)"thirty two bytes key sdf asdf 32", 256);
|
||||
|
||||
esp_aes_crypt_cbc(&m_dec_ctx, ESP_AES_DECRYPT, 32, m_dec_iv, (const uint8_t*)otaWriteData, (uint8_t*)&otaWriteData[0]);
|
||||
|
||||
if(strncmp((char*)&otaWriteData[0+24], "wellhub0", 8) != 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Invalid image!");
|
||||
esp_aes_free(&m_dec_ctx);
|
||||
return;
|
||||
}
|
||||
|
||||
while (1)
|
||||
{
|
||||
// int len = stream->available();
|
||||
int data_read = stream->readBytes(otaWriteData, BUFFSIZE);
|
||||
esp_aes_crypt_cbc(&m_dec_ctx, ESP_AES_DECRYPT, data_read, m_dec_iv, (const uint8_t*)otaWriteData, (uint8_t*)&otaWriteData[0]);
|
||||
|
||||
if (data_read < 0)
|
||||
{
|
||||
ESP_LOGE(TAG, "Error: SSL data read error");
|
||||
@ -208,6 +236,8 @@ void Ota::start()
|
||||
|
||||
ESP_LOGI(TAG, "Total Write binary data length : %d", binary_file_length);
|
||||
|
||||
esp_aes_free(&m_dec_ctx);
|
||||
|
||||
if (esp_ota_end(update_handle) != ESP_OK)
|
||||
{
|
||||
ESP_LOGE(TAG, "esp_ota_end failed!");
|
||||
|
||||
@ -11,6 +11,7 @@
|
||||
|
||||
#include "App.h"
|
||||
|
||||
|
||||
static const char * TAG = "main";
|
||||
|
||||
extern "C" void app_main(void)
|
||||
|
||||
8
ota.sh
8
ota.sh
@ -5,12 +5,16 @@
|
||||
idf.py clean
|
||||
idf.py -DROLE=SENDER build
|
||||
|
||||
rm build/wellhub.enc.bin
|
||||
|
||||
ret_val=$?
|
||||
|
||||
if (($ret_val != 0)); then
|
||||
exit
|
||||
fi
|
||||
|
||||
cp build/wellhub.bin /var/www/esp_ota
|
||||
lftp -c "open -u mirozmrzli@bigfoot-inc.com,3445trGGDSa9 ftp.bigfoot-inc.com; put build/wellhub.bin"
|
||||
image_enc/encrypt.py build/wellhub.bin build/wellhub.enc.bin
|
||||
|
||||
cp build/wellhub.enc.bin /var/www/esp_ota
|
||||
lftp -c "open -u mirozmrzli@bigfoot-inc.com,3445trGGDSa9 ftp.bigfoot-inc.com; put build/wellhub.enc.bin"
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user