@@ -110,6 +110,7 @@ String SOFTWARE_VERSION(SOFTWARE_VERSION_STR);
110
110
#include < Adafruit_SHT31.h>
111
111
#include < StreamString.h>
112
112
#include < DallasTemperature.h>
113
+ #include < SparkFun_SCD30_Arduino_Library.h>
113
114
#include < TinyGPS++.h>
114
115
#include " ./bmx280_i2c.h"
115
116
#include " ./sps30_i2c.h"
@@ -171,6 +172,7 @@ namespace cfg {
171
172
bool bmx280_read = BMX280_READ;
172
173
char height_above_sealevel[8 ] = " 0" ;
173
174
bool sht3x_read = SHT3X_READ;
175
+ bool scd30_read = SCD30_READ;
174
176
bool ds18b20_read = DS18B20_READ;
175
177
bool dnms_read = DNMS_READ;
176
178
char dnms_correction[LEN_DNMS_CORRECTION] = DNMS_CORRECTION;
@@ -250,6 +252,7 @@ bool htu21d_init_failed = false;
250
252
bool bmp_init_failed = false ;
251
253
bool bmx280_init_failed = false ;
252
254
bool sht3x_init_failed = false ;
255
+ bool scd30_init_failed = false ;
253
256
bool dnms_init_failed = false ;
254
257
bool gps_init_failed = false ;
255
258
bool airrohr_selftest_failed = false ;
@@ -321,6 +324,11 @@ Adafruit_SHT31 sht3x;
321
324
OneWire oneWire;
322
325
DallasTemperature ds18b20 (&oneWire);
323
326
327
+ /* ****************************************************************
328
+ * SCD30 declaration *
329
+ *****************************************************************/
330
+ SCD30 scd30;
331
+
324
332
/* ****************************************************************
325
333
* GPS declaration *
326
334
*****************************************************************/
@@ -378,6 +386,9 @@ float last_value_HTU21D_T = -128.0;
378
386
float last_value_HTU21D_H = -1.0 ;
379
387
float last_value_SHT3X_T = -128.0 ;
380
388
float last_value_SHT3X_H = -1.0 ;
389
+ float last_value_SCD30_T = -128.0 ;
390
+ float last_value_SCD30_H = -1.0 ;
391
+ uint16_t last_value_SCD30_CO2 = 0 ;
381
392
382
393
uint32_t sds_pm10_sum = 0 ;
383
394
uint32_t sds_pm25_sum = 0 ;
@@ -601,14 +612,12 @@ static void disable_unneeded_nmea() {
601
612
serialGPS->println (F (" $PUBX,40,VTG,0,0,0,0*5E" )); // Track made good and ground speed
602
613
}
603
614
604
-
605
615
/* ****************************************************************
606
616
* read config from spiffs *
607
617
*****************************************************************/
608
618
609
619
/* backward compatibility for the times when we stored booleans as strings */
610
- static bool boolFromJSON (const DynamicJsonDocument& json, const __FlashStringHelper* key)
611
- {
620
+ static bool boolFromJSON (const DynamicJsonDocument& json, const __FlashStringHelper* key) {
612
621
if (json[key].is <char *>()) {
613
622
return !strcmp_P (json[key].as <char *>(), PSTR (" true" ));
614
623
}
@@ -838,11 +847,9 @@ static float pressure_at_sealevel(const float temperature, const float pressure)
838
847
return pressure_at_sealevel;
839
848
}
840
849
841
-
842
850
/* ****************************************************************
843
851
* html helper functions *
844
852
*****************************************************************/
845
-
846
853
static void start_html_page (String& page_content, const String& title) {
847
854
last_page_load = millis ();
848
855
@@ -1051,7 +1058,6 @@ static void webserver_root() {
1051
1058
/* ****************************************************************
1052
1059
* Webserver config: show config page *
1053
1060
*****************************************************************/
1054
-
1055
1061
static void webserver_config_send_body_get (String& page_content) {
1056
1062
auto add_form_checkbox = [&page_content](const ConfigShapeId cfgid, const String& info) {
1057
1063
page_content += form_checkbox (cfgid, info, true );
@@ -1182,6 +1188,7 @@ static void webserver_config_send_body_get(String& page_content) {
1182
1188
add_form_checkbox_sensor (Config_htu21d_read, FPSTR (INTL_HTU21D));
1183
1189
add_form_checkbox_sensor (Config_bmx280_read, FPSTR (INTL_BMX280));
1184
1190
add_form_checkbox_sensor (Config_sht3x_read, FPSTR (INTL_SHT3X));
1191
+ add_form_checkbox_sensor (Config_scd30_read, FPSTR (INTL_SCD30));
1185
1192
1186
1193
// Paginate page after ~ 1500 Bytes
1187
1194
server.sendContent (page_content);
@@ -1445,6 +1452,7 @@ static void webserver_values() {
1445
1452
const String unit_Deg (" °" );
1446
1453
const String unit_P (" hPa" );
1447
1454
const String unit_T (" °C" );
1455
+ const String unit_CO2 (" ppm" );
1448
1456
const String unit_NC ();
1449
1457
const String unit_LA (F (" dB(A)" ));
1450
1458
float dew_point_temp;
@@ -1564,6 +1572,14 @@ static void webserver_values() {
1564
1572
add_table_value (FPSTR (SENSORS_SHT3X), FPSTR (INTL_DEW_POINT), isnan (dew_point_temp) ? " -" : String (dew_point_temp,1 ), unit_T);
1565
1573
page_content += FPSTR (EMPTY_ROW);
1566
1574
}
1575
+ if (cfg::scd30_read) {
1576
+ add_table_t_value (FPSTR (SENSORS_SCD30), FPSTR (INTL_TEMPERATURE), last_value_SCD30_T);
1577
+ add_table_h_value (FPSTR (SENSORS_SCD30), FPSTR (INTL_HUMIDITY), last_value_SCD30_H);
1578
+ add_table_value (FPSTR (SENSORS_SCD30), FPSTR (INTL_CO2_PPM), check_display_value (last_value_SCD30_CO2,0 ,0 ,0 ),unit_CO2);
1579
+ dew_point_temp = dew_point (last_value_SCD30_T, last_value_SCD30_H);
1580
+ add_table_value (FPSTR (SENSORS_SCD30), FPSTR (INTL_DEW_POINT), isnan (dew_point_temp) ? " -" : String (dew_point_temp,1 ), unit_T);
1581
+ page_content += FPSTR (EMPTY_ROW);
1582
+ }
1567
1583
if (cfg::ds18b20_read) {
1568
1584
add_table_t_value (FPSTR (SENSORS_DS18B20), FPSTR (INTL_TEMPERATURE), last_value_DS18B20_T);
1569
1585
page_content += FPSTR (EMPTY_ROW);
@@ -2032,6 +2048,17 @@ static void wifiConfig() {
2032
2048
SSID.toCharArray (wifiInfo[i].ssid , sizeof (wifiInfo[0 ].ssid ));
2033
2049
}
2034
2050
2051
+ // Use 13 channels if locale is not "EN"
2052
+ wifi_country_t wifi;
2053
+ wifi.policy = WIFI_COUNTRY_POLICY_MANUAL;
2054
+ strcpy (wifi.cc , INTL_LANG);
2055
+ wifi.nchan = (INTL_LANG[0 ] == ' E' && INTL_LANG[1 ] == ' N' ) ? 11 : 13 ;
2056
+ wifi.schan = 1 ;
2057
+
2058
+ #if defined(ESP8266)
2059
+ wifi_set_country (&wifi);
2060
+ #endif
2061
+
2035
2062
WiFi.mode (WIFI_AP);
2036
2063
const IPAddress apIP (192 , 168 , 4 , 1 );
2037
2064
WiFi.softAPConfig (apIP, apIP, IPAddress (255 , 255 , 255 , 0 ));
@@ -2060,6 +2087,16 @@ static void wifiConfig() {
2060
2087
}
2061
2088
2062
2089
WiFi.softAPdisconnect (true );
2090
+
2091
+ wifi.policy = WIFI_COUNTRY_POLICY_MANUAL;
2092
+ strcpy (wifi.cc , INTL_LANG);
2093
+ wifi.nchan = 13 ;
2094
+ wifi.schan = 1 ;
2095
+
2096
+ #if defined(ESP8266)
2097
+ wifi_set_country (&wifi);
2098
+ #endif
2099
+
2063
2100
WiFi.mode (WIFI_STA);
2064
2101
2065
2102
dnsServer.stop ();
@@ -2131,11 +2168,11 @@ static void connectWifi() {
2131
2168
WiFi.setAutoReconnect (true );
2132
2169
}
2133
2170
2134
- // Use 13 channels if locale is not "EN"
2171
+ // Use 13 channels for connect to known AP
2135
2172
wifi_country_t wifi;
2136
2173
wifi.policy = WIFI_COUNTRY_POLICY_MANUAL;
2137
2174
strcpy (wifi.cc , INTL_LANG);
2138
- wifi.nchan = (INTL_LANG[ 0 ] == ' E ' && INTL_LANG[ 1 ] == ' N ' ) ? 11 : 13 ;
2175
+ wifi.nchan = 13 ;
2139
2176
wifi.schan = 1 ;
2140
2177
2141
2178
#if defined(ESP8266)
@@ -2476,6 +2513,33 @@ static void fetchSensorSHT3x(String& s) {
2476
2513
debug_outln_verbose (FPSTR (DBG_TXT_END_READING), FPSTR (SENSORS_SHT3X));
2477
2514
}
2478
2515
2516
+ /* ****************************************************************
2517
+ * read SHT3x sensor values *
2518
+ *****************************************************************/
2519
+ static void fetchSensorSCD30 (String& s) {
2520
+ debug_outln_verbose (FPSTR (DBG_TXT_START_READING), FPSTR (SENSORS_SCD30));
2521
+
2522
+ const auto t = scd30.getTemperature ();
2523
+ const auto h = scd30.getHumidity ();
2524
+ const auto c = scd30.getCO2 ();
2525
+
2526
+ if (isnan (h) || isnan (t) || isnan (c)) {
2527
+ last_value_SCD30_T = -128.0 ;
2528
+ last_value_SCD30_H = -1.0 ;
2529
+ last_value_SCD30_CO2 = 0 ;
2530
+ debug_outln_error (F (" SCD30 read failed" ));
2531
+ } else {
2532
+ last_value_SCD30_T = t;
2533
+ last_value_SCD30_H = h;
2534
+ last_value_SCD30_CO2 = c;
2535
+ add_Value2Json (s, F (" SCD30_temperature" ), FPSTR (DBG_TXT_TEMPERATURE), last_value_SCD30_T);
2536
+ add_Value2Json (s, F (" SCD30_humidity" ), FPSTR (DBG_TXT_HUMIDITY), last_value_SCD30_H);
2537
+ add_Value2Json (s, F (" SCD30_co2_ppm" ), FPSTR (DBG_TXT_CO2PPM), last_value_SCD30_CO2);
2538
+ }
2539
+ debug_outln_info (FPSTR (DBG_TXT_SEP));
2540
+ debug_outln_verbose (FPSTR (DBG_TXT_END_READING), FPSTR (SENSORS_SCD30));
2541
+ }
2542
+
2479
2543
/* ****************************************************************
2480
2544
* read BMP280/BME280 sensor values *
2481
2545
*****************************************************************/
@@ -3725,17 +3789,20 @@ static void display_values() {
3725
3789
if (cfg::dht_read || cfg::ds18b20_read || cfg::htu21d_read || cfg::bmp_read || cfg::bmx280_read || cfg::sht3x_read) {
3726
3790
screens[screen_count++] = 3 ;
3727
3791
}
3728
- if (cfg::gps_read ) {
3792
+ if (cfg::scd30_read ) {
3729
3793
screens[screen_count++] = 4 ;
3730
3794
}
3731
- if (cfg::dnms_read ) {
3795
+ if (cfg::gps_read ) {
3732
3796
screens[screen_count++] = 5 ;
3733
3797
}
3798
+ if (cfg::dnms_read) {
3799
+ screens[screen_count++] = 6 ;
3800
+ }
3734
3801
if (cfg::display_wifi_info) {
3735
- screens[screen_count++] = 6 ; // Wifi info
3802
+ screens[screen_count++] = 7 ; // Wifi info
3736
3803
}
3737
3804
if (cfg::display_device_info) {
3738
- screens[screen_count++] = 7 ; // chipID, firmware and count of measurements
3805
+ screens[screen_count++] = 8 ; // chipID, firmware and count of measurements
3739
3806
}
3740
3807
// update size of "screens" when adding more screens!
3741
3808
if (cfg::has_display || cfg::has_sh1106 || lcd_2004) {
@@ -3769,27 +3836,29 @@ static void display_values() {
3769
3836
while (line_count < 3 ) { display_lines[line_count++] = emptyString; }
3770
3837
break ;
3771
3838
case 4 :
3839
+ display_header = " SCD30" ;
3840
+ display_lines[0 ] = " Temp.: " ; display_lines[0 ] += check_display_value (last_value_SCD30_H, -128 , 1 , 6 ); display_lines[0 ] += " °C" ;
3841
+ display_lines[1 ] = " Hum.: " ; display_lines[1 ] += check_display_value (last_value_SCD30_T, -1 , 1 , 6 ); display_lines[1 ] += " %" ;
3842
+ display_lines[2 ] = " CO2: " ; display_lines[2 ] += check_display_value (last_value_SCD30_CO2, 0 , 0 , 6 ); display_lines[2 ] += " ppm" ;
3843
+ case 5 :
3772
3844
display_header = " NEO6M" ;
3773
- display_lines[0 ] = " Lat: " ;
3774
- display_lines[0 ] += check_display_value (lat_value, -200.0 , 6 , 10 );
3775
- display_lines[1 ] = " Lon: " ;
3776
- display_lines[1 ] += check_display_value (lon_value, -200.0 , 6 , 10 );
3777
- display_lines[2 ] = " Alt: " ;
3778
- display_lines[2 ] += check_display_value (alt_value, -1000.0 , 2 , 10 );
3845
+ display_lines[0 ] = " Lat: " ; display_lines[0 ] += check_display_value (lat_value, -200.0 , 6 , 10 );
3846
+ display_lines[1 ] = " Lon: " ; display_lines[1 ] += check_display_value (lon_value, -200.0 , 6 , 10 );
3847
+ display_lines[2 ] = " Alt: " ; display_lines[2 ] += check_display_value (alt_value, -1000.0 , 2 , 10 );
3779
3848
break ;
3780
- case 5 :
3849
+ case 6 :
3781
3850
display_header = FPSTR (SENSORS_DNMS);
3782
3851
display_lines[0 ] = std::move (tmpl (F (" LAeq: {v} db(A)" ), check_display_value (la_eq_value, -1 , 1 , 6 )));
3783
3852
display_lines[1 ] = std::move (tmpl (F (" LA_max: {v} db(A)" ), check_display_value (la_max_value, -1 , 1 , 6 )));
3784
3853
display_lines[2 ] = std::move (tmpl (F (" LA_min: {v} db(A)" ), check_display_value (la_min_value, -1 , 1 , 6 )));
3785
3854
break ;
3786
- case 6 :
3855
+ case 7 :
3787
3856
display_header = F (" Wifi info" );
3788
3857
display_lines[0 ] = " IP: " ; display_lines[0 ] += WiFi.localIP ().toString ();
3789
3858
display_lines[1 ] = " SSID: " ; display_lines[1 ] += WiFi.SSID ();
3790
3859
display_lines[2 ] = std::move (tmpl (F (" Signal: {v} %" ), String (calcWiFiSignalQuality (last_signal_strength))));
3791
3860
break ;
3792
- case 7 :
3861
+ case 8 :
3793
3862
display_header = F (" Device Info" );
3794
3863
display_lines[0 ] = " ID: " ; display_lines[0 ] += esp_chipid;
3795
3864
display_lines[1 ] = " FW: " ; display_lines[1 ] += SOFTWARE_VERSION;
@@ -3864,20 +3933,24 @@ static void display_values() {
3864
3933
display_lines[1 ] = std::move (tmpl (F (" H: {v} %" ), check_display_value (h_value, -1 , 1 , 6 )));
3865
3934
break ;
3866
3935
case 4 :
3936
+ display_lines[0 ] = std::move (tmpl (F (" T/H: {v}" ), check_display_value (last_value_SCD30_T, -128 , 1 , 5 ) + " / " + check_display_value (last_value_SCD30_H,-1 ,0 ,3 )));
3937
+ display_lines[1 ] = std::move (tmpl (F (" CO2: {v} ppm" ), check_display_value (last_value_SCD30_CO2, 0 , 0 , 6 )));
3938
+ break ;
3939
+ case 5 :
3867
3940
display_lines[0 ] = " Lat: " ;
3868
3941
display_lines[0 ] += check_display_value (lat_value, -200.0 , 6 , 11 );
3869
3942
display_lines[1 ] = " Lon: " ;
3870
3943
display_lines[1 ] += check_display_value (lon_value, -200.0 , 6 , 11 );
3871
3944
break ;
3872
- case 5 :
3945
+ case 6 :
3873
3946
display_lines[0 ] = std::move (tmpl (F (" LAeq: {v} db(A)" ), check_display_value (la_eq_value, -1 , 1 , 6 )));
3874
3947
display_lines[1 ] = std::move (tmpl (F (" LA_max: {v} db(A)" ), check_display_value (la_max_value, -1 , 1 , 6 )));
3875
3948
break ;
3876
- case 6 :
3949
+ case 7 :
3877
3950
display_lines[0 ] = WiFi.localIP ().toString ();
3878
3951
display_lines[1 ] = WiFi.SSID ();
3879
3952
break ;
3880
- case 7 :
3953
+ case 8 :
3881
3954
display_lines[0 ] = " ID: " ;
3882
3955
display_lines[0 ] += esp_chipid;
3883
3956
display_lines[1 ] = " FW: " ;
@@ -4143,6 +4216,14 @@ static void powerOnTestSensors() {
4143
4216
}
4144
4217
}
4145
4218
4219
+ if (cfg::scd30_read) {
4220
+ debug_outln_info (F (" Read SCD30..." ));
4221
+ if (!scd30.begin ()) {
4222
+ debug_outln_error (F (" Check SCD30 wiring" ));
4223
+ scd30_init_failed = true ;
4224
+ }
4225
+ }
4226
+
4146
4227
if (cfg::ds18b20_read) {
4147
4228
oneWire.begin (ONEWIRE_PIN);
4148
4229
ds18b20.begin (); // Start DS18B20
@@ -4544,6 +4625,13 @@ void loop(void) {
4544
4625
sum_send_time += sendSensorCommunity (result, SHT3X_API_PIN, FPSTR (SENSORS_SHT3X), " SHT3X_" );
4545
4626
result = emptyString;
4546
4627
}
4628
+ if (cfg::scd30_read && (! scd30_init_failed )) {
4629
+ // getting temperature and humidity (optional)
4630
+ fetchSensorSCD30 (result);
4631
+ data += result;
4632
+ sum_send_time += sendSensorCommunity (result, SCD30_API_PIN, FPSTR (SENSORS_SCD30), " SCD30_" );
4633
+ result = emptyString;
4634
+ }
4547
4635
if (cfg::ds18b20_read) {
4548
4636
// getting temperature (optional)
4549
4637
fetchSensorDS18B20 (result);
0 commit comments