diff --git a/LICENSE b/.github/LICENSE similarity index 99% rename from LICENSE rename to .github/LICENSE index 0bdb991..5e54bd3 100644 --- a/LICENSE +++ b/.github/LICENSE @@ -671,4 +671,4 @@ into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. But first, please read -. \ No newline at end of file +. diff --git a/.github/README.md b/.github/README.md index b7d4011..4cfc9eb 100644 --- a/.github/README.md +++ b/.github/README.md @@ -1,9 +1,10 @@ -# BME680 library
[![Build Status](https://travis-ci.org/SV-Zanshin/BME680.svg?branch=master)](https://travis-ci.org/SV-Zanshin/BME680) [![DOI](https://zenodo.org/badge/139349456.svg)](https://zenodo.org/badge/latestdoi/139349456) [![arduino-library-badge](https://www.ardu-badge.com/badge/BME680.svg?)](https://www.ardu-badge.com/BME680) -*Arduino* library for using the [Bosch BME680](https://www.bosch-sensortec.com/bst/products/all_products/bme680) sensor which senses temperature, humidity, pressure and air quality. The BME680 is a tiny package and no hobbyist is going to be breadboarding this sensor directly, so one will be part of a breakout board. Here are some breakout board examples: +# BME680 library Bosch BME680
[![License: GPL v3](https://zanduino.github.io/Badges/GPLv3-blue.svg)](https://www.gnu.org/licenses/gpl-3.0) [![Build Status](https://travis-ci.org/SV-Zanshin/BME680.svg?branch=master)](https://travis-ci.org/SV-Zanshin/BME680) [![arduino-library-badge](https://www.ardu-badge.com/badge/BME680.svg?)](https://www.ardu-badge.com/BME680) [![DOI](https://zenodo.org/badge/139349456.svg)](https://zenodo.org/badge/latestdoi/139349456) [![Doxygen](https://zanduino.github.io/Badges/Doxygen-Badge.svg)](https://sv-zanshin.github.io/BME680/html/index.html) [![Wiki](https://zanduino.github.io/Badges/Documentation-Badge.svg)](https://github.com/SV-Zanshin/BME680/wiki) + +*Arduino* library for using the [Bosch BME680](https://www.bosch-sensortec.com/bst/products/all_products/bme680) sensor which senses temperature, humidity and pressure. The BME680 is a tiny package and no hobbyist is going to be breadboarding this sensor directly, so one will be part of a breakout board. Here are some breakout board examples: | Supplier | Image | Instructions | Comments | | --------- | ----- |------------ | -------- | -| [Sparkfun](https://www.sparkfun.com/products/16466) | | [Guide](https://learn.sparkfun.com/tutorials/sparkfun-environmental-sensor-breakout---bme680-qwiic-hookup-guide) | The Sparkfun board has pinouts for both SPI and I2C, one interface along one edge and other on the opposing side. The board is designed as part of the SparkFun [Qwiic Connect System](https://www.sparkfun.com/qwiic) that uses standardized plugs to daisy-chain I2C breakout boards together quickly. This package is designed to work with 3V systems and has no on-board 5V level shifting. | +| [Sparkfun](https://www.sparkfun.com/products/16466) | | [Guide](https://learn.sparkfun.com/tutorials/sparkfun-environmental-sensor-breakout---bme680-qwiic-hookup-guide) | The Sparkfun board has pinouts for both SPI and I2C, one interface along one edge and other on the opposing side. The board is designed as part of the SparkFun [Qwiic Connect System](https://www.sparkfun.com/qwiic) that uses standardized plugs to daisy-chain I2C breakout boards together quickly. This package is designed to work with 3V systems and has no on-board 5V level shifting. | | [Bluedot](https://www.bluedot.space/sensor-boards/bme680/) | | [Guide](https://www.bluedot.space/sensor-boards/bme680/) | This was my initial BME680 breakout board, purchased locally in Germany where it is manufactured. It has on-board level shifting and is therefore able to run on both 3V and 5V systems. There are fewer pinouts on this board than on the Sparkfun one, several of the pins have different uses depending upon whether I2C or SPI is selected | | [Adafruit](https://www.adafruit.com/product/3660) | | [Guide](https://learn.adafruit.com/adafruit-bme680-humidity-temperature-barometic-pressure-voc-gas/) | This breakout board is the most compact of the three, with the pinouts having different uses depending upon which communications method (I2C or SPI) is used. As with the Bluedot breakout board above, the Adafruit breakout board has integrated level-shifting and can therefore be run on both 3V and 5V systems. | @@ -27,4 +28,4 @@ The pressure sensor works in temperatures between -40°C and +85°C although the ### Environment gas sensing The gas sensor works by heating a small surface internally and measuring the resistance of the gas layer. This indicates the amount of volatile components in the air and can be used as an indirect means of measuring of air quality. The actual computation of "indoor air quality" is more complex than measuring the resistance, as the relative humidity, temperature, and element heating all play a role in determining that value. These calculations not only require the use of floating-point math, but are quite complex and memory-intensive and are not included in the library. If IAQ measurements are required, then the best solution is to use Bosch's [BSEC](https://www.bosch-sensortec.com/software-tools/software/bsec/) software - but keep in mind that it won't run on most smaller Arduino platforms. -![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) +[![Zanshin Logo](https://zanduino.github.io/Images/zanshinkanjitiny.gif) ](https://www.sv-zanshin.com) diff --git a/.gitignore b/.gitignore index 8f27cc8..3356502 100644 --- a/.gitignore +++ b/.gitignore @@ -95,4 +95,3 @@ Release # Files and directories from Doxygen # ######################################################################## html - diff --git a/.travis.yml b/.travis.yml index abf4631..2510e27 100644 --- a/.travis.yml +++ b/.travis.yml @@ -35,7 +35,9 @@ env: - DOXYFILE: $TRAVIS_BUILD_DIR/Doxyfile before_install: - - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) +# - source <(curl -SLs https://raw.githubusercontent.com/adafruit/travis-ci-arduino/master/install.sh) + - source <(curl -SLs https://zanduino.github.io/Travis/install.sh) + install: diff --git a/Doxyfile b/Doxyfile index fe1f0e4..defaf81 100644 --- a/Doxyfile +++ b/Doxyfile @@ -3,6 +3,8 @@ ## ## ## Date Developer Comments ## ## ========== ============================= ======================================================= ## +## 2020-06-08 https://github.com/SV-Zanshin Updated version to 1.0.7 ## +## 2020-06-01 https://github.com/SV-Zanshin Added "PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS" ## ## 2020-05-23 https://github.com/SV-Zanshin Removed e-mail addresses from file and updated version ## ## 2020-05-21 https://github.com/SV-Zanshin Updated "PROJECT_NUMBER" value to 1.0.5 ## ## 2020-05-17 https://github.com/SV-Zanshin Updated "PROJECT_NUMBER" value to 1.0.4 ## @@ -11,7 +13,7 @@ ###################################################################################################### DOXYFILE_ENCODING = UTF-8 PROJECT_NAME = BME680 -PROJECT_NUMBER = "Version 1.06" +PROJECT_NUMBER = "Version 1.0.7" PROJECT_BRIEF = "Arduino Library for the Bosch BME680 Temperature, Humidity, Pressure and Gas sensor" PROJECT_LOGO = OUTPUT_DIRECTORY = @@ -116,7 +118,7 @@ FILE_PATTERNS = *.ino \ *.cpp \ *.h RECURSIVE = YES -EXCLUDE = +EXCLUDE = EXCLUDE_SYMLINKS = NO EXCLUDE_PATTERNS = EXCLUDE_SYMBOLS = @@ -244,7 +246,7 @@ EXPAND_ONLY_PREDEF = NO SEARCH_INCLUDES = YES INCLUDE_PATH = INCLUDE_FILE_PATTERNS = -PREDEFINED = +PREDEFINED = DOXYGEN_SHOULD_SKIP_THIS EXPAND_AS_DEFINED = SKIP_FUNCTION_MACROS = YES TAGFILES = diff --git a/Images/README.md b/Images/README.md index a643f8b..031dbcb 100644 --- a/Images/README.md +++ b/Images/README.md @@ -1,5 +1,5 @@ # BME680 Images
-This directory contains the images used in the library documentation and wiki pages. +This directory contains the images used in the library documentation and wiki pages. The [Fritzing](https://fritzing.org/home/) sources are also included in the directory | File Name | Image | diff --git a/examples/ESP32FeatherWiFiDemo/.due.test.skip b/examples/ESP32FeatherWiFiDemo/.due.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.esp8266.test.skip b/examples/ESP32FeatherWiFiDemo/.esp8266.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.leonardo.test.skip b/examples/ESP32FeatherWiFiDemo/.leonardo.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.m4.test.skip b/examples/ESP32FeatherWiFiDemo/.m4.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.mega2560.test.skip b/examples/ESP32FeatherWiFiDemo/.mega2560.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.uno.test.skip b/examples/ESP32FeatherWiFiDemo/.uno.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/.zero.test.skip b/examples/ESP32FeatherWiFiDemo/.zero.test.skip new file mode 100644 index 0000000..e69de29 diff --git a/examples/ESP32FeatherWiFiDemo/ESP32FeatherWiFiDemo.ino b/examples/ESP32FeatherWiFiDemo/ESP32FeatherWiFiDemo.ino new file mode 100644 index 0000000..05b04ad --- /dev/null +++ b/examples/ESP32FeatherWiFiDemo/ESP32FeatherWiFiDemo.ino @@ -0,0 +1,304 @@ +/*! @file ESP32FeatherWiFiDemo.ino + +@section ESP32FeatherWiFiDemo_intro_section Description + +Example program for using an Arduino ESP32 based system (this sketch was developed and tested on a ESP32 Huzzah32 +Feather board from https://www.adafruit.com/product/3405) along with a BME680 connected via I2C to monitor the +temperature, pressure and humidity and report the values in a dynamic chart on a web page hosted by the ESP32 +and connected to a local network. + +Prior to compiling the program, the contents of the include file "Authentication.h" need to be updated to reflect +the local WiFi network to use and the corresponding authentication code. + +Once started, the IP-Address is set by the WiFi router and displayed on the serial output of the ESP32, this IP +address should then be entered as the URL in a web browser of a computer attached to the same network and the +data should be presented there, updated every 10 seconds. + +The Bosch BME680 sensor measures temperature, pressure, humidity and air quality and is described at +https://www.bosch-sensortec.com/bst/products/all_products/BME680. The datasheet is available from Bosch at +https://ae-bst.resource.bosch.com/media/_tech/media/datasheets/BST-BME680_DS001-11.pdf \n\n + +The most recent version of the BME680 library is available at https://github.com/SV-Zanshin/BME680 and the +documentation of the library as well as example programs are described in the project's wiki pages located at +https://github.com/SV-Zanshin/BME680/wiki. \n\n + +The BME680 is an extremely small physical package that is so tiny as to be impossible to solder at home, hence it +will be used as part of a third-party breakout board. There are several such boards available at this time, for +example \n +Company | Link +------- | ---------- +Sparkfun | https://www.sparkfun.com/products/14570 +BlueDot | https://www.bluedot.space/sensor-boards/bme680/ +Adafruit | https://learn.adafruit.com/adafruit-BME680-humidity-barometric-pressure-temperature-sensor-breakout \n\n + +Bosch supplies sample software that runs on various platforms, including the Arduino family; this can be downloaed +at https://github.com/BoschSensortec/BSEC-Arduino-library . This software is part of the Bosch "BSEC" (Bosch +Sensortec Environmental Cluster) framework and somewhat bulky and unwieldy for typical Arduino applications, hence +the choice to make a more compact and rather less abstract library. + +The pressure reading needs to be adjusted for altitude to get the adjusted pressure reading. There are numerous +sources on the internet for formulae converting from standard sea-level pressure to altitude, see the data sheet +for the BME180 on page 16 of http://www.adafruit.com/datasheets/BST-BMP180-DS000-09.pdf. Rather than put a +floating-point function in the library which may not be used but which would use space, an example altitude +computation function has been added to this example program to show how it might be done. + +@section ESP32FeatherWiFiDemolicense License + +This program is free software: you can redistribute it and/or modify it under the terms of the GNU General +Public License as published by the Free Software Foundation, either version 3 of the License, or (at your +option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. You should have received a copy of the GNU General Public License +along with this program. If not, see . + +@section ESP32FeatherWiFiDemoauthor Author + +Written by https://github.com/SV-Zanshin + +@section ESP32FeatherWiFiDemoversions Changelog + +Version | Date | Developer | Comments +------- | ---------- | ----------------------------- | ------------------------------------------- +1.0.0 | 2020-06-02 | https://github.com/SV-Zanshin | Ready to commit and publish as Issue #20 +1.0.0b | 2020-05-30 | https://github.com/SV-Zanshin | Initial coding +*/ + +#if !defined(ESP32) + #error This example program is designed specifically for the ESP32 platform and might not work on other platforms +#endif + +/******************************************************************************************************************* +** Declare all include files required ** +*******************************************************************************************************************/ +#include ///< Include the SPI standard library +#include ///< Include the SD Card standard library +#include ///< ESP32 WiFi Library +#include ///< WiFi Client library +#include ///< WiFi Web Server library +#include "WebPageContents.h" ///< Include external HTML and JavaScript definitions +#include "Zanshin_BME680.h" ///< The BME680 sensor library + +/******************************************************************************************************************* +** Declare all program constants ** +*******************************************************************************************************************/ + + /************************************************************************* + ** Please change the "WIFI_SSID", "WIFI_PASSWORD", "SD_CARD_SPI_CS_PIN" ** + ** and "SD_CARD_SPI_CD_PIN" constants to match your installation ** + *************************************************************************/ + +const char* FILE_NAME = "/BME_680.csv"; ///< Filename on SD-Card +const char* HOSTNAME = "BME680"; ///< Give the device a name +const char* WIFI_SSID = "NetworkSSID"; ///< Network SSID for connection +const char* WIFI_PASSWORD = "Password"; ///< Network authentication code +const uint32_t SERIAL_SPEED = 115200; ///< Set the baud rate for Serial I/O +const uint8_t POWER_PIN = A13; ///< Supply voltage through a divider +const uint8_t LED_PIN = 13; ///< This pin is the on-board red LED +const uint8_t SD_CARD_SPI_CS_PIN = 21; ///< Use Pin 21 (general GPIO) on the ESP32 for chip select +const uint8_t SD_CARD_SPI_CD_PIN = A5; ///< Use Pin A5 (general GPIO) on the ESP32 for carrier detect +const uint32_t SD_LOG_INTERVAL = 1000; ///< Milliseconds between measurements to SD-Card +const uint8_t SD_FLUSH_INTERVAL = 60; ///< do a "flush" after this number of writes +const float SEA_LEVEL_PRESSURE = 1013.25; ///< Standard atmosphere sea level pressure +/******************************************************************************************************************* +** Declare all global variables ** +*******************************************************************************************************************/ +WebServer server(80); ///< Instantiate a web server on port 80 +BME680_Class BME680; ///< Create an instance of the BME680 class +File dataFile; ///< Class for a SD-Card file +int32_t temperature; ///< BME680 temperature value +int32_t humidity; ///< BME680 humidity value +int32_t pressure; ///< BME680 pressure value +int32_t gas; ///< BME680 gas resistance value +int32_t start_pressure; ///< Initial pressure reading +bool sd_card_present = false; ///< Switch set when SD-Card detected +String jsonData; ///< JSON data string +uint16_t loopCounter = 0; ///< Counter for number of write operations since startup + +/******************************************************************************************************************* +** Macro that returns the floating point voltage. The formula is the analog value of POWER_PIN. Since this goes ** +** through a voltage divider the value is multiplied by 2. The register is 12-bit (0-4095) so we divide by 4095 ** +** and then by the 3.3V reference voltage and, finally, by the ADC reference voltage of 1.1V. ** +*******************************************************************************************************************/ +#define VOLTAGE ( analogRead(POWER_PIN) * 2 / 4095.0 * 3.3 * 1.1) + +void setup() +{ + /*! + @brief Arduino method called once at startup to initialize the system + @details This is an Arduino IDE method which is called first upon boot or restart. It is only called one time + and then control goes to the main "loop()" method, from which control never returns. The BME680, then + the SD-Card (if present, if not present then it is ignored), then the Wi-Fi connection are initialized + and configured here. + @return void + */ + pinMode(SD_CARD_SPI_CS_PIN, OUTPUT); // Chip-Select pin for the SD Card as output + pinMode(SD_CARD_SPI_CD_PIN, INPUT_PULLUP); // Carrier detect pin for the SD Card as input + digitalWrite(SD_CARD_SPI_CS_PIN, HIGH); // Deselect device by writing HIGH to it + pinMode(LED_PIN, OUTPUT); // Make the on-board LED an output pin + Serial.begin(SERIAL_SPEED); // Start the Serial comms at specified speed + /********************** + ** Initialize BME680 ** + **********************/ + Serial.print("Starting ESP32FeatherWiFiDemo for BME680\n"); + Serial.print("- Initializing BME680 sensor\n"); + while (!BME680.begin(I2C_STANDARD_MODE)) // Start using I2C, use first device found + { + Serial.print("- Unable to find BME680. Trying again in 5 seconds.\n"); + delay(5000); + } // of loop until device is located + Serial.print("- Setting 16x oversampling for all sensors\n"); + Serial.print("- Setting IIR filter to a value of 4 samples\n"); + Serial.print("- Turning off gas measurements\n"); + BME680.setOversampling(TemperatureSensor, Oversample16); // Use enumerated type values to set value + BME680.setOversampling(HumiditySensor, Oversample16); // Use enumerated type values to set value + BME680.setOversampling(PressureSensor, Oversample16); // Use enumerated type values to set value + BME680.setIIRFilter(IIR4); // Use enumerated type values to set value + BME680.setGas(0, 0); // Setting either to 0 turns off gas + BME680.getSensorData(temperature, humidity, start_pressure, gas); // Get most recent readings + /*************************************************************** + ** Initialize SD-Card for logging, if not found then continue ** + ***************************************************************/ + Serial.print("- Checking to see if SD Card connected\n"); + if (!digitalRead(SD_CARD_SPI_CD_PIN)) + { + sd_card_present = false; // if pin is high then no card inserted + } + else + { + uint8_t loopCounter = 10; ///< countdown to 0 to detect car + while (--loopCounter && !SD.begin(SD_CARD_SPI_CS_PIN)) // Try to start card using SPI + { + Serial.print("- Unable to find SD Card. Trying again in 5 seconds.\n"); + for (uint8_t i = 0; i < 50; i++) + { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); + delay(100); + } // loop to toggle LED light 10 times + } // of loop until device is located + if (loopCounter) sd_card_present = true; + } // if-then card is inserted + if (!sd_card_present) + { + Serial.print("- No SD-Card detected, continuing\n"); + } + else + { + Serial.print("- SD-Card Initialized\n"); + dataFile = SD.open(FILE_NAME, FILE_WRITE); // Open the logfile for writing and position to end-of-file + if (!dataFile) + { + Serial.print("Unable to open file \""); + Serial.print(FILE_NAME); + Serial.print("\" on SD-Card. Error. Skipping SD writes."); + sd_card_present = false; // turn off card + } + else + { + Serial.print("- File \""); + Serial.print(FILE_NAME); + Serial.print("\" successfully opened. Appending data.\n"); + dataFile.print("Seconds,SupplyVoltage,Temperature,Humidity,Altitude\n"); + } // if-then-else the file could be opened + } // if-then-else SD-Card located + /********************************************** + ** Connect to the specified wireless network ** + **********************************************/ + Serial.print("- Connecting to Wireless network \""); + Serial.print(WIFI_SSID); + Serial.print("\"."); + WiFi.begin(WIFI_SSID, WIFI_PASSWORD); // Connect to the specified WiFi router + while (WiFi.status() != WL_CONNECTED) // Loop until the connection is established + { + delay(1000); // wait one second before trying again + Serial.print("."); + } // for-next connection not established + WiFi.setHostname(HOSTNAME); // Give our device a name + // Show connection data + Serial.print("\n- Open browser to IP address \""); + Serial.print(WiFi.localIP()); + Serial.print("\"\n- or to \"http://BME680\" to view data.\n"); + server.on("/", handleRoot); // Routine for root page call + server.on("/readADC", handleADC); // Page called by AJAX + server.begin(); // Start server + Serial.print("HTTP server started\n"); + digitalWrite(LED_PIN, false); // Turn the LED off +} // of method "setup()" +void handleRoot() +{ + /*! + @brief Called when a request is sent from a browser client + @details When the ESP32 gets an IP address and that address is entered in a browser then this ISR get called to + handle that request. The response is to send the HTML page which is contained in the variable "MAIN_page" + which is set in the "WebPageContents.h" include file + @return void + */ + String s = MAIN_page; // Read HTML contents into a string + server.send(200, "text/html", s); // Send the string as HTML to the requester +} // of method "handleRoot()" +void handleADC() +{ + /*! + @brief Called when a "readADC"" request is sent from a browser client + @details When the browser client sends a GET request for a "readADC" this ISR is called, which then returns + the current value in the jsonData string, which is continuously updated in the main loop + @return void + */ + if (!sd_card_present) // If no SD-Card is present then we need to get data, + { // if there is an SD-Card then the data has already been fetched + getSensorData(); // get the BME680 data + } // if-then SD-Card not present + server.send(200, "text/plain", jsonData); // Send JSON to client ajax request +} // of method "handleADC()" +void loop() +{ + /*! + @brief Arduino method for the main program loop + @details This is the main program for the Arduino IDE, it is an infinite loop and keeps on repeating. + The timed measurements from the BME680 are handled here, while the actual web page serving and + responses are handled by the 2 ISRs - "handleADC()" and "handleRoot()". + @return void + */ + static uint32_t next_log_millis; ///< Millis() value for next SD-Card measurement time + server.handleClient(); // Handle client requests + if (millis() > next_log_millis) // if time to get another measurement from the BME680 + { // + next_log_millis = millis() + SD_LOG_INTERVAL; // set next time to get a reading + getSensorData(); // get the BME680 data + } // if-then time to get a measurement +} // of method "loop()" +void getSensorData() +{ + /*! + @brief Function to read the BME680 data and optionally write it to the SD-Card + @details The BME680 data is read in and if an SD-Card is present the values are written to it. The "jsonData" + string is also put together here so that a client request can immediately send the current data. This + is done because the frequency with which the data is written to the SD-Card is higher than that of the + web page refresh. + @return void + */ + BME680.getSensorData(temperature, humidity, pressure, gas); // Get the most recent readings from the BME680 + float altitude = 44330.0 * (1.0 - pow(((float)pressure/100) / SEA_LEVEL_PRESSURE, 0.1903)); + if (sd_card_present) // Log data to the SD-Card, if present + { + dataFile.print(millis() / 1000); + dataFile.print(","); + dataFile.print(VOLTAGE); + dataFile.print(","); + dataFile.print(temperature / 100.0, 2); + dataFile.print(","); + dataFile.print(humidity / 1000.0, 2); + dataFile.print(","); + dataFile.print(altitude, 2); + dataFile.print("\n"); + if (++loopCounter % SD_FLUSH_INTERVAL == 0) // Flush every N-Iterations + { // + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle LED before flushing buffer + dataFile.flush(); // flush pending writes to SD + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); // Toggle LED after flushing is complete + Serial.print("Flushed data to SD-Card\n"); + } // flush the buffer + } // if-then SD card is present + jsonData = "{\"SupplyVoltage\":\"" + String(VOLTAGE) + "\", \"Temperature\":\"" + + String(temperature / 100.0) + "\", \"Humidity\":\"" + String(humidity / 1000.0) + + "\", \"Altitude\":\"" + String(altitude) + "\"}"; +} // of method "getSensorData()" diff --git a/examples/ESP32FeatherWiFiDemo/WebPageContents.h b/examples/ESP32FeatherWiFiDemo/WebPageContents.h new file mode 100644 index 0000000..aad4a4a --- /dev/null +++ b/examples/ESP32FeatherWiFiDemo/WebPageContents.h @@ -0,0 +1,167 @@ +/*! + This character string "MAIN_page" is loaded into program memory and contains the web page that is served when a + browser calls up the site. It uses the javascript from https://www.chartjs.org to generate a page with a dynamic + chart and lists the data in tabular form underneath as well. + + Since this is used for demonstration purposes it has been kept basic and simple. + + Version | Date | Developer | Comments + ------- | ---------- | ----------------------------- | ------------------------------------------- + 1.0.0 | 2020-06-02 | https://github.com/SV-Zanshin | Ready to commit and publish as Issue #20 + +*/ + +const char MAIN_page[] PROGMEM = R"=====( + + + + ESP32FeatherWiFiDemo - BME680 demonstration program + + + + +
Zanshin Logo Zanshin
+
+ +
+
+ + +
TimeSupply (V)Temperature (°C)Relative Humidity (%)Altitude (m)
+
+
+
+ + + + + + + + Untitled Document + +)====="; \ No newline at end of file diff --git a/examples/README.md b/examples/README.md index 410061e..e9dc018 100644 --- a/examples/README.md +++ b/examples/README.md @@ -9,5 +9,6 @@ Various example programs illustrating the use of the *Arduino* BME680 library ar | software SPI Demo | [SoftSPIDemo.ino](https://github.com/SV-Zanshin/BME680/wiki/SoftSPIDemo.ino) | Identical to the I2C Demo program, but using SPI connectivity emulated in software | | Two I2C BME680s | [TwoDevicesI2CDemo.ino](https://github.com/SV-Zanshin/BME680/wiki/TwoDevicesI2CDemo.ino) | Example to illustrate attaching 2 BME680 devices with different addresses using I2C | | SD-Card Logging | [SDLoggerSPIDemo.ino](https://github.com/SV-Zanshin/BME680/wiki/SDLoggerSPIDemo.ino) | Example sketch using SPI for the BME680 and a SD-Card to log data at variable rates - faster logging when the measurements change rapidly and less frequent measurements when there is little change. | +| ESP32 WiFi demo | [ESP32FeatherWiFiDemo.ino](https://github.com/SV-Zanshin/BME680/wiki/ESP32FeatherWiFiDemo.ino) | Example sketch using I2C for the BME680 (and an optional SD-Card on SPI to log data) to connect to WiFi and dynamically display measurement data on a web page. | ![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) diff --git a/examples/SDLoggerSPIDemo/SDLoggerSPIDemo.ino b/examples/SDLoggerSPIDemo/SDLoggerSPIDemo.ino index 679e4ab..4d85034 100644 --- a/examples/SDLoggerSPIDemo/SDLoggerSPIDemo.ino +++ b/examples/SDLoggerSPIDemo/SDLoggerSPIDemo.ino @@ -28,7 +28,7 @@ This example program was designed as a simple data logger which defaults to meas Once either the temperature, pressure or humidity changes at a rate above that set in the constants TEMPERATURE_TRIP, PRESSURE_TRIP or HUMIDITY_TRIP then the measurement rate is sped up to read every second and to read more accurately. This was intended as a data logger inside a refrigerator or freezer, where most of the time there are constant -values but when the door is opened or the anti-icing cycle kicks in then readings need to be done more often. +values but when the door is opened or the defrosting cycle kicks in then readings need to be done more often. This example program initializes the BME680 to use SPI for communications. The library does not using floating point numbers to save on memory space and computation time. The values for Temperature, Pressure and Humidity are @@ -58,19 +58,41 @@ Written by https://github.com/SV-Zanshin @section SDLoggerSPIDemoversions Changelog Version | Date | Developer | Comments -------- | ---------- | ----------------------------- | ------------------------------------------------- +------- | ---------- | ----------------------------- | ----------------------------------------------------- +1.0.1 | 2020-06-01 | https://github.com/SV-Zanshin | Added Doxygen commenting for redefine of serial class 1.0.0 | 2020-05-27 | https://github.com/SV-Zanshin | Completed and tested 1.0.0b | 2020-05-22 | https://github.com/SV-Zanshin | Cloned from original SPIDemo program and modified */ #include "Zanshin_BME680.h" // Include the BME680 Sensor library -#include // Include the SPI standard library (it is also included in the BME680 library) +#include // Include the SPI standard library (also included in the BME680 library) #include // Include the SD Card standard library +#define SERIAL_ATTACHED // When commented out then no output is done to the serial port + +#ifndef SERIAL_ATTACHED +#ifndef DOXYGEN_SHOULD_SKIP_THIS +// override Serial output +#define Serial DummySerial +static class +{ + /*! + @class Serial + @Brief Redefine a dummy Serial class when no serial port is attached + */ +public: + void begin(...) {} ///< Redefine a dummy begin + void print(...) {} ///< Redefine a dummy print + void println(...) {} ///< Redefine a dummy println +} Serial; +#endif // of skipped Doxygen code +#endif + /******************************************************************************************************************* ** Declare all program constants ** *******************************************************************************************************************/ const uint8_t BME_680_SPI_CS_PIN = SS; ///< Use the standard SS pin for the BME680 -const uint8_t SD_CARD_SPI_CS_PIN = 24; ///< Use Pin A6 for the SD Card +const uint8_t SD_CARD_SPI_CS_PIN = 24; ///< Use Pin A6/D4 for the SD Card +const uint8_t LED_PIN = LED_BUILTIN; ///< Built-in LED pin const uint32_t SERIAL_SPEED = 115200; ///< Set the baud rate for Serial I/O const uint8_t NUMBER_READINGS = 10; ///< Number of readings to average const uint32_t LONG_DELAY = 10000; ///< Long delay in milliseconds - 10 seconds @@ -145,19 +167,25 @@ void setup() and then control goes to the main "loop()" method, from which control never returns @return void */ - digitalWrite(SD_CARD_SPI_CS_PIN, HIGH); // Write a high value to it in order to deselect device - digitalWrite(BME_680_SPI_CS_PIN, HIGH); // Write a high value to it in order to deselect device pinMode(BME_680_SPI_CS_PIN, OUTPUT); // Declare the Chip-Select pin for the BME680 as output pinMode(SD_CARD_SPI_CS_PIN, OUTPUT); // Declare the Chip-Select pin for the SD Card as output + pinMode(LED_PIN, OUTPUT); // Declare the builtin LED to be an output + digitalWrite(SD_CARD_SPI_CS_PIN, HIGH); // Write a high value to it in order to deselect device + digitalWrite(BME_680_SPI_CS_PIN, HIGH); // Write a high value to it in order to deselect device + digitalWrite(LED_PIN, HIGH); // Turn on the LED Serial.begin(SERIAL_SPEED); // Start serial port at Baud rate - #ifdef __AVR_ATmega32U4__ // If this is a 32U4 processor, + #ifdef __AVR_ATmega32U4__ // If this is a 32U4 processor, delay(3000); // then wait 3 seconds to initialize USB port #endif Serial.print(F("Starting SDLoggerSPIDemo example program for BME680\n- Initializing BME680 sensor\n")); while (!BME680.begin(BME_680_SPI_CS_PIN)) // Start BME680 using hardware SPI protocol { Serial.print(F("- Unable to find BME680. Trying again in 5 seconds.\n")); - delay(5000); + for (uint8_t i = 0; i < 50; i++) + { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); + delay(100); + } // loop to toggle LED light 10 times } // of loop until device is located normalMode(); BME680.getSensorData(data[idx].temperature, data[idx].humidity, data[idx].pressure, unused_gas); @@ -167,7 +195,11 @@ void setup() while (!SD.begin(SD_CARD_SPI_CS_PIN)) // Start card using hardware SPI protocol { Serial.print(F("- Unable to find SD Card. Trying again in 5 seconds.\n")); - delay(5000); + for (uint8_t i = 0; i < 50; i++) + { + digitalWrite(LED_PIN, !digitalRead(LED_PIN)); + delay(100); + } // loop to toggle LED light 10 times } // of loop until device is located Serial.print(F("- SD-Card Initialized\n")); dataFile = SD.open(FILE_NAME, FILE_WRITE); // Open the logfile for writing and position to end-of-file @@ -188,6 +220,7 @@ void setup() data[i].humidity = data[0].humidity; data[i].pressure = data[0].pressure; } // of for-next each array element + digitalWrite(LED_PIN, LOW); // turn off LED } // of method setup() void loop() { @@ -200,7 +233,8 @@ void loop() */ if (loopCounter % 25 == 0) // Header every 25 loops { // - Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa Avg Tmp Avg Hum Avg hPa\n==== ====== ====== ========= ======= ====== =========\n")); // Show header plus unicode "°C" symbol + Serial.print(F("\nLoop Temp\xC2\xB0\x43 Humid% Press hPa Avg Tmp Avg Hum Avg hPa\n" // Show header plus the + "==== ====== ====== ========= ======= ====== =========\n")); // unicode "°C" symbol } // if-then time to show headers // idx = (idx+1) % NUMBER_READINGS; // increment and clamp BME680.getSensorData(data[idx].temperature, data[idx].humidity, // Read once at beginning @@ -270,6 +304,11 @@ void loop() (uint8_t)(data[idx].pressure % 100)); dataFile.print(buf); - if (idx == 0) dataFile.flush(); // force a SD write every cycle + if (idx == 0) + { + digitalWrite(LED_PIN, HIGH); // turn on LED + dataFile.flush(); // force a SD write every cycle + digitalWrite(LED_PIN, LOW); // turn off LED + } // if-then time to flush buffer to SD-Card delay(delayTime); // Wait appropriate amount of time } // of method loop() \ No newline at end of file diff --git a/library.properties b/library.properties index 706ce79..5ee849e 100644 --- a/library.properties +++ b/library.properties @@ -1,5 +1,5 @@ name=BME680 -version=1.0.6 +version=1.0.7 author=https://github.com/SV-Zanshin maintainer=https://github.com/SV-Zanshin sentence=Arduino library to access and control the Bosch BME680 sensor and get temperature, humidity, pressure and gas readings. diff --git a/src/README.md b/src/README.md index 262ba2f..8d81d52 100644 --- a/src/README.md +++ b/src/README.md @@ -1,5 +1,6 @@ # BME680 library Header and Source files
[![Build Status](https://travis-ci.org/SV-Zanshin/BME680.svg?branch=master)](https://travis-ci.org/SV-Zanshin/BME680) [![DOI](https://zenodo.org/badge/139349456.svg)](https://zenodo.org/badge/latestdoi/139349456) [![arduino-library-badge](https://www.ardu-badge.com/badge/BME680.svg?)](https://www.ardu-badge.com/BME680) -This directory contains the two files that comprise [Bosch BME680](https://www.bosch-sensortec.com/bst/products/all_products/bme680) BME680 *Arduino* library. -The "Zanshin_BME680.h" is the library header file, and the code is contained in the "Zanshin_BME680.cpp" file. +This directory contains the two files that define [Bosch BME680](https://www.bosch-sensortec.com/bst/products/all_products/bme680) BME680 *Arduino* library. + +The "Zanshin_BME680.h" is the library header file, and the program code is contained in the "Zanshin_BME680.cpp" file. ![Zanshin Logo](https://www.sv-zanshin.com/r/images/site/gif/zanshinkanjitiny.gif) diff --git a/src/Zanshin_BME680.h b/src/Zanshin_BME680.h index 9588ac8..b14b73d 100644 --- a/src/Zanshin_BME680.h +++ b/src/Zanshin_BME680.h @@ -14,7 +14,7 @@ SPI using either the standard Arduino hardware SPI or software SPI. Depending up have 2 distinct I2C addresses - either 0x76 or 0x77.\n\n The most recent version of the library is available at https://github.com/SV-Zanshin/BME680 and extensive -documentation of the library as well as descriptions of the example programs are described in the project's wiki +documentation of the library as well as descriptions of the various example programs are described in the project's wiki pages located at https://github.com/SV-Zanshin/BME680/wiki \n The BME680 is an extremely small physical package that is so tiny as to be impossible to solder at home, hence it @@ -337,4 +337,4 @@ Version | Date | Developer | Comments return(structSize); } // of method putData() }; // of BME680 class definition -#endif \ No newline at end of file +#endif