I2C BME280 & TSL2561 support + two I2C buses (#158)

* I2C BME280 support
* Support for 2 I2C busses
* I2C TSL2561 support
* Ability to set the TSL2561 gain manually
This commit is contained in:
ShonP40 2022-02-13 12:45:58 +02:00 committed by GitHub
parent c7c6dc9efe
commit 3960110290
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 356 additions and 27 deletions

1
.gitignore vendored
View File

@ -11,3 +11,4 @@ Settings_*.h
.scripts
.DS_Store
cmake-build-*
build/

View File

@ -14,7 +14,7 @@ default_envs = esp32
[common_env_data]
platform = espressif32@3.5
framework = arduino
lib_deps_external =
lib_deps_external =
haimoz/SoftFilters@^0.1.0
marvinroger/AsyncMqttClient@^0.9.0
bblanchon/ArduinoJson@^6.17.3
@ -30,28 +30,32 @@ lib_deps_external =
adafruit/Adafruit Unified Sensor @ ^1.1.4
beegee-tokyo/DHT sensor library for ESPx @ ^1.18
starmbi/hp_BH1750 @ ^1.0.0
adafruit/Adafruit BME280 Library@^2.2.2
adafruit/Adafruit TSL2561@^1.1.0
[env:esp32]
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = esp32dev
lib_deps = ${common_env_data.lib_deps_external}
lib_deps =
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
upload_speed = 1500000
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D FIRMWARE='"esp32"'
[env:adafruit-huzzah32]
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = esp32dev
lib_deps = ${common_env_data.lib_deps_external}
lib_deps =
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D FIRMWARE='"adafruit-huzzah32"'
-D HUZZAH32
@ -59,12 +63,13 @@ build_flags =
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = esp32dev
lib_deps = ${common_env_data.lib_deps_external}
lib_deps =
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
upload_speed = 1500000
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D CORE_DEBUG_LEVEL=2
-D FIRMWARE='"esp32-verbose"'
-D VERBOSE
@ -73,13 +78,13 @@ build_flags =
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = m5stick-c
lib_deps =
lib_deps =
m5stack/M5StickC@^0.2.0
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D M5STICK
-D FIRMWARE='"m5stickc"'
@ -87,13 +92,13 @@ build_flags =
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = m5stick-c
lib_deps =
lib_deps =
m5stack/M5StickCPlus@^0.0.2
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D M5STICK
-D PLUS
-D FIRMWARE='"m5stickc-plus"'
@ -102,14 +107,14 @@ build_flags =
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = m5stack-atom
lib_deps =
lib_deps =
fastled/FastLED@^3.4.0
m5stack/m5atom@^0.0.5
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
monitor_filters = esp32_exception_decoder
build_flags =
build_flags =
-D M5ATOM
-D MATRIX
-D FIRMWARE='"m5atom-matrix"'
@ -118,10 +123,11 @@ build_flags =
platform = ${common_env_data.platform}
framework = ${common_env_data.framework}
board = esp32dev
lib_deps = ${common_env_data.lib_deps_external}
lib_deps =
${common_env_data.lib_deps_external}
board_build.partitions = partitions_singleapp.csv
monitor_speed = 115200
build_flags =
build_flags =
-D MACCHINA_A0
-D FIRMWARE='"macchina-a0"'

View File

@ -43,6 +43,14 @@
// Number of seconds between update checks
#define CHECK_FOR_UPDATES_INTERVAL 300
// I2C Defaults
#define DEFAULT_I2C_BUS_1_SDA 21
#define DEFAULT_I2C_BUS_1_SCL 22
#define DEFAULT_I2C_BUS 1
// TSL2561 Defaults
#define DEFAULT_TSL2561_I2C_GAIN "auto"
#ifdef VERSION
#define DEFAULT_AUTO_UPDATE true
#define DEFAULT_OTA_UPDATE false

View File

@ -1,4 +1,5 @@
#include <main.h>
#include "main.h"
bool sendTelemetry(int totalSeen, int totalFpSeen, int totalFpQueried, int totalFpReported)
{
if (!online)
@ -18,7 +19,7 @@ bool sendTelemetry(int totalSeen, int totalFpSeen, int totalFpQueried, int total
{
if (sendDiscoveryConnectivity() && sendDiscoveryUptime() && sendDiscoveryFreeMem() && sendSwitchDiscovery("Status LED", "config") && sendNumberDiscovery("Max Distance", "config") && sendSwitchDiscovery("Active Scan", "config") && sendSwitchDiscovery("Query", "config") && sendDiscoveryMotion()
#ifdef SENSORS
&& sendDiscoveryHumidity() && sendDiscoveryTemperature() && sendDiscoveryLux()
&& sendDiscoveryHumidity() && sendDiscoveryTemperature() && sendDiscoveryLux() && sendDiscoveryBME280Temperature() && sendDiscoveryBME280Humidity() && sendDiscoveryBME280Pressure() && sendDiscoveryTSL2561Lux()
#endif
)
{
@ -150,9 +151,35 @@ void connectToWifi()
dht11Pin = WiFiSettings.integer("dht11_pin", 0, "DHT11 sensor pin (0 for disable)");
dht22Pin = WiFiSettings.integer("dht22_pin", 0, "DHT22 sensor pin (0 for disable)");
BH1750_I2c = WiFiSettings.string("BH1750_I2c", "", "Ambient Light Sensor - I2C address of BH1750 Sensor, like 0x23 or 0x5C.");
I2CDebug = WiFiSettings.checkbox("I2CDebug", false, "Debug I2C address. Look at the serial log to get the correct address.");
WiFiSettings.heading("I2C Settings");
I2CDebug = WiFiSettings.checkbox("I2CDebug", false, "Debug I2C addreses. Look at the serial log to get the correct address");
WiFiSettings.html("h4", "Bus 1:");
I2C_Bus_1_SDA = WiFiSettings.integer("I2C_Bus_1_SDA", 0, 39, DEFAULT_I2C_BUS_1_SDA, "SDA pin (0 to disable)");
I2C_Bus_1_SCL = WiFiSettings.integer("I2C_Bus_1_SCL", 0, 39, DEFAULT_I2C_BUS_1_SCL, "SCL pin (0 to disable)");
WiFiSettings.html("h4", "Bus 2:");
I2C_Bus_2_SDA = WiFiSettings.integer("I2C_Bus_2_SDA", 0, "SDA pin (0 to disable)");
I2C_Bus_2_SCL = WiFiSettings.integer("I2C_Bus_2_SCL", 0, "SCL pin (0 to disable)");
WiFiSettings.heading("I2C Sensors");
WiFiSettings.html("h4", "BH1750 - Ambient Light Sensor:");
BH1750_I2c_Bus = WiFiSettings.integer("BH1750_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BH1750_I2c = WiFiSettings.string("BH1750_I2c", "", "I2C address (0x23 or 0x5C)");
WiFiSettings.html("h4", "BME280 - Weather Sensor:");
BME280_I2c_Bus = WiFiSettings.integer("BME280_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
BME280_I2c = WiFiSettings.string("BME280_I2c", "", "I2C address (0x76 or 0x77)");
WiFiSettings.html("h4", "TSL2561 - Ambient Light Sensor:");
TSL2561_I2c_Bus = WiFiSettings.integer("TSL2561_I2c_Bus", 1, 2, DEFAULT_I2C_BUS, "I2C Bus");
TSL2561_I2c = WiFiSettings.string("TSL2561_I2c", "", "I2C address (0x39, 0x49 or 0x29)");
TSL2561_I2c_Gain = WiFiSettings.string("TSL2561_I2c_Gain", DEFAULT_TSL2561_I2C_GAIN, "Gain (auto, 1x or 16x)");
#endif
WiFiSettings.hostname = "espresense-" + kebabify(room);
if (!WiFiSettings.connect(true, 60))
@ -188,8 +215,14 @@ void connectToWifi()
Serial.print("DHT22 Sensor: ");
Serial.println(dht22Pin ? "enabled" : "disabled");
Serial.print("BH1750_I2c Sensor: ");
Serial.println(BH1750_I2c + " on bus " + BH1750_I2c_Bus);
Serial.print("BME280_I2c Sensor: ");
Serial.println(BME280_I2c + " on bus " + BME280_I2c_Bus);
Serial.print("TSL2561_I2c Sensor: ");
Serial.println(TSL2561_I2c + " on bus " + TSL2561_I2c_Bus);
Serial.println(BH1750_I2c);
#endif
localIp = WiFi.localIP().toString();
id = slugify(room);
roomsTopic = CHANNEL + "/rooms/" + id;
@ -472,13 +505,21 @@ void setup()
bool state = false;
// if (! BH1750.begin(BH1750_TO_GROUND))
if (BH1750_I2c == "0x23")
if (BH1750_I2c == "0x23" && BH1750_I2c_Bus == 1)
{
state = BH1750.begin(BH1750_TO_GROUND);
state = BH1750.begin(BH1750_TO_GROUND, &Wire);
}
else if (BH1750_I2c == "0x5C")
else if (BH1750_I2c == "0x5C" && BH1750_I2c_Bus == 1)
{
state = BH1750.begin(BH1750_TO_VCC);
state = BH1750.begin(BH1750_TO_VCC, &Wire);
}
else if (BH1750_I2c == "0x23" && BH1750_I2c_Bus == 2)
{
state = BH1750.begin(BH1750_TO_GROUND, &Wire1);
}
else if (BH1750_I2c == "0x5C" && BH1750_I2c_Bus == 2)
{
state = BH1750.begin(BH1750_TO_VCC, &Wire1);
}
if (!state)
@ -509,9 +550,18 @@ void setup()
}
}
if (I2C_Bus_1_SDA != 0 && I2C_Bus_1_SDA != 0) {
Wire.begin(I2C_Bus_1_SDA, I2C_Bus_1_SCL);
Serial.println("\nInitialized I2C Bus 1");
}
if (I2C_Bus_2_SDA != 0 && I2C_Bus_2_SDA != 0) {
Wire1.begin(I2C_Bus_2_SDA, I2C_Bus_2_SCL);
Serial.println("\nInitialized I2C Bus 2");
}
if (I2CDebug)
{
Wire.begin();
Serial.println("\nI2C Scanner");
}
#endif
@ -629,6 +679,102 @@ void luxLoop()
}
}
void bme280Loop() {
if (BME280_I2c == "0x76" && BME280_I2c_Bus == 1) {
BME280_status = BME280.begin(0x76, &Wire);
} else if (BME280_I2c == "0x77" && BME280_I2c_Bus == 1) {
BME280_status = BME280.begin(0x77, &Wire);
} else if (BME280_I2c == "0x76" && BME280_I2c_Bus == 2) {
BME280_status = BME280.begin(0x76, &Wire1);
} else if (BME280_I2c == "0x77" && BME280_I2c_Bus == 2) {
BME280_status = BME280.begin(0x77, &Wire1);
} else {
Serial.println("BME280 - Invalid I2C address");
return;
}
if (!BME280_status) {
Serial.println("Couldn't find a BME280 sensor, check your wiring and I2C address!");
}
BME280.setSampling(Adafruit_BME280::MODE_NORMAL,
Adafruit_BME280::SAMPLING_X16, // Temperature
Adafruit_BME280::SAMPLING_X16, // Pressure
Adafruit_BME280::SAMPLING_X16, // Humidity
Adafruit_BME280::FILTER_X16,
//Adafruit_BME280::FILTER_OFF,
Adafruit_BME280::STANDBY_MS_1000
);
float temperature = BME280.readTemperature();
float humidity = BME280.readHumidity();
float pressure = BME280.readPressure() / 100.0F;
if (millis() - bme280PreviousMillis >= sensorInterval) {
mqttClient.publish((roomsTopic + "/bme280_temperature").c_str(), 0, 1, String(temperature).c_str());
mqttClient.publish((roomsTopic + "/bme280_humidity").c_str(), 0, 1, String(humidity).c_str());
mqttClient.publish((roomsTopic + "/bme280_pressure").c_str(), 0, 1, String(pressure).c_str());
bme280PreviousMillis = millis();
}
}
void tsl2561Loop() {
int tsl2561_address;
if (TSL2561_I2c == "0x39") {
tsl2561_address = 0x39;
} else if (TSL2561_I2c == "0x29") {
tsl2561_address = 0x29;
} else if (TSL2561_I2c == "0x49") {
tsl2561_address = 0x49;
} else {
Serial.println("TSL2561 - Invalid I2C address");
return;
}
Adafruit_TSL2561_Unified tsl = Adafruit_TSL2561_Unified(tsl2561_address);
if (TSL2561_I2c_Bus == 1) {
tsl.begin(&Wire);
} else if (TSL2561_I2c_Bus == 2) {
tsl.begin(&Wire1);
}
if (TSL2561_I2c_Gain == "auto") {
tsl.enableAutoRange(true);
} else if (TSL2561_I2c_Gain == "1x") {
tsl.setGain(TSL2561_GAIN_1X);
} else if (TSL2561_I2c_Gain == "16x") {
tsl.setGain(TSL2561_GAIN_16X);
} else {
Serial.println("TSL2561 - Invalid gain");
return;
}
tsl.setIntegrationTime(TSL2561_INTEGRATIONTIME_402MS);
sensors_event_t event;
tsl.getEvent(&event);
if (event.light) {
if (millis() - tsl2561PreviousMillis >= sensorInterval) {
mqttClient.publish((roomsTopic + "/tsl2561_lux").c_str(), 0, 1, String(event.light).c_str());
tsl2561PreviousMillis = millis();
}
} else {
Serial.println("TSL2561 - Sensor overloaded");
}
}
void l2cScanner()
{
if (!I2CDebug) return;
@ -644,7 +790,7 @@ void l2cScanner()
error = Wire.endTransmission();
if (error == 0)
{
Serial.print("I2C device found at address 0x");
Serial.print("I2C device found on bus 1 at address 0x");
if (address < 16)
{
@ -656,7 +802,34 @@ void l2cScanner()
}
else if (error == 4)
{
Serial.print("Unknow error at address 0x");
Serial.print("Unknow error on bus 1 at address 0x");
if (address < 16)
{
Serial.print("0");
}
Serial.println(address, HEX);
}
}
for (address = 1; address < 127; address++)
{
Wire1.beginTransmission(address);
error = Wire1.endTransmission();
if (error == 0)
{
Serial.print("I2C device found on bus 2 at address 0x");
if (address < 16)
{
Serial.print("0");
}
Serial.println(address, HEX);
nDevices++;
}
else if (error == 4)
{
Serial.print("Unknow error on bus 2 at address 0x");
if (address < 16)
{
Serial.print("0");
@ -689,6 +862,8 @@ void loop()
#ifdef SENSORS
dhtLoop();
luxLoop();
bme280Loop();
tsl2561Loop();
l2cScanner();
#endif
WiFiSettings.httpLoop();

View File

@ -27,13 +27,38 @@
#ifdef SENSORS
#include <DHTesp.h>
#include <Wire.h>
// I2C
int I2C_Bus_1_SDA;
int I2C_Bus_1_SCL;
int I2C_Bus_2_SDA;
int I2C_Bus_2_SCL;
bool I2CDebug;
unsigned long sensorInterval = 60000;
//GY-302 lux sensor
#include <hp_BH1750.h>
hp_BH1750 BH1750;
long ms_BH1750;
float lux_BH1750;
int lux_BH1750_MQTT;
String BH1750_I2c;
bool I2CDebug;
int BH1750_I2c_Bus;
//I2C BME280 sensor
#include <Adafruit_BME280.h>
Adafruit_BME280 BME280;
long BME280_status;
String BME280_I2c;
int BME280_I2c_Bus;
unsigned long bme280PreviousMillis = 0;
//I2C TSL2561 sensor
#include <Adafruit_TSL2561_U.h>
String TSL2561_I2c;
int TSL2561_I2c_Bus;
String TSL2561_I2c_Gain;
unsigned long tsl2561PreviousMillis = 0;
#endif
AsyncMqttClient mqttClient;
@ -473,8 +498,122 @@ bool sendDiscoveryLux()
String discoveryTopic = "homeassistant/sensor/espresense_" + ESPMAC + "/lux/config";
return pub(discoveryTopic.c_str(), 0, true, buffer);
}
bool sendDiscoveryBME280Temperature()
{
if (BME280_I2c.isEmpty()) return true;
DynamicJsonDocument doc(1200);
commonDiscovery(&doc);
doc["~"] = roomsTopic;
doc["name"] = "ESPresense " + room + " BME280 Temperature";
doc["uniq_id"] = Sprintf("espresense_%06" PRIx64 "_bme280_temperature", ESP.getEfuseMac() >> 24);
doc["avty_t"] = "~/status";
doc["stat_t"] = "~/bme280_temperature";
doc["dev_cla"] = "temperature";
doc["unit_of_meas"] = "°C";
doc["frc_upd"] = true;
char buffer[1200];
serializeJson(doc, buffer);
String discoveryTopic = "homeassistant/sensor/espresense_" + ESPMAC + "/bme280_temperature/config";
for (int i = 0; i < 10; i++)
{
if (mqttClient.publish(discoveryTopic.c_str(), 0, true, buffer))
return true;
delay(50);
}
return false;
}
bool sendDiscoveryBME280Humidity()
{
if (BME280_I2c.isEmpty()) return true;
DynamicJsonDocument doc(1200);
commonDiscovery(&doc);
doc["~"] = roomsTopic;
doc["name"] = "ESPresense " + room + " BME280 Humidity";
doc["uniq_id"] = Sprintf("espresense_%06" PRIx64 "_bme280_humidity", ESP.getEfuseMac() >> 24);
doc["avty_t"] = "~/status";
doc["stat_t"] = "~/bme280_humidity";
doc["dev_cla"] = "humidity";
doc["unit_of_meas"] = "%";
doc["frc_upd"] = true;
char buffer[1200];
serializeJson(doc, buffer);
String discoveryTopic = "homeassistant/sensor/espresense_" + ESPMAC + "/bme280_humidity/config";
for (int i = 0; i < 10; i++)
{
if (mqttClient.publish(discoveryTopic.c_str(), 0, true, buffer))
return true;
delay(50);
}
return false;
}
bool sendDiscoveryBME280Pressure()
{
if (BME280_I2c.isEmpty()) return true;
DynamicJsonDocument doc(1200);
commonDiscovery(&doc);
doc["~"] = roomsTopic;
doc["name"] = "ESPresense " + room + " BME280 Pressure";
doc["uniq_id"] = Sprintf("espresense_%06" PRIx64 "_bme280_pressure", ESP.getEfuseMac() >> 24);
doc["avty_t"] = "~/status";
doc["stat_t"] = "~/bme280_pressure";
doc["dev_cla"] = "pressure";
doc["unit_of_meas"] = "hPa";
doc["frc_upd"] = true;
char buffer[1200];
serializeJson(doc, buffer);
String discoveryTopic = "homeassistant/sensor/espresense_" + ESPMAC + "/bme280_pressure/config";
for (int i = 0; i < 10; i++)
{
if (mqttClient.publish(discoveryTopic.c_str(), 0, true, buffer))
return true;
delay(50);
}
return false;
}
bool sendDiscoveryTSL2561Lux()
{
if (TSL2561_I2c.isEmpty()) return true;
DynamicJsonDocument doc(1200);
commonDiscovery(&doc);
doc["~"] = roomsTopic;
doc["name"] = "ESPresense " + room + " TSL2561 Lux";
doc["uniq_id"] = Sprintf("espresense_%06" PRIx64 "_tsl2561_lux", ESP.getEfuseMac() >> 24);
doc["avty_t"] = "~/status";
doc["stat_t"] = "~/tsl2561_lux";
doc["dev_cla"] = "illuminance";
doc["unit_of_meas"] = "lx";
doc["frc_upd"] = true;
char buffer[1200];
serializeJson(doc, buffer);
String discoveryTopic = "homeassistant/sensor/espresense_" + ESPMAC + "/tsl2561_lux/config";
for (int i = 0; i < 10; i++)
{
if (mqttClient.publish(discoveryTopic.c_str(), 0, true, buffer))
return true;
delay(50);
}
return false;
}
#endif
bool sendSwitchDiscovery(String name, String entityCategory)
{
auto slug = slugify(name);