├── ESP32Cam - BME280.jpg ├── .gitignore ├── Error-AdafruitLibrary-ESP32Cam.png ├── lib ├── Adafruit_BME280_Library │ ├── assets │ │ └── board.jpg │ ├── library.properties │ ├── LICENSE │ ├── examples │ │ ├── bme280_unified │ │ │ └── bme280_unified.ino │ │ ├── bme280test │ │ │ └── bme280test.ino │ │ └── advancedsettings │ │ │ └── advancedsettings.ino │ ├── README.md │ ├── Adafruit_BME280.h │ └── Adafruit_BME280.cpp ├── Adafruit_BusIO │ ├── Adafruit_I2CRegister.h │ ├── library.properties │ ├── README.md │ ├── examples │ │ ├── i2c_address_detect │ │ │ └── i2c_address_detect.ino │ │ ├── spi_modetest │ │ │ └── spi_modetest.ino │ │ ├── spi_registers │ │ │ └── spi_registers.ino │ │ ├── spi_readwrite │ │ │ └── spi_readwrite.ino │ │ ├── i2corspi_register │ │ │ └── i2corspi_register.ino │ │ ├── i2c_registers │ │ │ └── i2c_registers.ino │ │ ├── i2c_readwrite │ │ │ └── i2c_readwrite.ino │ │ └── spi_register_bits │ │ │ └── spi_register_bits.ino │ ├── LICENSE │ ├── Adafruit_I2CDevice.h │ ├── Adafruit_BusIO_Register.h │ ├── Adafruit_SPIDevice.h │ ├── Adafruit_I2CDevice.cpp │ ├── Adafruit_BusIO_Register.cpp │ └── Adafruit_SPIDevice.cpp └── Adafruit_Unified_Sensor │ ├── library.properties │ ├── Adafruit_Sensor.cpp │ ├── examples │ └── sensortest │ │ └── sensortest.ino │ ├── Adafruit_Sensor.h │ ├── README.md │ └── LICENSE.txt ├── test └── README ├── platformio.ini ├── src └── main.cpp ├── include └── README └── README.md /ESP32Cam - BME280.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abish7643/ESP32Cam-I2CSensors/HEAD/ESP32Cam - BME280.jpg -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .pio 2 | .vscode/.browse.c_cpp.db* 3 | .vscode/c_cpp_properties.json 4 | .vscode/launch.json 5 | .vscode/ipch 6 | .vscode -------------------------------------------------------------------------------- /Error-AdafruitLibrary-ESP32Cam.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abish7643/ESP32Cam-I2CSensors/HEAD/Error-AdafruitLibrary-ESP32Cam.png -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/assets/board.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/abish7643/ESP32Cam-I2CSensors/HEAD/lib/Adafruit_BME280_Library/assets/board.jpg -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_I2CRegister.h: -------------------------------------------------------------------------------- 1 | #include "Adafruit_BusIO_Register.h" 2 | #ifndef _ADAFRUIT_I2C_REGISTER_H_ 3 | #define _ADAFRUIT_I2C_REGISTER_H_ 4 | 5 | typedef Adafruit_BusIO_Register Adafruit_I2CRegister; 6 | typedef Adafruit_BusIO_RegisterBits Adafruit_I2CRegisterBits; 7 | 8 | #endif 9 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit BusIO 2 | version=1.4.1 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=This is a library for abstracting away UART, I2C and SPI interfacing 6 | paragraph=This is a library for abstracting away UART, I2C and SPI interfacing 7 | category=Signal Input/Output 8 | url=https://github.com/adafruit/Adafruit_BusIO 9 | architectures=* 10 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit BME280 Library 2 | version=2.1.1 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Arduino library for BME280 sensors. 6 | paragraph=Arduino library for BME280 humidity and pressure sensors. 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit_BME280_Library 9 | architectures=* 10 | depends=Adafruit Unified Sensor 11 | -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/library.properties: -------------------------------------------------------------------------------- 1 | name=Adafruit Unified Sensor 2 | version=1.1.4 3 | author=Adafruit 4 | maintainer=Adafruit 5 | sentence=Required for all Adafruit Unified Sensor based libraries. 6 | paragraph=A unified sensor abstraction layer used by many Adafruit sensor libraries. 7 | category=Sensors 8 | url=https://github.com/adafruit/Adafruit_Sensor 9 | architectures=* 10 | includes=Adafruit_Sensor.h 11 | 12 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/README.md: -------------------------------------------------------------------------------- 1 | # Adafruit Bus IO Library [![Build Status](https://github.com/adafruit/Adafruit_BusIO/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BusIO/actions) 2 | 3 | 4 | This is a helper libary to abstract away I2C & SPI transactions and registers 5 | 6 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 7 | 8 | MIT license, all text above must be included in any redistribution 9 | -------------------------------------------------------------------------------- /test/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for PlatformIO Unit Testing and project tests. 3 | 4 | Unit Testing is a software testing method by which individual units of 5 | source code, sets of one or more MCU program modules together with associated 6 | control data, usage procedures, and operating procedures, are tested to 7 | determine whether they are fit for use. Unit testing finds problems early 8 | in the development cycle. 9 | 10 | More information about PlatformIO Unit Testing: 11 | - https://docs.platformio.org/page/plus/unit-testing.html 12 | -------------------------------------------------------------------------------- /platformio.ini: -------------------------------------------------------------------------------- 1 | ; PlatformIO Project Configuration File 2 | ; 3 | ; Build options: build flags, source filter 4 | ; Upload options: custom upload port, speed and extra flags 5 | ; Library options: dependencies, extra library storages 6 | ; Advanced options: extra scripting 7 | ; 8 | ; Please visit documentation for the other options and examples 9 | ; https://docs.platformio.org/page/projectconf.html 10 | 11 | [env:esp32cam] 12 | platform = espressif32 13 | board = esp32cam 14 | framework = arduino 15 | 16 | upload_port = /dev/ttyUSB0 17 | monitor_speed = 115200 18 | monitor_port = /dev/ttyUSB0 -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/i2c_address_detect/i2c_address_detect.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(0x10); 4 | 5 | void setup() { 6 | while (!Serial) { delay(10); } 7 | Serial.begin(115200); 8 | Serial.println("I2C address detection test"); 9 | 10 | if (!i2c_dev.begin()) { 11 | Serial.print("Did not find device at 0x"); 12 | Serial.println(i2c_dev.address(), HEX); 13 | while (1); 14 | } 15 | Serial.print("Device found on address 0x"); 16 | Serial.println(i2c_dev.address(), HEX); 17 | } 18 | 19 | void loop() { 20 | 21 | } 22 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/spi_modetest/spi_modetest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SPIDEVICE_CS 10 4 | Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1); 5 | //Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS, 13, 12, 11, 100000, SPI_BITORDER_MSBFIRST, SPI_MODE1); 6 | 7 | 8 | void setup() { 9 | while (!Serial) { delay(10); } 10 | Serial.begin(115200); 11 | Serial.println("SPI device mode test"); 12 | 13 | if (!spi_dev.begin()) { 14 | Serial.println("Could not initialize SPI device"); 15 | while (1); 16 | } 17 | } 18 | 19 | void loop() { 20 | Serial.println("\n\nTransfer test"); 21 | for (uint16_t x=0; x<=0xFF; x++) { 22 | uint8_t i = x; 23 | Serial.print("0x"); Serial.print(i, HEX); 24 | spi_dev.read(&i, 1, i); 25 | Serial.print("/"); Serial.print(i, HEX); 26 | Serial.print(", "); 27 | delay(25); 28 | } 29 | } -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/spi_registers/spi_registers.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define SPIDEVICE_CS 10 5 | Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS); 6 | 7 | void setup() { 8 | while (!Serial) { delay(10); } 9 | Serial.begin(115200); 10 | Serial.println("SPI device register test"); 11 | 12 | if (!spi_dev.begin()) { 13 | Serial.println("Could not initialize SPI device"); 14 | while (1); 15 | } 16 | 17 | Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&spi_dev, 0x0F, ADDRBIT8_HIGH_TOREAD); 18 | uint8_t id; 19 | id_reg.read(&id); 20 | Serial.print("ID register = 0x"); Serial.println(id, HEX); 21 | 22 | Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&spi_dev, 0x0C, ADDRBIT8_HIGH_TOREAD, 2, LSBFIRST); 23 | uint16_t thresh; 24 | thresh_reg.read(&thresh); 25 | Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX); 26 | 27 | thresh_reg.write(~thresh); 28 | 29 | Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX); 30 | } 31 | 32 | void loop() { 33 | 34 | } -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/spi_readwrite/spi_readwrite.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define SPIDEVICE_CS 10 4 | Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice(SPIDEVICE_CS); 5 | 6 | 7 | void setup() { 8 | while (!Serial) { delay(10); } 9 | Serial.begin(115200); 10 | Serial.println("SPI device read and write test"); 11 | 12 | if (!spi_dev.begin()) { 13 | Serial.println("Could not initialize SPI device"); 14 | while (1); 15 | } 16 | 17 | uint8_t buffer[32]; 18 | 19 | // Try to read 32 bytes 20 | spi_dev.read(buffer, 32); 21 | Serial.print("Read: "); 22 | for (uint8_t i=0; i<32; i++) { 23 | Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", "); 24 | } 25 | Serial.println(); 26 | 27 | // read a register by writing first, then reading 28 | buffer[0] = 0x8F; // we'll reuse the same buffer 29 | spi_dev.write_then_read(buffer, 1, buffer, 2, false); 30 | Serial.print("Write then Read: "); 31 | for (uint8_t i=0; i<2; i++) { 32 | Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", "); 33 | } 34 | Serial.println(); 35 | } 36 | 37 | void loop() { 38 | 39 | } 40 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Adafruit Industries 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_I2CDevice.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef Adafruit_I2CDevice_h 4 | #define Adafruit_I2CDevice_h 5 | 6 | ///< The class which defines how we will talk to this device over I2C 7 | class Adafruit_I2CDevice { 8 | public: 9 | Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire = &Wire); 10 | uint8_t address(void); 11 | bool begin(bool addr_detect = true); 12 | bool detected(void); 13 | 14 | bool read(uint8_t *buffer, size_t len, bool stop = true); 15 | bool write(uint8_t *buffer, size_t len, bool stop = true, 16 | uint8_t *prefix_buffer = NULL, size_t prefix_len = 0); 17 | bool write_then_read(uint8_t *write_buffer, size_t write_len, 18 | uint8_t *read_buffer, size_t read_len, 19 | bool stop = false); 20 | bool setSpeed(uint32_t desiredclk); 21 | 22 | /*! @brief How many bytes we can read in a transaction 23 | * @return The size of the Wire receive/transmit buffer */ 24 | size_t maxBufferSize() { return _maxBufferSize; } 25 | 26 | private: 27 | uint8_t _addr; 28 | TwoWire *_wire; 29 | bool _begun; 30 | size_t _maxBufferSize; 31 | }; 32 | 33 | #endif // Adafruit_I2CDevice_h 34 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/i2corspi_register/i2corspi_register.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // Define which interface to use by setting the unused interface to NULL! 4 | 5 | #define SPIDEVICE_CS 10 6 | Adafruit_SPIDevice *spi_dev = NULL; // new Adafruit_SPIDevice(SPIDEVICE_CS); 7 | 8 | #define I2C_ADDRESS 0x5D 9 | Adafruit_I2CDevice *i2c_dev = new Adafruit_I2CDevice(I2C_ADDRESS); 10 | 11 | void setup() { 12 | while (!Serial) { delay(10); } 13 | Serial.begin(115200); 14 | Serial.println("I2C or SPI device register test"); 15 | 16 | if (spi_dev && !spi_dev->begin()) { 17 | Serial.println("Could not initialize SPI device"); 18 | } 19 | 20 | if (i2c_dev) { 21 | if (i2c_dev->begin()) { 22 | Serial.print("Device found on I2C address 0x"); 23 | Serial.println(i2c_dev->address(), HEX); 24 | } else { 25 | Serial.print("Did not find I2C device at 0x"); 26 | Serial.println(i2c_dev->address(), HEX); 27 | } 28 | } 29 | 30 | Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(i2c_dev, spi_dev, ADDRBIT8_HIGH_TOREAD, 0x0F); 31 | uint8_t id; 32 | id_reg.read(&id); 33 | Serial.print("ID register = 0x"); Serial.println(id, HEX); 34 | } 35 | 36 | void loop() { 37 | 38 | } -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/i2c_registers/i2c_registers.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #define I2C_ADDRESS 0x60 5 | Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS); 6 | 7 | 8 | void setup() { 9 | while (!Serial) { delay(10); } 10 | Serial.begin(115200); 11 | Serial.println("I2C device register test"); 12 | 13 | if (!i2c_dev.begin()) { 14 | Serial.print("Did not find device at 0x"); 15 | Serial.println(i2c_dev.address(), HEX); 16 | while (1); 17 | } 18 | Serial.print("Device found on address 0x"); 19 | Serial.println(i2c_dev.address(), HEX); 20 | 21 | Adafruit_BusIO_Register id_reg = Adafruit_BusIO_Register(&i2c_dev, 0x0C, 2, LSBFIRST); 22 | uint16_t id; 23 | id_reg.read(&id); 24 | Serial.print("ID register = 0x"); Serial.println(id, HEX); 25 | 26 | Adafruit_BusIO_Register thresh_reg = Adafruit_BusIO_Register(&i2c_dev, 0x01, 2, LSBFIRST); 27 | uint16_t thresh; 28 | thresh_reg.read(&thresh); 29 | Serial.print("Initial threshold register = 0x"); Serial.println(thresh, HEX); 30 | 31 | thresh_reg.write(~thresh); 32 | 33 | Serial.print("Post threshold register = 0x"); Serial.println(thresh_reg.read(), HEX); 34 | } 35 | 36 | void loop() { 37 | 38 | } -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/i2c_readwrite/i2c_readwrite.ino: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define I2C_ADDRESS 0x60 4 | Adafruit_I2CDevice i2c_dev = Adafruit_I2CDevice(I2C_ADDRESS); 5 | 6 | 7 | void setup() { 8 | while (!Serial) { delay(10); } 9 | Serial.begin(115200); 10 | Serial.println("I2C device read and write test"); 11 | 12 | if (!i2c_dev.begin()) { 13 | Serial.print("Did not find device at 0x"); 14 | Serial.println(i2c_dev.address(), HEX); 15 | while (1); 16 | } 17 | Serial.print("Device found on address 0x"); 18 | Serial.println(i2c_dev.address(), HEX); 19 | 20 | uint8_t buffer[32]; 21 | // Try to read 32 bytes 22 | i2c_dev.read(buffer, 32); 23 | Serial.print("Read: "); 24 | for (uint8_t i=0; i<32; i++) { 25 | Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", "); 26 | } 27 | Serial.println(); 28 | 29 | // read a register by writing first, then reading 30 | buffer[0] = 0x0C; // we'll reuse the same buffer 31 | i2c_dev.write_then_read(buffer, 1, buffer, 2, false); 32 | Serial.print("Write then Read: "); 33 | for (uint8_t i=0; i<2; i++) { 34 | Serial.print("0x"); Serial.print(buffer[i], HEX); Serial.print(", "); 35 | } 36 | Serial.println(); 37 | } 38 | 39 | void loop() { 40 | 41 | } 42 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | #include "Arduino.h" 2 | // #include "esp_camera.h" 3 | #include 4 | #include 5 | #include 6 | 7 | // -----------------I2C----------------- 8 | #define I2C_SDA 14 // SDA Connected to GPIO 14 9 | #define I2C_SCL 15 // SCL Connected to GPIO 15 10 | TwoWire I2CSensors = TwoWire(0); 11 | 12 | // BME 280 (Using I2C) 13 | Adafruit_BME280 bme; 14 | 15 | // Sensor Variable (BME280) 16 | float temperature, humidity; 17 | 18 | void setup() 19 | { 20 | Serial.begin(115200); 21 | 22 | I2CSensors.begin(I2C_SDA, I2C_SCL, 100000); 23 | 24 | // BME 280 (0x77 or 0x76 will be the address) 25 | if (!bme.begin(0x76, &I2CSensors)) 26 | { 27 | Serial.println("Couldn't Find BME280 Sensor"); 28 | while (1) 29 | ; 30 | } 31 | else 32 | { 33 | Serial.println("BME280 Sensor Found"); 34 | } 35 | } 36 | 37 | void loop() 38 | { 39 | // -------------Temperature (C)------------------ 40 | 41 | temperature = bme.readTemperature(); 42 | Serial.print("Temperature = "); 43 | Serial.print(temperature); 44 | Serial.print(" *C - "); 45 | 46 | // ---------------------------------------------- 47 | 48 | // ---------------Humidity (%)------------------- 49 | 50 | humidity = bme.readHumidity(); 51 | Serial.print("Humidity = "); 52 | Serial.print(humidity); 53 | Serial.println(" %"); 54 | 55 | // ---------------------------------------------- 56 | 57 | delay(1000); 58 | } -------------------------------------------------------------------------------- /include/README: -------------------------------------------------------------------------------- 1 | 2 | This directory is intended for project header files. 3 | 4 | A header file is a file containing C declarations and macro definitions 5 | to be shared between several project source files. You request the use of a 6 | header file in your project source file (C, C++, etc) located in `src` folder 7 | by including it, with the C preprocessing directive `#include'. 8 | 9 | ```src/main.c 10 | 11 | #include "header.h" 12 | 13 | int main (void) 14 | { 15 | ... 16 | } 17 | ``` 18 | 19 | Including a header file produces the same results as copying the header file 20 | into each source file that needs it. Such copying would be time-consuming 21 | and error-prone. With a header file, the related declarations appear 22 | in only one place. If they need to be changed, they can be changed in one 23 | place, and programs that include the header file will automatically use the 24 | new version when next recompiled. The header file eliminates the labor of 25 | finding and changing all the copies as well as the risk that a failure to 26 | find one copy will result in inconsistencies within a program. 27 | 28 | In C, the usual convention is to give header files names that end with `.h'. 29 | It is most portable to use only letters, digits, dashes, and underscores in 30 | header file names, and at most one dot. 31 | 32 | Read more about using header files in official GCC documentation: 33 | 34 | * Include Syntax 35 | * Include Operation 36 | * Once-Only Headers 37 | * Computed Includes 38 | 39 | https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html 40 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015, Limor Fried & Kevin Townsend for Adafruit Industries 2 | All rights reserved. 3 | 4 | Redistribution and use in source and binary forms, with or without 5 | modification, are permitted provided that the following conditions are met: 6 | 7 | * Redistributions of source code must retain the above copyright notice, 8 | this list of conditions and the following disclaimer. 9 | * Redistributions in binary form must reproduce the above copyright 10 | notice, this list of conditions and the following disclaimer in the 11 | documentation and/or other materials provided with the distribution. 12 | * Neither the name of Adafruit Industries nor the names of its 13 | contributors may be used to endorse or promote products derived from 14 | this software without specific prior written permission. 15 | 16 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 17 | AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 | IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 | ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 20 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 21 | CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 22 | SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 23 | INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 24 | CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 25 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 | POSSIBILITY OF SUCH DAMAGE. 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ESP32Cam with I2C Sensor Example 2 | 3 | Read detailed blog at [how-to-use-i2c-sensor-bme280-with-esp32cam](https://3iinc.xyz/blog/how-to-use-i2c-sensor-bme280-with-esp32cam/). 4 | 5 | ## I2C Bus 6 | 7 | Define SDA and SCL Pins, Pin Number 14 and 15 are selected respectively. 8 | ```cpp 9 | #define I2C_SDA 14 10 | #define I2C_SCL 15 11 | ``` 12 | 13 | Create a Two Wire Instance. 14 | ```cpp 15 | TwoWire I2CSensors = TwoWire(0); 16 | ``` 17 | 18 | In setup(), intialize the Two Wire Instance by passing in the SDA & SCL Pins and the clock frequency. 19 | ```cpp 20 | I2CSensors.begin(I2C_SDA, I2C_SCL, 100000); 21 | ``` 22 | 23 | ![Interfacing](https://github.com/abish7643/ESP32Cam-I2CSensors/blob/master/ESP32Cam%20-%20BME280.jpg "BME280 Connected to I2C Bus") 24 | 25 | ## Expected Error (With Adafruit Library) 26 | 27 | An expected error while using Adafruit Libraries is that "sensor_t" will be conflicting with the ESP32Cam Board since it is declared both in Adafruit Library and ESP32Cam Board Library. This happens only when you include "esp_camera.h", that is if you use camera. 28 | 29 | ```bash 30 | In file included from src/main.cpp:4:0: 31 | lib/Adafruit_Unified_Sensor/Adafruit_Sensor.h:155:3: error: conflicting declaration 'typedef struct sensor_t sensor_t' 32 | } sensor_t; 33 | ^ 34 | In file included from /home/abish/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32-camera/esp_camera.h:70:0, 35 | from src/main.cpp:2: 36 | /home/abish/.platformio/packages/framework-arduinoespressif32/tools/sdk/include/esp32-camera/sensor.h:133:3: note: previous declaration as 'typedef struct _sensor sensor_t' 37 | } sensor_t; 38 | ^ 39 | *** [.pio/build/esp32cam/src/main.cpp.o] Error 1 40 | ``` 41 | 42 | ![Error](https://github.com/abish7643/ESP32Cam-I2CSensors/blob/master/Error-AdafruitLibrary-ESP32Cam.png "Conflicting Declaration") 43 | 44 | Inorder to fix this, rename all the "sensor_t" instances to another name, for example "sensor_t1". I used Sublime Text for renaming all this at once. Also I have attached the modified libraries. Rename yourself if you want to use the latest version of the library when it releases. -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/examples/bme280_unified/bme280_unified.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | This example shows how to take Sensor Events instead of direct readings 4 | 5 | Designed specifically to work with the Adafruit BME280 Breakout 6 | ----> http://www.adafruit.com/products/2652 7 | 8 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 9 | to interface. 10 | 11 | Adafruit invests time and resources providing this open source code, 12 | please support Adafruit and open-source hardware by purchasing products 13 | from Adafruit! 14 | 15 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 16 | BSD license, all text above must be included in any redistribution 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | Adafruit_BME280 bme; // use I2C interface 24 | Adafruit_Sensor *bme_temp = bme.getTemperatureSensor(); 25 | Adafruit_Sensor *bme_pressure = bme.getPressureSensor(); 26 | Adafruit_Sensor *bme_humidity = bme.getHumiditySensor(); 27 | 28 | void setup() { 29 | Serial.begin(9600); 30 | Serial.println(F("BME280 Sensor event test")); 31 | 32 | if (!bme.begin()) { 33 | Serial.println(F("Could not find a valid BME280 sensor, check wiring!")); 34 | while (1) delay(10); 35 | } 36 | 37 | bme_temp->printSensorDetails(); 38 | bme_pressure->printSensorDetails(); 39 | bme_humidity->printSensorDetails(); 40 | } 41 | 42 | void loop() { 43 | sensors_event_t temp_event, pressure_event, humidity_event; 44 | bme_temp->getEvent(&temp_event); 45 | bme_pressure->getEvent(&pressure_event); 46 | bme_humidity->getEvent(&humidity_event); 47 | 48 | Serial.print(F("Temperature = ")); 49 | Serial.print(temp_event.temperature); 50 | Serial.println(" *C"); 51 | 52 | Serial.print(F("Humidity = ")); 53 | Serial.print(humidity_event.relative_humidity); 54 | Serial.println(" %"); 55 | 56 | Serial.print(F("Pressure = ")); 57 | Serial.print(pressure_event.pressure); 58 | Serial.println(" hPa"); 59 | 60 | Serial.println(); 61 | delay(1000); 62 | } -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/Adafruit_Sensor.cpp: -------------------------------------------------------------------------------- 1 | #include "Adafruit_Sensor.h" 2 | 3 | /**************************************************************************/ 4 | /*! 5 | @brief Prints sensor information to serial console 6 | */ 7 | /**************************************************************************/ 8 | void Adafruit_Sensor::printSensorDetails(void) { 9 | sensor_t1 sensor; 10 | getSensor(&sensor); 11 | Serial.println(F("------------------------------------")); 12 | Serial.print(F("Sensor: ")); 13 | Serial.println(sensor.name); 14 | Serial.print(F("Type: ")); 15 | switch ((sensors_type_t)sensor.type) { 16 | case SENSOR_TYPE_ACCELEROMETER: 17 | Serial.print(F("Acceleration (m/s2)")); 18 | break; 19 | case SENSOR_TYPE_MAGNETIC_FIELD: 20 | Serial.print(F("Magnetic (uT)")); 21 | break; 22 | case SENSOR_TYPE_ORIENTATION: 23 | Serial.print(F("Orientation (degrees)")); 24 | break; 25 | case SENSOR_TYPE_GYROSCOPE: 26 | Serial.print(F("Gyroscopic (rad/s)")); 27 | break; 28 | case SENSOR_TYPE_LIGHT: 29 | Serial.print(F("Light (lux)")); 30 | break; 31 | case SENSOR_TYPE_PRESSURE: 32 | Serial.print(F("Pressure (hPa)")); 33 | break; 34 | case SENSOR_TYPE_PROXIMITY: 35 | Serial.print(F("Distance (cm)")); 36 | break; 37 | case SENSOR_TYPE_GRAVITY: 38 | Serial.print(F("Gravity (m/s2)")); 39 | break; 40 | case SENSOR_TYPE_LINEAR_ACCELERATION: 41 | Serial.print(F("Linear Acceleration (m/s2)")); 42 | break; 43 | case SENSOR_TYPE_ROTATION_VECTOR: 44 | Serial.print(F("Rotation vector")); 45 | break; 46 | case SENSOR_TYPE_RELATIVE_HUMIDITY: 47 | Serial.print(F("Relative Humidity (%)")); 48 | break; 49 | case SENSOR_TYPE_AMBIENT_TEMPERATURE: 50 | Serial.print(F("Ambient Temp (C)")); 51 | break; 52 | case SENSOR_TYPE_OBJECT_TEMPERATURE: 53 | Serial.print(F("Object Temp (C)")); 54 | break; 55 | case SENSOR_TYPE_VOLTAGE: 56 | Serial.print(F("Voltage (V)")); 57 | break; 58 | case SENSOR_TYPE_CURRENT: 59 | Serial.print(F("Current (mA)")); 60 | break; 61 | case SENSOR_TYPE_COLOR: 62 | Serial.print(F("Color (RGBA)")); 63 | break; 64 | } 65 | 66 | Serial.println(); 67 | Serial.print(F("Driver Ver: ")); 68 | Serial.println(sensor.version); 69 | Serial.print(F("Unique ID: ")); 70 | Serial.println(sensor.sensor_id); 71 | Serial.print(F("Min Value: ")); 72 | Serial.println(sensor.min_value); 73 | Serial.print(F("Max Value: ")); 74 | Serial.println(sensor.max_value); 75 | Serial.print(F("Resolution: ")); 76 | Serial.println(sensor.resolution); 77 | Serial.println(F("------------------------------------\n")); 78 | } 79 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_BusIO_Register.h: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #ifndef Adafruit_BusIO_Register_h 6 | #define Adafruit_BusIO_Register_h 7 | 8 | typedef enum _Adafruit_BusIO_SPIRegType { 9 | ADDRBIT8_HIGH_TOREAD = 0, 10 | AD8_HIGH_TOREAD_AD7_HIGH_TOINC = 1, 11 | ADDRBIT8_HIGH_TOWRITE = 2, 12 | } Adafruit_BusIO_SPIRegType; 13 | 14 | /*! 15 | * @brief The class which defines a device register (a location to read/write 16 | * data from) 17 | */ 18 | class Adafruit_BusIO_Register { 19 | public: 20 | Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, uint16_t reg_addr, 21 | uint8_t width = 1, uint8_t byteorder = LSBFIRST, 22 | uint8_t address_width = 1); 23 | Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, uint16_t reg_addr, 24 | Adafruit_BusIO_SPIRegType type, uint8_t width = 1, 25 | uint8_t byteorder = LSBFIRST, 26 | uint8_t address_width = 1); 27 | 28 | Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, 29 | Adafruit_SPIDevice *spidevice, 30 | Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, 31 | uint8_t width = 1, uint8_t byteorder = LSBFIRST, 32 | uint8_t address_width = 1); 33 | 34 | bool read(uint8_t *buffer, uint8_t len); 35 | bool read(uint8_t *value); 36 | bool read(uint16_t *value); 37 | uint32_t read(void); 38 | uint32_t readCached(void); 39 | bool write(uint8_t *buffer, uint8_t len); 40 | bool write(uint32_t value, uint8_t numbytes = 0); 41 | 42 | uint8_t width(void); 43 | 44 | void print(Stream *s = &Serial); 45 | void println(Stream *s = &Serial); 46 | 47 | private: 48 | Adafruit_I2CDevice *_i2cdevice; 49 | Adafruit_SPIDevice *_spidevice; 50 | Adafruit_BusIO_SPIRegType _spiregtype; 51 | uint16_t _address; 52 | uint8_t _width, _addrwidth, _byteorder; 53 | uint8_t _buffer[4]; // we wont support anything larger than uint32 for 54 | // non-buffered read 55 | uint32_t _cached = 0; 56 | }; 57 | 58 | /*! 59 | * @brief The class which defines a slice of bits from within a device register 60 | * (a location to read/write data from) 61 | */ 62 | class Adafruit_BusIO_RegisterBits { 63 | public: 64 | Adafruit_BusIO_RegisterBits(Adafruit_BusIO_Register *reg, uint8_t bits, 65 | uint8_t shift); 66 | bool write(uint32_t value); 67 | uint32_t read(void); 68 | 69 | private: 70 | Adafruit_BusIO_Register *_register; 71 | uint8_t _bits, _shift; 72 | }; 73 | 74 | #endif // BusIO_Register_h 75 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/README.md: -------------------------------------------------------------------------------- 1 | # Adafruit BME280 Library [![Build Status](https://github.com/adafruit/Adafruit_BME280_Library/workflows/Arduino%20Library%20CI/badge.svg)](https://github.com/adafruit/Adafruit_BME280_Library/actions)[![Documentation](https://github.com/adafruit/ci-arduino/blob/master/assets/doxygen_badge.svg)](http://adafruit.github.io/Adafruit_BME280_Library/html/index.html) 2 | 3 | 4 | 5 | 6 | This is a library for the Adafruit BME280 Humidity, Barometric Pressure + Temp sensor 7 | 8 | Designed specifically to work with the Adafruit BME280 Breakout 9 | * http://www.adafruit.com/products/2652 10 | 11 | Adafruit invests time and resources providing this open source code, please support Adafruit and open-source hardware by purchasing products from Adafruit! 12 | 13 | # Installation 14 | To install, use the Arduino Library Manager and search for "Adafruit BME280" and install the library. 15 | 16 | ## Dependencies 17 | * [Adafruit Unified Sensor Driver](https://github.com/adafruit/Adafruit_Sensor) 18 | 19 | # Contributing 20 | 21 | Contributions are welcome! Please read our [Code of Conduct](https://github.com/adafruit/Adafruit_PM25AQI/blob/master/CODE_OF_CONDUCT.md>) 22 | before contributing to help this project stay welcoming. 23 | 24 | ## Documentation and doxygen 25 | Documentation is produced by doxygen. Contributions should include documentation for any new code added. 26 | 27 | Some examples of how to use doxygen can be found in these guide pages: 28 | 29 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen 30 | 31 | https://learn.adafruit.com/the-well-automated-arduino-library/doxygen-tips 32 | 33 | ## Formatting and clang-format 34 | This library uses [`clang-format`](https://releases.llvm.org/download.html) to standardize the formatting of `.cpp` and `.h` files. 35 | Contributions should be formatted using `clang-format`: 36 | 37 | The `-i` flag will make the changes to the file. 38 | ```bash 39 | clang-format -i *.cpp *.h 40 | ``` 41 | If you prefer to make the changes yourself, running `clang-format` without the `-i` flag will print out a formatted version of the file. You can save this to a file and diff it against the original to see the changes. 42 | 43 | Note that the formatting output by `clang-format` is what the automated formatting checker will expect. Any diffs from this formatting will result in a failed build until they are addressed. Using the `-i` flag is highly recommended. 44 | 45 | ### clang-format resources 46 | * [Binary builds and source available on the LLVM downloads page](https://releases.llvm.org/download.html) 47 | * [Documentation and IDE integration](https://clang.llvm.org/docs/ClangFormat.html) 48 | 49 | ## About this Driver 50 | Written by Ladyada for Adafruit Industries. 51 | 52 | BSD license, check license.txt for more information 53 | 54 | All text above must be included in any redistribution 55 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/examples/bme280test/bme280test.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | 4 | Designed specifically to work with the Adafruit BME280 Breakout 5 | ----> http://www.adafruit.com/products/2650 6 | 7 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | to interface. The device's I2C address is either 0x76 or 0x77. 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit andopen-source hardware by purchasing products 12 | from Adafruit! 13 | 14 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | See the LICENSE file for details. 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define BME_SCK 13 25 | #define BME_MISO 12 26 | #define BME_MOSI 11 27 | #define BME_CS 10 28 | 29 | #define SEALEVELPRESSURE_HPA (1013.25) 30 | 31 | Adafruit_BME280 bme; // I2C 32 | //Adafruit_BME280 bme(BME_CS); // hardware SPI 33 | //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI 34 | 35 | unsigned long delayTime; 36 | 37 | void setup() { 38 | Serial.begin(9600); 39 | while(!Serial); // time to get serial running 40 | Serial.println(F("BME280 test")); 41 | 42 | unsigned status; 43 | 44 | // default settings 45 | status = bme.begin(); 46 | // You can also pass in a Wire library object like &Wire2 47 | // status = bme.begin(0x76, &Wire2) 48 | if (!status) { 49 | Serial.println("Could not find a valid BME280 sensor, check wiring, address, sensor ID!"); 50 | Serial.print("SensorID was: 0x"); Serial.println(bme.sensorID(),16); 51 | Serial.print(" ID of 0xFF probably means a bad address, a BMP 180 or BMP 085\n"); 52 | Serial.print(" ID of 0x56-0x58 represents a BMP 280,\n"); 53 | Serial.print(" ID of 0x60 represents a BME 280.\n"); 54 | Serial.print(" ID of 0x61 represents a BME 680.\n"); 55 | while (1) delay(10); 56 | } 57 | 58 | Serial.println("-- Default Test --"); 59 | delayTime = 1000; 60 | 61 | Serial.println(); 62 | } 63 | 64 | 65 | void loop() { 66 | printValues(); 67 | delay(delayTime); 68 | } 69 | 70 | 71 | void printValues() { 72 | Serial.print("Temperature = "); 73 | Serial.print(bme.readTemperature()); 74 | Serial.println(" *C"); 75 | 76 | Serial.print("Pressure = "); 77 | 78 | Serial.print(bme.readPressure() / 100.0F); 79 | Serial.println(" hPa"); 80 | 81 | Serial.print("Approx. Altitude = "); 82 | Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); 83 | Serial.println(" m"); 84 | 85 | Serial.print("Humidity = "); 86 | Serial.print(bme.readHumidity()); 87 | Serial.println(" %"); 88 | 89 | Serial.println(); 90 | } -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_SPIDevice.h: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #ifndef Adafruit_SPIDevice_h 4 | #define Adafruit_SPIDevice_h 5 | 6 | // some modern SPI definitions don't have BitOrder enum 7 | #if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \ 8 | defined(ESP8266) || defined(TEENSYDUINO) || \ 9 | defined(ARDUINO_ARCH_SPRESENSE) || defined(ARDUINO_attinyxy7) || \ 10 | defined(ARDUINO_attinyxy6) || defined(ARDUINO_attinyxy4) || \ 11 | defined(ARDUINO_attinyxy2) || defined(ARDUINO_AVR_ATmega4809) || \ 12 | defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \ 13 | defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \ 14 | defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \ 15 | defined(ARDUINO_AVR_ATmega808) 16 | typedef enum _BitOrder { 17 | SPI_BITORDER_MSBFIRST = MSBFIRST, 18 | SPI_BITORDER_LSBFIRST = LSBFIRST, 19 | } BitOrder; 20 | 21 | #elif defined(ESP32) 22 | 23 | // some modern SPI definitions don't have BitOrder enum and have different SPI 24 | // mode defines 25 | typedef enum _BitOrder { 26 | SPI_BITORDER_MSBFIRST = SPI_MSBFIRST, 27 | SPI_BITORDER_LSBFIRST = SPI_LSBFIRST, 28 | } BitOrder; 29 | 30 | #else 31 | // Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST 32 | #define SPI_BITORDER_MSBFIRST MSBFIRST 33 | #define SPI_BITORDER_LSBFIRST LSBFIRST 34 | #endif 35 | 36 | #if defined(__AVR__) || defined(TEENSYDUINO) 37 | typedef volatile uint8_t BusIO_PortReg; 38 | typedef uint8_t BusIO_PortMask; 39 | #define BUSIO_USE_FAST_PINIO 40 | 41 | #elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \ 42 | defined(ARDUINO_ARCH_SAMD) 43 | typedef volatile uint32_t BusIO_PortReg; 44 | typedef uint32_t BusIO_PortMask; 45 | #define BUSIO_USE_FAST_PINIO 46 | 47 | #elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \ 48 | !defined(ARDUINO_ARCH_MBED) 49 | typedef volatile uint32_t BusIO_PortReg; 50 | typedef uint32_t BusIO_PortMask; 51 | #define BUSIO_USE_FAST_PINIO 52 | 53 | #else 54 | #undef BUSIO_USE_FAST_PINIO 55 | #endif 56 | 57 | /**! The class which defines how we will talk to this device over SPI **/ 58 | class Adafruit_SPIDevice { 59 | public: 60 | Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000, 61 | BitOrder dataOrder = SPI_BITORDER_MSBFIRST, 62 | uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI); 63 | 64 | Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi, 65 | uint32_t freq = 1000000, 66 | BitOrder dataOrder = SPI_BITORDER_MSBFIRST, 67 | uint8_t dataMode = SPI_MODE0); 68 | 69 | bool begin(void); 70 | bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF); 71 | bool write(uint8_t *buffer, size_t len, uint8_t *prefix_buffer = NULL, 72 | size_t prefix_len = 0); 73 | bool write_then_read(uint8_t *write_buffer, size_t write_len, 74 | uint8_t *read_buffer, size_t read_len, 75 | uint8_t sendvalue = 0xFF); 76 | 77 | uint8_t transfer(uint8_t send); 78 | void transfer(uint8_t *buffer, size_t len); 79 | void beginTransaction(void); 80 | void endTransaction(void); 81 | 82 | private: 83 | SPIClass *_spi; 84 | SPISettings *_spiSetting; 85 | uint32_t _freq; 86 | BitOrder _dataOrder; 87 | uint8_t _dataMode; 88 | 89 | int8_t _cs, _sck, _mosi, _miso; 90 | #ifdef BUSIO_USE_FAST_PINIO 91 | BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort; 92 | BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask; 93 | #endif 94 | bool _begun; 95 | }; 96 | 97 | #endif // Adafruit_SPIDevice_h 98 | -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/examples/sensortest/sensortest.ino: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | /* Assign a unique ID to this sensor at the same time */ 6 | /* Uncomment following line for default Wire bus */ 7 | Adafruit_ADXL343 accel = Adafruit_ADXL343(12345); 8 | 9 | /* NeoTrellis M4, etc. */ 10 | /* Uncomment following line for Wire1 bus */ 11 | //Adafruit_ADXL343 accel = Adafruit_ADXL343(12345, &Wire1); 12 | 13 | void displaySensorDetails(void) 14 | { 15 | sensor_t1 sensor; 16 | accel.getSensor(&sensor); 17 | Serial.println("------------------------------------"); 18 | Serial.print ("Sensor: "); Serial.println(sensor.name); 19 | Serial.print ("Driver Ver: "); Serial.println(sensor.version); 20 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); 21 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" m/s^2"); 22 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" m/s^2"); 23 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" m/s^2"); 24 | Serial.println("------------------------------------"); 25 | Serial.println(""); 26 | delay(500); 27 | } 28 | 29 | void displayDataRate(void) 30 | { 31 | Serial.print ("Data Rate: "); 32 | 33 | switch(accel.getDataRate()) 34 | { 35 | case ADXL343_DATARATE_3200_HZ: 36 | Serial.print ("3200 "); 37 | break; 38 | case ADXL343_DATARATE_1600_HZ: 39 | Serial.print ("1600 "); 40 | break; 41 | case ADXL343_DATARATE_800_HZ: 42 | Serial.print ("800 "); 43 | break; 44 | case ADXL343_DATARATE_400_HZ: 45 | Serial.print ("400 "); 46 | break; 47 | case ADXL343_DATARATE_200_HZ: 48 | Serial.print ("200 "); 49 | break; 50 | case ADXL343_DATARATE_100_HZ: 51 | Serial.print ("100 "); 52 | break; 53 | case ADXL343_DATARATE_50_HZ: 54 | Serial.print ("50 "); 55 | break; 56 | case ADXL343_DATARATE_25_HZ: 57 | Serial.print ("25 "); 58 | break; 59 | case ADXL343_DATARATE_12_5_HZ: 60 | Serial.print ("12.5 "); 61 | break; 62 | case ADXL343_DATARATE_6_25HZ: 63 | Serial.print ("6.25 "); 64 | break; 65 | case ADXL343_DATARATE_3_13_HZ: 66 | Serial.print ("3.13 "); 67 | break; 68 | case ADXL343_DATARATE_1_56_HZ: 69 | Serial.print ("1.56 "); 70 | break; 71 | case ADXL343_DATARATE_0_78_HZ: 72 | Serial.print ("0.78 "); 73 | break; 74 | case ADXL343_DATARATE_0_39_HZ: 75 | Serial.print ("0.39 "); 76 | break; 77 | case ADXL343_DATARATE_0_20_HZ: 78 | Serial.print ("0.20 "); 79 | break; 80 | case ADXL343_DATARATE_0_10_HZ: 81 | Serial.print ("0.10 "); 82 | break; 83 | default: 84 | Serial.print ("???? "); 85 | break; 86 | } 87 | Serial.println(" Hz"); 88 | } 89 | 90 | void displayRange(void) 91 | { 92 | Serial.print ("Range: +/- "); 93 | 94 | switch(accel.getRange()) 95 | { 96 | case ADXL343_RANGE_16_G: 97 | Serial.print ("16 "); 98 | break; 99 | case ADXL343_RANGE_8_G: 100 | Serial.print ("8 "); 101 | break; 102 | case ADXL343_RANGE_4_G: 103 | Serial.print ("4 "); 104 | break; 105 | case ADXL343_RANGE_2_G: 106 | Serial.print ("2 "); 107 | break; 108 | default: 109 | Serial.print ("?? "); 110 | break; 111 | } 112 | Serial.println(" g"); 113 | } 114 | 115 | void setup(void) 116 | { 117 | Serial.begin(9600); 118 | while (!Serial); 119 | Serial.println("Accelerometer Test"); Serial.println(""); 120 | 121 | /* Initialise the sensor */ 122 | if(!accel.begin()) 123 | { 124 | /* There was a problem detecting the ADXL343 ... check your connections */ 125 | Serial.println("Ooops, no ADXL343 detected ... Check your wiring!"); 126 | while(1); 127 | } 128 | 129 | /* Set the range to whatever is appropriate for your project */ 130 | accel.setRange(ADXL343_RANGE_16_G); 131 | // accel.setRange(ADXL343_RANGE_8_G); 132 | // accel.setRange(ADXL343_RANGE_4_G); 133 | // accel.setRange(ADXL343_RANGE_2_G); 134 | 135 | /* Display some basic information on this sensor */ 136 | displaySensorDetails(); 137 | displayDataRate(); 138 | displayRange(); 139 | Serial.println(""); 140 | } 141 | 142 | void loop(void) 143 | { 144 | /* Get a new sensor event */ 145 | sensors_event_t event; 146 | accel.getEvent(&event); 147 | 148 | /* Display the results (acceleration is measured in m/s^2) */ 149 | Serial.print("X: "); Serial.print(event.acceleration.x); Serial.print(" "); 150 | Serial.print("Y: "); Serial.print(event.acceleration.y); Serial.print(" "); 151 | Serial.print("Z: "); Serial.print(event.acceleration.z); Serial.print(" ");Serial.println("m/s^2 "); 152 | delay(500); 153 | } 154 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/examples/advancedsettings/advancedsettings.ino: -------------------------------------------------------------------------------- 1 | /*************************************************************************** 2 | This is a library for the BME280 humidity, temperature & pressure sensor 3 | 4 | Designed specifically to work with the Adafruit BME280 Breakout 5 | ----> http://www.adafruit.com/products/2650 6 | 7 | These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | to interface. The device's I2C address is either 0x76 or 0x77. 9 | 10 | Adafruit invests time and resources providing this open source code, 11 | please support Adafruit andopen-source hardware by purchasing products 12 | from Adafruit! 13 | 14 | Written by Limor Fried & Kevin Townsend for Adafruit Industries. 15 | BSD license, all text above must be included in any redistribution 16 | See the LICENSE file for details. 17 | ***************************************************************************/ 18 | 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #define BME_SCK 13 25 | #define BME_MISO 12 26 | #define BME_MOSI 11 27 | #define BME_CS 10 28 | 29 | #define SEALEVELPRESSURE_HPA (1013.25) 30 | 31 | Adafruit_BME280 bme; // I2C 32 | //Adafruit_BME280 bme(BME_CS); // hardware SPI 33 | //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // software SPI 34 | 35 | unsigned long delayTime; 36 | 37 | void setup() { 38 | Serial.begin(9600); 39 | Serial.println(F("BME280 test")); 40 | 41 | if (! bme.begin(0x77, &Wire)) { 42 | Serial.println("Could not find a valid BME280 sensor, check wiring!"); 43 | while (1); 44 | } 45 | 46 | Serial.println("-- Default Test --"); 47 | Serial.println("normal mode, 16x oversampling for all, filter off,"); 48 | Serial.println("0.5ms standby period"); 49 | delayTime = 5000; 50 | 51 | 52 | // For more details on the following scenarious, see chapter 53 | // 3.5 "Recommended modes of operation" in the datasheet 54 | 55 | /* 56 | // weather monitoring 57 | Serial.println("-- Weather Station Scenario --"); 58 | Serial.println("forced mode, 1x temperature / 1x humidity / 1x pressure oversampling,"); 59 | Serial.println("filter off"); 60 | bme.setSampling(Adafruit_BME280::MODE_FORCED, 61 | Adafruit_BME280::SAMPLING_X1, // temperature 62 | Adafruit_BME280::SAMPLING_X1, // pressure 63 | Adafruit_BME280::SAMPLING_X1, // humidity 64 | Adafruit_BME280::FILTER_OFF ); 65 | 66 | // suggested rate is 1/60Hz (1m) 67 | delayTime = 60000; // in milliseconds 68 | */ 69 | 70 | /* 71 | // humidity sensing 72 | Serial.println("-- Humidity Sensing Scenario --"); 73 | Serial.println("forced mode, 1x temperature / 1x humidity / 0x pressure oversampling"); 74 | Serial.println("= pressure off, filter off"); 75 | bme.setSampling(Adafruit_BME280::MODE_FORCED, 76 | Adafruit_BME280::SAMPLING_X1, // temperature 77 | Adafruit_BME280::SAMPLING_NONE, // pressure 78 | Adafruit_BME280::SAMPLING_X1, // humidity 79 | Adafruit_BME280::FILTER_OFF ); 80 | 81 | // suggested rate is 1Hz (1s) 82 | delayTime = 1000; // in milliseconds 83 | */ 84 | 85 | /* 86 | // indoor navigation 87 | Serial.println("-- Indoor Navigation Scenario --"); 88 | Serial.println("normal mode, 16x pressure / 2x temperature / 1x humidity oversampling,"); 89 | Serial.println("0.5ms standby period, filter 16x"); 90 | bme.setSampling(Adafruit_BME280::MODE_NORMAL, 91 | Adafruit_BME280::SAMPLING_X2, // temperature 92 | Adafruit_BME280::SAMPLING_X16, // pressure 93 | Adafruit_BME280::SAMPLING_X1, // humidity 94 | Adafruit_BME280::FILTER_X16, 95 | Adafruit_BME280::STANDBY_MS_0_5 ); 96 | 97 | // suggested rate is 25Hz 98 | // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) + (2 * H_ovs + 0.5) 99 | // T_ovs = 2 100 | // P_ovs = 16 101 | // H_ovs = 1 102 | // = 40ms (25Hz) 103 | // with standby time that should really be 24.16913... Hz 104 | delayTime = 41; 105 | */ 106 | 107 | /* 108 | // gaming 109 | Serial.println("-- Gaming Scenario --"); 110 | Serial.println("normal mode, 4x pressure / 1x temperature / 0x humidity oversampling,"); 111 | Serial.println("= humidity off, 0.5ms standby period, filter 16x"); 112 | bme.setSampling(Adafruit_BME280::MODE_NORMAL, 113 | Adafruit_BME280::SAMPLING_X1, // temperature 114 | Adafruit_BME280::SAMPLING_X4, // pressure 115 | Adafruit_BME280::SAMPLING_NONE, // humidity 116 | Adafruit_BME280::FILTER_X16, 117 | Adafruit_BME280::STANDBY_MS_0_5 ); 118 | 119 | // Suggested rate is 83Hz 120 | // 1 + (2 * T_ovs) + (2 * P_ovs + 0.5) 121 | // T_ovs = 1 122 | // P_ovs = 4 123 | // = 11.5ms + 0.5ms standby 124 | delayTime = 12; 125 | */ 126 | 127 | Serial.println(); 128 | } 129 | 130 | 131 | void loop() { 132 | // Only needed in forced mode! In normal mode, you can remove the next line. 133 | bme.takeForcedMeasurement(); // has no effect in normal mode 134 | 135 | printValues(); 136 | delay(delayTime); 137 | } 138 | 139 | 140 | void printValues() { 141 | Serial.print("Temperature = "); 142 | Serial.print(bme.readTemperature()); 143 | Serial.println(" *C"); 144 | 145 | Serial.print("Pressure = "); 146 | 147 | Serial.print(bme.readPressure() / 100.0F); 148 | Serial.println(" hPa"); 149 | 150 | Serial.print("Approx. Altitude = "); 151 | Serial.print(bme.readAltitude(SEALEVELPRESSURE_HPA)); 152 | Serial.println(" m"); 153 | 154 | Serial.print("Humidity = "); 155 | Serial.print(bme.readHumidity()); 156 | Serial.println(" %"); 157 | 158 | Serial.println(); 159 | } 160 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_I2CDevice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //#define DEBUG_SERIAL Serial 5 | 6 | /*! 7 | * @brief Create an I2C device at a given address 8 | * @param addr The 7-bit I2C address for the device 9 | * @param theWire The I2C bus to use, defaults to &Wire 10 | */ 11 | Adafruit_I2CDevice::Adafruit_I2CDevice(uint8_t addr, TwoWire *theWire) { 12 | _addr = addr; 13 | _wire = theWire; 14 | _begun = false; 15 | #ifdef ARDUINO_ARCH_SAMD 16 | _maxBufferSize = 250; // as defined in Wire.h's RingBuffer 17 | #else 18 | _maxBufferSize = 32; 19 | #endif 20 | } 21 | 22 | /*! 23 | * @brief Initializes and does basic address detection 24 | * @param addr_detect Whether we should attempt to detect the I2C address 25 | * with a scan. 99% of sensors/devices don't mind but once in a while, they spaz 26 | * on a scan! 27 | * @return True if I2C initialized and a device with the addr found 28 | */ 29 | bool Adafruit_I2CDevice::begin(bool addr_detect) { 30 | _wire->begin(); 31 | _begun = true; 32 | 33 | if (addr_detect) { 34 | return detected(); 35 | } 36 | return true; 37 | } 38 | 39 | /*! 40 | * @brief Scans I2C for the address - note will give a false-positive 41 | * if there's no pullups on I2C 42 | * @return True if I2C initialized and a device with the addr found 43 | */ 44 | bool Adafruit_I2CDevice::detected(void) { 45 | // Init I2C if not done yet 46 | if (!_begun && !begin()) { 47 | return false; 48 | } 49 | 50 | // A basic scanner, see if it ACK's 51 | _wire->beginTransmission(_addr); 52 | if (_wire->endTransmission() == 0) { 53 | return true; 54 | } 55 | return false; 56 | } 57 | 58 | /*! 59 | * @brief Write a buffer or two to the I2C device. Cannot be more than 60 | * maxBufferSize() bytes. 61 | * @param buffer Pointer to buffer of data to write 62 | * @param len Number of bytes from buffer to write 63 | * @param prefix_buffer Pointer to optional array of data to write before 64 | * buffer. Cannot be more than maxBufferSize() bytes. 65 | * @param prefix_len Number of bytes from prefix buffer to write 66 | * @param stop Whether to send an I2C STOP signal on write 67 | * @return True if write was successful, otherwise false. 68 | */ 69 | bool Adafruit_I2CDevice::write(uint8_t *buffer, size_t len, bool stop, 70 | uint8_t *prefix_buffer, size_t prefix_len) { 71 | if ((len + prefix_len) > maxBufferSize()) { 72 | // currently not guaranteed to work if more than 32 bytes! 73 | // we will need to find out if some platforms have larger 74 | // I2C buffer sizes :/ 75 | #ifdef DEBUG_SERIAL 76 | DEBUG_SERIAL.println(F("\tI2CDevice could not write such a large buffer")); 77 | #endif 78 | return false; 79 | } 80 | 81 | _wire->beginTransmission(_addr); 82 | 83 | // Write the prefix data (usually an address) 84 | if ((prefix_len != 0) && (prefix_buffer != NULL)) { 85 | if (_wire->write(prefix_buffer, prefix_len) != prefix_len) { 86 | #ifdef DEBUG_SERIAL 87 | DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); 88 | #endif 89 | return false; 90 | } 91 | } 92 | 93 | // Write the data itself 94 | if (_wire->write(buffer, len) != len) { 95 | #ifdef DEBUG_SERIAL 96 | DEBUG_SERIAL.println(F("\tI2CDevice failed to write")); 97 | #endif 98 | return false; 99 | } 100 | 101 | #ifdef DEBUG_SERIAL 102 | 103 | DEBUG_SERIAL.print(F("\tI2CWRITE @ 0x")); 104 | DEBUG_SERIAL.print(_addr, HEX); 105 | DEBUG_SERIAL.print(F(" :: ")); 106 | if ((prefix_len != 0) && (prefix_buffer != NULL)) { 107 | for (uint16_t i = 0; i < prefix_len; i++) { 108 | DEBUG_SERIAL.print(F("0x")); 109 | DEBUG_SERIAL.print(prefix_buffer[i], HEX); 110 | DEBUG_SERIAL.print(F(", ")); 111 | } 112 | } 113 | for (uint16_t i = 0; i < len; i++) { 114 | DEBUG_SERIAL.print(F("0x")); 115 | DEBUG_SERIAL.print(buffer[i], HEX); 116 | DEBUG_SERIAL.print(F(", ")); 117 | if (i % 32 == 31) { 118 | DEBUG_SERIAL.println(); 119 | } 120 | } 121 | DEBUG_SERIAL.println(); 122 | #endif 123 | 124 | #ifdef DEBUG_SERIAL 125 | // DEBUG_SERIAL.print("Stop: "); DEBUG_SERIAL.println(stop); 126 | #endif 127 | 128 | if (_wire->endTransmission(stop) == 0) { 129 | #ifdef DEBUG_SERIAL 130 | // DEBUG_SERIAL.println("Sent!"); 131 | #endif 132 | return true; 133 | } else { 134 | #ifdef DEBUG_SERIAL 135 | DEBUG_SERIAL.println("Failed to send!"); 136 | #endif 137 | return false; 138 | } 139 | } 140 | 141 | /*! 142 | * @brief Read from I2C into a buffer from the I2C device. 143 | * Cannot be more than maxBufferSize() bytes. 144 | * @param buffer Pointer to buffer of data to read into 145 | * @param len Number of bytes from buffer to read. 146 | * @param stop Whether to send an I2C STOP signal on read 147 | * @return True if read was successful, otherwise false. 148 | */ 149 | bool Adafruit_I2CDevice::read(uint8_t *buffer, size_t len, bool stop) { 150 | if (len > maxBufferSize()) { 151 | // currently not guaranteed to work if more than 32 bytes! 152 | // we will need to find out if some platforms have larger 153 | // I2C buffer sizes :/ 154 | #ifdef DEBUG_SERIAL 155 | DEBUG_SERIAL.println(F("\tI2CDevice could not read such a large buffer")); 156 | #endif 157 | return false; 158 | } 159 | 160 | size_t recv = _wire->requestFrom((uint8_t)_addr, (uint8_t)len, (uint8_t)stop); 161 | if (recv != len) { 162 | // Not enough data available to fulfill our obligation! 163 | #ifdef DEBUG_SERIAL 164 | DEBUG_SERIAL.print(F("\tI2CDevice did not receive enough data: ")); 165 | DEBUG_SERIAL.println(recv); 166 | #endif 167 | return false; 168 | } 169 | 170 | for (uint16_t i = 0; i < len; i++) { 171 | buffer[i] = _wire->read(); 172 | } 173 | 174 | #ifdef DEBUG_SERIAL 175 | DEBUG_SERIAL.print(F("\tI2CREAD @ 0x")); 176 | DEBUG_SERIAL.print(_addr, HEX); 177 | DEBUG_SERIAL.print(F(" :: ")); 178 | for (uint16_t i = 0; i < len; i++) { 179 | DEBUG_SERIAL.print(F("0x")); 180 | DEBUG_SERIAL.print(buffer[i], HEX); 181 | DEBUG_SERIAL.print(F(", ")); 182 | if (len % 32 == 31) { 183 | DEBUG_SERIAL.println(); 184 | } 185 | } 186 | DEBUG_SERIAL.println(); 187 | #endif 188 | 189 | return true; 190 | } 191 | 192 | /*! 193 | * @brief Write some data, then read some data from I2C into another buffer. 194 | * Cannot be more than maxBufferSize() bytes. The buffers can point to 195 | * same/overlapping locations. 196 | * @param write_buffer Pointer to buffer of data to write from 197 | * @param write_len Number of bytes from buffer to write. 198 | * @param read_buffer Pointer to buffer of data to read into. 199 | * @param read_len Number of bytes from buffer to read. 200 | * @param stop Whether to send an I2C STOP signal between the write and read 201 | * @return True if write & read was successful, otherwise false. 202 | */ 203 | bool Adafruit_I2CDevice::write_then_read(uint8_t *write_buffer, 204 | size_t write_len, uint8_t *read_buffer, 205 | size_t read_len, bool stop) { 206 | if (!write(write_buffer, write_len, stop)) { 207 | return false; 208 | } 209 | 210 | return read(read_buffer, read_len); 211 | } 212 | 213 | /*! 214 | * @brief Returns the 7-bit address of this device 215 | * @return The 7-bit address of this device 216 | */ 217 | uint8_t Adafruit_I2CDevice::address(void) { return _addr; } 218 | 219 | /*! 220 | * @brief Change the I2C clock speed to desired (relies on 221 | * underlying Wire support! 222 | * @param desiredclk The desired I2C SCL frequency 223 | * @return True if this platform supports changing I2C speed. 224 | * Not necessarily that the speed was achieved! 225 | */ 226 | bool Adafruit_I2CDevice::setSpeed(uint32_t desiredclk) { 227 | #if (ARDUINO >= 157) && !defined(ARDUINO_STM32_FEATHER) 228 | _wire->setClock(desiredclk); 229 | return true; 230 | #else 231 | return false; 232 | #endif 233 | } 234 | -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/Adafruit_Sensor.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2008 The Android Open Source Project 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software< /span> 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | /* Update by K. Townsend (Adafruit Industries) for lighter typedefs, and 18 | * extended sensor support to include color, voltage and current */ 19 | 20 | #ifndef _ADAFRUIT_SENSOR_H 21 | #define _ADAFRUIT_SENSOR_H 22 | 23 | #ifndef ARDUINO 24 | #include 25 | #elif ARDUINO >= 100 26 | #include "Arduino.h" 27 | #include "Print.h" 28 | #else 29 | #include "WProgram.h" 30 | #endif 31 | 32 | /* Constants */ 33 | #define SENSORS_GRAVITY_EARTH (9.80665F) /**< Earth's gravity in m/s^2 */ 34 | #define SENSORS_GRAVITY_MOON (1.6F) /**< The moon's gravity in m/s^2 */ 35 | #define SENSORS_GRAVITY_SUN (275.0F) /**< The sun's gravity in m/s^2 */ 36 | #define SENSORS_GRAVITY_STANDARD (SENSORS_GRAVITY_EARTH) 37 | #define SENSORS_MAGFIELD_EARTH_MAX \ 38 | (60.0F) /**< Maximum magnetic field on Earth's surface */ 39 | #define SENSORS_MAGFIELD_EARTH_MIN \ 40 | (30.0F) /**< Minimum magnetic field on Earth's surface */ 41 | #define SENSORS_PRESSURE_SEALEVELHPA \ 42 | (1013.25F) /**< Average sea level pressure is 1013.25 hPa */ 43 | #define SENSORS_DPS_TO_RADS \ 44 | (0.017453293F) /**< Degrees/s to rad/s multiplier \ 45 | */ 46 | #define SENSORS_RADS_TO_DPS \ 47 | (57.29577793F) /**< Rad/s to degrees/s multiplier */ 48 | #define SENSORS_GAUSS_TO_MICROTESLA \ 49 | (100) /**< Gauss to micro-Tesla multiplier */ 50 | 51 | /** Sensor types */ 52 | typedef enum { 53 | SENSOR_TYPE_ACCELEROMETER = (1), /**< Gravity + linear acceleration */ 54 | SENSOR_TYPE_MAGNETIC_FIELD = (2), 55 | SENSOR_TYPE_ORIENTATION = (3), 56 | SENSOR_TYPE_GYROSCOPE = (4), 57 | SENSOR_TYPE_LIGHT = (5), 58 | SENSOR_TYPE_PRESSURE = (6), 59 | SENSOR_TYPE_PROXIMITY = (8), 60 | SENSOR_TYPE_GRAVITY = (9), 61 | SENSOR_TYPE_LINEAR_ACCELERATION = 62 | (10), /**< Acceleration not including gravity */ 63 | SENSOR_TYPE_ROTATION_VECTOR = (11), 64 | SENSOR_TYPE_RELATIVE_HUMIDITY = (12), 65 | SENSOR_TYPE_AMBIENT_TEMPERATURE = (13), 66 | SENSOR_TYPE_OBJECT_TEMPERATURE = (14), 67 | SENSOR_TYPE_VOLTAGE = (15), 68 | SENSOR_TYPE_CURRENT = (16), 69 | SENSOR_TYPE_COLOR = (17) 70 | } sensors_type_t; 71 | 72 | /** struct sensors_vec_s is used to return a vector in a common format. */ 73 | typedef struct { 74 | union { 75 | float v[3]; ///< 3D vector elements 76 | struct { 77 | float x; ///< X component of vector 78 | float y; ///< Y component of vector 79 | float z; ///< Z component of vector 80 | }; ///< Struct for holding XYZ component 81 | /* Orientation sensors */ 82 | struct { 83 | float roll; /**< Rotation around the longitudinal axis (the plane body, 'X 84 | axis'). Roll is positive and increasing when moving 85 | downward. -90 degrees <= roll <= 90 degrees */ 86 | float pitch; /**< Rotation around the lateral axis (the wing span, 'Y 87 | axis'). Pitch is positive and increasing when moving 88 | upwards. -180 degrees <= pitch <= 180 degrees) */ 89 | float heading; /**< Angle between the longitudinal axis (the plane body) 90 | and magnetic north, measured clockwise when viewing from 91 | the top of the device. 0-359 degrees */ 92 | }; ///< Struct for holding roll/pitch/heading 93 | }; ///< Union that can hold 3D vector array, XYZ components or 94 | ///< roll/pitch/heading 95 | int8_t status; ///< Status byte 96 | uint8_t reserved[3]; ///< Reserved 97 | } sensors_vec_t; 98 | 99 | /** struct sensors_color_s is used to return color data in a common format. */ 100 | typedef struct { 101 | union { 102 | float c[3]; ///< Raw 3-element data 103 | /* RGB color space */ 104 | struct { 105 | float r; /**< Red component */ 106 | float g; /**< Green component */ 107 | float b; /**< Blue component */ 108 | }; ///< RGB data in floating point notation 109 | }; ///< Union of various ways to describe RGB colorspace 110 | uint32_t rgba; /**< 24-bit RGBA value */ 111 | } sensors_color_t; 112 | 113 | /* Sensor event (36 bytes) */ 114 | /** struct sensor_event_s is used to provide a single sensor event in a common 115 | * format. */ 116 | typedef struct { 117 | int32_t version; /**< must be sizeof(struct sensors_event_t) */ 118 | int32_t sensor_id; /**< unique sensor identifier */ 119 | int32_t type; /**< sensor type */ 120 | int32_t reserved0; /**< reserved */ 121 | int32_t timestamp; /**< time is in milliseconds */ 122 | union { 123 | float data[4]; ///< Raw data 124 | sensors_vec_t acceleration; /**< acceleration values are in meter per second 125 | per second (m/s^2) */ 126 | sensors_vec_t 127 | magnetic; /**< magnetic vector values are in micro-Tesla (uT) */ 128 | sensors_vec_t orientation; /**< orientation values are in degrees */ 129 | sensors_vec_t gyro; /**< gyroscope values are in rad/s */ 130 | float temperature; /**< temperature is in degrees centigrade (Celsius) */ 131 | float distance; /**< distance in centimeters */ 132 | float light; /**< light in SI lux units */ 133 | float pressure; /**< pressure in hectopascal (hPa) */ 134 | float relative_humidity; /**< relative humidity in percent */ 135 | float current; /**< current in milliamps (mA) */ 136 | float voltage; /**< voltage in volts (V) */ 137 | sensors_color_t color; /**< color in RGB component values */ 138 | }; ///< Union for the wide ranges of data we can carry 139 | } sensors_event_t; 140 | 141 | /* Sensor details (40 bytes) */ 142 | /** struct sensor_s is used to describe basic information about a specific 143 | * sensor. */ 144 | typedef struct { 145 | char name[12]; /**< sensor name */ 146 | int32_t version; /**< version of the hardware + driver */ 147 | int32_t sensor_id; /**< unique sensor identifier */ 148 | int32_t type; /**< this sensor's type (ex. SENSOR_TYPE_LIGHT) */ 149 | float max_value; /**< maximum value of this sensor's value in SI units */ 150 | float min_value; /**< minimum value of this sensor's value in SI units */ 151 | float resolution; /**< smallest difference between two values reported by this 152 | sensor */ 153 | int32_t min_delay; /**< min delay in microseconds between events. zero = not a 154 | constant rate */ 155 | } sensor_t1; 156 | 157 | /** @brief Common sensor interface to unify various sensors. 158 | * Intentionally modeled after sensors.h in the Android API: 159 | * https://github.com/android/platform_hardware_libhardware/blob/master/include/hardware/sensors.h 160 | */ 161 | class Adafruit_Sensor { 162 | public: 163 | // Constructor(s) 164 | Adafruit_Sensor() {} 165 | virtual ~Adafruit_Sensor() {} 166 | 167 | // These must be defined by the subclass 168 | 169 | /*! @brief Whether we should automatically change the range (if possible) for 170 | higher precision 171 | @param enabled True if we will try to autorange */ 172 | virtual void enableAutoRange(bool enabled) { 173 | (void)enabled; /* suppress unused warning */ 174 | }; 175 | 176 | /*! @brief Get the latest sensor event 177 | @returns True if able to fetch an event */ 178 | virtual bool getEvent(sensors_event_t *) = 0; 179 | /*! @brief Get info about the sensor itself */ 180 | virtual void getSensor(sensor_t1 *) = 0; 181 | 182 | void printSensorDetails(void); 183 | 184 | private: 185 | bool _autoRange; 186 | }; 187 | 188 | #endif 189 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/examples/spi_register_bits/spi_register_bits.ino: -------------------------------------------------------------------------------- 1 | /*************************************************** 2 | 3 | This is an example for how to use Adafruit_BusIO_RegisterBits from Adafruit_BusIO library. 4 | 5 | Designed specifically to work with the Adafruit RTD Sensor 6 | ----> https://www.adafruit.com/products/3328 7 | uisng a MAX31865 RTD-to-Digital Converter 8 | ----> https://datasheets.maximintegrated.com/en/ds/MAX31865.pdf 9 | 10 | This sensor uses SPI to communicate, 4 pins are required to 11 | interface. 12 | A fifth pin helps to detect when a new conversion is ready. 13 | 14 | Adafruit invests time and resources providing this open source code, 15 | please support Adafruit and open-source hardware by purchasing 16 | products from Adafruit! 17 | 18 | Example written (2020/3) by Andreas Hardtung/AnHard. 19 | BSD license, all text above must be included in any redistribution 20 | ****************************************************/ 21 | 22 | #include 23 | #include 24 | 25 | #define MAX31865_SPI_SPEED (5000000) 26 | #define MAX31865_SPI_BITORDER (SPI_BITORDER_MSBFIRST) 27 | #define MAX31865_SPI_MODE (SPI_MODE1) 28 | 29 | #define MAX31865_SPI_CS (10) 30 | #define MAX31865_READY_PIN (2) 31 | 32 | 33 | Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE, &SPI); // Hardware SPI 34 | // Adafruit_SPIDevice spi_dev = Adafruit_SPIDevice( MAX31865_SPI_CS, 13, 12, 11, MAX31865_SPI_SPEED, MAX31865_SPI_BITORDER, MAX31865_SPI_MODE); // Software SPI 35 | 36 | // MAX31865 chip related ********************************************************************************************* 37 | Adafruit_BusIO_Register config_reg = Adafruit_BusIO_Register(&spi_dev, 0x00, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST); 38 | Adafruit_BusIO_RegisterBits bias_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 7); 39 | Adafruit_BusIO_RegisterBits auto_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 6); 40 | Adafruit_BusIO_RegisterBits oneS_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 5); 41 | Adafruit_BusIO_RegisterBits wire_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 4); 42 | Adafruit_BusIO_RegisterBits faultT_bits = Adafruit_BusIO_RegisterBits(&config_reg, 2, 2); 43 | Adafruit_BusIO_RegisterBits faultR_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 1); 44 | Adafruit_BusIO_RegisterBits fi50hz_bit = Adafruit_BusIO_RegisterBits(&config_reg, 1, 0); 45 | 46 | Adafruit_BusIO_Register rRatio_reg = Adafruit_BusIO_Register(&spi_dev, 0x01, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); 47 | Adafruit_BusIO_RegisterBits rRatio_bits = Adafruit_BusIO_RegisterBits(&rRatio_reg, 15, 1); 48 | Adafruit_BusIO_RegisterBits fault_bit = Adafruit_BusIO_RegisterBits(&rRatio_reg, 1, 0); 49 | 50 | Adafruit_BusIO_Register maxRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x03, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); 51 | Adafruit_BusIO_RegisterBits maxRratio_bits = Adafruit_BusIO_RegisterBits(&maxRratio_reg, 15, 1); 52 | 53 | Adafruit_BusIO_Register minRratio_reg = Adafruit_BusIO_Register(&spi_dev, 0x05, ADDRBIT8_HIGH_TOWRITE, 2, MSBFIRST); 54 | Adafruit_BusIO_RegisterBits minRratio_bits = Adafruit_BusIO_RegisterBits(&minRratio_reg, 15, 1); 55 | 56 | Adafruit_BusIO_Register fault_reg = Adafruit_BusIO_Register(&spi_dev, 0x07, ADDRBIT8_HIGH_TOWRITE, 1, MSBFIRST); 57 | Adafruit_BusIO_RegisterBits range_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 7); 58 | Adafruit_BusIO_RegisterBits range_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 6); 59 | Adafruit_BusIO_RegisterBits refin_high_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 5); 60 | Adafruit_BusIO_RegisterBits refin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 4); 61 | Adafruit_BusIO_RegisterBits rtdin_low_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 3); 62 | Adafruit_BusIO_RegisterBits voltage_fault_bit = Adafruit_BusIO_RegisterBits(&fault_reg, 1, 2); 63 | 64 | // Print the details of the configuration register. 65 | void printConfig( void ) { 66 | Serial.print("BIAS: "); if (bias_bit.read() ) Serial.print("ON"); else Serial.print("OFF"); 67 | Serial.print(", AUTO: "); if (auto_bit.read() ) Serial.print("ON"); else Serial.print("OFF"); 68 | Serial.print(", ONES: "); if (oneS_bit.read() ) Serial.print("ON"); else Serial.print("OFF"); 69 | Serial.print(", WIRE: "); if (wire_bit.read() ) Serial.print("3"); else Serial.print("2/4"); 70 | Serial.print(", FAULTCLEAR: "); if (faultR_bit.read() ) Serial.print("ON"); else Serial.print("OFF"); 71 | Serial.print(", "); if (fi50hz_bit.read() ) Serial.print("50HZ"); else Serial.print("60HZ"); 72 | Serial.println(); 73 | } 74 | 75 | // Check and print faults. Then clear them. 76 | void checkFaults( void ) { 77 | if (fault_bit.read()) { 78 | Serial.print("MAX: "); Serial.println(maxRratio_bits.read()); 79 | Serial.print("VAL: "); Serial.println( rRatio_bits.read()); 80 | Serial.print("MIN: "); Serial.println(minRratio_bits.read()); 81 | 82 | if (range_high_fault_bit.read() ) Serial.println("Range high fault"); 83 | if ( range_low_fault_bit.read() ) Serial.println("Range low fault"); 84 | if (refin_high_fault_bit.read() ) Serial.println("REFIN high fault"); 85 | if ( refin_low_fault_bit.read() ) Serial.println("REFIN low fault"); 86 | if ( rtdin_low_fault_bit.read() ) Serial.println("RTDIN low fault"); 87 | if ( voltage_fault_bit.read() ) Serial.println("Voltage fault"); 88 | 89 | faultR_bit.write(1); // clear fault 90 | } 91 | } 92 | 93 | void setup() { 94 | #if (MAX31865_1_READY_PIN != -1) 95 | pinMode(MAX31865_READY_PIN ,INPUT_PULLUP); 96 | #endif 97 | 98 | while (!Serial) { delay(10); } 99 | Serial.begin(115200); 100 | Serial.println("SPI Adafruit_BusIO_RegisterBits test on MAX31865"); 101 | 102 | if (!spi_dev.begin()) { 103 | Serial.println("Could not initialize SPI device"); 104 | while (1); 105 | } 106 | 107 | // Set up for automode 50Hz. We don't care about selfheating. We want the highest possible sampling rate. 108 | auto_bit.write(0); // Don't switch filtermode while auto_mode is on. 109 | fi50hz_bit.write(1); // Set filter to 50Hz mode. 110 | faultR_bit.write(1); // Clear faults. 111 | bias_bit.write(1); // In automode we want to have the bias current always on. 112 | delay(5); // Wait until bias current settles down. 113 | // 10.5 time constants of the input RC network is required. 114 | // 10ms worst case for 10kω reference resistor and a 0.1µF capacitor across the RTD inputs. 115 | // Adafruit Module has 0.1µF and only 430/4300ω So here 0.43/4.3ms 116 | auto_bit.write(1); // Now we can set automode. Automatically starting first conversion. 117 | 118 | // Test the READY_PIN 119 | #if (defined( MAX31865_READY_PIN ) && (MAX31865_READY_PIN != -1)) 120 | int i = 0; 121 | while (digitalRead(MAX31865_READY_PIN) && i++ <= 100) { delay(1); } 122 | if (i >= 100) { 123 | Serial.print("ERROR: Max31865 Pin detection does not work. PIN:"); 124 | Serial.println(MAX31865_READY_PIN); 125 | } 126 | #else 127 | delay(100); 128 | #endif 129 | 130 | // Set ratio range. 131 | // Setting the temperatures would need some more calculation - not related to Adafruit_BusIO_RegisterBits. 132 | uint16_t ratio = rRatio_bits.read(); 133 | maxRratio_bits.write( (ratio < 0x8fffu-1000u) ? ratio + 1000u : 0x8fffu ); 134 | minRratio_bits.write( (ratio > 1000u) ? ratio - 1000u : 0u ); 135 | 136 | printConfig(); 137 | checkFaults(); 138 | } 139 | 140 | void loop() { 141 | #if (defined( MAX31865_READY_PIN ) && (MAX31865_1_READY_PIN != -1)) 142 | // Is converstion ready? 143 | if (!digitalRead(MAX31865_READY_PIN)) 144 | #else 145 | // Warant conversion is ready. 146 | delay(21); // 21ms for 50Hz-mode. 19ms in 60Hz-mode. 147 | #endif 148 | { 149 | // Read ratio, calculate temperature, scale, filter and print. 150 | Serial.println( rRatio2C( rRatio_bits.read() ) * 100.0f, 0); // Temperature scaled by 100 151 | // Check, print, clear faults. 152 | checkFaults(); 153 | } 154 | 155 | // Do something else. 156 | //delay(15000); 157 | } 158 | 159 | 160 | // Module/Sensor related. Here Adafruit PT100 module with a 2_Wire PT100 Class C ***************************** 161 | float rRatio2C(uint16_t ratio) { 162 | // A simple linear conversion. 163 | const float R0 = 100.0f; 164 | const float Rref = 430.0f; 165 | const float alphaPT = 0.003850f; 166 | const float ADCmax = (1u << 15) - 1.0f; 167 | const float rscale = Rref / ADCmax; 168 | // Measured temperature in boiling water 101.08°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C. 169 | // Measured temperature in ice/water bath 0.76°C with factor a = 1 and b = 0. Rref and MAX at about 22±2°C. 170 | //const float a = 1.0f / (alphaPT * R0); 171 | const float a = (100.0f/101.08f) / (alphaPT * R0); 172 | //const float b = 0.0f; // 101.08 173 | const float b = -0.76f; // 100.32 > 101.08 174 | 175 | return filterRing( ((ratio * rscale) - R0) * a + b ); 176 | } 177 | 178 | // General purpose ********************************************************************************************* 179 | #define RINGLENGTH 250 180 | float filterRing( float newVal ) { 181 | static float ring[RINGLENGTH] = { 0.0 }; 182 | static uint8_t ringIndex = 0; 183 | static bool ringFull = false; 184 | 185 | if ( ringIndex == RINGLENGTH ) { ringFull = true; ringIndex = 0; } 186 | ring[ringIndex] = newVal; 187 | uint8_t loopEnd = (ringFull) ? RINGLENGTH : ringIndex + 1; 188 | float ringSum = 0.0f; 189 | for (uint8_t i = 0; i < loopEnd; i++) ringSum += ring[i]; 190 | ringIndex++; 191 | return ringSum / loopEnd; 192 | } 193 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_BusIO_Register.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /*! 4 | * @brief Create a register we access over an I2C Device (which defines the 5 | * bus and address) 6 | * @param i2cdevice The I2CDevice to use for underlying I2C access 7 | * @param reg_addr The address pointer value for the I2C/SMBus register, can 8 | * be 8 or 16 bits 9 | * @param width The width of the register data itself, defaults to 1 byte 10 | * @param byteorder The byte order of the register (used when width is > 1), 11 | * defaults to LSBFIRST 12 | * @param address_width The width of the register address itself, defaults 13 | * to 1 byte 14 | */ 15 | Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_I2CDevice *i2cdevice, 16 | uint16_t reg_addr, 17 | uint8_t width, 18 | uint8_t byteorder, 19 | uint8_t address_width) { 20 | _i2cdevice = i2cdevice; 21 | _spidevice = NULL; 22 | _addrwidth = address_width; 23 | _address = reg_addr; 24 | _byteorder = byteorder; 25 | _width = width; 26 | } 27 | 28 | /*! 29 | * @brief Create a register we access over an SPI Device (which defines the 30 | * bus and CS pin) 31 | * @param spidevice The SPIDevice to use for underlying SPI access 32 | * @param reg_addr The address pointer value for the SPI register, can 33 | * be 8 or 16 bits 34 | * @param type The method we use to read/write data to SPI (which is not 35 | * as well defined as I2C) 36 | * @param width The width of the register data itself, defaults to 1 byte 37 | * @param byteorder The byte order of the register (used when width is > 1), 38 | * defaults to LSBFIRST 39 | * @param address_width The width of the register address itself, defaults 40 | * to 1 byte 41 | */ 42 | Adafruit_BusIO_Register::Adafruit_BusIO_Register(Adafruit_SPIDevice *spidevice, 43 | uint16_t reg_addr, 44 | Adafruit_BusIO_SPIRegType type, 45 | uint8_t width, 46 | uint8_t byteorder, 47 | uint8_t address_width) { 48 | _spidevice = spidevice; 49 | _spiregtype = type; 50 | _i2cdevice = NULL; 51 | _addrwidth = address_width; 52 | _address = reg_addr; 53 | _byteorder = byteorder; 54 | _width = width; 55 | } 56 | 57 | /*! 58 | * @brief Create a register we access over an I2C or SPI Device. This is a 59 | * handy function because we can pass in NULL for the unused interface, allowing 60 | * libraries to mass-define all the registers 61 | * @param i2cdevice The I2CDevice to use for underlying I2C access, if NULL 62 | * we use SPI 63 | * @param spidevice The SPIDevice to use for underlying SPI access, if NULL 64 | * we use I2C 65 | * @param reg_addr The address pointer value for the I2C/SMBus/SPI register, 66 | * can be 8 or 16 bits 67 | * @param type The method we use to read/write data to SPI (which is not 68 | * as well defined as I2C) 69 | * @param width The width of the register data itself, defaults to 1 byte 70 | * @param byteorder The byte order of the register (used when width is > 1), 71 | * defaults to LSBFIRST 72 | * @param address_width The width of the register address itself, defaults 73 | * to 1 byte 74 | */ 75 | Adafruit_BusIO_Register::Adafruit_BusIO_Register( 76 | Adafruit_I2CDevice *i2cdevice, Adafruit_SPIDevice *spidevice, 77 | Adafruit_BusIO_SPIRegType type, uint16_t reg_addr, uint8_t width, 78 | uint8_t byteorder, uint8_t address_width) { 79 | _spidevice = spidevice; 80 | _i2cdevice = i2cdevice; 81 | _spiregtype = type; 82 | _addrwidth = address_width; 83 | _address = reg_addr; 84 | _byteorder = byteorder; 85 | _width = width; 86 | } 87 | 88 | /*! 89 | * @brief Write a buffer of data to the register location 90 | * @param buffer Pointer to data to write 91 | * @param len Number of bytes to write 92 | * @return True on successful write (only really useful for I2C as SPI is 93 | * uncheckable) 94 | */ 95 | bool Adafruit_BusIO_Register::write(uint8_t *buffer, uint8_t len) { 96 | 97 | uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), 98 | (uint8_t)(_address >> 8)}; 99 | 100 | if (_i2cdevice) { 101 | return _i2cdevice->write(buffer, len, true, addrbuffer, _addrwidth); 102 | } 103 | if (_spidevice) { 104 | if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { 105 | addrbuffer[0] &= ~0x80; 106 | } 107 | if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { 108 | addrbuffer[0] |= 0x80; 109 | } 110 | if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { 111 | addrbuffer[0] &= ~0x80; 112 | addrbuffer[0] |= 0x40; 113 | } 114 | return _spidevice->write(buffer, len, addrbuffer, _addrwidth); 115 | } 116 | return false; 117 | } 118 | 119 | /*! 120 | * @brief Write up to 4 bytes of data to the register location 121 | * @param value Data to write 122 | * @param numbytes How many bytes from 'value' to write 123 | * @return True on successful write (only really useful for I2C as SPI is 124 | * uncheckable) 125 | */ 126 | bool Adafruit_BusIO_Register::write(uint32_t value, uint8_t numbytes) { 127 | if (numbytes == 0) { 128 | numbytes = _width; 129 | } 130 | if (numbytes > 4) { 131 | return false; 132 | } 133 | 134 | // store a copy 135 | _cached = value; 136 | 137 | for (int i = 0; i < numbytes; i++) { 138 | if (_byteorder == LSBFIRST) { 139 | _buffer[i] = value & 0xFF; 140 | } else { 141 | _buffer[numbytes - i - 1] = value & 0xFF; 142 | } 143 | value >>= 8; 144 | } 145 | return write(_buffer, numbytes); 146 | } 147 | 148 | /*! 149 | * @brief Read data from the register location. This does not do any error 150 | * checking! 151 | * @return Returns 0xFFFFFFFF on failure, value otherwise 152 | */ 153 | uint32_t Adafruit_BusIO_Register::read(void) { 154 | if (!read(_buffer, _width)) { 155 | return -1; 156 | } 157 | 158 | uint32_t value = 0; 159 | 160 | for (int i = 0; i < _width; i++) { 161 | value <<= 8; 162 | if (_byteorder == LSBFIRST) { 163 | value |= _buffer[_width - i - 1]; 164 | } else { 165 | value |= _buffer[i]; 166 | } 167 | } 168 | 169 | return value; 170 | } 171 | 172 | /*! 173 | * @brief Read cached data from last time we wrote to this register 174 | * @return Returns 0xFFFFFFFF on failure, value otherwise 175 | */ 176 | uint32_t Adafruit_BusIO_Register::readCached(void) { return _cached; } 177 | 178 | /*! 179 | * @brief Read a buffer of data from the register location 180 | * @param buffer Pointer to data to read into 181 | * @param len Number of bytes to read 182 | * @return True on successful write (only really useful for I2C as SPI is 183 | * uncheckable) 184 | */ 185 | bool Adafruit_BusIO_Register::read(uint8_t *buffer, uint8_t len) { 186 | uint8_t addrbuffer[2] = {(uint8_t)(_address & 0xFF), 187 | (uint8_t)(_address >> 8)}; 188 | 189 | if (_i2cdevice) { 190 | return _i2cdevice->write_then_read(addrbuffer, _addrwidth, buffer, len); 191 | } 192 | if (_spidevice) { 193 | if (_spiregtype == ADDRBIT8_HIGH_TOREAD) { 194 | addrbuffer[0] |= 0x80; 195 | } 196 | if (_spiregtype == ADDRBIT8_HIGH_TOWRITE) { 197 | addrbuffer[0] &= ~0x80; 198 | } 199 | if (_spiregtype == AD8_HIGH_TOREAD_AD7_HIGH_TOINC) { 200 | addrbuffer[0] |= 0x80 | 0x40; 201 | } 202 | return _spidevice->write_then_read(addrbuffer, _addrwidth, buffer, len); 203 | } 204 | return false; 205 | } 206 | 207 | /*! 208 | * @brief Read 2 bytes of data from the register location 209 | * @param value Pointer to uint16_t variable to read into 210 | * @return True on successful write (only really useful for I2C as SPI is 211 | * uncheckable) 212 | */ 213 | bool Adafruit_BusIO_Register::read(uint16_t *value) { 214 | if (!read(_buffer, 2)) { 215 | return false; 216 | } 217 | 218 | if (_byteorder == LSBFIRST) { 219 | *value = _buffer[1]; 220 | *value <<= 8; 221 | *value |= _buffer[0]; 222 | } else { 223 | *value = _buffer[0]; 224 | *value <<= 8; 225 | *value |= _buffer[1]; 226 | } 227 | return true; 228 | } 229 | 230 | /*! 231 | * @brief Read 1 byte of data from the register location 232 | * @param value Pointer to uint8_t variable to read into 233 | * @return True on successful write (only really useful for I2C as SPI is 234 | * uncheckable) 235 | */ 236 | bool Adafruit_BusIO_Register::read(uint8_t *value) { 237 | if (!read(_buffer, 1)) { 238 | return false; 239 | } 240 | 241 | *value = _buffer[0]; 242 | return true; 243 | } 244 | 245 | /*! 246 | * @brief Pretty printer for this register 247 | * @param s The Stream to print to, defaults to &Serial 248 | */ 249 | void Adafruit_BusIO_Register::print(Stream *s) { 250 | uint32_t val = read(); 251 | s->print("0x"); 252 | s->print(val, HEX); 253 | } 254 | 255 | /*! 256 | * @brief Pretty printer for this register 257 | * @param s The Stream to print to, defaults to &Serial 258 | */ 259 | void Adafruit_BusIO_Register::println(Stream *s) { 260 | print(s); 261 | s->println(); 262 | } 263 | 264 | /*! 265 | * @brief Create a slice of the register that we can address without 266 | * touching other bits 267 | * @param reg The Adafruit_BusIO_Register which defines the bus/register 268 | * @param bits The number of bits wide we are slicing 269 | * @param shift The number of bits that our bit-slice is shifted from LSB 270 | */ 271 | Adafruit_BusIO_RegisterBits::Adafruit_BusIO_RegisterBits( 272 | Adafruit_BusIO_Register *reg, uint8_t bits, uint8_t shift) { 273 | _register = reg; 274 | _bits = bits; 275 | _shift = shift; 276 | } 277 | 278 | /*! 279 | * @brief Read 4 bytes of data from the register 280 | * @return data The 4 bytes to read 281 | */ 282 | uint32_t Adafruit_BusIO_RegisterBits::read(void) { 283 | uint32_t val = _register->read(); 284 | val >>= _shift; 285 | return val & ((1 << (_bits)) - 1); 286 | } 287 | 288 | /*! 289 | * @brief Write 4 bytes of data to the register 290 | * @param data The 4 bytes to write 291 | * @return True on successful write (only really useful for I2C as SPI is 292 | * uncheckable) 293 | */ 294 | bool Adafruit_BusIO_RegisterBits::write(uint32_t data) { 295 | uint32_t val = _register->read(); 296 | 297 | // mask off the data before writing 298 | uint32_t mask = (1 << (_bits)) - 1; 299 | data &= mask; 300 | 301 | mask <<= _shift; 302 | val &= ~mask; // remove the current data at that spot 303 | val |= data << _shift; // and add in the new data 304 | 305 | return _register->write(val, _register->width()); 306 | } 307 | 308 | /*! 309 | * @brief The width of the register data, helpful for doing calculations 310 | * @returns The data width used when initializing the register 311 | */ 312 | uint8_t Adafruit_BusIO_Register::width(void) { return _width; } 313 | -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/README.md: -------------------------------------------------------------------------------- 1 | # Adafruit Unified Sensor Driver # 2 | 3 | Many small embedded systems exist to collect data from sensors, analyse the data, and either take an appropriate action or send that sensor data to another system for processing. 4 | 5 | One of the many challenges of embedded systems design is the fact that parts you used today may be out of production tomorrow, or system requirements may change and you may need to choose a different sensor down the road. 6 | 7 | Creating new drivers is a relatively easy task, but integrating them into existing systems is both error prone and time consuming since sensors rarely use the exact same units of measurement. 8 | 9 | By reducing all data to a single **sensors\_event\_t** 'type' and settling on specific, **standardised SI units** for each sensor family the same sensor types return values that are comparable with any other similar sensor. This enables you to switch sensor models with very little impact on the rest of the system, which can help mitigate some of the risks and problems of sensor availability and code reuse. 10 | 11 | The unified sensor abstraction layer is also useful for data-logging and data-transmission since you only have one well-known type to log or transmit over the air or wire. 12 | 13 | ## Unified Sensor Drivers ## 14 | 15 | The following drivers are based on the Adafruit Unified Sensor Driver: 16 | 17 | **Accelerometers** 18 | - [Adafruit\_ADXL345](https://github.com/adafruit/Adafruit_ADXL345) 19 | - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC) 20 | - [Adafruit\_MMA8451\_Library](https://github.com/adafruit/Adafruit_MMA8451_Library) 21 | 22 | **Gyroscope** 23 | - [Adafruit\_L3GD20\_U](https://github.com/adafruit/Adafruit_L3GD20_U) 24 | 25 | **Light** 26 | - [Adafruit\_TSL2561](https://github.com/adafruit/Adafruit_TSL2561) 27 | - [Adafruit\_TSL2591\_Library](https://github.com/adafruit/Adafruit_TSL2591_Library) 28 | 29 | **Magnetometers** 30 | - [Adafruit\_LSM303DLHC](https://github.com/adafruit/Adafruit_LSM303DLHC) 31 | - [Adafruit\_HMC5883\_Unified](https://github.com/adafruit/Adafruit_HMC5883_Unified) 32 | 33 | **Barometric Pressure** 34 | - [Adafruit\_BMP085\_Unified](https://github.com/adafruit/Adafruit_BMP085_Unified) 35 | - [Adafruit\_BMP183\_Unified\_Library](https://github.com/adafruit/Adafruit_BMP183_Unified_Library) 36 | 37 | **Humidity & Temperature** 38 | - [DHT-sensor-library](https://github.com/adafruit/DHT-sensor-library) 39 | 40 | **Humidity, Temperature, & Barometric Pressure** 41 | - [Adafruit_BME280_Library](https://github.com/adafruit/Adafruit_BME280_Library/) 42 | 43 | **Orientation** 44 | - [Adafruit_BNO055](https://github.com/adafruit/Adafruit_BNO055) 45 | 46 | **All in one device** 47 | - [Adafruit_LSM9DS0](https://github.com/adafruit/Adafruit_LSM9DS0_Library) (accelerometer, gyroscope, magnetometer) 48 | - [Adafruit_LSM9DS1](https://github.com/adafruit/Adafruit_LSM9DS1/) (accelerometer, gyroscope, magnetometer) 49 | 50 | 51 | ## How Does it Work? ## 52 | 53 | Any driver that supports the Adafruit unified sensor abstraction layer will implement the Adafruit\_Sensor base class. There are two main typedefs and one enum defined in Adafruit_Sensor.h that are used to 'abstract' away the sensor details and values: 54 | 55 | **Sensor Types (sensors\_type\_t)** 56 | 57 | These pre-defined sensor types are used to properly handle the two related typedefs below, and allows us determine what types of units the sensor uses, etc. 58 | 59 | ```c++ 60 | /** Sensor types */ 61 | typedef enum 62 | { 63 | SENSOR_TYPE_ACCELEROMETER = (1), 64 | SENSOR_TYPE_MAGNETIC_FIELD = (2), 65 | SENSOR_TYPE_ORIENTATION = (3), 66 | SENSOR_TYPE_GYROSCOPE = (4), 67 | SENSOR_TYPE_LIGHT = (5), 68 | SENSOR_TYPE_PRESSURE = (6), 69 | SENSOR_TYPE_PROXIMITY = (8), 70 | SENSOR_TYPE_GRAVITY = (9), 71 | SENSOR_TYPE_LINEAR_ACCELERATION = (10), 72 | SENSOR_TYPE_ROTATION_VECTOR = (11), 73 | SENSOR_TYPE_RELATIVE_HUMIDITY = (12), 74 | SENSOR_TYPE_AMBIENT_TEMPERATURE = (13), 75 | SENSOR_TYPE_VOLTAGE = (15), 76 | SENSOR_TYPE_CURRENT = (16), 77 | SENSOR_TYPE_COLOR = (17) 78 | } sensors_type_t; 79 | ``` 80 | 81 | **Sensor Details (sensor\_t)** 82 | 83 | This typedef describes the specific capabilities of this sensor, and allows us to know what sensor we are using beneath the abstraction layer. 84 | 85 | ```c++ 86 | /* Sensor details (40 bytes) */ 87 | /** struct sensor_s is used to describe basic information about a specific sensor. */ 88 | typedef struct 89 | { 90 | char name[12]; 91 | int32_t version; 92 | int32_t sensor_id; 93 | int32_t type; 94 | float max_value; 95 | float min_value; 96 | float resolution; 97 | int32_t min_delay; 98 | } sensor_t1; 99 | ``` 100 | 101 | The individual fields are intended to be used as follows: 102 | 103 | - **name**: The sensor name or ID, up to a maximum of twelve characters (ex. "MPL115A2") 104 | - **version**: The version of the sensor HW and the driver to allow us to differentiate versions of the board or driver 105 | - **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network 106 | - **type**: The sensor type, based on **sensors\_type\_t** in sensors.h 107 | - **max\_value**: The maximum value that this sensor can return (in the appropriate SI unit) 108 | - **min\_value**: The minimum value that this sensor can return (in the appropriate SI unit) 109 | - **resolution**: The smallest difference between two values that this sensor can report (in the appropriate SI unit) 110 | - **min\_delay**: The minimum delay in microseconds between two sensor events, or '0' if there is no constant sensor rate 111 | 112 | **Sensor Data/Events (sensors\_event\_t)** 113 | 114 | This typedef is used to return sensor data from any sensor supported by the abstraction layer, using standard SI units and scales. 115 | 116 | ```c++ 117 | /* Sensor event (36 bytes) */ 118 | /** struct sensor_event_s is used to provide a single sensor event in a common format. */ 119 | typedef struct 120 | { 121 | int32_t version; 122 | int32_t sensor_id; 123 | int32_t type; 124 | int32_t reserved0; 125 | int32_t timestamp; 126 | union 127 | { 128 | float data[4]; 129 | sensors_vec_t acceleration; 130 | sensors_vec_t magnetic; 131 | sensors_vec_t orientation; 132 | sensors_vec_t gyro; 133 | float temperature; 134 | float distance; 135 | float light; 136 | float pressure; 137 | float relative_humidity; 138 | float current; 139 | float voltage; 140 | sensors_color_t color; 141 | }; 142 | } sensors_event_t; 143 | ``` 144 | It includes the following fields: 145 | 146 | - **version**: Contain 'sizeof(sensors\_event\_t)' to identify which version of the API we're using in case this changes in the future 147 | - **sensor\_id**: A unique sensor identifier that is used to differentiate this specific sensor instance from any others that are present on the system or in the sensor network (must match the sensor\_id value in the corresponding sensor\_t enum above!) 148 | - **type**: the sensor type, based on **sensors\_type\_t** in sensors.h 149 | - **timestamp**: time in milliseconds when the sensor value was read 150 | - **data[4]**: An array of four 32-bit values that allows us to encapsulate any type of sensor data via a simple union (further described below) 151 | 152 | **Required Functions** 153 | 154 | In addition to the two standard types and the sensor type enum, all drivers based on Adafruit_Sensor must also implement the following two functions: 155 | 156 | ```c++ 157 | bool getEvent(sensors_event_t*); 158 | ``` 159 | Calling this function will populate the supplied sensors\_event\_t reference with the latest available sensor data. You should call this function as often as you want to update your data. 160 | 161 | ```c++ 162 | void getSensor(sensor_t1*); 163 | ``` 164 | Calling this function will provide some basic information about the sensor (the sensor name, driver version, min and max values, etc. 165 | 166 | **Standardised SI values for sensors\_event\_t** 167 | 168 | A key part of the abstraction layer is the standardisation of values on SI units of a particular scale, which is accomplished via the data[4] union in sensors\_event\_t above. This 16 byte union includes fields for each main sensor type, and uses the following SI units and scales: 169 | 170 | - **acceleration**: values are in **meter per second per second** (m/s^2) 171 | - **magnetic**: values are in **micro-Tesla** (uT) 172 | - **orientation**: values are in **degrees** 173 | - **gyro**: values are in **rad/s** 174 | - **temperature**: values in **degrees centigrade** (Celsius) 175 | - **distance**: values are in **centimeters** 176 | - **light**: values are in **SI lux** units 177 | - **pressure**: values are in **hectopascal** (hPa) 178 | - **relative\_humidity**: values are in **percent** 179 | - **current**: values are in **milliamps** (mA) 180 | - **voltage**: values are in **volts** (V) 181 | - **color**: values are in 0..1.0 RGB channel luminosity and 32-bit RGBA format 182 | 183 | ## The Unified Driver Abstraction Layer in Practice ## 184 | 185 | Using the unified sensor abstraction layer is relatively easy once a compliant driver has been created. 186 | 187 | Every compliant sensor can now be read using a single, well-known 'type' (sensors\_event\_t), and there is a standardised way of interrogating a sensor about its specific capabilities (via sensor\_t). 188 | 189 | An example of reading the [TSL2561](https://github.com/adafruit/Adafruit_TSL2561) light sensor can be seen below: 190 | 191 | ```c++ 192 | Adafruit_TSL2561 tsl = Adafruit_TSL2561(TSL2561_ADDR_FLOAT, 12345); 193 | ... 194 | /* Get a new sensor event */ 195 | sensors_event_t event; 196 | tsl.getEvent(&event); 197 | 198 | /* Display the results (light is measured in lux) */ 199 | if (event.light) 200 | { 201 | Serial.print(event.light); Serial.println(" lux"); 202 | } 203 | else 204 | { 205 | /* If event.light = 0 lux the sensor is probably saturated 206 | and no reliable data could be generated! */ 207 | Serial.println("Sensor overload"); 208 | } 209 | ``` 210 | 211 | Similarly, we can get the basic technical capabilities of this sensor with the following code: 212 | 213 | ```c++ 214 | sensor_t1 sensor; 215 | 216 | sensor_t1 sensor; 217 | tsl.getSensor(&sensor); 218 | 219 | /* Display the sensor details */ 220 | Serial.println("------------------------------------"); 221 | Serial.print ("Sensor: "); Serial.println(sensor.name); 222 | Serial.print ("Driver Ver: "); Serial.println(sensor.version); 223 | Serial.print ("Unique ID: "); Serial.println(sensor.sensor_id); 224 | Serial.print ("Max Value: "); Serial.print(sensor.max_value); Serial.println(" lux"); 225 | Serial.print ("Min Value: "); Serial.print(sensor.min_value); Serial.println(" lux"); 226 | Serial.print ("Resolution: "); Serial.print(sensor.resolution); Serial.println(" lux"); 227 | Serial.println("------------------------------------"); 228 | Serial.println(""); 229 | ``` 230 | -------------------------------------------------------------------------------- /lib/Adafruit_Unified_Sensor/LICENSE.txt: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright [yyyy] [name of copyright owner] 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. 203 | -------------------------------------------------------------------------------- /lib/Adafruit_BusIO/Adafruit_SPIDevice.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | //#define DEBUG_SERIAL Serial 5 | 6 | /*! 7 | * @brief Create an SPI device with the given CS pin and settins 8 | * @param cspin The arduino pin number to use for chip select 9 | * @param freq The SPI clock frequency to use, defaults to 1MHz 10 | * @param dataOrder The SPI data order to use for bits within each byte, 11 | * defaults to SPI_BITORDER_MSBFIRST 12 | * @param dataMode The SPI mode to use, defaults to SPI_MODE0 13 | * @param theSPI The SPI bus to use, defaults to &theSPI 14 | */ 15 | Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq, 16 | BitOrder dataOrder, uint8_t dataMode, 17 | SPIClass *theSPI) { 18 | _cs = cspin; 19 | _sck = _mosi = _miso = -1; 20 | _spi = theSPI; 21 | _begun = false; 22 | _spiSetting = new SPISettings(freq, dataOrder, dataMode); 23 | _freq = freq; 24 | _dataOrder = dataOrder; 25 | _dataMode = dataMode; 26 | } 27 | 28 | /*! 29 | * @brief Create an SPI device with the given CS pin and settins 30 | * @param cspin The arduino pin number to use for chip select 31 | * @param sckpin The arduino pin number to use for SCK 32 | * @param misopin The arduino pin number to use for MISO, set to -1 if not 33 | * used 34 | * @param mosipin The arduino pin number to use for MOSI, set to -1 if not 35 | * used 36 | * @param freq The SPI clock frequency to use, defaults to 1MHz 37 | * @param dataOrder The SPI data order to use for bits within each byte, 38 | * defaults to SPI_BITORDER_MSBFIRST 39 | * @param dataMode The SPI mode to use, defaults to SPI_MODE0 40 | */ 41 | Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, 42 | int8_t misopin, int8_t mosipin, 43 | uint32_t freq, BitOrder dataOrder, 44 | uint8_t dataMode) { 45 | _cs = cspin; 46 | _sck = sckpin; 47 | _miso = misopin; 48 | _mosi = mosipin; 49 | 50 | #ifdef BUSIO_USE_FAST_PINIO 51 | csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin)); 52 | csPinMask = digitalPinToBitMask(cspin); 53 | if (mosipin != -1) { 54 | mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin)); 55 | mosiPinMask = digitalPinToBitMask(mosipin); 56 | } 57 | if (misopin != -1) { 58 | misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin)); 59 | misoPinMask = digitalPinToBitMask(misopin); 60 | } 61 | clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin)); 62 | clkPinMask = digitalPinToBitMask(sckpin); 63 | #endif 64 | 65 | _freq = freq; 66 | _dataOrder = dataOrder; 67 | _dataMode = dataMode; 68 | _begun = false; 69 | _spiSetting = new SPISettings(freq, dataOrder, dataMode); 70 | _spi = NULL; 71 | } 72 | 73 | /*! 74 | * @brief Initializes SPI bus and sets CS pin high 75 | * @return Always returns true because there's no way to test success of SPI 76 | * init 77 | */ 78 | bool Adafruit_SPIDevice::begin(void) { 79 | pinMode(_cs, OUTPUT); 80 | digitalWrite(_cs, HIGH); 81 | 82 | if (_spi) { // hardware SPI 83 | _spi->begin(); 84 | } else { 85 | pinMode(_sck, OUTPUT); 86 | 87 | if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) { 88 | // idle low on mode 0 and 1 89 | digitalWrite(_sck, LOW); 90 | } else { 91 | // idle high on mode 2 or 3 92 | digitalWrite(_sck, HIGH); 93 | } 94 | if (_mosi != -1) { 95 | pinMode(_mosi, OUTPUT); 96 | digitalWrite(_mosi, HIGH); 97 | } 98 | if (_miso != -1) { 99 | pinMode(_miso, INPUT); 100 | } 101 | } 102 | 103 | _begun = true; 104 | return true; 105 | } 106 | 107 | /*! 108 | * @brief Transfer (send/receive) one byte over hard/soft SPI 109 | * @param buffer The buffer to send and receive at the same time 110 | * @param len The number of bytes to transfer 111 | */ 112 | void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) { 113 | if (_spi) { 114 | // hardware SPI is easy 115 | _spi->transfer(buffer, len); 116 | return; 117 | } 118 | 119 | uint8_t startbit; 120 | if (_dataOrder == SPI_BITORDER_LSBFIRST) { 121 | startbit = 0x1; 122 | } else { 123 | startbit = 0x80; 124 | } 125 | 126 | bool towrite, lastmosi = !(buffer[0] & startbit); 127 | uint8_t bitdelay_us = (1000000 / _freq) / 2; 128 | 129 | // for softSPI we'll do it by hand 130 | for (size_t i = 0; i < len; i++) { 131 | // software SPI 132 | uint8_t reply = 0; 133 | uint8_t send = buffer[i]; 134 | 135 | /* 136 | Serial.print("\tSending software SPI byte 0x"); 137 | Serial.print(send, HEX); 138 | Serial.print(" -> 0x"); 139 | */ 140 | 141 | // Serial.print(send, HEX); 142 | for (uint8_t b = startbit; b != 0; 143 | b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) { 144 | 145 | if (bitdelay_us) { 146 | delayMicroseconds(bitdelay_us); 147 | } 148 | 149 | if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) { 150 | towrite = send & b; 151 | if ((_mosi != -1) && (lastmosi != towrite)) { 152 | #ifdef BUSIO_USE_FAST_PINIO 153 | if (towrite) 154 | *mosiPort |= mosiPinMask; 155 | else 156 | *mosiPort &= ~mosiPinMask; 157 | #else 158 | digitalWrite(_mosi, towrite); 159 | #endif 160 | lastmosi = towrite; 161 | } 162 | 163 | #ifdef BUSIO_USE_FAST_PINIO 164 | *clkPort |= clkPinMask; // Clock high 165 | #else 166 | digitalWrite(_sck, HIGH); 167 | #endif 168 | 169 | if (bitdelay_us) { 170 | delayMicroseconds(bitdelay_us); 171 | } 172 | 173 | if (_miso != -1) { 174 | #ifdef BUSIO_USE_FAST_PINIO 175 | if (*misoPort & misoPinMask) { 176 | #else 177 | if (digitalRead(_miso)) { 178 | #endif 179 | reply |= b; 180 | } 181 | } 182 | 183 | #ifdef BUSIO_USE_FAST_PINIO 184 | *clkPort &= ~clkPinMask; // Clock low 185 | #else 186 | digitalWrite(_sck, LOW); 187 | #endif 188 | } else { // if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) 189 | 190 | #ifdef BUSIO_USE_FAST_PINIO 191 | *clkPort |= clkPinMask; // Clock high 192 | #else 193 | digitalWrite(_sck, HIGH); 194 | #endif 195 | 196 | if (bitdelay_us) { 197 | delayMicroseconds(bitdelay_us); 198 | } 199 | 200 | if (_mosi != -1) { 201 | #ifdef BUSIO_USE_FAST_PINIO 202 | if (send & b) 203 | *mosiPort |= mosiPinMask; 204 | else 205 | *mosiPort &= ~mosiPinMask; 206 | #else 207 | digitalWrite(_mosi, send & b); 208 | #endif 209 | } 210 | 211 | #ifdef BUSIO_USE_FAST_PINIO 212 | *clkPort &= ~clkPinMask; // Clock low 213 | #else 214 | digitalWrite(_sck, LOW); 215 | #endif 216 | 217 | if (_miso != -1) { 218 | #ifdef BUSIO_USE_FAST_PINIO 219 | if (*misoPort & misoPinMask) { 220 | #else 221 | if (digitalRead(_miso)) { 222 | #endif 223 | reply |= b; 224 | } 225 | } 226 | } 227 | if (_miso != -1) { 228 | buffer[i] = reply; 229 | } 230 | } 231 | } 232 | return; 233 | } 234 | 235 | /*! 236 | * @brief Transfer (send/receive) one byte over hard/soft SPI 237 | * @param send The byte to send 238 | * @return The byte received while transmitting 239 | */ 240 | uint8_t Adafruit_SPIDevice::transfer(uint8_t send) { 241 | uint8_t data = send; 242 | transfer(&data, 1); 243 | return data; 244 | } 245 | 246 | /*! 247 | * @brief Manually begin a transaction (calls beginTransaction if hardware 248 | * SPI) 249 | */ 250 | void Adafruit_SPIDevice::beginTransaction(void) { 251 | if (_spi) { 252 | _spi->beginTransaction(*_spiSetting); 253 | } 254 | } 255 | 256 | /*! 257 | * @brief Manually end a transaction (calls endTransaction if hardware SPI) 258 | */ 259 | void Adafruit_SPIDevice::endTransaction(void) { 260 | if (_spi) { 261 | _spi->endTransaction(); 262 | } 263 | } 264 | 265 | /*! 266 | * @brief Write a buffer or two to the SPI device. 267 | * @param buffer Pointer to buffer of data to write 268 | * @param len Number of bytes from buffer to write 269 | * @param prefix_buffer Pointer to optional array of data to write before 270 | * buffer. 271 | * @param prefix_len Number of bytes from prefix buffer to write 272 | * @return Always returns true because there's no way to test success of SPI 273 | * writes 274 | */ 275 | bool Adafruit_SPIDevice::write(uint8_t *buffer, size_t len, 276 | uint8_t *prefix_buffer, size_t prefix_len) { 277 | if (_spi) { 278 | _spi->beginTransaction(*_spiSetting); 279 | } 280 | 281 | digitalWrite(_cs, LOW); 282 | // do the writing 283 | for (size_t i = 0; i < prefix_len; i++) { 284 | transfer(prefix_buffer[i]); 285 | } 286 | for (size_t i = 0; i < len; i++) { 287 | transfer(buffer[i]); 288 | } 289 | digitalWrite(_cs, HIGH); 290 | 291 | if (_spi) { 292 | _spi->endTransaction(); 293 | } 294 | 295 | #ifdef DEBUG_SERIAL 296 | DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); 297 | if ((prefix_len != 0) && (prefix_buffer != NULL)) { 298 | for (uint16_t i = 0; i < prefix_len; i++) { 299 | DEBUG_SERIAL.print(F("0x")); 300 | DEBUG_SERIAL.print(prefix_buffer[i], HEX); 301 | DEBUG_SERIAL.print(F(", ")); 302 | } 303 | } 304 | for (uint16_t i = 0; i < len; i++) { 305 | DEBUG_SERIAL.print(F("0x")); 306 | DEBUG_SERIAL.print(buffer[i], HEX); 307 | DEBUG_SERIAL.print(F(", ")); 308 | if (i % 32 == 31) { 309 | DEBUG_SERIAL.println(); 310 | } 311 | } 312 | DEBUG_SERIAL.println(); 313 | #endif 314 | 315 | return true; 316 | } 317 | 318 | /*! 319 | * @brief Read from SPI into a buffer from the SPI device. 320 | * @param buffer Pointer to buffer of data to read into 321 | * @param len Number of bytes from buffer to read. 322 | * @param sendvalue The 8-bits of data to write when doing the data read, 323 | * defaults to 0xFF 324 | * @return Always returns true because there's no way to test success of SPI 325 | * writes 326 | */ 327 | bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) { 328 | memset(buffer, sendvalue, len); // clear out existing buffer 329 | if (_spi) { 330 | _spi->beginTransaction(*_spiSetting); 331 | } 332 | digitalWrite(_cs, LOW); 333 | transfer(buffer, len); 334 | digitalWrite(_cs, HIGH); 335 | 336 | if (_spi) { 337 | _spi->endTransaction(); 338 | } 339 | 340 | #ifdef DEBUG_SERIAL 341 | DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); 342 | for (uint16_t i = 0; i < len; i++) { 343 | DEBUG_SERIAL.print(F("0x")); 344 | DEBUG_SERIAL.print(buffer[i], HEX); 345 | DEBUG_SERIAL.print(F(", ")); 346 | if (len % 32 == 31) { 347 | DEBUG_SERIAL.println(); 348 | } 349 | } 350 | DEBUG_SERIAL.println(); 351 | #endif 352 | 353 | return true; 354 | } 355 | 356 | /*! 357 | * @brief Write some data, then read some data from SPI into another buffer. 358 | * The buffers can point to same/overlapping locations. This does not 359 | * transmit-receive at the same time! 360 | * @param write_buffer Pointer to buffer of data to write from 361 | * @param write_len Number of bytes from buffer to write. 362 | * @param read_buffer Pointer to buffer of data to read into. 363 | * @param read_len Number of bytes from buffer to read. 364 | * @param sendvalue The 8-bits of data to write when doing the data read, 365 | * defaults to 0xFF 366 | * @return Always returns true because there's no way to test success of SPI 367 | * writes 368 | */ 369 | bool Adafruit_SPIDevice::write_then_read(uint8_t *write_buffer, 370 | size_t write_len, uint8_t *read_buffer, 371 | size_t read_len, uint8_t sendvalue) { 372 | if (_spi) { 373 | _spi->beginTransaction(*_spiSetting); 374 | } 375 | 376 | digitalWrite(_cs, LOW); 377 | // do the writing 378 | for (size_t i = 0; i < write_len; i++) { 379 | transfer(write_buffer[i]); 380 | } 381 | 382 | #ifdef DEBUG_SERIAL 383 | DEBUG_SERIAL.print(F("\tSPIDevice Wrote: ")); 384 | for (uint16_t i = 0; i < write_len; i++) { 385 | DEBUG_SERIAL.print(F("0x")); 386 | DEBUG_SERIAL.print(write_buffer[i], HEX); 387 | DEBUG_SERIAL.print(F(", ")); 388 | if (write_len % 32 == 31) { 389 | DEBUG_SERIAL.println(); 390 | } 391 | } 392 | DEBUG_SERIAL.println(); 393 | #endif 394 | 395 | // do the reading 396 | for (size_t i = 0; i < read_len; i++) { 397 | read_buffer[i] = transfer(sendvalue); 398 | } 399 | 400 | #ifdef DEBUG_SERIAL 401 | DEBUG_SERIAL.print(F("\tSPIDevice Read: ")); 402 | for (uint16_t i = 0; i < read_len; i++) { 403 | DEBUG_SERIAL.print(F("0x")); 404 | DEBUG_SERIAL.print(read_buffer[i], HEX); 405 | DEBUG_SERIAL.print(F(", ")); 406 | if (read_len % 32 == 31) { 407 | DEBUG_SERIAL.println(); 408 | } 409 | } 410 | DEBUG_SERIAL.println(); 411 | #endif 412 | 413 | digitalWrite(_cs, HIGH); 414 | 415 | if (_spi) { 416 | _spi->endTransaction(); 417 | } 418 | 419 | return true; 420 | } 421 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/Adafruit_BME280.h: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_BME280.h 3 | * 4 | * Designed specifically to work with the Adafruit BME280 Breakout 5 | * ----> http://www.adafruit.com/products/2650 6 | * 7 | * These sensors use I2C or SPI to communicate, 2 or 4 pins are required 8 | * to interface. 9 | * 10 | * Adafruit invests time and resources providing this open source code, 11 | * please support Adafruit and open-source hardware by purchasing 12 | * products from Adafruit! 13 | * 14 | * Written by Kevin "KTOWN" Townsend for Adafruit Industries. 15 | * 16 | * BSD license, all text here must be included in any redistribution. 17 | * See the LICENSE file for details. 18 | * 19 | */ 20 | 21 | #ifndef __BME280_H__ 22 | #define __BME280_H__ 23 | 24 | #include "Arduino.h" 25 | 26 | #include 27 | #include 28 | #include 29 | 30 | /*! 31 | * @brief default I2C address 32 | */ 33 | #define BME280_ADDRESS (0x77) // Primary I2C Address 34 | /*! 35 | * @brief alternate I2C address 36 | */ 37 | #define BME280_ADDRESS_ALTERNATE (0x76) // Alternate Address 38 | 39 | /*! 40 | * @brief Register addresses 41 | */ 42 | enum { 43 | BME280_REGISTER_DIG_T1 = 0x88, 44 | BME280_REGISTER_DIG_T2 = 0x8A, 45 | BME280_REGISTER_DIG_T3 = 0x8C, 46 | 47 | BME280_REGISTER_DIG_P1 = 0x8E, 48 | BME280_REGISTER_DIG_P2 = 0x90, 49 | BME280_REGISTER_DIG_P3 = 0x92, 50 | BME280_REGISTER_DIG_P4 = 0x94, 51 | BME280_REGISTER_DIG_P5 = 0x96, 52 | BME280_REGISTER_DIG_P6 = 0x98, 53 | BME280_REGISTER_DIG_P7 = 0x9A, 54 | BME280_REGISTER_DIG_P8 = 0x9C, 55 | BME280_REGISTER_DIG_P9 = 0x9E, 56 | 57 | BME280_REGISTER_DIG_H1 = 0xA1, 58 | BME280_REGISTER_DIG_H2 = 0xE1, 59 | BME280_REGISTER_DIG_H3 = 0xE3, 60 | BME280_REGISTER_DIG_H4 = 0xE4, 61 | BME280_REGISTER_DIG_H5 = 0xE5, 62 | BME280_REGISTER_DIG_H6 = 0xE7, 63 | 64 | BME280_REGISTER_CHIPID = 0xD0, 65 | BME280_REGISTER_VERSION = 0xD1, 66 | BME280_REGISTER_SOFTRESET = 0xE0, 67 | 68 | BME280_REGISTER_CAL26 = 0xE1, // R calibration stored in 0xE1-0xF0 69 | 70 | BME280_REGISTER_CONTROLHUMID = 0xF2, 71 | BME280_REGISTER_STATUS = 0XF3, 72 | BME280_REGISTER_CONTROL = 0xF4, 73 | BME280_REGISTER_CONFIG = 0xF5, 74 | BME280_REGISTER_PRESSUREDATA = 0xF7, 75 | BME280_REGISTER_TEMPDATA = 0xFA, 76 | BME280_REGISTER_HUMIDDATA = 0xFD 77 | }; 78 | 79 | /**************************************************************************/ 80 | /*! 81 | @brief calibration data 82 | */ 83 | /**************************************************************************/ 84 | typedef struct { 85 | uint16_t dig_T1; ///< temperature compensation value 86 | int16_t dig_T2; ///< temperature compensation value 87 | int16_t dig_T3; ///< temperature compensation value 88 | 89 | uint16_t dig_P1; ///< pressure compensation value 90 | int16_t dig_P2; ///< pressure compensation value 91 | int16_t dig_P3; ///< pressure compensation value 92 | int16_t dig_P4; ///< pressure compensation value 93 | int16_t dig_P5; ///< pressure compensation value 94 | int16_t dig_P6; ///< pressure compensation value 95 | int16_t dig_P7; ///< pressure compensation value 96 | int16_t dig_P8; ///< pressure compensation value 97 | int16_t dig_P9; ///< pressure compensation value 98 | 99 | uint8_t dig_H1; ///< humidity compensation value 100 | int16_t dig_H2; ///< humidity compensation value 101 | uint8_t dig_H3; ///< humidity compensation value 102 | int16_t dig_H4; ///< humidity compensation value 103 | int16_t dig_H5; ///< humidity compensation value 104 | int8_t dig_H6; ///< humidity compensation value 105 | } bme280_calib_data; 106 | /*=========================================================================*/ 107 | 108 | class Adafruit_BME280; 109 | 110 | /** Adafruit Unified Sensor interface for temperature component of BME280 */ 111 | class Adafruit_BME280_Temp : public Adafruit_Sensor { 112 | public: 113 | /** @brief Create an Adafruit_Sensor compatible object for the temp sensor 114 | @param parent A pointer to the BME280 class */ 115 | Adafruit_BME280_Temp(Adafruit_BME280 *parent) { _theBME280 = parent; } 116 | bool getEvent(sensors_event_t *); 117 | void getSensor(sensor_t1 *); 118 | 119 | private: 120 | int _sensorID = 280; 121 | Adafruit_BME280 *_theBME280 = NULL; 122 | }; 123 | 124 | /** Adafruit Unified Sensor interface for pressure component of BME280 */ 125 | class Adafruit_BME280_Pressure : public Adafruit_Sensor { 126 | public: 127 | /** @brief Create an Adafruit_Sensor compatible object for the pressure sensor 128 | @param parent A pointer to the BME280 class */ 129 | Adafruit_BME280_Pressure(Adafruit_BME280 *parent) { _theBME280 = parent; } 130 | bool getEvent(sensors_event_t *); 131 | void getSensor(sensor_t1 *); 132 | 133 | private: 134 | int _sensorID = 280; 135 | Adafruit_BME280 *_theBME280 = NULL; 136 | }; 137 | 138 | /** Adafruit Unified Sensor interface for humidity component of BME280 */ 139 | class Adafruit_BME280_Humidity : public Adafruit_Sensor { 140 | public: 141 | /** @brief Create an Adafruit_Sensor compatible object for the humidity sensor 142 | @param parent A pointer to the BME280 class */ 143 | Adafruit_BME280_Humidity(Adafruit_BME280 *parent) { _theBME280 = parent; } 144 | bool getEvent(sensors_event_t *); 145 | void getSensor(sensor_t1 *); 146 | 147 | private: 148 | int _sensorID = 280; 149 | Adafruit_BME280 *_theBME280 = NULL; 150 | }; 151 | 152 | /**************************************************************************/ 153 | /*! 154 | @brief Class that stores state and functions for interacting with BME280 IC 155 | */ 156 | /**************************************************************************/ 157 | class Adafruit_BME280 { 158 | public: 159 | /**************************************************************************/ 160 | /*! 161 | @brief sampling rates 162 | */ 163 | /**************************************************************************/ 164 | enum sensor_sampling { 165 | SAMPLING_NONE = 0b000, 166 | SAMPLING_X1 = 0b001, 167 | SAMPLING_X2 = 0b010, 168 | SAMPLING_X4 = 0b011, 169 | SAMPLING_X8 = 0b100, 170 | SAMPLING_X16 = 0b101 171 | }; 172 | 173 | /**************************************************************************/ 174 | /*! 175 | @brief power modes 176 | */ 177 | /**************************************************************************/ 178 | enum sensor_mode { 179 | MODE_SLEEP = 0b00, 180 | MODE_FORCED = 0b01, 181 | MODE_NORMAL = 0b11 182 | }; 183 | 184 | /**************************************************************************/ 185 | /*! 186 | @brief filter values 187 | */ 188 | /**************************************************************************/ 189 | enum sensor_filter { 190 | FILTER_OFF = 0b000, 191 | FILTER_X2 = 0b001, 192 | FILTER_X4 = 0b010, 193 | FILTER_X8 = 0b011, 194 | FILTER_X16 = 0b100 195 | }; 196 | 197 | /**************************************************************************/ 198 | /*! 199 | @brief standby duration in ms 200 | */ 201 | /**************************************************************************/ 202 | enum standby_duration { 203 | STANDBY_MS_0_5 = 0b000, 204 | STANDBY_MS_10 = 0b110, 205 | STANDBY_MS_20 = 0b111, 206 | STANDBY_MS_62_5 = 0b001, 207 | STANDBY_MS_125 = 0b010, 208 | STANDBY_MS_250 = 0b011, 209 | STANDBY_MS_500 = 0b100, 210 | STANDBY_MS_1000 = 0b101 211 | }; 212 | 213 | // constructors 214 | Adafruit_BME280(); 215 | Adafruit_BME280(int8_t cspin, SPIClass *theSPI = &SPI); 216 | Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, int8_t sckpin); 217 | ~Adafruit_BME280(void); 218 | bool begin(uint8_t addr = BME280_ADDRESS, TwoWire *theWire = &Wire); 219 | bool init(); 220 | 221 | void setSampling(sensor_mode mode = MODE_NORMAL, 222 | sensor_sampling tempSampling = SAMPLING_X16, 223 | sensor_sampling pressSampling = SAMPLING_X16, 224 | sensor_sampling humSampling = SAMPLING_X16, 225 | sensor_filter filter = FILTER_OFF, 226 | standby_duration duration = STANDBY_MS_0_5); 227 | 228 | void takeForcedMeasurement(); 229 | float readTemperature(void); 230 | float readPressure(void); 231 | float readHumidity(void); 232 | 233 | float readAltitude(float seaLevel); 234 | float seaLevelForAltitude(float altitude, float pressure); 235 | uint32_t sensorID(void); 236 | 237 | float getTemperatureCompensation(void); 238 | void setTemperatureCompensation(float); 239 | 240 | Adafruit_Sensor *getTemperatureSensor(void); 241 | Adafruit_Sensor *getPressureSensor(void); 242 | Adafruit_Sensor *getHumiditySensor(void); 243 | 244 | protected: 245 | TwoWire *_wire; //!< pointer to a TwoWire object 246 | SPIClass *_spi; //!< pointer to SPI object 247 | 248 | Adafruit_BME280_Temp *temp_sensor = NULL; 249 | //!< Adafruit_Sensor compat temperature sensor component 250 | 251 | Adafruit_BME280_Pressure *pressure_sensor = NULL; 252 | //!< Adafruit_Sensor compat pressure sensor component 253 | 254 | Adafruit_BME280_Humidity *humidity_sensor = NULL; 255 | //!< Adafruit_Sensor compat humidity sensor component 256 | 257 | void readCoefficients(void); 258 | bool isReadingCalibration(void); 259 | uint8_t spixfer(uint8_t x); 260 | 261 | void write8(byte reg, byte value); 262 | uint8_t read8(byte reg); 263 | uint16_t read16(byte reg); 264 | uint32_t read24(byte reg); 265 | int16_t readS16(byte reg); 266 | uint16_t read16_LE(byte reg); // little endian 267 | int16_t readS16_LE(byte reg); // little endian 268 | 269 | uint8_t _i2caddr; //!< I2C addr for the TwoWire interface 270 | int32_t _sensorID; //!< ID of the BME Sensor 271 | int32_t t_fine; //!< temperature with high resolution, stored as an attribute 272 | //!< as this is used for temperature compensation reading 273 | //!< humidity and pressure 274 | 275 | int8_t _cs; //!< for the SPI interface 276 | int8_t _mosi; //!< for the SPI interface 277 | int8_t _miso; //!< for the SPI interface 278 | int8_t _sck; //!< for the SPI interface 279 | 280 | int32_t t_fine_adjust = 0; //!< add to compensate temp readings and in turn 281 | //!< to pressure and humidity readings 282 | 283 | bme280_calib_data _bme280_calib; //!< here calibration data is stored 284 | 285 | /**************************************************************************/ 286 | /*! 287 | @brief config register 288 | */ 289 | /**************************************************************************/ 290 | struct config { 291 | // inactive duration (standby time) in normal mode 292 | // 000 = 0.5 ms 293 | // 001 = 62.5 ms 294 | // 010 = 125 ms 295 | // 011 = 250 ms 296 | // 100 = 500 ms 297 | // 101 = 1000 ms 298 | // 110 = 10 ms 299 | // 111 = 20 ms 300 | unsigned int t_sb : 3; ///< inactive duration (standby time) in normal mode 301 | 302 | // filter settings 303 | // 000 = filter off 304 | // 001 = 2x filter 305 | // 010 = 4x filter 306 | // 011 = 8x filter 307 | // 100 and above = 16x filter 308 | unsigned int filter : 3; ///< filter settings 309 | 310 | // unused - don't set 311 | unsigned int none : 1; ///< unused - don't set 312 | unsigned int spi3w_en : 1; ///< unused - don't set 313 | 314 | /// @return combined config register 315 | unsigned int get() { return (t_sb << 5) | (filter << 2) | spi3w_en; } 316 | }; 317 | config _configReg; //!< config register object 318 | 319 | /**************************************************************************/ 320 | /*! 321 | @brief ctrl_meas register 322 | */ 323 | /**************************************************************************/ 324 | struct ctrl_meas { 325 | // temperature oversampling 326 | // 000 = skipped 327 | // 001 = x1 328 | // 010 = x2 329 | // 011 = x4 330 | // 100 = x8 331 | // 101 and above = x16 332 | unsigned int osrs_t : 3; ///< temperature oversampling 333 | 334 | // pressure oversampling 335 | // 000 = skipped 336 | // 001 = x1 337 | // 010 = x2 338 | // 011 = x4 339 | // 100 = x8 340 | // 101 and above = x16 341 | unsigned int osrs_p : 3; ///< pressure oversampling 342 | 343 | // device mode 344 | // 00 = sleep 345 | // 01 or 10 = forced 346 | // 11 = normal 347 | unsigned int mode : 2; ///< device mode 348 | 349 | /// @return combined ctrl register 350 | unsigned int get() { return (osrs_t << 5) | (osrs_p << 2) | mode; } 351 | }; 352 | ctrl_meas _measReg; //!< measurement register object 353 | 354 | /**************************************************************************/ 355 | /*! 356 | @brief ctrl_hum register 357 | */ 358 | /**************************************************************************/ 359 | struct ctrl_hum { 360 | /// unused - don't set 361 | unsigned int none : 5; 362 | 363 | // pressure oversampling 364 | // 000 = skipped 365 | // 001 = x1 366 | // 010 = x2 367 | // 011 = x4 368 | // 100 = x8 369 | // 101 and above = x16 370 | unsigned int osrs_h : 3; ///< pressure oversampling 371 | 372 | /// @return combined ctrl hum register 373 | unsigned int get() { return (osrs_h); } 374 | }; 375 | ctrl_hum _humReg; //!< hum register object 376 | }; 377 | 378 | #endif 379 | -------------------------------------------------------------------------------- /lib/Adafruit_BME280_Library/Adafruit_BME280.cpp: -------------------------------------------------------------------------------- 1 | /*! 2 | * @file Adafruit_BME280.cpp 3 | * 4 | * @mainpage Adafruit BME280 humidity, temperature & pressure sensor 5 | * 6 | * @section intro_sec Introduction 7 | * 8 | * Driver for the BME280 humidity, temperature & pressure sensor 9 | * 10 | * These sensors use I2C or SPI to communicate, 2 or 4 pins are required 11 | * to interface. 12 | * 13 | * Designed specifically to work with the Adafruit BME280 Breakout 14 | * ----> http://www.adafruit.com/products/2652 15 | * 16 | * Adafruit invests time and resources providing this open source code, 17 | * please support Adafruit and open-source hardware by purchasing 18 | * products from Adafruit! 19 | * 20 | * @section author Author 21 | * 22 | * Written by Kevin "KTOWN" Townsend for Adafruit Industries. 23 | * 24 | * @section license License 25 | * 26 | * BSD license, all text here must be included in any redistribution. 27 | * See the LICENSE file for details. 28 | * 29 | */ 30 | 31 | #include "Adafruit_BME280.h" 32 | #include "Arduino.h" 33 | #include 34 | #include 35 | 36 | /*! 37 | * @brief class constructor 38 | */ 39 | Adafruit_BME280::Adafruit_BME280() : _cs(-1), _mosi(-1), _miso(-1), _sck(-1) {} 40 | 41 | /*! 42 | * @brief class constructor if using hardware SPI 43 | * @param cspin the chip select pin to use 44 | * @param *theSPI 45 | * optional SPI object 46 | */ 47 | Adafruit_BME280::Adafruit_BME280(int8_t cspin, SPIClass *theSPI) { 48 | _cs = cspin; 49 | _mosi = _miso = _sck = -1; 50 | _spi = theSPI; 51 | } 52 | 53 | /*! 54 | * @brief class constructor if using software SPI 55 | * @param cspin the chip select pin to use 56 | * @param mosipin the MOSI pin to use 57 | * @param misopin the MISO pin to use 58 | * @param sckpin the SCK pin to use 59 | */ 60 | Adafruit_BME280::Adafruit_BME280(int8_t cspin, int8_t mosipin, int8_t misopin, 61 | int8_t sckpin) 62 | : _cs(cspin), _mosi(mosipin), _miso(misopin), _sck(sckpin) {} 63 | 64 | Adafruit_BME280::~Adafruit_BME280(void) { 65 | if (temp_sensor) { 66 | delete temp_sensor; 67 | } 68 | if (pressure_sensor) { 69 | delete pressure_sensor; 70 | } 71 | if (humidity_sensor) { 72 | delete humidity_sensor; 73 | } 74 | } 75 | 76 | /*! 77 | * @brief Initialise sensor with given parameters / settings 78 | * @param addr the I2C address the device can be found on 79 | * @param theWire the I2C object to use, defaults to &Wire 80 | * @returns true on success, false otherwise 81 | */ 82 | bool Adafruit_BME280::begin(uint8_t addr, TwoWire *theWire) { 83 | bool status = false; 84 | _i2caddr = addr; 85 | _wire = theWire; 86 | status = init(); 87 | 88 | return status; 89 | } 90 | 91 | /*! 92 | * @brief Initialise sensor with given parameters / settings 93 | * @returns true on success, false otherwise 94 | */ 95 | bool Adafruit_BME280::init() { 96 | // init I2C or SPI sensor interface 97 | if (_cs == -1) { 98 | // I2C 99 | _wire->begin(); 100 | } else { 101 | digitalWrite(_cs, HIGH); 102 | pinMode(_cs, OUTPUT); 103 | if (_sck == -1) { 104 | // hardware SPI 105 | _spi->begin(); 106 | } else { 107 | // software SPI 108 | pinMode(_sck, OUTPUT); 109 | pinMode(_mosi, OUTPUT); 110 | pinMode(_miso, INPUT); 111 | } 112 | } 113 | 114 | // check if sensor, i.e. the chip ID is correct 115 | _sensorID = read8(BME280_REGISTER_CHIPID); 116 | if (_sensorID != 0x60) 117 | return false; 118 | 119 | // reset the device using soft-reset 120 | // this makes sure the IIR is off, etc. 121 | write8(BME280_REGISTER_SOFTRESET, 0xB6); 122 | 123 | // wait for chip to wake up. 124 | delay(10); 125 | 126 | // if chip is still reading calibration, delay 127 | while (isReadingCalibration()) 128 | delay(10); 129 | 130 | readCoefficients(); // read trimming parameters, see DS 4.2.2 131 | 132 | setSampling(); // use defaults 133 | 134 | delay(100); 135 | 136 | return true; 137 | } 138 | 139 | /*! 140 | * @brief setup sensor with given parameters / settings 141 | * 142 | * This is simply a overload to the normal begin()-function, so SPI users 143 | * don't get confused about the library requiring an address. 144 | * @param mode the power mode to use for the sensor 145 | * @param tempSampling the temp samping rate to use 146 | * @param pressSampling the pressure sampling rate to use 147 | * @param humSampling the humidity sampling rate to use 148 | * @param filter the filter mode to use 149 | * @param duration the standby duration to use 150 | */ 151 | void Adafruit_BME280::setSampling(sensor_mode mode, 152 | sensor_sampling tempSampling, 153 | sensor_sampling pressSampling, 154 | sensor_sampling humSampling, 155 | sensor_filter filter, 156 | standby_duration duration) { 157 | _measReg.mode = mode; 158 | _measReg.osrs_t = tempSampling; 159 | _measReg.osrs_p = pressSampling; 160 | 161 | _humReg.osrs_h = humSampling; 162 | _configReg.filter = filter; 163 | _configReg.t_sb = duration; 164 | 165 | // making sure sensor is in sleep mode before setting configuration 166 | // as it otherwise may be ignored 167 | write8(BME280_REGISTER_CONTROL, MODE_SLEEP); 168 | 169 | // you must make sure to also set REGISTER_CONTROL after setting the 170 | // CONTROLHUMID register, otherwise the values won't be applied (see 171 | // DS 5.4.3) 172 | write8(BME280_REGISTER_CONTROLHUMID, _humReg.get()); 173 | write8(BME280_REGISTER_CONFIG, _configReg.get()); 174 | write8(BME280_REGISTER_CONTROL, _measReg.get()); 175 | } 176 | 177 | /*! 178 | * @brief Encapsulate hardware and software SPI transfer into one 179 | * function 180 | * @param x the data byte to transfer 181 | * @returns the data byte read from the device 182 | */ 183 | uint8_t Adafruit_BME280::spixfer(uint8_t x) { 184 | // hardware SPI 185 | if (_sck == -1) 186 | return _spi->transfer(x); 187 | 188 | // software SPI 189 | uint8_t reply = 0; 190 | for (int i = 7; i >= 0; i--) { 191 | reply <<= 1; 192 | digitalWrite(_sck, LOW); 193 | digitalWrite(_mosi, x & (1 << i)); 194 | digitalWrite(_sck, HIGH); 195 | if (digitalRead(_miso)) 196 | reply |= 1; 197 | } 198 | return reply; 199 | } 200 | 201 | /*! 202 | * @brief Writes an 8 bit value over I2C or SPI 203 | * @param reg the register address to write to 204 | * @param value the value to write to the register 205 | */ 206 | void Adafruit_BME280::write8(byte reg, byte value) { 207 | if (_cs == -1) { 208 | _wire->beginTransmission((uint8_t)_i2caddr); 209 | _wire->write((uint8_t)reg); 210 | _wire->write((uint8_t)value); 211 | _wire->endTransmission(); 212 | } else { 213 | if (_sck == -1) 214 | _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); 215 | digitalWrite(_cs, LOW); 216 | spixfer(reg & ~0x80); // write, bit 7 low 217 | spixfer(value); 218 | digitalWrite(_cs, HIGH); 219 | if (_sck == -1) 220 | _spi->endTransaction(); // release the SPI bus 221 | } 222 | } 223 | 224 | /*! 225 | * @brief Reads an 8 bit value over I2C or SPI 226 | * @param reg the register address to read from 227 | * @returns the data byte read from the device 228 | */ 229 | uint8_t Adafruit_BME280::read8(byte reg) { 230 | uint8_t value; 231 | 232 | if (_cs == -1) { 233 | _wire->beginTransmission((uint8_t)_i2caddr); 234 | _wire->write((uint8_t)reg); 235 | _wire->endTransmission(); 236 | _wire->requestFrom((uint8_t)_i2caddr, (byte)1); 237 | value = _wire->read(); 238 | } else { 239 | if (_sck == -1) 240 | _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); 241 | digitalWrite(_cs, LOW); 242 | spixfer(reg | 0x80); // read, bit 7 high 243 | value = spixfer(0); 244 | digitalWrite(_cs, HIGH); 245 | if (_sck == -1) 246 | _spi->endTransaction(); // release the SPI bus 247 | } 248 | return value; 249 | } 250 | 251 | /*! 252 | * @brief Reads a 16 bit value over I2C or SPI 253 | * @param reg the register address to read from 254 | * @returns the 16 bit data value read from the device 255 | */ 256 | uint16_t Adafruit_BME280::read16(byte reg) { 257 | uint16_t value; 258 | 259 | if (_cs == -1) { 260 | _wire->beginTransmission((uint8_t)_i2caddr); 261 | _wire->write((uint8_t)reg); 262 | _wire->endTransmission(); 263 | _wire->requestFrom((uint8_t)_i2caddr, (byte)2); 264 | value = (_wire->read() << 8) | _wire->read(); 265 | } else { 266 | if (_sck == -1) 267 | _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); 268 | digitalWrite(_cs, LOW); 269 | spixfer(reg | 0x80); // read, bit 7 high 270 | value = (spixfer(0) << 8) | spixfer(0); 271 | digitalWrite(_cs, HIGH); 272 | if (_sck == -1) 273 | _spi->endTransaction(); // release the SPI bus 274 | } 275 | 276 | return value; 277 | } 278 | 279 | /*! 280 | * @brief Reads a signed 16 bit little endian value over I2C or SPI 281 | * @param reg the register address to read from 282 | * @returns the 16 bit data value read from the device 283 | */ 284 | uint16_t Adafruit_BME280::read16_LE(byte reg) { 285 | uint16_t temp = read16(reg); 286 | return (temp >> 8) | (temp << 8); 287 | } 288 | 289 | /*! 290 | * @brief Reads a signed 16 bit value over I2C or SPI 291 | * @param reg the register address to read from 292 | * @returns the 16 bit data value read from the device 293 | */ 294 | int16_t Adafruit_BME280::readS16(byte reg) { return (int16_t)read16(reg); } 295 | 296 | /*! 297 | * @brief Reads a signed little endian 16 bit value over I2C or SPI 298 | * @param reg the register address to read from 299 | * @returns the 16 bit data value read from the device 300 | */ 301 | int16_t Adafruit_BME280::readS16_LE(byte reg) { 302 | return (int16_t)read16_LE(reg); 303 | } 304 | 305 | /*! 306 | * @brief Reads a 24 bit value over I2C 307 | * @param reg the register address to read from 308 | * @returns the 24 bit data value read from the device 309 | */ 310 | uint32_t Adafruit_BME280::read24(byte reg) { 311 | uint32_t value; 312 | 313 | if (_cs == -1) { 314 | _wire->beginTransmission((uint8_t)_i2caddr); 315 | _wire->write((uint8_t)reg); 316 | _wire->endTransmission(); 317 | _wire->requestFrom((uint8_t)_i2caddr, (byte)3); 318 | 319 | value = _wire->read(); 320 | value <<= 8; 321 | value |= _wire->read(); 322 | value <<= 8; 323 | value |= _wire->read(); 324 | } else { 325 | if (_sck == -1) 326 | _spi->beginTransaction(SPISettings(500000, MSBFIRST, SPI_MODE0)); 327 | digitalWrite(_cs, LOW); 328 | spixfer(reg | 0x80); // read, bit 7 high 329 | 330 | value = spixfer(0); 331 | value <<= 8; 332 | value |= spixfer(0); 333 | value <<= 8; 334 | value |= spixfer(0); 335 | 336 | digitalWrite(_cs, HIGH); 337 | if (_sck == -1) 338 | _spi->endTransaction(); // release the SPI bus 339 | } 340 | 341 | return value; 342 | } 343 | 344 | /*! 345 | * @brief Take a new measurement (only possible in forced mode) 346 | */ 347 | void Adafruit_BME280::takeForcedMeasurement() { 348 | // If we are in forced mode, the BME sensor goes back to sleep after each 349 | // measurement and we need to set it to forced mode once at this point, so 350 | // it will take the next measurement and then return to sleep again. 351 | // In normal mode simply does new measurements periodically. 352 | if (_measReg.mode == MODE_FORCED) { 353 | // set to forced mode, i.e. "take next measurement" 354 | write8(BME280_REGISTER_CONTROL, _measReg.get()); 355 | // wait until measurement has been completed, otherwise we would read 356 | // the values from the last measurement 357 | while (read8(BME280_REGISTER_STATUS) & 0x08) 358 | delay(1); 359 | } 360 | } 361 | 362 | /*! 363 | * @brief Reads the factory-set coefficients 364 | */ 365 | void Adafruit_BME280::readCoefficients(void) { 366 | _bme280_calib.dig_T1 = read16_LE(BME280_REGISTER_DIG_T1); 367 | _bme280_calib.dig_T2 = readS16_LE(BME280_REGISTER_DIG_T2); 368 | _bme280_calib.dig_T3 = readS16_LE(BME280_REGISTER_DIG_T3); 369 | 370 | _bme280_calib.dig_P1 = read16_LE(BME280_REGISTER_DIG_P1); 371 | _bme280_calib.dig_P2 = readS16_LE(BME280_REGISTER_DIG_P2); 372 | _bme280_calib.dig_P3 = readS16_LE(BME280_REGISTER_DIG_P3); 373 | _bme280_calib.dig_P4 = readS16_LE(BME280_REGISTER_DIG_P4); 374 | _bme280_calib.dig_P5 = readS16_LE(BME280_REGISTER_DIG_P5); 375 | _bme280_calib.dig_P6 = readS16_LE(BME280_REGISTER_DIG_P6); 376 | _bme280_calib.dig_P7 = readS16_LE(BME280_REGISTER_DIG_P7); 377 | _bme280_calib.dig_P8 = readS16_LE(BME280_REGISTER_DIG_P8); 378 | _bme280_calib.dig_P9 = readS16_LE(BME280_REGISTER_DIG_P9); 379 | 380 | _bme280_calib.dig_H1 = read8(BME280_REGISTER_DIG_H1); 381 | _bme280_calib.dig_H2 = readS16_LE(BME280_REGISTER_DIG_H2); 382 | _bme280_calib.dig_H3 = read8(BME280_REGISTER_DIG_H3); 383 | _bme280_calib.dig_H4 = ((int8_t)read8(BME280_REGISTER_DIG_H4) << 4) | 384 | (read8(BME280_REGISTER_DIG_H4 + 1) & 0xF); 385 | _bme280_calib.dig_H5 = ((int8_t)read8(BME280_REGISTER_DIG_H5 + 1) << 4) | 386 | (read8(BME280_REGISTER_DIG_H5) >> 4); 387 | _bme280_calib.dig_H6 = (int8_t)read8(BME280_REGISTER_DIG_H6); 388 | } 389 | 390 | /*! 391 | * @brief return true if chip is busy reading cal data 392 | * @returns true if reading calibration, false otherwise 393 | */ 394 | bool Adafruit_BME280::isReadingCalibration(void) { 395 | uint8_t const rStatus = read8(BME280_REGISTER_STATUS); 396 | 397 | return (rStatus & (1 << 0)) != 0; 398 | } 399 | 400 | /*! 401 | * @brief Returns the temperature from the sensor 402 | * @returns the temperature read from the device 403 | */ 404 | float Adafruit_BME280::readTemperature(void) { 405 | int32_t var1, var2; 406 | 407 | int32_t adc_T = read24(BME280_REGISTER_TEMPDATA); 408 | if (adc_T == 0x800000) // value in case temp measurement was disabled 409 | return NAN; 410 | adc_T >>= 4; 411 | 412 | var1 = ((((adc_T >> 3) - ((int32_t)_bme280_calib.dig_T1 << 1))) * 413 | ((int32_t)_bme280_calib.dig_T2)) >> 414 | 11; 415 | 416 | var2 = (((((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1)) * 417 | ((adc_T >> 4) - ((int32_t)_bme280_calib.dig_T1))) >> 418 | 12) * 419 | ((int32_t)_bme280_calib.dig_T3)) >> 420 | 14; 421 | 422 | t_fine = var1 + var2 + t_fine_adjust; 423 | 424 | float T = (t_fine * 5 + 128) >> 8; 425 | return T / 100; 426 | } 427 | 428 | /*! 429 | * @brief Returns the pressure from the sensor 430 | * @returns the pressure value (in Pascal) read from the device 431 | */ 432 | float Adafruit_BME280::readPressure(void) { 433 | int64_t var1, var2, p; 434 | 435 | readTemperature(); // must be done first to get t_fine 436 | 437 | int32_t adc_P = read24(BME280_REGISTER_PRESSUREDATA); 438 | if (adc_P == 0x800000) // value in case pressure measurement was disabled 439 | return NAN; 440 | adc_P >>= 4; 441 | 442 | var1 = ((int64_t)t_fine) - 128000; 443 | var2 = var1 * var1 * (int64_t)_bme280_calib.dig_P6; 444 | var2 = var2 + ((var1 * (int64_t)_bme280_calib.dig_P5) << 17); 445 | var2 = var2 + (((int64_t)_bme280_calib.dig_P4) << 35); 446 | var1 = ((var1 * var1 * (int64_t)_bme280_calib.dig_P3) >> 8) + 447 | ((var1 * (int64_t)_bme280_calib.dig_P2) << 12); 448 | var1 = 449 | (((((int64_t)1) << 47) + var1)) * ((int64_t)_bme280_calib.dig_P1) >> 33; 450 | 451 | if (var1 == 0) { 452 | return 0; // avoid exception caused by division by zero 453 | } 454 | p = 1048576 - adc_P; 455 | p = (((p << 31) - var2) * 3125) / var1; 456 | var1 = (((int64_t)_bme280_calib.dig_P9) * (p >> 13) * (p >> 13)) >> 25; 457 | var2 = (((int64_t)_bme280_calib.dig_P8) * p) >> 19; 458 | 459 | p = ((p + var1 + var2) >> 8) + (((int64_t)_bme280_calib.dig_P7) << 4); 460 | return (float)p / 256; 461 | } 462 | 463 | /*! 464 | * @brief Returns the humidity from the sensor 465 | * @returns the humidity value read from the device 466 | */ 467 | float Adafruit_BME280::readHumidity(void) { 468 | readTemperature(); // must be done first to get t_fine 469 | 470 | int32_t adc_H = read16(BME280_REGISTER_HUMIDDATA); 471 | if (adc_H == 0x8000) // value in case humidity measurement was disabled 472 | return NAN; 473 | 474 | int32_t v_x1_u32r; 475 | 476 | v_x1_u32r = (t_fine - ((int32_t)76800)); 477 | 478 | v_x1_u32r = (((((adc_H << 14) - (((int32_t)_bme280_calib.dig_H4) << 20) - 479 | (((int32_t)_bme280_calib.dig_H5) * v_x1_u32r)) + 480 | ((int32_t)16384)) >> 481 | 15) * 482 | (((((((v_x1_u32r * ((int32_t)_bme280_calib.dig_H6)) >> 10) * 483 | (((v_x1_u32r * ((int32_t)_bme280_calib.dig_H3)) >> 11) + 484 | ((int32_t)32768))) >> 485 | 10) + 486 | ((int32_t)2097152)) * 487 | ((int32_t)_bme280_calib.dig_H2) + 488 | 8192) >> 489 | 14)); 490 | 491 | v_x1_u32r = (v_x1_u32r - (((((v_x1_u32r >> 15) * (v_x1_u32r >> 15)) >> 7) * 492 | ((int32_t)_bme280_calib.dig_H1)) >> 493 | 4)); 494 | 495 | v_x1_u32r = (v_x1_u32r < 0) ? 0 : v_x1_u32r; 496 | v_x1_u32r = (v_x1_u32r > 419430400) ? 419430400 : v_x1_u32r; 497 | float h = (v_x1_u32r >> 12); 498 | return h / 1024.0; 499 | } 500 | 501 | /*! 502 | * Calculates the altitude (in meters) from the specified atmospheric 503 | * pressure (in hPa), and sea-level pressure (in hPa). 504 | * @param seaLevel Sea-level pressure in hPa 505 | * @returns the altitude value read from the device 506 | */ 507 | float Adafruit_BME280::readAltitude(float seaLevel) { 508 | // Equation taken from BMP180 datasheet (page 16): 509 | // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf 510 | 511 | // Note that using the equation from wikipedia can give bad results 512 | // at high altitude. See this thread for more information: 513 | // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 514 | 515 | float atmospheric = readPressure() / 100.0F; 516 | return 44330.0 * (1.0 - pow(atmospheric / seaLevel, 0.1903)); 517 | } 518 | 519 | /*! 520 | * Calculates the pressure at sea level (in hPa) from the specified 521 | * altitude (in meters), and atmospheric pressure (in hPa). 522 | * @param altitude Altitude in meters 523 | * @param atmospheric Atmospheric pressure in hPa 524 | * @returns the pressure at sea level (in hPa) from the specified altitude 525 | */ 526 | float Adafruit_BME280::seaLevelForAltitude(float altitude, float atmospheric) { 527 | // Equation taken from BMP180 datasheet (page 17): 528 | // http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf 529 | 530 | // Note that using the equation from wikipedia can give bad results 531 | // at high altitude. See this thread for more information: 532 | // http://forums.adafruit.com/viewtopic.php?f=22&t=58064 533 | 534 | return atmospheric / pow(1.0 - (altitude / 44330.0), 5.255); 535 | } 536 | 537 | /*! 538 | * Returns Sensor ID found by init() for diagnostics 539 | * @returns Sensor ID 0x60 for BME280, 0x56, 0x57, 0x58 BMP280 540 | */ 541 | uint32_t Adafruit_BME280::sensorID(void) { return _sensorID; } 542 | 543 | /*! 544 | * Returns the current temperature compensation value in degrees Celcius 545 | * @returns the current temperature compensation value in degrees Celcius 546 | */ 547 | float Adafruit_BME280::getTemperatureCompensation(void) { 548 | return float(((t_fine_adjust * 5) >> 8) / 100); 549 | }; 550 | 551 | /*! 552 | * Sets a value to be added to each temperature reading. This adjusted 553 | * temperature is used in pressure and humidity readings. 554 | * @param adjustment Value to be added to each tempature reading in Celcius 555 | */ 556 | void Adafruit_BME280::setTemperatureCompensation(float adjustment) { 557 | // convert the value in C into and adjustment to t_fine 558 | t_fine_adjust = ((int32_t(adjustment * 100) << 8)) / 5; 559 | }; 560 | 561 | /*! 562 | @brief Gets an Adafruit Unified Sensor object for the temp sensor component 563 | @return Adafruit_Sensor pointer to temperature sensor 564 | */ 565 | Adafruit_Sensor *Adafruit_BME280::getTemperatureSensor(void) { 566 | if (!temp_sensor) { 567 | temp_sensor = new Adafruit_BME280_Temp(this); 568 | } 569 | 570 | return temp_sensor; 571 | } 572 | 573 | /*! 574 | @brief Gets an Adafruit Unified Sensor object for the pressure sensor 575 | component 576 | @return Adafruit_Sensor pointer to pressure sensor 577 | */ 578 | Adafruit_Sensor *Adafruit_BME280::getPressureSensor(void) { 579 | if (!pressure_sensor) { 580 | pressure_sensor = new Adafruit_BME280_Pressure(this); 581 | } 582 | return pressure_sensor; 583 | } 584 | 585 | /*! 586 | @brief Gets an Adafruit Unified Sensor object for the humidity sensor 587 | component 588 | @return Adafruit_Sensor pointer to humidity sensor 589 | */ 590 | Adafruit_Sensor *Adafruit_BME280::getHumiditySensor(void) { 591 | if (!humidity_sensor) { 592 | humidity_sensor = new Adafruit_BME280_Humidity(this); 593 | } 594 | return humidity_sensor; 595 | } 596 | 597 | /**************************************************************************/ 598 | /*! 599 | @brief Gets the sensor_t1 data for the BME280's temperature sensor 600 | */ 601 | /**************************************************************************/ 602 | void Adafruit_BME280_Temp::getSensor(sensor_t1 *sensor) { 603 | /* Clear the sensor_t1 object */ 604 | memset(sensor, 0, sizeof(sensor_t1)); 605 | 606 | /* Insert the sensor name in the fixed length char array */ 607 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 608 | sensor->name[sizeof(sensor->name) - 1] = 0; 609 | sensor->version = 1; 610 | sensor->sensor_id = _sensorID; 611 | sensor->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; 612 | sensor->min_delay = 0; 613 | sensor->min_value = -40.0; /* Temperature range -40 ~ +85 C */ 614 | sensor->max_value = +85.0; 615 | sensor->resolution = 0.01; /* 0.01 C */ 616 | } 617 | 618 | /**************************************************************************/ 619 | /*! 620 | @brief Gets the temperature as a standard sensor event 621 | @param event Sensor event object that will be populated 622 | @returns True 623 | */ 624 | /**************************************************************************/ 625 | bool Adafruit_BME280_Temp::getEvent(sensors_event_t *event) { 626 | /* Clear the event */ 627 | memset(event, 0, sizeof(sensors_event_t)); 628 | 629 | event->version = sizeof(sensors_event_t); 630 | event->sensor_id = _sensorID; 631 | event->type = SENSOR_TYPE_AMBIENT_TEMPERATURE; 632 | event->timestamp = millis(); 633 | event->temperature = _theBME280->readTemperature(); 634 | return true; 635 | } 636 | 637 | /**************************************************************************/ 638 | /*! 639 | @brief Gets the sensor_t1 data for the BME280's pressure sensor 640 | */ 641 | /**************************************************************************/ 642 | void Adafruit_BME280_Pressure::getSensor(sensor_t1 *sensor) { 643 | /* Clear the sensor_t1 object */ 644 | memset(sensor, 0, sizeof(sensor_t1)); 645 | 646 | /* Insert the sensor name in the fixed length char array */ 647 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 648 | sensor->name[sizeof(sensor->name) - 1] = 0; 649 | sensor->version = 1; 650 | sensor->sensor_id = _sensorID; 651 | sensor->type = SENSOR_TYPE_PRESSURE; 652 | sensor->min_delay = 0; 653 | sensor->min_value = 300.0; /* 300 ~ 1100 hPa */ 654 | sensor->max_value = 1100.0; 655 | sensor->resolution = 0.012; /* 0.12 hPa relative */ 656 | } 657 | 658 | /**************************************************************************/ 659 | /*! 660 | @brief Gets the pressure as a standard sensor event 661 | @param event Sensor event object that will be populated 662 | @returns True 663 | */ 664 | /**************************************************************************/ 665 | bool Adafruit_BME280_Pressure::getEvent(sensors_event_t *event) { 666 | /* Clear the event */ 667 | memset(event, 0, sizeof(sensors_event_t)); 668 | 669 | event->version = sizeof(sensors_event_t); 670 | event->sensor_id = _sensorID; 671 | event->type = SENSOR_TYPE_PRESSURE; 672 | event->timestamp = millis(); 673 | event->pressure = _theBME280->readPressure() / 100; // convert Pa to hPa 674 | return true; 675 | } 676 | 677 | /**************************************************************************/ 678 | /*! 679 | @brief Gets the sensor_t1 data for the BME280's humidity sensor 680 | */ 681 | /**************************************************************************/ 682 | void Adafruit_BME280_Humidity::getSensor(sensor_t1 *sensor) { 683 | /* Clear the sensor_t1 object */ 684 | memset(sensor, 0, sizeof(sensor_t1)); 685 | 686 | /* Insert the sensor name in the fixed length char array */ 687 | strncpy(sensor->name, "BME280", sizeof(sensor->name) - 1); 688 | sensor->name[sizeof(sensor->name) - 1] = 0; 689 | sensor->version = 1; 690 | sensor->sensor_id = _sensorID; 691 | sensor->type = SENSOR_TYPE_RELATIVE_HUMIDITY; 692 | sensor->min_delay = 0; 693 | sensor->min_value = 0; 694 | sensor->max_value = 100; /* 0 - 100 % */ 695 | sensor->resolution = 3; /* 3% accuracy */ 696 | } 697 | 698 | /**************************************************************************/ 699 | /*! 700 | @brief Gets the humidity as a standard sensor event 701 | @param event Sensor event object that will be populated 702 | @returns True 703 | */ 704 | /**************************************************************************/ 705 | bool Adafruit_BME280_Humidity::getEvent(sensors_event_t *event) { 706 | /* Clear the event */ 707 | memset(event, 0, sizeof(sensors_event_t)); 708 | 709 | event->version = sizeof(sensors_event_t); 710 | event->sensor_id = _sensorID; 711 | event->type = SENSOR_TYPE_RELATIVE_HUMIDITY; 712 | event->timestamp = millis(); 713 | event->relative_humidity = _theBME280->readHumidity(); 714 | return true; 715 | } 716 | --------------------------------------------------------------------------------