Browse Source

Initial commit

Thomas Buck 4 years ago
commit
4ba97119a7
9 changed files with 567 additions and 0 deletions
  1. 1
    0
      .gitignore
  2. 67
    0
      .travis.yml
  3. 39
    0
      include/README
  4. 46
    0
      lib/README
  5. 156
    0
      lib/SHT2x/SHT2x.cpp
  6. 63
    0
      lib/SHT2x/SHT2x.h
  7. 20
    0
      platformio.ini
  8. 164
    0
      src/main.cpp
  9. 11
    0
      test/README

+ 1
- 0
.gitignore View File

@@ -0,0 +1 @@
1
+.pio

+ 67
- 0
.travis.yml View File

@@ -0,0 +1,67 @@
1
+# Continuous Integration (CI) is the practice, in software
2
+# engineering, of merging all developer working copies with a shared mainline
3
+# several times a day < https://docs.platformio.org/page/ci/index.html >
4
+#
5
+# Documentation:
6
+#
7
+# * Travis CI Embedded Builds with PlatformIO
8
+#   < https://docs.travis-ci.com/user/integration/platformio/ >
9
+#
10
+# * PlatformIO integration with Travis CI
11
+#   < https://docs.platformio.org/page/ci/travis.html >
12
+#
13
+# * User Guide for `platformio ci` command
14
+#   < https://docs.platformio.org/page/userguide/cmd_ci.html >
15
+#
16
+#
17
+# Please choose one of the following templates (proposed below) and uncomment
18
+# it (remove "# " before each line) or use own configuration according to the
19
+# Travis CI documentation (see above).
20
+#
21
+
22
+
23
+#
24
+# Template #1: General project. Test it using existing `platformio.ini`.
25
+#
26
+
27
+# language: python
28
+# python:
29
+#     - "2.7"
30
+#
31
+# sudo: false
32
+# cache:
33
+#     directories:
34
+#         - "~/.platformio"
35
+#
36
+# install:
37
+#     - pip install -U platformio
38
+#     - platformio update
39
+#
40
+# script:
41
+#     - platformio run
42
+
43
+
44
+#
45
+# Template #2: The project is intended to be used as a library with examples.
46
+#
47
+
48
+# language: python
49
+# python:
50
+#     - "2.7"
51
+#
52
+# sudo: false
53
+# cache:
54
+#     directories:
55
+#         - "~/.platformio"
56
+#
57
+# env:
58
+#     - PLATFORMIO_CI_SRC=path/to/test/file.c
59
+#     - PLATFORMIO_CI_SRC=examples/file.ino
60
+#     - PLATFORMIO_CI_SRC=path/to/test/directory
61
+#
62
+# install:
63
+#     - pip install -U platformio
64
+#     - platformio update
65
+#
66
+# script:
67
+#     - platformio ci --lib="." --board=ID_1 --board=ID_2 --board=ID_N

+ 39
- 0
include/README View File

@@ -0,0 +1,39 @@
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

+ 46
- 0
lib/README View File

@@ -0,0 +1,46 @@
1
+
2
+This directory is intended for project specific (private) libraries.
3
+PlatformIO will compile them to static libraries and link into executable file.
4
+
5
+The source code of each library should be placed in a an own separate directory
6
+("lib/your_library_name/[here are source files]").
7
+
8
+For example, see a structure of the following two libraries `Foo` and `Bar`:
9
+
10
+|--lib
11
+|  |
12
+|  |--Bar
13
+|  |  |--docs
14
+|  |  |--examples
15
+|  |  |--src
16
+|  |     |- Bar.c
17
+|  |     |- Bar.h
18
+|  |  |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html
19
+|  |
20
+|  |--Foo
21
+|  |  |- Foo.c
22
+|  |  |- Foo.h
23
+|  |
24
+|  |- README --> THIS FILE
25
+|
26
+|- platformio.ini
27
+|--src
28
+   |- main.c
29
+
30
+and a contents of `src/main.c`:
31
+```
32
+#include <Foo.h>
33
+#include <Bar.h>
34
+
35
+int main (void)
36
+{
37
+  ...
38
+}
39
+
40
+```
41
+
42
+PlatformIO Library Dependency Finder will find automatically dependent
43
+libraries scanning project source files.
44
+
45
+More information about PlatformIO Library Dependency Finder
46
+- https://docs.platformio.org/page/librarymanager/ldf.html

+ 156
- 0
lib/SHT2x/SHT2x.cpp View File

@@ -0,0 +1,156 @@
1
+/*
2
+ SHT2x - Humidity Library for Arduino.
3
+ Get humidity and temperature from the HTU21D/SHT2x sensors.
4
+
5
+ Hardware Setup:
6
+ Attach the SDA pin to A4, SCL to A5.
7
+
8
+ Software:
9
+ Call SHT2x.Begin() in setup.
10
+ SHT2x.ReadHumidity() will return a float containing the humidity. Ex: 54.7
11
+ SHT2x.ReadTemperature() will return a float containing the temperature in Celsius. Ex: 24.1
12
+ SHT2x.SetResolution(byte: 0b.76543210) sets the resolution of the readings.
13
+
14
+  Copyright (C) 2015  Nuno Chaveiro  nchaveiro[at]gmail.com  Lisbon, Portugal
15
+  Copyright (C) 2020  Thomas Buck <thomas@xythobuz.de>
16
+*/
17
+
18
+#include <Wire.h>
19
+#include "SHT2x.h"
20
+
21
+SHT2x::SHT2x(uint8_t _addr, TwoWire* _wire) {
22
+    addr = _addr;
23
+    wire = _wire;
24
+}
25
+
26
+void SHT2x::begin(void) {
27
+    wire->begin();
28
+}
29
+
30
+bool SHT2x::GetAlive(void) {
31
+    uint16_t r = readSensor(TRIGGER_TEMP_MEASURE_HOLD);
32
+    if ((r == ERROR_TIMEOUT) || (r == ERROR_CRC)) {
33
+        return false;
34
+    }
35
+    return true;
36
+}
37
+
38
+/**********************************************************
39
+ * GetHumidity
40
+ *  Gets the current humidity from the sensor.
41
+ *
42
+ * @return float - The relative humidity in %RH
43
+ **********************************************************/
44
+float SHT2x::GetHumidity(void) {
45
+    return (-6.0 + 125.0 / 65536.0 * (float)(readSensor(TRIGGER_HUMD_MEASURE_HOLD)));
46
+}
47
+
48
+/**********************************************************
49
+ * GetTemperature
50
+ *  Gets the current temperature from the sensor.
51
+ *
52
+ * @return float - The temperature in Deg C
53
+ **********************************************************/
54
+float SHT2x::GetTemperature(void) {
55
+    return (-46.85 + 175.72 / 65536.0 * (float)(readSensor(TRIGGER_TEMP_MEASURE_HOLD)));
56
+}
57
+
58
+/**********************************************************
59
+ * Sets the sensor resolution to one of four levels:
60
+ *  0/0 = 12bit RH, 14bit Temp
61
+ *  0/1 = 8bit RH, 12bit Temp
62
+ *  1/0 = 10bit RH, 13bit Temp
63
+ *  1/1 = 11bit RH, 11bit Temp
64
+ *  Power on default is 0/0
65
+ **********************************************************/
66
+void SHT2x::setResolution(uint8_t resolution) {
67
+    uint8_t userRegister = read_user_register(); //Go get the current register state
68
+    userRegister &= B01111110; //Turn off the resolution bits
69
+    resolution &= B10000001; //Turn off all other bits but resolution bits
70
+    userRegister |= resolution; //Mask in the requested resolution bits
71
+
72
+    //Request a write to user register
73
+    wire->beginTransmission(addr);
74
+    wire->write(WRITE_USER_REG); //Write to the user register
75
+    wire->write(userRegister); //Write the new resolution bits
76
+    wire->endTransmission();
77
+}
78
+
79
+uint8_t SHT2x::read_user_register(void) {
80
+    uint8_t userRegister;
81
+
82
+    //Request the user register
83
+    wire->beginTransmission(addr);
84
+    wire->write(READ_USER_REG); //Read the user register
85
+    wire->endTransmission();
86
+
87
+    //Read result
88
+    wire->requestFrom(addr, 1);
89
+
90
+    userRegister = wire->read();
91
+
92
+    return userRegister;
93
+}
94
+
95
+uint16_t SHT2x::readSensor(uint8_t command) {
96
+    uint16_t result;
97
+
98
+    wire->beginTransmission(addr); //begin
99
+    wire->write(command);                     //send the pointer location
100
+    wire->endTransmission();                  //end
101
+
102
+    //Hang out while measurement is taken. 50mS max, page 4 of datasheet.
103
+    delay(55);
104
+
105
+    //Comes back in three bytes, data(MSB) / data(LSB) / Checksum
106
+    wire->requestFrom(addr, 3);
107
+
108
+    //Wait for data to become available
109
+    int counter = 0;
110
+    while (wire->available() < 3) {
111
+        counter++;
112
+        delay(1);
113
+        if(counter > 100) return ERROR_TIMEOUT; //Error timout
114
+    }
115
+
116
+    //Store the result
117
+    result = ((wire->read()) << 8);
118
+    result |= wire->read();
119
+    //Check validity
120
+    uint8_t checksum = wire->read();
121
+    if(check_crc(result, checksum) != 0) return(ERROR_CRC); //Error checksum
122
+    //sensorStatus = rawTemperature & 0x0003; //get status bits
123
+    result &= ~0x0003;   // clear two low bits (status bits)
124
+    return result;
125
+}
126
+
127
+//Give this function the 2 byte message (measurement) and the check_value byte from the HTU21D
128
+//If it returns 0, then the transmission was good
129
+//If it returns something other than 0, then the communication was corrupted
130
+//From: http://www.nongnu.org/avr-libc/user-manual/group__util__crc.html
131
+//POLYNOMIAL = 0x0131 = x^8 + x^5 + x^4 + 1 : http://en.wikipedia.org/wiki/Computation_of_cyclic_redundancy_checks
132
+#define SHIFTED_DIVISOR 0x988000 // This is the 0x0131 polynomial shifted to farthest left of three bytes
133
+
134
+uint8_t SHT2x::check_crc(uint16_t message_from_sensor, uint8_t check_value_from_sensor) {
135
+    // Pad with 8 bits because we have to add in the check value
136
+    uint32_t remainder = (uint32_t)message_from_sensor << 8;
137
+
138
+    // Add on the check value
139
+    remainder |= check_value_from_sensor;
140
+    uint32_t divsor = (uint32_t)SHIFTED_DIVISOR;
141
+
142
+    // Operate on only 16 positions of max 24.
143
+    // The remaining 8 are our remainder and should be zero when we're done.
144
+    for (int i = 0; i < 16; i++) {
145
+        // Check if there is a one in the left position
146
+        if (remainder & ((uint32_t)1 << (23 - i))) {
147
+            remainder ^= divsor;
148
+        }
149
+
150
+        // Rotate the divsor max 16 times so that we have 8 bits left of a remainder
151
+        divsor >>= 1;
152
+    }
153
+
154
+    return (uint8_t)remainder;
155
+}
156
+

+ 63
- 0
lib/SHT2x/SHT2x.h View File

@@ -0,0 +1,63 @@
1
+/*
2
+ SHT2x - Humidity Library for Arduino.
3
+ Get humidity and temperature from the HTU21D/SHT2x sensors.
4
+
5
+ Hardware Setup:
6
+ Attach the SDA pin to A4, SCL to A5.
7
+
8
+ Software:
9
+ Call SHT2x.Begin() in setup.
10
+ SHT2x.ReadHumidity() will return a float containing the humidity. Ex: 54.7
11
+ SHT2x.ReadTemperature() will return a float containing the temperature in Celsius. Ex: 24.1
12
+ SHT2x.SetResolution(byte: 0b.76543210) sets the resolution of the readings.
13
+
14
+  Copyright (C) 2015  Nuno Chaveiro  nchaveiro[at]gmail.com  Lisbon, Portugal
15
+  Copyright (C) 2020  Thomas Buck <thomas@xythobuz.de>
16
+*/
17
+
18
+#if defined(ARDUINO) && ARDUINO >= 100
19
+ #include "Arduino.h"
20
+#else
21
+ #include "WProgram.h"
22
+#endif
23
+
24
+#include <Wire.h>
25
+
26
+#ifndef SHT2X_H
27
+#define SHT2X_H
28
+
29
+// Unshifted 7-bit I2C address for the sensor
30
+#define HTDU21D_ADDRESS             0x40
31
+
32
+#define TRIGGER_TEMP_MEASURE_HOLD   0xE3
33
+#define TRIGGER_HUMD_MEASURE_HOLD   0xE5
34
+#define TRIGGER_TEMP_MEASURE_NOHOLD 0xF3
35
+#define TRIGGER_HUMD_MEASURE_NOHOLD 0xF5
36
+
37
+#define WRITE_USER_REG              0xE6
38
+#define READ_USER_REG               0xE7
39
+#define SOFT_RESET                  0xFE
40
+
41
+#define ERROR_CRC                   998
42
+#define ERROR_TIMEOUT               999
43
+
44
+class SHT2x {
45
+    public:
46
+        SHT2x(uint8_t _addr = HTDU21D_ADDRESS, TwoWire* _wire = &Wire);
47
+        void     begin();
48
+        bool     GetAlive(void);
49
+        float    GetHumidity(void);
50
+        float    GetTemperature(void);
51
+        void     setResolution(uint8_t resBits);
52
+        uint8_t  read_user_register(void);
53
+        uint16_t readSensor(uint8_t command);
54
+
55
+    private:
56
+        uint8_t  check_crc(uint16_t message_from_sensor, uint8_t check_value_from_sensor);
57
+
58
+        uint8_t addr;
59
+        TwoWire* wire;
60
+};
61
+
62
+#endif
63
+

+ 20
- 0
platformio.ini View File

@@ -0,0 +1,20 @@
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:esp01]
12
+platform = espressif8266@2.3.2
13
+board = esp01
14
+framework = arduino
15
+lib_deps =
16
+    Wire
17
+    ESP8266 Influxdb@1.3.0
18
+    Adafruit Unified Sensor@1.1.1
19
+    Adafruit BME280 Library@2.0.0
20
+

+ 164
- 0
src/main.cpp View File

@@ -0,0 +1,164 @@
1
+#include <Arduino.h>
2
+#include <Wire.h>
3
+#include <ESP8266WiFi.h>
4
+#include <InfluxDb.h>
5
+#include <ESP8266WebServer.h>
6
+#include <ESP8266mDNS.h>
7
+#include <Adafruit_BME280.h>
8
+#include <SHT2x.h>
9
+
10
+const char* sensor_location = "SENSOR_NAME_GOES_HERE";
11
+
12
+const char* ssid = "YOUR_SSID_HERE";
13
+const char* password = "YOUR_PASS_HERE";
14
+
15
+#define INFLUXDB_HOST "INFLUX_DB_SERVER_IP_HERE"
16
+#define INFLUXDB_PORT 8086
17
+#define INFLUXDB_DATABASE "INFLUX_DB_DATABASE_NAME_HERE"
18
+
19
+#define SENSOR_HOSTNAME_PREFIX "ESP-"
20
+
21
+Influxdb influx(INFLUXDB_HOST, INFLUXDB_PORT);
22
+ESP8266WebServer server(80);
23
+TwoWire Wire2;
24
+SHT2x sht(HTDU21D_ADDRESS, &Wire2);
25
+Adafruit_BME280 bme;
26
+bool found_bme = false;
27
+bool found_sht = false;
28
+
29
+void handleRoot() {
30
+    String message = "ESP8266 BME280 Sensor";
31
+    message += "\n\nLocation: ";
32
+    message += sensor_location;
33
+    message += "\nMAC: ";
34
+    message += WiFi.macAddress();
35
+
36
+    if (found_bme) {
37
+        message += "\n\nBME280:";
38
+        message += "\nTemperature: ";
39
+        message += String(bme.readTemperature());
40
+        message += "\nHumidity: ";
41
+        message += String(bme.readHumidity());
42
+        message += "\nPressure: ";
43
+        message += String(bme.readPressure());
44
+    }
45
+
46
+    if (found_sht) {
47
+        message += "\n\nSHT21:";
48
+        message += "\nTemperature: ";
49
+        message += String(sht.GetTemperature());
50
+        message += "\nHumidity: ";
51
+        message += String(sht.GetHumidity());
52
+    }
53
+
54
+    if ((!found_bme) && (!found_sht)) {
55
+        message += "\n\nNo Sensor available!";
56
+    }
57
+
58
+    message += "\n";
59
+    server.send(200, "text/plain", message);
60
+}
61
+
62
+void setup() {
63
+    pinMode(1, OUTPUT);
64
+    digitalWrite(1, LOW); // LED on
65
+    delay(500);
66
+    digitalWrite(1, HIGH); // LED off
67
+    delay(500);
68
+    digitalWrite(1, LOW); // LED on
69
+    delay(500);
70
+    digitalWrite(1, HIGH); // LED off
71
+    delay(500);
72
+
73
+    Wire2.begin(2, 0);
74
+    found_bme = (!bme.begin(0x76, &Wire2)) ? false : true;
75
+    found_sht = sht.GetAlive();
76
+
77
+    if ((!found_bme) && (!found_sht)) {
78
+        // no sensor available
79
+        while (1) {
80
+            digitalWrite(1, !digitalRead(1));
81
+            delay(100);
82
+        }
83
+    }
84
+
85
+    String hostname = SENSOR_HOSTNAME_PREFIX;
86
+    hostname += sensor_location;
87
+    WiFi.hostname(hostname);
88
+
89
+    WiFi.mode(WIFI_STA);
90
+    WiFi.begin(ssid, password);
91
+
92
+    MDNS.begin(hostname);
93
+
94
+    while (WiFi.status() != WL_CONNECTED) {
95
+        delay(250);
96
+        digitalWrite(1, !digitalRead(1));
97
+    }
98
+
99
+    influx.setDb(INFLUXDB_DATABASE);
100
+
101
+    server.on("/", handleRoot);
102
+    server.begin();
103
+}
104
+
105
+#define SERVER_HANDLE_INTERVAL 10 // in ms
106
+#define DB_WRITE_INTERVAL (30 * 1000) // in ms
107
+#define LED_BLINK_INTERVAL (2 * 1000) // in ms
108
+
109
+unsigned long last_server_handle_time = 0;
110
+unsigned long last_db_write_time = 0;
111
+unsigned long last_led_blink_time = 0;
112
+
113
+void loop() {
114
+    unsigned long time = millis();
115
+
116
+    if ((time - last_server_handle_time) >= SERVER_HANDLE_INTERVAL) {
117
+        last_server_handle_time = time;
118
+
119
+        server.handleClient();
120
+        MDNS.update();
121
+    }
122
+
123
+    if ((time - last_db_write_time) >= DB_WRITE_INTERVAL) {
124
+        last_db_write_time = time;
125
+
126
+        if (found_bme) {
127
+            InfluxData measurement("environment");
128
+            measurement.addTag("location", sensor_location);
129
+            measurement.addTag("device", WiFi.macAddress());
130
+            measurement.addTag("sensor", "bme280");
131
+
132
+            measurement.addValue("temperature", bme.readTemperature());
133
+            measurement.addValue("pressure", bme.readPressure());
134
+            measurement.addValue("humidity", bme.readHumidity());
135
+
136
+            boolean success = influx.write(measurement);
137
+            if (!success) {
138
+                digitalWrite(1, !digitalRead(1));
139
+            }
140
+        }
141
+
142
+        if (found_sht) {
143
+            InfluxData measurement("environment");
144
+            measurement.addTag("location", sensor_location);
145
+            measurement.addTag("device", WiFi.macAddress());
146
+            measurement.addTag("sensor", "sht21");
147
+
148
+            measurement.addValue("temperature", sht.GetTemperature());
149
+            measurement.addValue("humidity", sht.GetHumidity());
150
+
151
+            boolean success = influx.write(measurement);
152
+            if (!success) {
153
+                digitalWrite(1, !digitalRead(1));
154
+            }
155
+        }
156
+    }
157
+
158
+    if ((time - last_led_blink_time) >= LED_BLINK_INTERVAL) {
159
+        last_led_blink_time = time;
160
+
161
+        digitalWrite(1, !digitalRead(1));
162
+    }
163
+}
164
+

+ 11
- 0
test/README View File

@@ -0,0 +1,11 @@
1
+
2
+This directory is intended for PIO 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 PIO Unit Testing:
11
+- https://docs.platformio.org/page/plus/unit-testing.html

Loading…
Cancel
Save