|
@ -42,6 +42,10 @@ uint8_t temprature_sens_read(); |
|
|
|
|
|
|
|
|
static const char* TAG = "MAIN"; |
|
|
static const char* TAG = "MAIN"; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define TIME_TO_SLEEP 60 // seconds
|
|
|
|
|
|
constexpr unsigned int dhcp_interval = 60*60; |
|
|
|
|
|
|
|
|
WiFiMulti wifiMulti; |
|
|
WiFiMulti wifiMulti; |
|
|
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display(GxEPD2_213_B72(/*CS=SS*/ TFT_CS, /*DC=*/ TFT_DC, /*RST=*/ TFT_RST, /*BUSY=*/ -1)); // GDEH0213B72
|
|
|
GxEPD2_BW<GxEPD2_213_B72, GxEPD2_213_B72::HEIGHT> display(GxEPD2_213_B72(/*CS=SS*/ TFT_CS, /*DC=*/ TFT_DC, /*RST=*/ TFT_RST, /*BUSY=*/ -1)); // GDEH0213B72
|
|
|
static constexpr uint8_t y_offset = 6; |
|
|
static constexpr uint8_t y_offset = 6; |
|
@ -56,6 +60,18 @@ BH1750 lightMeter; |
|
|
XD0OTA ota("esp32-weatherstation"); |
|
|
XD0OTA ota("esp32-weatherstation"); |
|
|
XD0MQTT mqtt; |
|
|
XD0MQTT mqtt; |
|
|
|
|
|
|
|
|
|
|
|
struct __attribute__((packed)) network_t { |
|
|
|
|
|
uint32_t ip; |
|
|
|
|
|
uint32_t dns; |
|
|
|
|
|
uint32_t gateway; |
|
|
|
|
|
uint32_t subnet; |
|
|
|
|
|
char ssid[64]; |
|
|
|
|
|
char password[64]; |
|
|
|
|
|
int32_t channel; |
|
|
|
|
|
time_t last_dhcp; |
|
|
|
|
|
}; |
|
|
|
|
|
RTC_DATA_ATTR network_t network; |
|
|
|
|
|
|
|
|
struct __attribute__((packed)) sensor_readings_t { |
|
|
struct __attribute__((packed)) sensor_readings_t { |
|
|
float temperature = NAN; // °C
|
|
|
float temperature = NAN; // °C
|
|
|
float humidity = NAN; // %H
|
|
|
float humidity = NAN; // %H
|
|
@ -79,15 +95,111 @@ sensor_readings_t sensors_a4cf1211c3e4, sensors_246f28d1fa5c, sensors_246f28d1a0 |
|
|
|
|
|
|
|
|
SensorHistory history_pressure(30); |
|
|
SensorHistory history_pressure(30); |
|
|
|
|
|
|
|
|
uint32_t lastDisplayUpdate = 0; |
|
|
RTC_DATA_ATTR time_t lastDisplayRefresh = 0; |
|
|
uint32_t lastDisplayRefresh = 0; |
|
|
struct __attribute__((packed)) sensors_active_t { |
|
|
bool bme280_active = false; |
|
|
bool bme280 = false; |
|
|
bool bme680_active = false; |
|
|
bool bme680 = false; |
|
|
bool uv_active = false; |
|
|
bool uv = false; |
|
|
bool light_active = false; |
|
|
bool light = false; |
|
|
bool sds_active = false; |
|
|
bool sds = false; |
|
|
|
|
|
}; |
|
|
|
|
|
RTC_DATA_ATTR sensors_active_t sensors_active; |
|
|
|
|
|
|
|
|
float station_height = 0; |
|
|
float station_height = 0; |
|
|
|
|
|
RTC_DATA_ATTR int bootCount = 0; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
time_t getTimestamp() { |
|
|
|
|
|
struct timeval tv; |
|
|
|
|
|
gettimeofday(&tv, NULL); |
|
|
|
|
|
return tv.tv_sec; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void poweroffDevices() { |
|
|
|
|
|
display.powerOff(); |
|
|
|
|
|
|
|
|
|
|
|
// ToDo: Sensors
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void gotoSleep(unsigned int sleep_time = TIME_TO_SLEEP) { |
|
|
|
|
|
mqtt.end(); |
|
|
|
|
|
WiFi.disconnect(); |
|
|
|
|
|
WiFi.mode(WIFI_OFF); |
|
|
|
|
|
|
|
|
|
|
|
poweroffDevices(); |
|
|
|
|
|
|
|
|
|
|
|
//rtc_gpio_isolate(GPIO_NUM_12);
|
|
|
|
|
|
|
|
|
|
|
|
esp_sleep_enable_timer_wakeup(sleep_time * 1000000LL); |
|
|
|
|
|
esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_OFF); |
|
|
|
|
|
Serial.println("going to to sleep for " + String(sleep_time) + |
|
|
|
|
|
" Seconds"); |
|
|
|
|
|
Serial.flush(); |
|
|
|
|
|
esp_deep_sleep_start(); |
|
|
|
|
|
delay(1); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
void wifiConnect() { |
|
|
|
|
|
WiFi.persistent(false); |
|
|
|
|
|
WiFi.setHostname("esp32-weatherstation"); |
|
|
|
|
|
|
|
|
|
|
|
wifiMulti.addAP(WIFI_SSID, WIFI_PASSWD); |
|
|
|
|
|
wifiMulti.addAP(WIFI_SSID2, WIFI_PASSWD2); |
|
|
|
|
|
wifiMulti.addAP(WIFI_SSID3, WIFI_PASSWD3); |
|
|
|
|
|
|
|
|
|
|
|
IPAddress ip = IPAddress(network.ip); |
|
|
|
|
|
IPAddress dns = IPAddress(network.dns); |
|
|
|
|
|
IPAddress subnet = IPAddress(network.subnet); |
|
|
|
|
|
IPAddress gateway = IPAddress(network.gateway); |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("previous dhcp: " + String(getTimestamp() - network.last_dhcp) + "s ago"); |
|
|
|
|
|
|
|
|
|
|
|
if ( ip != INADDR_NONE && dns != INADDR_NONE && gateway != INADDR_NONE && subnet != INADDR_NONE |
|
|
|
|
|
&& ((ip[0] == 192 && ip[1] == 168) || (ip[0] == 172 && ip[1] == 16)) |
|
|
|
|
|
&& strlen(network.ssid) > 0 && strlen(network.password) > 0 |
|
|
|
|
|
&& (getTimestamp() - network.last_dhcp < dhcp_interval) |
|
|
|
|
|
) { |
|
|
|
|
|
|
|
|
|
|
|
ESP_LOGD("WiFi", "STATIC IP"); |
|
|
|
|
|
WiFi.config(ip, gateway, subnet, dns); |
|
|
|
|
|
WiFi.begin(network.ssid, network.password, network.channel); |
|
|
|
|
|
for (int tries=0; WiFi.status() != WL_CONNECTED && tries < 10; tries++) { |
|
|
|
|
|
ESP_LOGD("WiFi", "."); |
|
|
|
|
|
delay(500); |
|
|
|
|
|
} |
|
|
|
|
|
} else { |
|
|
|
|
|
ESP_LOGD("WiFi", "DHCP"); |
|
|
|
|
|
for (int tries=0; wifiMulti.run() != WL_CONNECTED && tries < 20; tries++) { |
|
|
|
|
|
Serial.print("."); |
|
|
|
|
|
delay(500); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
network.ip = (uint32_t)WiFi.localIP(); |
|
|
|
|
|
network.dns = (uint32_t)WiFi.dnsIP(); |
|
|
|
|
|
network.gateway = (uint32_t)WiFi.gatewayIP(); |
|
|
|
|
|
network.subnet = (uint32_t)WiFi.subnetMask(); |
|
|
|
|
|
strncpy(network.ssid, WiFi.SSID().c_str(), 64); |
|
|
|
|
|
strncpy(network.password, WiFi.psk().c_str(), 64); |
|
|
|
|
|
network.channel = WiFi.channel(); |
|
|
|
|
|
network.last_dhcp = getTimestamp(); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
|
|
|
if(WiFi.status() == WL_CONNECTED) { |
|
|
|
|
|
ESP_LOGD("WiFi", "connected"); |
|
|
|
|
|
//ESP_LOGD("WiFi", (WiFi.localIP().toString().c_str()));
|
|
|
|
|
|
|
|
|
|
|
|
} else { |
|
|
|
|
|
ESP_LOGE("WiFi", "could not connect to WiFi"); |
|
|
|
|
|
ESP_LOGE(TAG, "restarting"); |
|
|
|
|
|
ESP.restart(); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void helloWorld() |
|
|
void helloWorld() |
|
|
{ |
|
|
{ |
|
@ -101,7 +213,11 @@ void helloWorld() |
|
|
// center bounding box by transposition of origin:
|
|
|
// center bounding box by transposition of origin:
|
|
|
uint16_t x = ((display.width() - tbw) / 2) - tbx; |
|
|
uint16_t x = ((display.width() - tbw) / 2) - tbx; |
|
|
uint16_t y = ((display.height() - tbh) / 2) - tby; |
|
|
uint16_t y = ((display.height() - tbh) / 2) - tby; |
|
|
display.setFullWindow(); |
|
|
if (display.epd2.hasFastPartialUpdate) { |
|
|
|
|
|
display.setPartialWindow(0, 0, display.width(), display.height()); |
|
|
|
|
|
} else { |
|
|
|
|
|
display.setFullWindow(); |
|
|
|
|
|
} |
|
|
display.firstPage(); |
|
|
display.firstPage(); |
|
|
do |
|
|
do |
|
|
{ |
|
|
{ |
|
@ -139,13 +255,14 @@ void getTime(char* ptr, size_t maxsize, const char* format) { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void getSensorMeasurements() { |
|
|
void getSensorMeasurements() { |
|
|
if (bme280_active) { |
|
|
if (sensors_active.bme280) { |
|
|
bme280.takeForcedMeasurement(); |
|
|
bme280.takeForcedMeasurement(); |
|
|
sensor_readings.temperature = bme280.readTemperature(); |
|
|
sensor_readings.temperature = bme280.readTemperature(); |
|
|
sensor_readings.humidity = bme280.readHumidity(); |
|
|
sensor_readings.humidity = bme280.readHumidity(); |
|
|
sensor_readings.pressure_raw = bme280.readPressure(); |
|
|
sensor_readings.pressure_raw = bme280.readPressure(); |
|
|
} |
|
|
} |
|
|
if (bme680_active) { |
|
|
if (sensors_active.bme680) { |
|
|
|
|
|
bme680.endReading(); // ToDo
|
|
|
if (bme680.performReading()) { |
|
|
if (bme680.performReading()) { |
|
|
sensor_readings.temperature = bme680.temperature; |
|
|
sensor_readings.temperature = bme680.temperature; |
|
|
sensor_readings.humidity = bme680.humidity; |
|
|
sensor_readings.humidity = bme680.humidity; |
|
@ -174,13 +291,13 @@ void getSensorMeasurements() { |
|
|
|
|
|
|
|
|
history_pressure.addValue(sensor_readings.pressure); |
|
|
history_pressure.addValue(sensor_readings.pressure); |
|
|
|
|
|
|
|
|
if (uv_active) { |
|
|
if (sensors_active.uv) { |
|
|
sensor_readings.uvi = uv.readUVI(); |
|
|
sensor_readings.uvi = uv.readUVI(); |
|
|
sensor_readings.uva = uv.readUVA(); |
|
|
sensor_readings.uva = uv.readUVA(); |
|
|
sensor_readings.uvb = uv.readUVB(); |
|
|
sensor_readings.uvb = uv.readUVB(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (light_active) { |
|
|
if (sensors_active.light) { |
|
|
sensor_readings.lux = lightMeter.readLightLevel(); |
|
|
sensor_readings.lux = lightMeter.readLightLevel(); |
|
|
// auto-adjust sensitivity
|
|
|
// auto-adjust sensitivity
|
|
|
if (sensor_readings.lux < 0) { |
|
|
if (sensor_readings.lux < 0) { |
|
@ -200,7 +317,7 @@ void getSensorMeasurements() { |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sds_active) { |
|
|
if (sensors_active.sds) { |
|
|
PmResult pm = sds.readPm(); |
|
|
PmResult pm = sds.readPm(); |
|
|
if (pm.isOk()) { |
|
|
if (pm.isOk()) { |
|
|
sensor_readings.pm10 = pm.pm10; |
|
|
sensor_readings.pm10 = pm.pm10; |
|
@ -354,7 +471,7 @@ void displayValues() { |
|
|
display.printf("%.1f k\xe9", sensor_readings.voc / 1000.0F); |
|
|
display.printf("%.1f k\xe9", sensor_readings.voc / 1000.0F); |
|
|
// PM
|
|
|
// PM
|
|
|
float pm10, pm25; |
|
|
float pm10, pm25; |
|
|
if (sds_active) { |
|
|
if (sensors_active.sds) { |
|
|
pm10 = sensor_readings.pm10; |
|
|
pm10 = sensor_readings.pm10; |
|
|
pm25 = sensor_readings.pm25; |
|
|
pm25 = sensor_readings.pm25; |
|
|
} else if (!isnan(sensors_a4cf1211c3e4.pm10) || !isnan(sensors_a4cf1211c3e4.pm25)) { |
|
|
} else if (!isnan(sensors_a4cf1211c3e4.pm10) || !isnan(sensors_a4cf1211c3e4.pm25)) { |
|
@ -378,7 +495,7 @@ void displayValues() { |
|
|
display.printf("%.1f", pm25); |
|
|
display.printf("%.1f", pm25); |
|
|
// Lux
|
|
|
// Lux
|
|
|
float lux; |
|
|
float lux; |
|
|
if (light_active) { |
|
|
if (sensors_active.light) { |
|
|
lux = sensor_readings.lux; |
|
|
lux = sensor_readings.lux; |
|
|
} else if (!isnan(sensors_a4cf1211c3e4.lux)) { |
|
|
} else if (!isnan(sensors_a4cf1211c3e4.lux)) { |
|
|
lux = sensors_a4cf1211c3e4.lux; |
|
|
lux = sensors_a4cf1211c3e4.lux; |
|
@ -395,7 +512,7 @@ void displayValues() { |
|
|
display.printf("%.1f lx", lux); |
|
|
display.printf("%.1f lx", lux); |
|
|
// UV
|
|
|
// UV
|
|
|
float uvi, uva, uvb; |
|
|
float uvi, uva, uvb; |
|
|
if (uv_active) { |
|
|
if (sensors_active.uv) { |
|
|
uvi = sensor_readings.uvi; |
|
|
uvi = sensor_readings.uvi; |
|
|
uva = sensor_readings.uva; |
|
|
uva = sensor_readings.uva; |
|
|
uvb = sensor_readings.uvb; |
|
|
uvb = sensor_readings.uvb; |
|
@ -449,7 +566,7 @@ void displayValues() { |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void printValues() { |
|
|
void printValues() { |
|
|
if (bme280_active || bme680_active) { |
|
|
if (sensors_active.bme280 || sensors_active.bme680) { |
|
|
#define SEALEVELPRESSURE_HPA (1013.25) |
|
|
#define SEALEVELPRESSURE_HPA (1013.25) |
|
|
Serial.print("Temperature = "); |
|
|
Serial.print("Temperature = "); |
|
|
Serial.print(sensor_readings.temperature); |
|
|
Serial.print(sensor_readings.temperature); |
|
@ -468,7 +585,7 @@ void printValues() { |
|
|
Serial.println(" %"); |
|
|
Serial.println(" %"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (bme680_active) { |
|
|
if (sensors_active.bme680) { |
|
|
Serial.print("VOC = "); |
|
|
Serial.print("VOC = "); |
|
|
Serial.print(sensor_readings.voc / 1000.0F); |
|
|
Serial.print(sensor_readings.voc / 1000.0F); |
|
|
Serial.println(" kOhm"); |
|
|
Serial.println(" kOhm"); |
|
@ -476,14 +593,14 @@ void printValues() { |
|
|
|
|
|
|
|
|
Serial.println(); |
|
|
Serial.println(); |
|
|
|
|
|
|
|
|
if (uv_active) { |
|
|
if (sensors_active.uv) { |
|
|
Serial.print("UV Index reading: "); Serial.println(sensor_readings.uvi); |
|
|
Serial.print("UV Index reading: "); Serial.println(sensor_readings.uvi); |
|
|
Serial.print("Raw UVA reading: "); Serial.println(sensor_readings.uva); |
|
|
Serial.print("Raw UVA reading: "); Serial.println(sensor_readings.uva); |
|
|
Serial.print("Raw UVB reading: "); Serial.println(sensor_readings.uvb); |
|
|
Serial.print("Raw UVB reading: "); Serial.println(sensor_readings.uvb); |
|
|
Serial.println(); |
|
|
Serial.println(); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sds_active) { |
|
|
if (sensors_active.sds) { |
|
|
Serial.print("PM2.5 = "); |
|
|
Serial.print("PM2.5 = "); |
|
|
Serial.print(sensor_readings.pm25); |
|
|
Serial.print(sensor_readings.pm25); |
|
|
Serial.print(", PM10 = "); |
|
|
Serial.print(", PM10 = "); |
|
@ -499,63 +616,56 @@ void printValues() { |
|
|
|
|
|
|
|
|
void sendValues() { |
|
|
void sendValues() { |
|
|
/* send values MQTT */ |
|
|
/* send values MQTT */ |
|
|
if (bme280_active || bme680_active) { |
|
|
if (sensors_active.bme280 || sensors_active.bme680) { |
|
|
String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); |
|
|
String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); |
|
|
String topic_humidity = String("thomas/sensor/") + ota.getMAC() + String("/humidity"); |
|
|
String topic_humidity = String("thomas/sensor/") + ota.getMAC() + String("/humidity"); |
|
|
String topic_pressure = String("thomas/sensor/") + ota.getMAC() + String("/pressure"); |
|
|
String topic_pressure = String("thomas/sensor/") + ota.getMAC() + String("/pressure"); |
|
|
mqtt.publishf(topic_temperature.c_str(), "%.2f", sensor_readings.temperature); |
|
|
mqtt.publishf2(topic_temperature.c_str(), 1, 1, "%.2f", sensor_readings.temperature); |
|
|
delay(10); |
|
|
delay(10); |
|
|
mqtt.publishf(topic_humidity.c_str(), "%.2f", sensor_readings.humidity); |
|
|
mqtt.publishf2(topic_humidity.c_str(), 1, 1, "%.2f", sensor_readings.humidity); |
|
|
delay(10); |
|
|
delay(10); |
|
|
mqtt.publishf(topic_pressure.c_str(), "%.2f", sensor_readings.pressure); |
|
|
mqtt.publishf2(topic_pressure.c_str(), 1, 1, "%.2f", sensor_readings.pressure); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
if (bme680_active) { |
|
|
if (sensors_active.bme680) { |
|
|
String topic_voc = String("thomas/sensor/") + ota.getMAC() + String("/voc"); |
|
|
String topic_voc = String("thomas/sensor/") + ota.getMAC() + String("/voc"); |
|
|
mqtt.publishf(topic_voc.c_str(), "%.2f", sensor_readings.voc / 1000.0F); |
|
|
mqtt.publishf2(topic_voc.c_str(), 1, 1, "%.2f", sensor_readings.voc / 1000.0F); |
|
|
delay(10); |
|
|
|
|
|
} |
|
|
|
|
|
if (!bme280_active && !bme680_active) { |
|
|
|
|
|
String topic_temperature = String("thomas/sensor/") + ota.getMAC() + String("/temperature"); |
|
|
|
|
|
float esp32_temperature = (temprature_sens_read() - 32) / 1.8; |
|
|
|
|
|
char temperature[8]; sprintf(temperature, "%.2f", esp32_temperature-29.40); |
|
|
|
|
|
mqtt.publish(topic_temperature.c_str(), temperature, strlen(temperature)); |
|
|
|
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (uv_active) { |
|
|
if (sensors_active.uv) { |
|
|
String topic_uvi = String("thomas/sensor/") + ota.getMAC() + String("/uvi"); |
|
|
String topic_uvi = String("thomas/sensor/") + ota.getMAC() + String("/uvi"); |
|
|
String topic_uva = String("thomas/sensor/") + ota.getMAC() + String("/uva"); |
|
|
String topic_uva = String("thomas/sensor/") + ota.getMAC() + String("/uva"); |
|
|
String topic_uvb = String("thomas/sensor/") + ota.getMAC() + String("/uvb"); |
|
|
String topic_uvb = String("thomas/sensor/") + ota.getMAC() + String("/uvb"); |
|
|
mqtt.publishf(topic_uvi.c_str(), "%.2f", sensor_readings.uvi); |
|
|
mqtt.publishf2(topic_uvi.c_str(), 1, 1, "%.2f", sensor_readings.uvi); |
|
|
mqtt.publishf(topic_uva.c_str(), "%.2f", sensor_readings.uva); |
|
|
mqtt.publishf2(topic_uva.c_str(), 1, 1, "%.2f", sensor_readings.uva); |
|
|
mqtt.publishf(topic_uvb.c_str(), "%.2f", sensor_readings.uvb); |
|
|
mqtt.publishf2(topic_uvb.c_str(), 1, 1, "%.2f", sensor_readings.uvb); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (light_active) { |
|
|
if (sensors_active.light) { |
|
|
String topic_lux = String("thomas/sensor/") + ota.getMAC() + String("/lux"); |
|
|
String topic_lux = String("thomas/sensor/") + ota.getMAC() + String("/lux"); |
|
|
mqtt.publishf(topic_lux.c_str(), "%.2f", sensor_readings.lux); |
|
|
mqtt.publishf2(topic_lux.c_str(), 1, 1, "%.2f", sensor_readings.lux); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if (sds_active) { |
|
|
if (sensors_active.sds) { |
|
|
String topic_pm10 = String("thomas/sensor/") + ota.getMAC() + String("/pm10"); |
|
|
String topic_pm10 = String("thomas/sensor/") + ota.getMAC() + String("/pm10"); |
|
|
String topic_pm25 = String("thomas/sensor/") + ota.getMAC() + String("/pm25"); |
|
|
String topic_pm25 = String("thomas/sensor/") + ota.getMAC() + String("/pm25"); |
|
|
mqtt.publishf(topic_pm10.c_str(), "%.2f", sensor_readings.pm10); |
|
|
mqtt.publishf2(topic_pm10.c_str(), 1, 1, "%.2f", sensor_readings.pm10); |
|
|
mqtt.publishf(topic_pm25.c_str(), "%.2f", sensor_readings.pm25); |
|
|
mqtt.publishf2(topic_pm25.c_str(), 1, 1, "%.2f", sensor_readings.pm25); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
{ |
|
|
String topic_battery = String("thomas/sensor/") + ota.getMAC() + String("/battery"); |
|
|
String topic_battery = String("thomas/sensor/") + ota.getMAC() + String("/battery"); |
|
|
mqtt.publishf(topic_battery.c_str(), "%.2f", (sensor_readings.battery/4096.0)*2*3.42); |
|
|
mqtt.publishf2(topic_battery.c_str(), 1, 1, "%.2f", (sensor_readings.battery/4096.0)*2*3.42); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
{ |
|
|
{ |
|
|
String topic_rssi = String("thomas/sensor/") + ota.getMAC() + String("/rssi"); |
|
|
String topic_rssi = String("thomas/sensor/") + ota.getMAC() + String("/rssi"); |
|
|
mqtt.publishf(topic_rssi.c_str(), "%d", sensor_readings.rssi); |
|
|
mqtt.publishf2(topic_rssi.c_str(), 1, 1, "%d", sensor_readings.rssi); |
|
|
delay(10); |
|
|
delay(10); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
@ -569,7 +679,11 @@ void sendValues() { |
|
|
void setup() |
|
|
void setup() |
|
|
{ |
|
|
{ |
|
|
Serial.begin(115200); |
|
|
Serial.begin(115200); |
|
|
delay(10); |
|
|
|
|
|
|
|
|
esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause(); |
|
|
|
|
|
++bootCount; |
|
|
|
|
|
Serial.println("Boot number: " + String(bootCount)); |
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "setup hardware and sensors"); |
|
|
ESP_LOGD(TAG, "setup hardware and sensors"); |
|
|
|
|
|
|
|
@ -583,20 +697,21 @@ void setup() |
|
|
adcAttachPin(_VBAT); |
|
|
adcAttachPin(_VBAT); |
|
|
adcStart(_VBAT); |
|
|
adcStart(_VBAT); |
|
|
|
|
|
|
|
|
// initialize e-paper display
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
SPI.begin(18, 19, 23, TFT_CS); // MISO is not connected to TFT_MISO!
|
|
|
|
|
|
display.init(); |
|
|
|
|
|
|
|
|
|
|
|
#define BME_SDA 21 |
|
|
#define BME_SDA 21 |
|
|
#define BME_SCL 22 |
|
|
#define BME_SCL 22 |
|
|
Wire.begin(BME_SDA, BME_SCL); |
|
|
Wire.begin(BME_SDA, BME_SCL); |
|
|
if (bme280.begin()) { |
|
|
if (bme280.begin()) { |
|
|
bme280_active = true; |
|
|
sensors_active.bme280 = true; |
|
|
} else { |
|
|
} else { |
|
|
ESP_LOGE(TAG, "Could not find a valid BME280 sensor, check wiring!"); |
|
|
ESP_LOGE(TAG, "Could not find a valid BME280 sensor, check wiring!"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
if (bme680.begin()) { |
|
|
if (bme680.begin()) { |
|
|
bme680_active = true; |
|
|
sensors_active.bme680 = true; |
|
|
|
|
|
|
|
|
// Set up oversampling and filter initialization
|
|
|
// Set up oversampling and filter initialization
|
|
|
bme680.setTemperatureOversampling(BME680_OS_8X); |
|
|
bme680.setTemperatureOversampling(BME680_OS_8X); |
|
@ -604,12 +719,15 @@ void setup() |
|
|
bme680.setPressureOversampling(BME680_OS_4X); |
|
|
bme680.setPressureOversampling(BME680_OS_4X); |
|
|
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3); |
|
|
bme680.setIIRFilterSize(BME680_FILTER_SIZE_3); |
|
|
bme680.setGasHeater(320, 150); // 320*C for 150 ms
|
|
|
bme680.setGasHeater(320, 150); // 320*C for 150 ms
|
|
|
|
|
|
bme680.beginReading(); |
|
|
} else { |
|
|
} else { |
|
|
ESP_LOGE(TAG, "Could not find a valid BME680 sensor, check wiring!"); |
|
|
ESP_LOGE(TAG, "Could not find a valid BME680 sensor, check wiring!"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
if (uv.begin()) { |
|
|
if (uv.begin()) { |
|
|
uv_active = true; |
|
|
sensors_active.uv = true; |
|
|
|
|
|
|
|
|
uv.setIntegrationTime(VEML6075_100MS); // Set the integration constant
|
|
|
uv.setIntegrationTime(VEML6075_100MS); // Set the integration constant
|
|
|
uv.setHighDynamic(true); // Set the high dynamic mode
|
|
|
uv.setHighDynamic(true); // Set the high dynamic mode
|
|
@ -622,55 +740,66 @@ void setup() |
|
|
Serial.println("Failed to communicate with VEML6075 sensor, check wiring?"); |
|
|
Serial.println("Failed to communicate with VEML6075 sensor, check wiring?"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
if (lightMeter.begin()) { |
|
|
if (lightMeter.begin()) { |
|
|
light_active = true; |
|
|
sensors_active.light = true; |
|
|
} else { |
|
|
} else { |
|
|
Serial.println("Failed to communicate with BH1750 sensor, check wiring?"); |
|
|
Serial.println("Failed to communicate with BH1750 sensor, check wiring?"); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
sds.begin(); |
|
|
sds.begin(); |
|
|
|
|
|
|
|
|
FirmwareVersionResult sds_fw = sds.queryFirmwareVersion(); |
|
|
Serial.println("millis(): " + String(millis())); |
|
|
if (sds_fw.isOk()) { |
|
|
|
|
|
sds_active = true; |
|
|
|
|
|
|
|
|
|
|
|
sds.setActiveReportingMode(); // ensures sensor is in 'active' reporting mode
|
|
|
if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { |
|
|
sds.setCustomWorkingPeriod(5); // sensor sends data every 3 minutes
|
|
|
FirmwareVersionResult sds_fw = sds.queryFirmwareVersion(); |
|
|
} else { |
|
|
if (sds_fw.isOk()) { |
|
|
Serial.println("Failed to communicate with SDS011 sensor, check wiring?"); |
|
|
sensors_active.sds = true; |
|
|
|
|
|
|
|
|
|
|
|
sds.setActiveReportingMode(); // ensures sensor is in 'active' reporting mode
|
|
|
|
|
|
sds.setCustomWorkingPeriod(5); // sensor sends data every 3 minutes
|
|
|
|
|
|
} else { |
|
|
|
|
|
Serial.println("Failed to communicate with SDS011 sensor, check wiring?"); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
//display.clearScreen();
|
|
|
Serial.println("millis(): " + String(millis())); |
|
|
//display.refresh();
|
|
|
|
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "displaying welcome screen"); |
|
|
// initialize e-paper display
|
|
|
helloWorld(); |
|
|
SPI.begin(18, 19, 23, TFT_CS); // MISO is not connected to TFT_MISO!
|
|
|
display.powerOff(); |
|
|
display.init(0, false, false); |
|
|
|
|
|
display.setRotation(1); |
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "connecting to WiFi"); |
|
|
Serial.println("millis(): " + String(millis())); |
|
|
|
|
|
|
|
|
WiFi.setHostname("esp32-weatherstation"); |
|
|
if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { |
|
|
|
|
|
// wakeup not caused by deep sleep
|
|
|
|
|
|
display.clearScreen(); |
|
|
|
|
|
display.refresh(); |
|
|
|
|
|
helloWorld(); |
|
|
|
|
|
display.powerOff(); |
|
|
|
|
|
} else { |
|
|
|
|
|
// wakeup by deep sleep
|
|
|
|
|
|
// displayValues();
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
wifiMulti.addAP(WIFI_SSID, WIFI_PASSWD); |
|
|
ESP_LOGD(TAG, "connecting to WiFi"); |
|
|
wifiMulti.addAP(WIFI_SSID2, WIFI_PASSWD2); |
|
|
Serial.println("millis(): " + String(millis())); |
|
|
wifiMulti.addAP(WIFI_SSID3, WIFI_PASSWD3); |
|
|
|
|
|
|
|
|
|
|
|
for (int tries=0; wifiMulti.run() != WL_CONNECTED && tries < 10; tries++) { |
|
|
wifiConnect(); |
|
|
Serial.print("."); |
|
|
|
|
|
delay(500); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
if(wifiMulti.run() == WL_CONNECTED) { |
|
|
WiFi.waitForConnectResult(); |
|
|
Serial.println(""); |
|
|
//displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height);
|
|
|
Serial.println("WiFi connected"); |
|
|
|
|
|
Serial.println("IP address: "); |
|
|
|
|
|
Serial.println(WiFi.localIP()); |
|
|
|
|
|
displayIcoPartial(ico_wifi16, display.width()-20, y_offset+0, ico_wifi16_width, ico_wifi16_height); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
ESP_LOGD(TAG, "trying to fetch over-the-air update"); |
|
|
if (wakeup_reason == ESP_SLEEP_WAKEUP_UNDEFINED || bootCount == 1) { |
|
|
if (WiFi.status() == WL_CONNECTED) { |
|
|
// wakeup not caused by deep sleep
|
|
|
ota.update(); |
|
|
ESP_LOGD(TAG, "trying to fetch over-the-air update"); |
|
|
|
|
|
if (WiFi.status() == WL_CONNECTED) { |
|
|
|
|
|
ota.update(); |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
WiFi.setSleep(true); |
|
|
WiFi.setSleep(true); |
|
@ -684,7 +813,6 @@ void setup() |
|
|
if (!ota.getMAC().equals("246f28d1eff4")) mqtt.subscribe("thomas/sensor/246f28d1eff4/#", receiveMqtt); |
|
|
if (!ota.getMAC().equals("246f28d1eff4")) mqtt.subscribe("thomas/sensor/246f28d1eff4/#", receiveMqtt); |
|
|
|
|
|
|
|
|
/* temp: publish version */ |
|
|
/* temp: publish version */ |
|
|
delay(5000); |
|
|
|
|
|
String topic_version = String("thomas/sensor/") + ota.getMAC() + String("/version"); |
|
|
String topic_version = String("thomas/sensor/") + ota.getMAC() + String("/version"); |
|
|
const char* fw_version_str = String(FW_VERSION).c_str(); |
|
|
const char* fw_version_str = String(FW_VERSION).c_str(); |
|
|
mqtt.publish(topic_version.c_str(), fw_version_str, strlen(fw_version_str)); |
|
|
mqtt.publish(topic_version.c_str(), fw_version_str, strlen(fw_version_str)); |
|
@ -705,27 +833,27 @@ void setup() |
|
|
*/ |
|
|
*/ |
|
|
void loop() |
|
|
void loop() |
|
|
{ |
|
|
{ |
|
|
/* Do an e-paper display refresh every 1 minutes */ |
|
|
/* if(wifiMulti.run() != WL_CONNECTED) {
|
|
|
if (millis() - lastDisplayUpdate >= 1*60*1000) { |
|
|
Serial.println("WiFi not connected!"); |
|
|
lastDisplayUpdate = millis(); |
|
|
delay(1000); |
|
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
/* Do a full refresh every hour */ |
|
|
/* Do a full refresh every hour */ |
|
|
if (millis() - lastDisplayRefresh >= 60*60*1000) { |
|
|
if (getTimestamp() - lastDisplayRefresh >= 60*60) { |
|
|
lastDisplayRefresh = millis(); |
|
|
Serial.printf("last display refresh :%ds ago", getTimestamp() - lastDisplayRefresh); |
|
|
display.clearScreen(); |
|
|
lastDisplayRefresh = getTimestamp(); |
|
|
display.refresh(); |
|
|
display.clearScreen(); |
|
|
} |
|
|
display.refresh(); |
|
|
|
|
|
|
|
|
getSensorMeasurements(); |
|
|
|
|
|
displayValues(); |
|
|
|
|
|
printValues(); |
|
|
|
|
|
sendValues(); |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
if(wifiMulti.run() != WL_CONNECTED) { |
|
|
getSensorMeasurements(); |
|
|
Serial.println("WiFi not connected!"); |
|
|
displayValues(); |
|
|
delay(1000); |
|
|
printValues(); |
|
|
} |
|
|
sendValues(); |
|
|
|
|
|
|
|
|
|
|
|
int runtime = millis()/1000; |
|
|
|
|
|
if (runtime < 0 || runtime >= TIME_TO_SLEEP) runtime = 0; |
|
|
|
|
|
|
|
|
|
|
|
gotoSleep(TIME_TO_SLEEP - runtime); |
|
|
delay(2000); |
|
|
delay(2000); |
|
|
} |
|
|
} |
|
|