Skip to content

Commit

Permalink
Merge pull request #5 from airalab/new_sensor_dbmeter
Browse files Browse the repository at this point in the history
New sensor Noise meter
  • Loading branch information
LoSk-p authored Jun 13, 2024
2 parents 884eb89 + 2bb6aa5 commit 7dfc6fc
Show file tree
Hide file tree
Showing 11 changed files with 225 additions and 12 deletions.
3 changes: 3 additions & 0 deletions airrohr-firmware/airrohr-cfg.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ enum ConfigShapeId {
Config_www_basicauth_enabled,
Config_dht_read,
Config_htu21d_read,
Config_dbmeter_read,
Config_ppd_read,
Config_sds_read,
Config_gc_read,
Expand Down Expand Up @@ -109,6 +110,7 @@ static constexpr char CFG_KEY_FS_PWD[] PROGMEM = "fs_pwd";
static constexpr char CFG_KEY_WWW_BASICAUTH_ENABLED[] PROGMEM = "www_basicauth_enabled";
static constexpr char CFG_KEY_DHT_READ[] PROGMEM = "dht_read";
static constexpr char CFG_KEY_HTU21D_READ[] PROGMEM = "htu21d_read";
static constexpr char CFG_KEY_DBMETER_READ[] PROGMEM = "dbmeter_read";
static constexpr char CFG_KEY_PPD_READ[] PROGMEM = "ppd_read";
static constexpr char CFG_KEY_SDS_READ[] PROGMEM = "sds_read";
static constexpr char CFG_KEY_GC_READ[] PROGMEM = "gc_read";
Expand Down Expand Up @@ -182,6 +184,7 @@ static constexpr ConfigShapeEntry configShape[] PROGMEM = {
{ Config_Type_Bool, 0, CFG_KEY_WWW_BASICAUTH_ENABLED, &cfg::www_basicauth_enabled },
{ Config_Type_Bool, 0, CFG_KEY_DHT_READ, &cfg::dht_read },
{ Config_Type_Bool, 0, CFG_KEY_HTU21D_READ, &cfg::htu21d_read },
{ Config_Type_Bool, 0, CFG_KEY_DBMETER_READ, &cfg::dbmeter_read },
{ Config_Type_Bool, 0, CFG_KEY_PPD_READ, &cfg::ppd_read },
{ Config_Type_Bool, 0, CFG_KEY_SDS_READ, &cfg::sds_read },
{ Config_Type_Bool, 0, CFG_KEY_GC_READ, &cfg::gc_read },
Expand Down
1 change: 1 addition & 0 deletions airrohr-firmware/airrohr-cfg.h.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
Bool www_basicauth_enabled
Bool dht_read
Bool htu21d_read
Bool dbmeter_read
Bool ppd_read
Bool sds_read
Bool gc_read
Expand Down
108 changes: 105 additions & 3 deletions airrohr-firmware/airrohr-firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
#include <pgmspace.h>

// increment on change
#define SOFTWARE_VERSION_STR "R_2022-137"
#define SOFTWARE_VERSION_STR "R_2024-06"
String SOFTWARE_VERSION(SOFTWARE_VERSION_STR);

/*****************************************************************
Expand Down Expand Up @@ -114,6 +114,7 @@ String SOFTWARE_VERSION(SOFTWARE_VERSION_STR);
#include "./bmx280_i2c.h"
#include "./sps30_i2c.h"
#include "./dnms_i2c.h"
#include "./dbmeter_regs.h"

#include "./intl.h"

Expand Down Expand Up @@ -162,6 +163,7 @@ namespace cfg {
// (in)active sensors
bool dht_read = DHT_READ;
bool htu21d_read = HTU21D_READ;
bool dbmeter_read = DBMETER_READ;
bool ppd_read = PPD_READ;
bool sds_read = SDS_READ;
bool gc_read = GC_READ;
Expand Down Expand Up @@ -258,6 +260,7 @@ LoggerConfig loggerConfigs[LoggerCount];

long int sample_count = 0;
bool htu21d_init_failed = false;
bool dbmeter_init_failed = false;
bool bmp_init_failed = false;
bool bmx280_init_failed = false;
bool sht3x_init_failed = false;
Expand Down Expand Up @@ -376,6 +379,7 @@ bool send_now = false;
unsigned long starttime;
unsigned long time_point_device_start_ms;
unsigned long starttime_SDS;
unsigned long starttime_DB;
unsigned long starttime_GPS;
unsigned long starttime_NPM;
unsigned long last_NPM;
Expand Down Expand Up @@ -412,6 +416,12 @@ float last_value_HTU21D_H = -1.0;
float last_value_SHT3X_T = -128.0;
float last_value_SHT3X_H = -1.0;

uint8_t last_value_DBMETER = 0;
uint8_t last_value_DBMETER_max = 0;
uint32_t last_value_DBMETER_sum = 0;
uint8_t last_value_DBMETER_count = 0;
float last_value_DBMETER_mean = 0;

uint32_t sds_pm10_sum = 0;
uint32_t sds_pm25_sum = 0;
uint32_t sds_val_count = 0;
Expand Down Expand Up @@ -629,6 +639,21 @@ static void initSensorCCS811() {
}
}

/*****************************************************************
* init DB Meter sensor *
*****************************************************************/

static void initDBMeter() {
// Read version register
uint8_t version = dbmeter_readreg(DBM_REG_VERSION);
if (version != 255) {
debug_outln_info(F("DB Meter version = "), String(version));
} else {
debug_outln_info(F("Check DB Meter wiring..."));
dbmeter_init_failed = true;
}
}

/*****************************************************************
* read SDS011 sensor serial and firmware date *
*****************************************************************/
Expand Down Expand Up @@ -1340,6 +1365,7 @@ static void webserver_config_send_body_get(String& page_content) {

add_form_checkbox_sensor(Config_dht_read, FPSTR(INTL_DHT22));
add_form_checkbox_sensor(Config_htu21d_read, FPSTR(INTL_HTU21D));
add_form_checkbox_sensor(Config_dbmeter_read, FPSTR(INTL_DBMETER));
add_form_checkbox_sensor(Config_bmx280_read, FPSTR(INTL_BMX280));
add_form_checkbox_sensor(Config_sht3x_read, FPSTR(INTL_SHT3X));

Expand Down Expand Up @@ -1613,6 +1639,7 @@ static void webserver_values() {
start_html_page(page_content, FPSTR(INTL_CURRENT_DATA));
const String unit_Deg("°");
const String unit_P("hPa");
const String unit_DB("db");
const String unit_NC();
const String unit_LA(F("dB(A)"));

Expand Down Expand Up @@ -1726,6 +1753,12 @@ static void webserver_values() {
add_table_h_value(FPSTR(SENSORS_HTU21D), FPSTR(INTL_HUMIDITY), last_value_HTU21D_H);
page_content += FPSTR(EMPTY_ROW);
}
if (cfg::dbmeter_read) {
add_table_value(FPSTR(SENSORS_DBMETER), FPSTR(INTL_NOISE), String(last_value_DBMETER), unit_DB);
add_table_value(FPSTR(SENSORS_DBMETER), FPSTR(INTL_NOISE_MAX), String(last_value_DBMETER_max), unit_DB);
add_table_value(FPSTR(SENSORS_DBMETER), FPSTR(INTL_NOISE_MEAN), String(last_value_DBMETER_mean), unit_DB);
page_content += FPSTR(EMPTY_ROW);
}
if (cfg::bmp_read) {
add_table_t_value(FPSTR(SENSORS_BMP180), FPSTR(INTL_TEMPERATURE), last_value_BMP_T);
add_table_value(FPSTR(SENSORS_BMP180), FPSTR(INTL_PRESSURE), check_display_value(last_value_BMP_P / 100.0f, (-1 / 100.0f), 2, 0), unit_P);
Expand Down Expand Up @@ -2270,6 +2303,7 @@ static void wifiConfig() {
debug_outln_info_bool(F("DHT: "), cfg::dht_read);
debug_outln_info_bool(F("DS18B20: "), cfg::ds18b20_read);
debug_outln_info_bool(F("HTU21D: "), cfg::htu21d_read);
debug_outln_info_bool(F("DBMETER: "), cfg::dbmeter_read);
debug_outln_info_bool(F("BMP: "), cfg::bmp_read);
debug_outln_info_bool(F("DNMS: "), cfg::dnms_read);
debug_outln_info_bool(F("CCS811: "), cfg::ccs811_read);
Expand Down Expand Up @@ -2713,6 +2747,59 @@ static void fetchSensorHTU21D(String& s) {
debug_outln_verbose(FPSTR(DBG_TXT_END_READING), FPSTR(SENSORS_HTU21D));
}

/*****************************************************************
* read DB meter sensor values *
*****************************************************************/
static void fetchSensorDBMeter(String& s) {
debug_outln_verbose(FPSTR(DBG_TXT_START_READING), FPSTR(SENSORS_DBMETER));
if (is_SDS_running && cfg::sds_read) {
debug_outln_verbose(F("Don't measure noise: SDS is running"));
} else {
Wire.setClock(10000);
uint8_t db = dbmeter_readreg(DBM_REG_DECIBEL);
if (db == 255) {
last_value_DBMETER = 0;
last_value_DBMETER_max = 0;
last_value_DBMETER_mean = 0;
last_value_DBMETER_count = 0;
last_value_DBMETER_sum = 0;
debug_outln_error(F("DB Meter read failed"));
} else {
last_value_DBMETER = db;
if (last_value_DBMETER > last_value_DBMETER_max) {
last_value_DBMETER_max = last_value_DBMETER;
}
last_value_DBMETER_sum += last_value_DBMETER;
last_value_DBMETER_count++;
last_value_DBMETER_mean = (float)last_value_DBMETER_sum / (float)last_value_DBMETER_count;
}
Wire.setClock(100000);
}
if (send_now) {
debug_outln_info(F("Noise sum: "), last_value_DBMETER_sum);
debug_outln_info(F("Noise count: "), last_value_DBMETER_count);
debug_outln_info(F("Noise max: "), last_value_DBMETER_max);
debug_outln_info(F("Noise mean: "), last_value_DBMETER_mean);
debug_outln_info(FPSTR(DBG_TXT_SEP));
add_Value2Json(s, F("PCBA_noiseMax"), FPSTR(DBG_TXT_DECIBEL), last_value_DBMETER_max);
add_Value2Json(s, F("PCBA_noiseAvg"), FPSTR(DBG_TXT_DECIBEL), last_value_DBMETER_mean);
last_value_DBMETER_max = 0;
last_value_DBMETER_mean = 0;
last_value_DBMETER_count = 0;
last_value_DBMETER_sum = 0;
}
debug_outln_verbose(FPSTR(DBG_TXT_END_READING), FPSTR(SENSORS_DBMETER));
}

uint8_t dbmeter_readreg (uint8_t regaddr) {
Wire.beginTransmission(DBM_ADDR);
Wire.write(regaddr);
Wire.endTransmission();
Wire.requestFrom(DBM_ADDR, 1);
delay(10);
return Wire.read();
}

/*****************************************************************
* read BMP180 sensor values *
*****************************************************************/
Expand Down Expand Up @@ -4486,6 +4573,11 @@ static void powerOnTestSensors() {
}
}

if (cfg::dbmeter_read) {
debug_outln_info(F("Read DB Meter..."));
initDBMeter();
}

if (cfg::bmp_read) {
debug_outln_info(F("Read BMP..."));
if (!bmp.begin()) {
Expand Down Expand Up @@ -4764,7 +4856,7 @@ void setup(void) {

starttime = millis(); // store the start time
last_update_attempt = time_point_device_start_ms = starttime;
last_display_millis = starttime_SDS = starttime;
last_display_millis = starttime_SDS = starttime_DB = starttime;
if (cfg::file_write) {
writeDataFile("Start measuring");
}
Expand All @@ -4778,7 +4870,7 @@ void setup(void) {
*****************************************************************/
void loop(void) {
String result_PPD, result_SDS, result_PMS, result_HPM, result_CCS;
String result_GPS, result_DNMS, result_GC;
String result_GPS, result_DNMS, result_GC, result_DB;

unsigned sum_send_time = 0;

Expand Down Expand Up @@ -4837,6 +4929,13 @@ void loop(void) {
fetchSensorPPD(result_PPD);
}

if ((msSince(starttime_DB) > SAMPLETIME_DBMETER_MS) || send_now) {
starttime_DB = act_milli;
if (cfg::dbmeter_read && (! dbmeter_init_failed)) {
fetchSensorDBMeter(result_DB);
}
}

if ((msSince(starttime_SDS) > SAMPLETIME_SDS_MS) || send_now) {
starttime_SDS = act_milli;
if (cfg::sds_read) {
Expand Down Expand Up @@ -4898,6 +4997,9 @@ void loop(void) {
fetchSensorGC(result_GC);
data += result_GC;
}
if (cfg::dbmeter_read && (! dbmeter_init_failed)) {
data += result_DB;
}
if (((cfg::ccs811_read) || (cfg::ccs811_27_read)) && (! ccs811_init_failed)) {
data += result_CCS;
}
Expand Down
21 changes: 21 additions & 0 deletions airrohr-firmware/dbmeter_regs.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
// I2C address for the module
#define DBM_ADDR 0x48

// Device registers
#define DBM_REG_VERSION 0x00
#define DBM_REG_ID3 0x01
#define DBM_REG_ID2 0x02
#define DBM_REG_ID1 0x03
#define DBM_REG_ID0 0x04
#define DBM_REG_SCRATCH 0x05
#define DBM_REG_CONTROL 0x06
#define DBM_REG_TAVG_HIGH 0x07
#define DBM_REG_TAVG_LOW 0x08
#define DBM_REG_RESET 0x09
#define DBM_REG_DECIBEL 0x0A
#define DBM_REG_MIN 0x0B
#define DBM_REG_MAX 0x0C
#define DBM_REG_THR_MIN 0x0D
#define DBM_REG_THR_MAX 0x0E
#define DBM_REG_HISTORY_0 0x14
#define DBM_REG_HISTORY_99 0x77
1 change: 1 addition & 0 deletions airrohr-firmware/defines.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ constexpr const unsigned long SAMPLETIME_NPM_MS = 1000;
constexpr const unsigned long WARMUPTIME_NPM_MS = 15000;
constexpr const unsigned long READINGTIME_NPM_MS = 15000; // how long we read data from the PM sensors
constexpr const unsigned long SAMPLETIME_GPS_MS = 50;
constexpr const unsigned long SAMPLETIME_DBMETER_MS = 1000;
constexpr const unsigned long DISPLAY_UPDATE_INTERVAL_MS = 5000; // time between switching display to next "screen"
constexpr const unsigned long ONE_DAY_IN_MS = 24 * 60 * 60 * 1000;
constexpr const unsigned long PAUSE_BETWEEN_UPDATE_ATTEMPTS_MS = ONE_DAY_IN_MS; // check for firmware updates once a day
Expand Down
3 changes: 3 additions & 0 deletions airrohr-firmware/ext_def.h
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ static const char MEASUREMENT_NAME_INFLUX[] PROGMEM = "feinstaub";
// Geiger Counter
#define GC_READ 0

// Becibel Meter
#define DBMETER_READ 0

// SDS011, the more expensive version of the particle sensor
#define SDS_READ 1
#define SDS_API_PIN 1
Expand Down
70 changes: 70 additions & 0 deletions airrohr-firmware/get-platformio.py

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions airrohr-firmware/html-content.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const char TXT_CONTENT_TYPE_TEXT_PLAIN[] PROGMEM = "text/plain";
const char TXT_CONTENT_TYPE_IMAGE_PNG[] PROGMEM = "image/png";

const char DBG_TXT_TEMPERATURE[] PROGMEM = "Temperature (°C): ";
const char DBG_TXT_DECIBEL[] PROGMEM = "Noise Level (DB): ";
const char DBG_TXT_HUMIDITY[] PROGMEM = "Humidity (%): ";
const char DBG_TXT_PRESSURE[] PROGMEM = "Pressure (hPa): ";
const char DBG_TXT_START_READING[] PROGMEM = "R/ ";
Expand Down Expand Up @@ -34,6 +35,7 @@ const char SENSORS_SPS30[] PROGMEM = "Sensirion SPS30";
const char SENSORS_DHT22[] PROGMEM = "DHT22";
const char SENSORS_DS18B20[] PROGMEM = "DS18B20";
const char SENSORS_HTU21D[] PROGMEM = "HTU21D";
const char SENSORS_DBMETER[] PROGMEM = "Noise Sensor";
const char SENSORS_SHT3X[] PROGMEM = "SHT3x";
const char SENSORS_BMP180[] PROGMEM = "BMP180";
const char SENSORS_BME280[] PROGMEM = "BME280";
Expand Down
4 changes: 4 additions & 0 deletions airrohr-firmware/intl_en.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const char INTL_SENSORS[] PROGMEM = "Sensors";
const char INTL_MORE_SENSORS[] PROGMEM = "More Sensors";
const char INTL_SDS011[] PROGMEM = "SDS011 ({pm})";
const char INTL_GC[] PROGMEM = "Geiger counter";
const char INTL_DBMETER[] PROGMEM = "Noise Level Sensor, (sending interval must be > 30 s)";
const char INTL_PMS[] PROGMEM = "Plantower PMS(1,3,5,6,7)003 ({pm})";
const char INTL_HPM[] PROGMEM = "Honeywell PM ({pm})";
const char INTL_NPM[] PROGMEM = "Tera Sensor Next PM ({pm})";
Expand Down Expand Up @@ -104,6 +105,9 @@ const char INTL_TIME_SINCE_LAST_MEASUREMENT[] PROGMEM = " seconds since last mea
const char INTL_PARTICLES_PER_LITER[] PROGMEM = "particles/liter";
const char INTL_PARTICULATE_MATTER[] PROGMEM = "particulate matter";
const char INTL_TEMPERATURE[] PROGMEM = "temperature";
const char INTL_NOISE[] PROGMEM = "noise";
const char INTL_NOISE_MAX[] PROGMEM = "max noise";
const char INTL_NOISE_MEAN[] PROGMEM = "mean noise";
const char INTL_HUMIDITY[] PROGMEM = "humidity";
const char INTL_PRESSURE[] PROGMEM = "air pressure";
const char INTL_RADIATION[] PROGMEM = "Radiation";
Expand Down
4 changes: 4 additions & 0 deletions airrohr-firmware/intl_ru.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ const char INTL_SENSORS[] PROGMEM = "Датчики";
const char INTL_MORE_SENSORS[] PROGMEM = "Больше датчиков";
const char INTL_SDS011[] PROGMEM = "SDS011 ({pm})";
const char INTL_GC[] PROGMEM = "Счетчик Гейгера ({cpm})";
const char INTL_DBMETER[] PROGMEM = "Датчик уровня шума, (интервал отправки должен быть > 30 сек)";
const char INTL_PMS[] PROGMEM = "Plantower PMS(1,3,5,6,7)003 ({pm})";
const char INTL_HPM[] PROGMEM = "Honeywell PM ({pm})";
const char INTL_NPM[] PROGMEM = "Tera Sensor Next PM ({pm})";
Expand Down Expand Up @@ -104,6 +105,9 @@ const char INTL_TIME_SINCE_LAST_MEASUREMENT[] PROGMEM = " секунд посл
const char INTL_PARTICLES_PER_LITER[] PROGMEM = "Частицы/ литр";
const char INTL_PARTICULATE_MATTER[] PROGMEM = "Датчик пыли";
const char INTL_TEMPERATURE[] PROGMEM = "Температура";
const char INTL_NOISE[] PROGMEM = "Шум";
const char INTL_NOISE_MAX[] PROGMEM = "Максимальный шум";
const char INTL_NOISE_MEAN[] PROGMEM = "Средний шум";
const char INTL_HUMIDITY[] PROGMEM = "Относительная влажность";
const char INTL_PRESSURE[] PROGMEM = "Давление воздуха";
const char INTL_RADIATION[] PROGMEM = "Радиация";
Expand Down
20 changes: 11 additions & 9 deletions airrohr-firmware/platformio.ini
Original file line number Diff line number Diff line change
Expand Up @@ -43,17 +43,19 @@ board_build.f_cpu = 160000000L
; (like OneWire, LiquidCrystal_I2C and TinyGPSPlus)

lib_deps_external =
1@2.3.5 ; OneWire
576@1.1.4 ; LiquidCrystal_I2C
Adafruit BMP085 Library@1.0.1
Adafruit HTU21DF Library@1.0.2
Adafruit SHT31 Library@1.1.6
bblanchon/ArduinoJson@6.16.1
milesburton/DallasTemperature@3.8.0
ESP8266_SSD1306@4.1.0
1655@1.0.2 ; TinyGPSPlus, formerly this was referenced as mikalhart/TinyGPSPlus#v0.95
paulstoffregen/OneWire@2.3.7
marcoschwartz/LiquidCrystal_I2C@1.1.4
adafruit/Adafruit BMP085 Library@1.0.1
adafruit/Adafruit HTU21DF Library@1.0.5
https://github.com/adafruit/Adafruit_SHT31.git#1.2.0
milesburton/DallasTemperature@3.9.1
sparkfun/SparkFun SCD30 Arduino Library @ ^1.0.13
bblanchon/ArduinoJson@6.18.3
ThingPulse/ESP8266 and ESP32 OLED driver for SSD1306 displays @ ^4.2.1
mikalhart/TinyGPSPlus@1.0.2
climateguard/ClimateGuard RadSens@^1.1.1
sparkfun/SparkFun CCS811 Arduino Library@^2.0.3
arduino-libraries/ArduinoHttpClient@^0.6.0

; system libraries from platform -> no version number
lib_deps_esp8266_platform =
Expand Down

0 comments on commit 7dfc6fc

Please sign in to comment.