Просмотр исходного кода

Moved moisture sensor and updater into own files. Added relais support (only testing for now).

Thomas Buck 4 лет назад
Родитель
Сommit
0223dc2088
9 измененных файлов: 737 добавлений и 94 удалений
  1. 52
    0
      include/SimpleUpdater.h
  2. 20
    8
      include/config.h
  3. 23
    0
      include/moisture.h
  4. 23
    0
      include/relais.h
  5. 11
    0
      platformio.ini
  6. 133
    0
      src/SimpleUpdater.cpp
  7. 309
    86
      src/main.cpp
  8. 83
    0
      src/moisture.cpp
  9. 83
    0
      src/relais.cpp

+ 52
- 0
include/SimpleUpdater.h Просмотреть файл

@@ -0,0 +1,52 @@
1
+/*
2
+ * SimpleUpdater.h
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#ifndef __ESP_SIMPLE_UPDATER__
15
+#define __ESP_SIMPLE_UPDATER__
16
+
17
+#if defined(ARDUINO_ARCH_ESP8266)
18
+#include <ESP8266WebServer.h>
19
+#include <ESP8266HTTPUpdateServer.h>
20
+#define UPDATE_WEB_SERVER ESP8266WebServer
21
+#elif defined(ARDUINO_ARCH_ESP32)
22
+#include <WebServer.h>
23
+#define UPDATE_WEB_SERVER WebServer
24
+#else
25
+#error Platform not supported!
26
+#endif
27
+
28
+class SimpleUpdater {
29
+public:
30
+    SimpleUpdater(String _uri = String("/update"));
31
+    void setup(UPDATE_WEB_SERVER *_server);
32
+    
33
+private:
34
+
35
+#if defined(ARDUINO_ARCH_ESP8266)
36
+    
37
+    ESP8266HTTPUpdateServer updateServer;
38
+
39
+#elif defined(ARDUINO_ARCH_ESP32)
40
+    
41
+    void get(void);
42
+    void postResult(void);
43
+    void postUpload(void);
44
+    
45
+#endif
46
+    
47
+    String uri;
48
+    UPDATE_WEB_SERVER *server;
49
+};
50
+
51
+#endif // __ESP_SIMPLE_UPDATER__
52
+

src/config.h → include/config.h Просмотреть файл

@@ -1,8 +1,21 @@
1
+/*
2
+ * config.h
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
1 14
 #ifndef __ESP_ENV_CONFIG__
2 15
 #define __ESP_ENV_CONFIG__
3 16
 
4 17
 // Sketch version
5
-const char* esp_env_version = "0.2.0";
18
+const char* esp_env_version = "0.4.0";
6 19
 
7 20
 // location of sensor, used in DB and hostname
8 21
 //const char* sensor_location = "livingroom";
@@ -11,7 +24,9 @@ const char* esp_env_version = "0.2.0";
11 24
 //const char* sensor_location = "kitchen";
12 25
 //const char* sensor_location = "hallway";
13 26
 //const char* sensor_location = "tent";
14
-const char* sensor_location = "storage";
27
+//const char* sensor_location = "storage";
28
+//const char* sensor_location = "greenhouse";
29
+const char* sensor_location = "testing";
15 30
 
16 31
 #define SENSOR_HOSTNAME_PREFIX "ESP-"
17 32
 
@@ -24,6 +39,9 @@ const char* password = "WIFI_PASSWORD_HERE";
24 39
 #define INFLUXDB_PORT 8086
25 40
 #define INFLUXDB_DATABASE "roomsensorsdiy"
26 41
 
42
+// feature selection
43
+#define ENABLE_INFLUXDB_LOGGING
44
+
27 45
 // all given in milliseconds
28 46
 #define SERVER_HANDLE_INTERVAL 10
29 47
 #define DB_WRITE_INTERVAL (30 * 1000)
@@ -32,11 +50,5 @@ const char* password = "WIFI_PASSWORD_HERE";
32 50
 #define LED_CONNECT_BLINK_INTERVAL 250
33 51
 #define LED_ERROR_BLINK_INTERVAL 100
34 52
 
35
-// feature selection
36
-#define ENABLE_DATABASE_WRITES
37
-#define ENABLE_LED_HEARTBEAT_BLINK
38
-#define DONT_RUN_WITHOUT_SENSORS
39
-#define HTTP_SHOW_ESP_STATS
40
-
41 53
 #endif // __ESP_ENV_CONFIG__
42 54
 

+ 23
- 0
include/moisture.h Просмотреть файл

@@ -0,0 +1,23 @@
1
+/*
2
+ * moisture.h
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#ifndef __ESP_ADC_MOISTURE_SENSOR__
15
+#define __ESP_ADC_MOISTURE_SENSOR__
16
+
17
+int moisture_count(void);
18
+int moisture_read(int sensor);
19
+int moisture_max(void);
20
+void moisture_init(void);
21
+
22
+#endif // __ESP_ADC_MOISTURE_SENSOR__
23
+

+ 23
- 0
include/relais.h Просмотреть файл

@@ -0,0 +1,23 @@
1
+/*
2
+ * relais.h
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#ifndef __ESP_RELAIS_ACTOR__
15
+#define __ESP_RELAIS_ACTOR__
16
+
17
+int relais_count(void);
18
+int relais_enable(int relais, unsigned long time);
19
+void relais_init(void);
20
+void relais_run(void);
21
+
22
+#endif // __ESP_RELAIS_ACTOR__
23
+

+ 11
- 0
platformio.ini Просмотреть файл

@@ -18,3 +18,14 @@ lib_deps =
18 18
     Adafruit Unified Sensor
19 19
     Adafruit BME280 Library
20 20
 
21
+[env:esp32dev]
22
+platform = espressif32
23
+board = esp32dev
24
+framework = arduino
25
+upload_protocol = esptool
26
+lib_deps =
27
+    Wire
28
+    Adafruit Unified Sensor
29
+    Adafruit BME280 Library
30
+    https://github.com/tobiasschuerg/InfluxDB-Client-for-Arduino.git#66ed5d031caab6953cc79b407a4b49d33b1126dc
31
+

+ 133
- 0
src/SimpleUpdater.cpp Просмотреть файл

@@ -0,0 +1,133 @@
1
+/*
2
+ * SimpleUpdater.cpp
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#if defined(ARDUINO_ARCH_ESP8266)
15
+#include <ESP8266HTTPUpdateServer.h>
16
+#elif defined(ARDUINO_ARCH_ESP32)
17
+#include <Update.h>
18
+#endif
19
+
20
+#include "SimpleUpdater.h"
21
+
22
+#if defined(ARDUINO_ARCH_ESP32)
23
+
24
+void SimpleUpdater::get(void) {
25
+    String uploadPage = F(
26
+        "<html><head>"
27
+        "<script src='https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js'></script>"
28
+        "<title>SimpleUpdater ESP32</title>"
29
+        "</head><body>"
30
+        "<h1>SimpleUpdater</h1>"
31
+        "<form method='POST' action='#' enctype='multipart/form-data' id='upload_form'>"
32
+        "<input type='file' name='update'>"
33
+        "<input type='submit' value='Update'>"
34
+        "</form>"
35
+        "<div id='prg'>progress: 0%</div>"
36
+        "<a href=\"/\">Back to Main Page</a>"
37
+        "<script>"
38
+        "$('form').submit(function(e){"
39
+        "e.preventDefault();"
40
+        "var form = $('#upload_form')[0];"
41
+        "var data = new FormData(form);"
42
+        " $.ajax({"
43
+        "url: '/update',"
44
+        "type: 'POST',"
45
+        "data: data,"
46
+        "contentType: false,"
47
+        "processData:false,"
48
+        "xhr: function() {"
49
+        "var xhr = new window.XMLHttpRequest();"
50
+        "xhr.upload.addEventListener('progress', function(evt) {"
51
+        "if (evt.lengthComputable) {"
52
+        "var per = evt.loaded / evt.total;"
53
+        "$('#prg').html('progress: ' + Math.round(per*100) + '%');"
54
+        "}"
55
+        "}, false);"
56
+        "return xhr;"
57
+        "},"
58
+        "success:function(d, s) {"
59
+        "console.log('success!')" 
60
+        "},"
61
+        "error: function (a, b, c) {"
62
+        "}"
63
+        "});"
64
+        "});"
65
+        "</script>"
66
+        "</body></html>"
67
+    );
68
+    
69
+    server->send(200, "text/html", uploadPage);
70
+}
71
+
72
+void SimpleUpdater::postResult(void) {
73
+    server->sendHeader("Connection", "close");
74
+    server->send(200, "text/plain", (Update.hasError()) ? "FAIL" : "OK");
75
+    ESP.restart();
76
+}
77
+
78
+void SimpleUpdater::postUpload(void) {
79
+    HTTPUpload& upload = server->upload();
80
+    if (upload.status == UPLOAD_FILE_START) {
81
+        Serial.printf("Update: %s\n", upload.filename.c_str());
82
+        // start with max available size
83
+        if (!Update.begin(UPDATE_SIZE_UNKNOWN)) {
84
+            Update.printError(Serial);
85
+        }
86
+    } else if (upload.status == UPLOAD_FILE_WRITE) {
87
+        // flashing firmware to ESP
88
+        if (Update.write(upload.buf, upload.currentSize) != upload.currentSize) {
89
+            Update.printError(Serial);
90
+        }
91
+    } else if (upload.status == UPLOAD_FILE_END) {
92
+        // true to set the size to the current progress
93
+        if (Update.end(true)) {
94
+            Serial.printf("Update Success: %u\nRebooting...\n", upload.totalSize);
95
+        } else {
96
+            Update.printError(Serial);
97
+        }
98
+    }
99
+}
100
+
101
+#endif
102
+
103
+void SimpleUpdater::setup(UPDATE_WEB_SERVER *_server) {
104
+    if (_server == NULL) {
105
+        return;
106
+    }
107
+    
108
+    server = _server;
109
+    
110
+#if defined(ARDUINO_ARCH_ESP8266)
111
+    
112
+    updateServer.setup(server);
113
+    
114
+#elif defined(ARDUINO_ARCH_ESP32)
115
+    
116
+    server->on(uri.c_str(), HTTP_POST, [this]() {
117
+        postResult();
118
+    }, [this]() {
119
+        postUpload();
120
+    });
121
+    
122
+    server->on(uri.c_str(), HTTP_GET, [this]() {
123
+        get();
124
+    });
125
+    
126
+#endif
127
+}
128
+
129
+SimpleUpdater::SimpleUpdater(String _uri) {
130
+    uri = _uri;
131
+    server = NULL;
132
+}
133
+

+ 309
- 86
src/main.cpp Просмотреть файл

@@ -1,110 +1,261 @@
1
+/*
2
+ * main.cpp
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
1 14
 #include <Arduino.h>
2 15
 #include <Wire.h>
16
+#include <Adafruit_BME280.h>
17
+#include <SHT2x.h>
18
+
19
+#if defined(ARDUINO_ARCH_ESP8266)
20
+
3 21
 #include <ESP8266WiFi.h>
4 22
 #include <ESP8266WebServer.h>
5 23
 #include <ESP8266mDNS.h>
6
-#include <ESP8266HTTPUpdateServer.h>
7
-#include <Adafruit_BME280.h>
8
-#include <SHT2x.h>
24
+
25
+#define ESP_PLATFORM_NAME "ESP8266"
26
+
27
+#elif defined(ARDUINO_ARCH_ESP32)
28
+
29
+#include <WiFi.h>
30
+#include <WebServer.h>
31
+#include <ESPmDNS.h>
32
+
33
+#define ESP_PLATFORM_NAME "ESP32"
34
+
35
+#endif
36
+
9 37
 #include "config.h"
38
+#include "moisture.h"
39
+#include "relais.h"
40
+#include "SimpleUpdater.h"
41
+
42
+#define BUILTIN_LED_PIN 1
43
+
44
+UPDATE_WEB_SERVER server(80);
45
+SimpleUpdater updater;
10 46
 
11
-#ifdef ENABLE_DATABASE_WRITES
47
+#ifdef ENABLE_INFLUXDB_LOGGING
12 48
 #include <InfluxDb.h>
49
+
13 50
 Influxdb influx(INFLUXDB_HOST, INFLUXDB_PORT);
14
-#endif // ENABLE_DATABASE_WRITES
15 51
 
16
-#define BUILTIN_LED_PIN 1
52
+#define INFLUX_MAX_ERRORS_RESET 10
53
+int error_count = 0;
54
+#endif // ENABLE_INFLUXDB_LOGGING
55
+
56
+#define SHT_I2C_ADDRESS HTDU21D_ADDRESS
57
+#define BME_I2C_ADDRESS_1 0x76
58
+#define BME_I2C_ADDRESS_2 0x77
17 59
 
18
-ESP8266WebServer server(80);
19
-ESP8266HTTPUpdateServer updater;
60
+#if defined(ARDUINO_ARCH_ESP8266)
61
+
62
+#define I2C_SDA_PIN 2
63
+#define I2C_SCL_PIN 0
20 64
 
21 65
 TwoWire Wire2;
22
-SHT2x sht(HTDU21D_ADDRESS, &Wire2);
23
-Adafruit_BME280 bme;
66
+SHT2x sht(SHT_I2C_ADDRESS, &Wire2);
67
+
68
+#elif defined(ARDUINO_ARCH_ESP32)
24 69
 
25
-bool found_bme = false;
70
+SHT2x sht(SHT_I2C_ADDRESS, &Wire);
71
+
72
+#endif
73
+
74
+Adafruit_BME280 bme1, bme2;
75
+
76
+bool found_bme1 = false;
77
+bool found_bme2 = false;
26 78
 bool found_sht = false;
27 79
 
28 80
 unsigned long last_server_handle_time = 0;
29 81
 unsigned long last_db_write_time = 0;
30 82
 unsigned long last_led_blink_time = 0;
31 83
 
84
+static void relaisTest() {
85
+    for (int i = 0; i < 10; i++) {
86
+        relais_enable(i, 400 + (i * 1000));
87
+        delay(100);
88
+    }
89
+}
90
+
91
+void handleRelaisTest() {
92
+    String message = F("<html><head>\n");
93
+    message += F("<title>" ESP_PLATFORM_NAME " Environment Sensor</title>\n");
94
+    message += F("</head><body>\n");
95
+    message += F("<p>Relais Test started!</p>\n");
96
+    message += F("<p><a href=\"/\">Return to Home</a></p>\n");
97
+    message += F("</body></html>\n");
98
+    
99
+    server.send(200, "text/html", message);
100
+    
101
+    relaisTest();
102
+}
103
+
32 104
 void handleRoot() {
33
-    String message = F("ESP8266 Environment Sensor");
34
-    message += F("\n\n");
105
+    String message = F("<html><head>\n");
106
+    message += F("<title>" ESP_PLATFORM_NAME " Environment Sensor</title>\n");
107
+    message += F("</head><body>\n");
108
+    message += F("<h1>" ESP_PLATFORM_NAME " Environment Sensor</h1>\n");
109
+    message += F("\n<p>\n");
35 110
     message += F("Version: ");
36 111
     message += esp_env_version;
37
-    message += F("\n");
112
+    message += F("\n<br>\n");
38 113
     message += F("Location: ");
39 114
     message += sensor_location;
40
-    message += F("\n");
115
+    message += F("\n<br>\n");
41 116
     message += F("MAC: ");
42 117
     message += WiFi.macAddress();
118
+    message += F("\n</p>\n");
43 119
 
44
-#ifdef HTTP_SHOW_ESP_STATS
45
-    message += F("\n");
120
+#if defined(ARDUINO_ARCH_ESP8266)
121
+    
122
+    message += F("\n<p>\n");
46 123
     message += F("Reset reason: ");
47 124
     message += ESP.getResetReason();
48
-    message += F("\n");
125
+    message += F("\n<br>\n");
49 126
     message += F("Free heap: ");
50 127
     message += String(ESP.getFreeHeap());
51 128
     message += F(" (");
52 129
     message += String(ESP.getHeapFragmentation());
53 130
     message += F("% fragmentation)");
54
-    message += F("\n");
131
+    message += F("\n<br>\n");
55 132
     message += F("Free sketch space: ");
56 133
     message += String(ESP.getFreeSketchSpace());
57
-    message += F("\n");
134
+    message += F("\n<br>\n");
58 135
     message += F("Flash chip real size: ");
59 136
     message += String(ESP.getFlashChipRealSize());
60 137
 
61 138
     if (ESP.getFlashChipSize() != ESP.getFlashChipRealSize()) {
62
-        message += F("\n");
139
+        message += F("\n<br>\n");
63 140
         message += F("WARNING: sdk chip size (");
64 141
         message += (ESP.getFlashChipSize());
65 142
         message += F(") does not match!");
66 143
     }
67
-#endif // HTTP_SHOW_ESP_STATS
144
+    
145
+    message += F("\n</p>\n");
146
+    
147
+#elif defined(ARDUINO_ARCH_ESP32)
148
+
149
+    message += F("\n<p>\n");
150
+    message += F("Free heap: ");
151
+    message += String(ESP.getFreeHeap() / 1024.0);
152
+    message += F("k\n<br>\n");
153
+    message += F("Free sketch space: ");
154
+    message += String(ESP.getFreeSketchSpace() / 1024.0);
155
+    message += F("k\n<br>\n");
156
+    message += F("Flash chip size: ");
157
+    message += String(ESP.getFlashChipSize() / 1024.0);
158
+    message += F("k\n</p>\n");
159
+    
160
+#endif
161
+
162
+    message += F("\n<p>\n");
163
+    if (found_bme1) {
164
+        message += F("BME280 Low:");
165
+        message += F("\n<br>\n");
166
+        message += F("Temperature: ");
167
+        message += String(bme1.readTemperature());
168
+        message += F("\n<br>\n");
169
+        message += F("Humidity: ");
170
+        message += String(bme1.readHumidity());
171
+        message += F("\n<br>\n");
172
+        message += F("Pressure: ");
173
+        message += String(bme1.readPressure());
174
+    } else {
175
+        message += F("BME280 (low) not connected!");
176
+    }
177
+    message += F("\n</p>\n");
68 178
 
69
-    if (found_bme) {
70
-        message += F("\n\n");
71
-        message += F("BME280:");
72
-        message += F("\n");
179
+    message += F("\n<p>\n");
180
+    if (found_bme2) {
181
+        message += F("BME280 High:");
182
+        message += F("\n<br>\n");
73 183
         message += F("Temperature: ");
74
-        message += String(bme.readTemperature());
75
-        message += F("\n");
184
+        message += String(bme2.readTemperature());
185
+        message += F("\n<br>\n");
76 186
         message += F("Humidity: ");
77
-        message += String(bme.readHumidity());
78
-        message += F("\n");
187
+        message += String(bme2.readHumidity());
188
+        message += F("\n<br>\n");
79 189
         message += F("Pressure: ");
80
-        message += String(bme.readPressure());
190
+        message += String(bme2.readPressure());
191
+    } else {
192
+        message += F("BME280 (high) not connected!");
81 193
     }
194
+    message += F("\n</p>\n");
82 195
 
196
+    message += F("\n<p>\n");
83 197
     if (found_sht) {
84
-        message += F("\n\n");
85 198
         message += F("SHT21:");
86
-        message += F("\n");
199
+        message += F("\n<br>\n");
87 200
         message += F("Temperature: ");
88 201
         message += String(sht.GetTemperature());
89
-        message += F("\n");
202
+        message += F("\n<br>\n");
90 203
         message += F("Humidity: ");
91 204
         message += String(sht.GetHumidity());
205
+    } else {
206
+        message += F("SHT21 not connected!");
92 207
     }
93
-
94
-    if ((!found_bme) && (!found_sht)) {
95
-        message += F("\n\n");
96
-        message += F("No Sensor available!");
208
+    message += F("\n</p>\n");
209
+
210
+    for (int i = 0; i < moisture_count(); i++) {
211
+        int moisture = moisture_read(i);
212
+        if (moisture < moisture_max()) {
213
+            message += F("\n<p>\n");
214
+            message += F("Sensor ");
215
+            message += String(i + 1);
216
+            message += F(":\n<br>\n");
217
+            message += F("Moisture: ");
218
+            message += String(moisture);
219
+            message += F(" / ");
220
+            message += String(moisture_max());
221
+            message += F("\n</p>\n");
222
+        }
223
+    }
224
+    
225
+    if (moisture_count() <= 0) {
226
+        message += F("\n<p>\n");
227
+        message += F("No moisture sensors configured!");
228
+        message += F("\n</p>\n");
97 229
     }
98 230
 
99
-    message += F("\n\n");
100
-    message += F("Try /update for OTA firmware updates!");
231
+    message += F("<p>\n");
232
+    message += F("Try <a href=\"/update\">/update</a> for OTA firmware updates!\n");
233
+    message += F("</p>\n");
234
+    
235
+    message += F("<p>\n");
236
+#ifdef ENABLE_INFLUXDB_LOGGING
237
+    message += F("InfluxDB: ");
238
+    message += INFLUXDB_DATABASE;
239
+    message += F(" @ ");
240
+    message += INFLUXDB_HOST;
241
+    message += F(":");
242
+    message += String(INFLUXDB_PORT);
101 243
     message += F("\n");
102
-
103
-    server.send(200, "text/plain", message);
244
+#else
245
+    message += F("InfluxDB logging not enabled!\n");
246
+#endif
247
+    message += F("</p>\n");
248
+    
249
+    message += F("<p><a href=\"/relaistest\">Relais Test</a></p>\n");
250
+    message += F("</body></html>\n");
251
+
252
+    server.send(200, "text/html", message);
104 253
 }
105 254
 
106 255
 void setup() {
107 256
     pinMode(BUILTIN_LED_PIN, OUTPUT);
257
+    
258
+    relais_init();
108 259
 
109 260
     // Blink LED for init
110 261
     for (int i = 0; i < 2; i++) {
@@ -113,26 +264,56 @@ void setup() {
113 264
         digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
114 265
         delay(LED_INIT_BLINK_INTERVAL);
115 266
     }
267
+    
268
+    moisture_init();
116 269
 
117 270
     // Init I2C and try to connect to sensors
118
-    Wire2.begin(2, 0);
119
-    found_bme = (!bme.begin(0x76, &Wire2)) ? false : true;
120
-    found_sht = sht.GetAlive();
271
+#if defined(ARDUINO_ARCH_ESP8266)
121 272
 
122
-#ifdef DONT_RUN_WITHOUT_SENSORS
123
-    if ((!found_bme) && (!found_sht)) {
124
-        // no sensor available
125
-        while (1) {
126
-            digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
127
-            delay(LED_ERROR_BLINK_INTERVAL);
128
-        }
129
-    }
130
-#endif // DONT_RUN_WITHOUT_SENSORS
273
+    Wire2.begin(I2C_SDA_PIN, I2C_SCL_PIN);
274
+    found_bme1 = (!bme1.begin(BME_I2C_ADDRESS_1, &Wire2)) ? false : true;
275
+    found_bme2 = (!bme2.begin(BME_I2C_ADDRESS_2, &Wire2)) ? false : true;
276
+
277
+#elif defined(ARDUINO_ARCH_ESP32)
278
+
279
+    Wire.begin();
280
+    found_bme1 = (!bme1.begin(BME_I2C_ADDRESS_1, &Wire)) ? false : true;
281
+    found_bme2 = (!bme2.begin(BME_I2C_ADDRESS_2, &Wire)) ? false : true;
282
+
283
+#endif
131 284
 
132
-    // Set hostname
285
+    found_sht = sht.GetAlive();
286
+
287
+    // Build hostname string
133 288
     String hostname = SENSOR_HOSTNAME_PREFIX;
134 289
     hostname += sensor_location;
290
+
291
+#if defined(ARDUINO_ARCH_ESP8266)
292
+
293
+    // Connect to WiFi AP
135 294
     WiFi.hostname(hostname);
295
+    WiFi.mode(WIFI_STA);
296
+    WiFi.begin(ssid, password);
297
+    while (WiFi.status() != WL_CONNECTED) {
298
+        delay(LED_CONNECT_BLINK_INTERVAL);
299
+        digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
300
+    }
301
+    
302
+#elif defined(ARDUINO_ARCH_ESP32)
303
+
304
+    // Set hostname workaround
305
+    WiFi.config(INADDR_NONE, INADDR_NONE, INADDR_NONE);
306
+    WiFi.setHostname(hostname.c_str());
307
+    
308
+    // Workaround for WiFi connecting only every 2nd reset
309
+    // https://github.com/espressif/arduino-esp32/issues/2501#issuecomment-513602522
310
+    WiFi.onEvent([](WiFiEvent_t event, WiFiEventInfo_t info) {
311
+        if (info.disconnected.reason == 202) {
312
+            esp_sleep_enable_timer_wakeup(10);
313
+            esp_deep_sleep_start();
314
+            delay(100);
315
+        }
316
+    }, WiFiEvent_t::SYSTEM_EVENT_STA_DISCONNECTED);
136 317
 
137 318
     // Connect to WiFi AP
138 319
     WiFi.mode(WIFI_STA);
@@ -141,46 +322,75 @@ void setup() {
141 322
         delay(LED_CONNECT_BLINK_INTERVAL);
142 323
         digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
143 324
     }
325
+    
326
+    // Set hostname workaround
327
+    WiFi.setHostname(hostname.c_str());
328
+
329
+#endif
144 330
 
145
-#ifdef ENABLE_DATABASE_WRITES
331
+#ifdef ENABLE_INFLUXDB_LOGGING
146 332
     // Setup InfluxDB Client
147 333
     influx.setDb(INFLUXDB_DATABASE);
148
-#endif // ENABLE_DATABASE_WRITES
334
+#endif // ENABLE_INFLUXDB_LOGGING
149 335
 
150 336
     // Setup HTTP Server
151
-    MDNS.begin(hostname);
337
+    MDNS.begin(hostname.c_str());
152 338
     updater.setup(&server);
153 339
     server.on("/", handleRoot);
340
+    server.on("/relaistest", handleRelaisTest);
154 341
     server.begin();
155 342
     MDNS.addService("http", "tcp", 80);
156 343
 }
157 344
 
158 345
 void handleServers() {
159 346
     server.handleClient();
347
+    
348
+#if defined(ARDUINO_ARCH_ESP8266)
160 349
     MDNS.update();
350
+#endif
351
+}
352
+
353
+static boolean writeMeasurement(InfluxData &measurement) {
354
+    boolean success = influx.write(measurement);
355
+    if (!success) {
356
+        error_count++;
357
+        for (int i = 0; i < 10; i++) {
358
+            digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
359
+            delay(LED_ERROR_BLINK_INTERVAL);
360
+            digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
361
+            delay(LED_ERROR_BLINK_INTERVAL);
362
+        }
363
+    }
364
+    return success;
161 365
 }
162 366
 
163
-#ifdef ENABLE_DATABASE_WRITES
367
+#ifdef ENABLE_INFLUXDB_LOGGING
164 368
 void writeDatabase() {
165
-    if (found_bme) {
369
+    if (found_bme1) {
166 370
         InfluxData measurement("environment");
167 371
         measurement.addTag("location", sensor_location);
372
+        measurement.addTag("placement", "1");
168 373
         measurement.addTag("device", WiFi.macAddress());
169 374
         measurement.addTag("sensor", "bme280");
170 375
 
171
-        measurement.addValue("temperature", bme.readTemperature());
172
-        measurement.addValue("pressure", bme.readPressure());
173
-        measurement.addValue("humidity", bme.readHumidity());
174
-
175
-        boolean success = influx.write(measurement);
176
-        if (!success) {
177
-            for (int i = 0; i < 10; i++) {
178
-                digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
179
-                delay(LED_ERROR_BLINK_INTERVAL);
180
-                digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
181
-                delay(LED_ERROR_BLINK_INTERVAL);
182
-            }
183
-        }
376
+        measurement.addValue("temperature", bme1.readTemperature());
377
+        measurement.addValue("pressure", bme1.readPressure());
378
+        measurement.addValue("humidity", bme1.readHumidity());
379
+
380
+        writeMeasurement(measurement);
381
+    }
382
+    if (found_bme2) {
383
+        InfluxData measurement("environment");
384
+        measurement.addTag("location", sensor_location);
385
+        measurement.addTag("placement", "2");
386
+        measurement.addTag("device", WiFi.macAddress());
387
+        measurement.addTag("sensor", "bme280");
388
+
389
+        measurement.addValue("temperature", bme2.readTemperature());
390
+        measurement.addValue("pressure", bme2.readPressure());
391
+        measurement.addValue("humidity", bme2.readHumidity());
392
+
393
+        writeMeasurement(measurement);
184 394
     }
185 395
 
186 396
     if (found_sht) {
@@ -192,39 +402,52 @@ void writeDatabase() {
192 402
         measurement.addValue("temperature", sht.GetTemperature());
193 403
         measurement.addValue("humidity", sht.GetHumidity());
194 404
 
195
-        boolean success = influx.write(measurement);
196
-        if (!success) {
197
-            for (int i = 0; i < 10; i++) {
198
-                digitalWrite(BUILTIN_LED_PIN, LOW); // LED on
199
-                delay(LED_ERROR_BLINK_INTERVAL);
200
-                digitalWrite(BUILTIN_LED_PIN, HIGH); // LED off
201
-                delay(LED_ERROR_BLINK_INTERVAL);
202
-            }
405
+        writeMeasurement(measurement);
406
+    }
407
+    
408
+    for (int i = 0; i < moisture_count(); i++) {
409
+        int moisture = moisture_read(i);
410
+        if (moisture < moisture_max()) {
411
+            InfluxData measurement("moisture");
412
+            measurement.addTag("location", sensor_location);
413
+            measurement.addTag("device", WiFi.macAddress());
414
+            measurement.addTag("sensor", String(i + 1));
415
+
416
+            measurement.addValue("value", moisture);
417
+            measurement.addValue("maximum", moisture_max());
418
+
419
+            writeMeasurement(measurement);
203 420
         }
204 421
     }
205 422
 }
206
-#endif // ENABLE_DATABASE_WRITES
423
+#endif // ENABLE_INFLUXDB_LOGGING
207 424
 
208 425
 void loop() {
209 426
     unsigned long time = millis();
427
+    
428
+    relais_run();
210 429
 
211 430
     if ((time - last_server_handle_time) >= SERVER_HANDLE_INTERVAL) {
212 431
         last_server_handle_time = time;
213 432
         handleServers();
214 433
     }
215 434
 
216
-#ifdef ENABLE_DATABASE_WRITES
435
+#ifdef ENABLE_INFLUXDB_LOGGING
217 436
     if ((time - last_db_write_time) >= DB_WRITE_INTERVAL) {
218 437
         last_db_write_time = time;
219 438
         writeDatabase();
220 439
     }
221
-#endif // ENABLE_DATABASE_WRITES
440
+    
441
+#ifdef INFLUX_MAX_ERRORS_RESET
442
+    if (error_count >= INFLUX_MAX_ERRORS_RESET) {
443
+        ESP.restart();
444
+    }
445
+#endif // INFLUX_MAX_ERRORS_RESET
446
+#endif // ENABLE_INFLUXDB_LOGGING
222 447
 
223
-#ifdef ENABLE_LED_HEARTBEAT_BLINK
224 448
     if ((time - last_led_blink_time) >= LED_BLINK_INTERVAL) {
225 449
         last_led_blink_time = time;
226 450
         digitalWrite(BUILTIN_LED_PIN, !digitalRead(BUILTIN_LED_PIN));
227 451
     }
228
-#endif // ENABLE_LED_HEARTBEAT_BLINK
229 452
 }
230 453
 

+ 83
- 0
src/moisture.cpp Просмотреть файл

@@ -0,0 +1,83 @@
1
+/*
2
+ * moisture.cpp
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#include <Arduino.h>
15
+#include "moisture.h"
16
+
17
+#if defined(ARDUINO_ARCH_ESP8266)
18
+
19
+int moisture_count(void) {
20
+    return 0;
21
+}
22
+
23
+int moisture_read(int sensor) {
24
+    return 0;
25
+}
26
+
27
+int moisture_max(void) {
28
+    return 0;
29
+}
30
+
31
+void moisture_init(void) { }
32
+
33
+#elif defined(ARDUINO_ARCH_ESP32)
34
+
35
+#include <driver/adc.h>
36
+
37
+#define ADC_OVERSAMPLE 20
38
+#define ADC_BITWIDTH 12
39
+#define ADC_BITS ADC_WIDTH_BIT_12
40
+#define ADC_ATTENUATION ADC_ATTEN_DB_11
41
+
42
+#define SENSOR_COUNT 6
43
+adc1_channel_t sensor_pin[SENSOR_COUNT] = {
44
+    ADC1_CHANNEL_0, ADC1_CHANNEL_3,
45
+    ADC1_CHANNEL_6, ADC1_CHANNEL_7,
46
+    ADC1_CHANNEL_4, ADC1_CHANNEL_5
47
+};
48
+
49
+static int adc_read_oversampled(adc1_channel_t pin) {
50
+    uint32_t sample_sum = 0;
51
+    
52
+    for (int i = 0; i < ADC_OVERSAMPLE; i++) {
53
+        sample_sum += adc1_get_raw(pin);
54
+    }
55
+    
56
+    return sample_sum / ADC_OVERSAMPLE;
57
+}
58
+
59
+int moisture_count(void) {
60
+    return SENSOR_COUNT;
61
+}
62
+
63
+int moisture_read(int sensor) {
64
+    if ((sensor < 0) || (sensor > SENSOR_COUNT)) {
65
+        return -1;
66
+    }
67
+    
68
+    return adc_read_oversampled(sensor_pin[sensor]);
69
+}
70
+
71
+int moisture_max(void) {
72
+    return (1 << ADC_BITWIDTH) - 1;
73
+}
74
+
75
+void moisture_init(void) {
76
+    adc1_config_width(ADC_BITS);
77
+    for (int i = 0; i < SENSOR_COUNT; i++) {
78
+        adc1_config_channel_atten(sensor_pin[i], ADC_ATTENUATION);
79
+    }
80
+}
81
+
82
+#endif
83
+

+ 83
- 0
src/relais.cpp Просмотреть файл

@@ -0,0 +1,83 @@
1
+/*
2
+ * relais.cpp
3
+ *
4
+ * ESP8266 / ESP32 Environmental Sensor
5
+ *
6
+ * ----------------------------------------------------------------------------
7
+ * "THE BEER-WARE LICENSE" (Revision 42):
8
+ * <xythobuz@xythobuz.de> wrote this file.  As long as you retain this notice
9
+ * you can do whatever you want with this stuff. If we meet some day, and you
10
+ * think this stuff is worth it, you can buy me a beer in return.   Thomas Buck
11
+ * ----------------------------------------------------------------------------
12
+ */
13
+
14
+#include <Arduino.h>
15
+#include "relais.h"
16
+
17
+#if defined(ARDUINO_ARCH_ESP8266)
18
+
19
+int relais_count(void) {
20
+    return 0;
21
+}
22
+
23
+int relais_enable(int relais, unsigned long time) {
24
+    return 0;
25
+}
26
+
27
+void relais_init(void) { }
28
+void relais_run(void) { }
29
+
30
+#elif defined(ARDUINO_ARCH_ESP32)
31
+
32
+#define RELAIS_COUNT 10
33
+
34
+struct relais_state {
35
+    unsigned long turn_off;
36
+};
37
+
38
+static struct relais_state state[RELAIS_COUNT];
39
+static int gpios[RELAIS_COUNT] = {
40
+    0, 15, 2, 4,
41
+    16, 17, 5, 18,
42
+    19, 23
43
+};
44
+
45
+static void relais_set(int relais, int state) {
46
+    digitalWrite(gpios[relais], state ? LOW : HIGH);
47
+}
48
+
49
+int relais_count(void) {
50
+    return RELAIS_COUNT;
51
+}
52
+
53
+int relais_enable(int relais, unsigned long time) {
54
+    if ((relais < 0) || (relais >= RELAIS_COUNT)) {
55
+        return -1;
56
+    }
57
+    
58
+    relais_set(relais, 1);
59
+    state[relais].turn_off = millis() + time;
60
+    return 0;
61
+}
62
+
63
+void relais_init(void) {
64
+    for (int i = 0; i < RELAIS_COUNT; i++) {
65
+        pinMode(gpios[i], OUTPUT);
66
+        relais_set(i, 0);
67
+        
68
+        state[i].turn_off = 0;
69
+    }
70
+}
71
+
72
+void relais_run(void) {
73
+    for (int i = 0; i < RELAIS_COUNT; i++) {
74
+        if (state[i].turn_off > 0) {
75
+            if (millis() >= state[i].turn_off) {
76
+                relais_set(i, 0);
77
+            }
78
+        }
79
+    }
80
+}
81
+
82
+#endif
83
+

Загрузка…
Отмена
Сохранить