From aa00aab7b66f922e97ed3c5ca3f05d70cfcc024c Mon Sep 17 00:00:00 2001 From: Thomas Basler Date: Sun, 20 Oct 2019 00:03:22 +0200 Subject: [PATCH] Inital commit --- .gitignore | 5 + .travis.yml | 67 ++++++++++++ .vscode/extensions.json | 7 ++ .vscode/settings.json | 6 ++ include/README | 39 +++++++ lib/README | 46 ++++++++ platformio.ini | 27 +++++ src/main.cpp | 233 ++++++++++++++++++++++++++++++++++++++++ test/README | 11 ++ 9 files changed, 441 insertions(+) create mode 100644 .gitignore create mode 100644 .travis.yml create mode 100644 .vscode/extensions.json create mode 100644 .vscode/settings.json create mode 100644 include/README create mode 100644 lib/README create mode 100644 platformio.ini create mode 100644 src/main.cpp create mode 100644 test/README diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89cc49c --- /dev/null +++ b/.gitignore @@ -0,0 +1,5 @@ +.pio +.vscode/.browse.c_cpp.db* +.vscode/c_cpp_properties.json +.vscode/launch.json +.vscode/ipch diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..a8bbc57 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,67 @@ +# Continuous Integration (CI) is the practice, in software +# engineering, of merging all developer working copies with a shared mainline +# several times a day < https://docs.platformio.org/page/ci/index.html > +# +# Documentation: +# +# * Travis CI Embedded Builds with PlatformIO +# < https://docs.travis-ci.com/user/integration/platformio/ > +# +# * PlatformIO integration with Travis CI +# < https://docs.platformio.org/page/ci/travis.html > +# +# * User Guide for `platformio ci` command +# < https://docs.platformio.org/page/userguide/cmd_ci.html > +# +# +# Please choose one of the following templates (proposed below) and uncomment +# it (remove "# " before each line) or use own configuration according to the +# Travis CI documentation (see above). +# + + +# +# Template #1: General project. Test it using existing `platformio.ini`. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio run + + +# +# Template #2: The project is intended to be used as a library with examples. +# + +# language: python +# python: +# - "2.7" +# +# sudo: false +# cache: +# directories: +# - "~/.platformio" +# +# env: +# - PLATFORMIO_CI_SRC=path/to/test/file.c +# - PLATFORMIO_CI_SRC=examples/file.ino +# - PLATFORMIO_CI_SRC=path/to/test/directory +# +# install: +# - pip install -U platformio +# - platformio update +# +# script: +# - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N diff --git a/.vscode/extensions.json b/.vscode/extensions.json new file mode 100644 index 0000000..272828b --- /dev/null +++ b/.vscode/extensions.json @@ -0,0 +1,7 @@ +{ + // See http://go.microsoft.com/fwlink/?LinkId=827846 + // for the documentation about the extensions.json format + "recommendations": [ + "platformio.platformio-ide" + ] +} \ No newline at end of file diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..cc1b938 --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "terminal.integrated.env.windows": { + "PATH": "C:\\Users\\Thomas\\.platformio\\penv\\Scripts;C:\\Users\\Thomas\\.platformio\\penv;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Windows\\System32;C:\\Windows;C:\\Windows\\System32\\wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files (x86)\\GnuPG\\bin;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\Calibre2\\;C:\\Program Files\\TortoiseSVN\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Users\\Thomas\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files (x86)\\Nmap;C:\\Program Files\\Git\\bin;;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\iCLS\\;C:\\Windows\\System32;C:\\Windows;C:\\Windows\\System32\\wbem;C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\DAL;C:\\Program Files (x86)\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files\\Intel\\Intel(R) Management Engine Components\\IPT;C:\\Program Files (x86)\\GnuPG\\bin;C:\\Windows\\System32\\OpenSSH\\;C:\\Program Files (x86)\\Calibre2\\;C:\\Program Files\\TortoiseSVN\\bin;C:\\Program Files\\Microsoft VS Code\\bin;C:\\WINDOWS\\system32;C:\\WINDOWS;C:\\WINDOWS\\System32\\Wbem;C:\\WINDOWS\\System32\\WindowsPowerShell\\v1.0\\;C:\\WINDOWS\\System32\\OpenSSH\\;C:\\Users\\Thomas\\AppData\\Local\\Microsoft\\WindowsApps;C:\\Program Files\\Microsoft VS Code\\bin;C:\\Program Files (x86)\\Nmap;C:\\Program Files\\Git\\bin;", + "PLATFORMIO_CALLER": "vscode" + } +} \ No newline at end of file diff --git a/include/README b/include/README new file mode 100644 index 0000000..45496b1 --- /dev/null +++ b/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/lib/README b/lib/README new file mode 100644 index 0000000..8c9c29c --- /dev/null +++ b/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in a an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/platformio.ini b/platformio.ini new file mode 100644 index 0000000..7ccd064 --- /dev/null +++ b/platformio.ini @@ -0,0 +1,27 @@ +;PlatformIO Project Configuration File +; +; Build options: build flags, source filter +; Upload options: custom upload port, speed and extra flags +; Library options: dependencies, extra library storages +; Advanced options: extra scripting +; +; Please visit documentation for the other options and examples +; https://docs.platformio.org/page/projectconf.html + +[env:esp32] +platform = espressif32 +board = esp32dev +framework = arduino +upload_port = COM7 +board_build.partitions = no_ota.csv + +lib_deps = + https://github.com/me-no-dev/AsyncTCP + ESP Async WebServer + ESP-DASH + ArduinoJson + Button2 + BH1750 + Adafruit BME280 Library + Adafruit Unified Sensor + DHT sensor library \ No newline at end of file diff --git a/src/main.cpp b/src/main.cpp new file mode 100644 index 0000000..5cb643a --- /dev/null +++ b/src/main.cpp @@ -0,0 +1,233 @@ +#include "Adafruit_Sensor.h" +#include "DHT.h" +#include "DHT_U.h" +#include "esp_wifi.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#define I2C_SDA 25 +#define I2C_SCL 26 +#define DHT12_PIN 16 +#define BAT_ADC 33 +#define SALT_PIN 34 +#define SOIL_PIN 32 +#define BOOT_PIN 0 +#define POWER_CTRL 4 +#define USER_BUTTON 35 + +BH1750 lightMeter(0x23); //0x23 +Adafruit_BME280 bmp; //0x77 + +DHT_Unified dht(DHT12_PIN, DHT11); + +AsyncWebServer server(80); +Button2 button(BOOT_PIN); +Button2 useButton(USER_BUTTON); +WiFiMulti multi; + +#define WIFI_SSID "mqtt.binary-kitchen.de" +#define WIFI_PASSWD "test1234" + +bool bme_found = false; + +void smartConfigStart(Button2& b) +{ + Serial.println("smartConfigStart..."); + WiFi.disconnect(); + WiFi.beginSmartConfig(); + while (!WiFi.smartConfigDone()) { + Serial.print("."); + delay(200); + } + WiFi.stopSmartConfig(); + Serial.println(); + Serial.print("smartConfigStop Connected:"); + Serial.print(WiFi.SSID()); + Serial.print("PSW: "); + Serial.println(WiFi.psk()); +} + +void sleepHandler(Button2& b) +{ + Serial.println("Enter Deepsleep ..."); + esp_sleep_enable_ext1_wakeup(GPIO_SEL_35, ESP_EXT1_WAKEUP_ALL_LOW); + delay(1000); + esp_deep_sleep_start(); +} + +bool serverBegin() +{ + static bool isBegin = false; + if (isBegin) { + return true; + } + + ESPDash.init(server); + + isBegin = true; + if (MDNS.begin("soil")) { + Serial.println("MDNS responder started"); + } + // Add Respective Cards + if (bme_found) { + ESPDash.addTemperatureCard("temp", "BME Temperature/C", 0, 0); + ESPDash.addNumberCard("press", "BME Pressure/hPa", 0); + ESPDash.addNumberCard("alt", "BME Altitude/m", 0); + } + + ESPDash.addTemperatureCard("temp2", "DHT Temperature/C", 0, 0); + ESPDash.addHumidityCard("hum2", "DHT Humidity/%", 0); + ESPDash.addNumberCard("lux", "BH1750/lx", 0); + ESPDash.addHumidityCard("soil", "Soil", 0); + ESPDash.addNumberCard("salt", "Salt", 0); + ESPDash.addNumberCard("batt", "Battery/mV", 0); + server.begin(); + MDNS.addService("http", "tcp", 80); + return true; +} + +void setup() +{ + Serial.begin(115200); + WiFi.mode(WIFI_STA); + + wifi_config_t current_conf; + esp_wifi_get_config(WIFI_IF_STA, ¤t_conf); + int ssidlen = strlen((char*)(current_conf.sta.ssid)); + int passlen = strlen((char*)(current_conf.sta.password)); + + if (false && (ssidlen == 0 || passlen == 0)) { + multi.addAP(WIFI_SSID, WIFI_PASSWD); + Serial.println("Connect to defalut ssid, you can long press BOOT button enter smart config mode"); + while (multi.run() != WL_CONNECTED) { + Serial.print('.'); + } + } else { + WiFi.begin(WIFI_SSID, WIFI_PASSWD); + } + + if (WiFi.waitForConnectResult() != WL_CONNECTED) { + Serial.printf("WiFi connect fail!,please restart retry,or long press BOOT button enter smart config mode\n"); + } + if (WiFi.status() == WL_CONNECTED) { + Serial.print("IP Address: "); + Serial.println(WiFi.localIP()); + } + + button.setLongClickHandler(smartConfigStart); + useButton.setLongClickHandler(sleepHandler); + + Wire.begin(I2C_SDA, I2C_SCL); + + dht.begin(); + + //! Sensor power control pin , use deteced must set high + pinMode(POWER_CTRL, OUTPUT); + digitalWrite(POWER_CTRL, 1); + delay(1000); + + if (!bmp.begin()) { + Serial.println(F("Could not find a valid BMP280 sensor, check wiring!")); + bme_found = false; + } else { + bme_found = true; + } + + if (lightMeter.begin(BH1750::CONTINUOUS_HIGH_RES_MODE)) { + Serial.println(F("BH1750 Advanced begin")); + } else { + Serial.println(F("Error initialising BH1750")); + } +} + +uint32_t readSalt() +{ + uint8_t samples = 120; + uint32_t humi = 0; + uint16_t array[120]; + + for (int i = 0; i < samples; i++) { + array[i] = analogRead(SALT_PIN); + delay(2); + } + std::sort(array, array + samples); + for (int i = 0; i < samples; i++) { + if (i == 0 || i == samples - 1) + continue; + humi += array[i]; + } + humi /= samples - 2; + return humi; +} + +uint16_t readSoil() +{ + uint16_t soil = analogRead(SOIL_PIN); + return map(soil, 0, 4095, 100, 0); +} + +float readBattery() +{ + int vref = 1100; + uint16_t volt = analogRead(BAT_ADC); + float battery_voltage = ((float)volt / 4095.0) * 2.0 * 3.3 * (vref); + return battery_voltage; +} + +void loop() +{ + static uint64_t timestamp; + button.loop(); + useButton.loop(); + if (millis() - timestamp > 1000) { + timestamp = millis(); + if (WiFi.status() == WL_CONNECTED) { + if (serverBegin()) { + float lux = lightMeter.readLightLevel(); + + if (bme_found) { + float bme_temp = bmp.readTemperature(); + float bme_pressure = (bmp.readPressure() / 100.0F); + float bme_altitude = bmp.readAltitude(1013.25); + ESPDash.updateTemperatureCard("temp", (int)bme_temp); + ESPDash.updateNumberCard("press", (int)bme_pressure); + ESPDash.updateNumberCard("alt", (int)bme_altitude); + } + + sensors_event_t event; + dht.temperature().getEvent(&event); + float t12 = event.temperature; + // Read temperature as Fahrenheit (isFahrenheit = true) + dht.humidity().getEvent(&event); + float h12 = event.relative_humidity; + + if (!isnan(t12) && !isnan(h12)) { + ESPDash.updateTemperatureCard("temp2", (int)t12); + ESPDash.updateHumidityCard("hum2", (int)h12); + } + ESPDash.updateNumberCard("lux", (int)lux); + + uint16_t soil = readSoil(); + uint32_t salt = readSalt(); + float bat = readBattery(); + ESPDash.updateHumidityCard("soil", (int)soil); + ESPDash.updateNumberCard("salt", (int)salt); + ESPDash.updateNumberCard("batt", (int)bat); + + Serial.printf("DHTT:%.2f H:%.2f Lux:%.2f Soil:%u Salt:%u Bat:%.2f\n", + t12, h12, lux, soil, salt, bat); + } + } + } +} \ No newline at end of file diff --git a/test/README b/test/README new file mode 100644 index 0000000..c3b0ed6 --- /dev/null +++ b/test/README @@ -0,0 +1,11 @@ + +This directory is intended for PIO Unit Testing and project tests. + +Unit Testing is a software testing method by which individual units of +source code, sets of one or more MCU program modules together with associated +control data, usage procedures, and operating procedures, are tested to +determine whether they are fit for use. Unit testing finds problems early +in the development cycle. + +More information about PIO Unit Testing: +- https://docs.platformio.org/page/plus/unit-testing.html