Add BH1750 lux sensor support

This commit is contained in:
Djuri Baars 2024-06-29 02:19:25 +02:00
parent a9489c30f6
commit fb67893f85
10 changed files with 196 additions and 98 deletions

2
data

@ -1 +1 @@
Subproject commit 52e90dbdee7f53dcca5a9857dd411f98a569263a Subproject commit 59e2750cf3bc53958f9714d0daf8d26b9d1b441f

View File

@ -79,6 +79,7 @@ build_flags =
lib_deps = lib_deps =
${btclock_base.lib_deps} ${btclock_base.lib_deps}
robtillaart/PCA9685@^0.7.1 robtillaart/PCA9685@^0.7.1
claws/BH1750@^1.3.0
build_unflags = build_unflags =
${btclock_base.build_unflags} ${btclock_base.build_unflags}

View File

@ -10,6 +10,8 @@ Adafruit_MCP23X17 mcp2;
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
PCA9685 flArray(PCA_I2C_ADDR); PCA9685 flArray(PCA_I2C_ADDR);
BH1750 bh1750;
bool hasLuxSensor = false;
#endif #endif
std::vector<std::string> screenNameMap(SCREEN_COUNT); std::vector<std::string> screenNameMap(SCREEN_COUNT);
@ -401,6 +403,15 @@ void setupHardware()
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
setupFrontlight(); setupFrontlight();
Wire.beginTransmission(0x5C);
byte error = Wire.endTransmission();
if (error == 0) {
Serial.println(F("Found BH1750"));
hasLuxSensor = true;
bh1750.begin(BH1750::CONTINUOUS_LOW_RES_MODE, 0x5C);
}
#endif #endif
} }
@ -737,6 +748,10 @@ void setupFrontlight()
frontlightFadeInAll(preferences.getUInt("flEffectDelay"), true); frontlightFadeInAll(preferences.getUInt("flEffectDelay"), true);
} }
float getLightLevel() {
return bh1750.readLightLevel();
}
#endif #endif
String getHwRev() String getHwRev()
@ -769,3 +784,8 @@ String getFsRev()
fsHash.close(); fsHash.close();
return ret; return ret;
} }
bool hasLightLevel() {
return hasLuxSensor;
}

View File

@ -22,6 +22,7 @@
#include "lib/webserver.hpp" #include "lib/webserver.hpp"
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
#include "PCA9685.h" #include "PCA9685.h"
#include "BH1750.h"
#endif #endif
#define NTP_SERVER "pool.ntp.org" #define NTP_SERVER "pool.ntp.org"
@ -49,6 +50,8 @@ void finishSetup();
void setupMcp(); void setupMcp();
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
void setupFrontlight(); void setupFrontlight();
float getLightLevel();
bool hasLightLevel();
extern PCA9685 flArray; extern PCA9685 flArray;
#endif #endif
@ -67,5 +70,4 @@ void improv_set_error(improv::Error error);
void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info); void WiFiEvent(WiFiEvent_t event, WiFiEventInfo_t info);
String getHwRev(); String getHwRev();
bool isWhiteVersion(); bool isWhiteVersion();
String getFsRev(); String getFsRev();

View File

@ -65,6 +65,8 @@ void frontlightFadeInAll(int flDelayTime)
void frontlightFadeInAll(int flDelayTime, bool staggered) void frontlightFadeInAll(int flDelayTime, bool staggered)
{ {
if (frontlightIsOn())
return;
if (flInTransition) if (flInTransition)
return; return;
@ -113,6 +115,8 @@ void frontlightFadeOutAll(int flDelayTime)
void frontlightFadeOutAll(int flDelayTime, bool staggered) void frontlightFadeOutAll(int flDelayTime, bool staggered)
{ {
if (!frontlightIsOn())
return;
if (flInTransition) if (flInTransition)
return; return;
flInTransition = true; flInTransition = true;
@ -155,6 +159,22 @@ void frontlightFadeOutAll(int flDelayTime, bool staggered)
flInTransition = false; flInTransition = false;
} }
std::vector<uint16_t> frontlightGetStatus() {
std::vector<uint16_t> statuses;
for (int ledPin = 1; ledPin <= NUM_SCREENS; ledPin++)
{
uint16_t a = 0, b = 0;
flArray.getPWM(ledPin, &a, &b);
statuses.push_back(round(b-a/4096));
}
return statuses;
}
bool frontlightIsOn() {
return frontlightOn;
}
void frontlightFadeIn(uint num, int flDelayTime) void frontlightFadeIn(uint num, int flDelayTime)
{ {
for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5) for (int dutyCycle = 0; dutyCycle <= preferences.getUInt("flMaxBrightness"); dutyCycle += 5)
@ -166,6 +186,9 @@ void frontlightFadeIn(uint num, int flDelayTime)
void frontlightFadeOut(uint num, int flDelayTime) void frontlightFadeOut(uint num, int flDelayTime)
{ {
if (!frontlightIsOn())
return;
for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5) for (int dutyCycle = preferences.getUInt("flMaxBrightness"); dutyCycle >= 0; dutyCycle -= 5)
{ {
flArray.setPWM(num, 0, dutyCycle); flArray.setPWM(num, 0, dutyCycle);

View File

@ -65,7 +65,10 @@ void frontlightFadeOutAll();
void frontlightFadeIn(uint num); void frontlightFadeIn(uint num);
void frontlightFadeOut(uint num); void frontlightFadeOut(uint num);
std::vector<uint16_t> frontlightGetStatus();
void frontlightSetBrightness(uint brightness); void frontlightSetBrightness(uint brightness);
bool frontlightIsOn();
void frontlightFadeInAll(int flDelayTime); void frontlightFadeInAll(int flDelayTime);
void frontlightFadeInAll(int flDelayTime, bool staggered); void frontlightFadeInAll(int flDelayTime, bool staggered);

View File

@ -1,6 +1,7 @@
#include "ota.hpp" #include "ota.hpp"
TaskHandle_t taskOtaHandle = NULL; TaskHandle_t taskOtaHandle = NULL;
bool isOtaUpdating = false;
void setupOTA() { void setupOTA() {
if (preferences.getBool("otaEnabled", true)) { if (preferences.getBool("otaEnabled", true)) {
@ -47,7 +48,7 @@ void onOTAStart() {
// Stop all timers // Stop all timers
esp_timer_stop(screenRotateTimer); esp_timer_stop(screenRotateTimer);
esp_timer_stop(minuteTimer); esp_timer_stop(minuteTimer);
isOtaUpdating = true;
// Stop or suspend all tasks // Stop or suspend all tasks
// vTaskSuspend(priceUpdateTaskHandle); // vTaskSuspend(priceUpdateTaskHandle);
// vTaskSuspend(blockUpdateTaskHandle); // vTaskSuspend(blockUpdateTaskHandle);
@ -65,7 +66,7 @@ void onOTAStart() {
void handleOTATask(void *parameter) { void handleOTATask(void *parameter) {
for (;;) { for (;;) {
ArduinoOTA.handle(); // Allow OTA updates to occur ArduinoOTA.handle(); // Allow OTA updates to occur
vTaskDelay(pdMS_TO_TICKS(2500)); vTaskDelay(pdMS_TO_TICKS(2000));
} }
} }
@ -130,6 +131,7 @@ void onOTAError(ota_error_t error) {
Serial.println(F("\nOTA update error, restarting")); Serial.println(F("\nOTA update error, restarting"));
Wire.end(); Wire.end();
SPI.end(); SPI.end();
isOtaUpdating = false;
delay(1000); delay(1000);
ESP.restart(); ESP.restart();
} }
@ -141,3 +143,7 @@ void onOTAComplete() {
delay(1000); delay(1000);
ESP.restart(); ESP.restart();
} }
bool getIsOTAUpdating() {
return isOtaUpdating;
}

View File

@ -11,3 +11,5 @@ void onOTAProgress(unsigned int progress, unsigned int total);
void downloadUpdate(); void downloadUpdate();
void onOTAError(ota_error_t error); void onOTAError(ota_error_t error);
void onOTAComplete(); void onOTAComplete();
bool getIsOTAUpdating();

View File

@ -57,6 +57,8 @@ void setupWebserver()
#ifdef HAS_FRONTLIGHT #ifdef HAS_FRONTLIGHT
server.on("/api/frontlight/on", HTTP_GET, onApiFrontlightOn); server.on("/api/frontlight/on", HTTP_GET, onApiFrontlightOn);
server.on("/api/frontlight/flash", HTTP_GET, onApiFrontlightFlash); server.on("/api/frontlight/flash", HTTP_GET, onApiFrontlightFlash);
server.on("/api/frontlight/status", HTTP_GET, onApiFrontlightStatus);
server.on("/api/frontlight/brightness", HTTP_GET, onApiFrontlightSetBrightness); server.on("/api/frontlight/brightness", HTTP_GET, onApiFrontlightSetBrightness);
server.on("/api/frontlight/off", HTTP_GET, onApiFrontlightOff); server.on("/api/frontlight/off", HTTP_GET, onApiFrontlightOff);
@ -67,7 +69,8 @@ void setupWebserver()
// server.on("^\\/api\\/lights\\/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", HTTP_GET, // server.on("^\\/api\\/lights\\/([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$", HTTP_GET,
// onApiLightsSetColor); // onApiLightsSetColor);
if (preferences.getBool("otaEnabled", true)) { if (preferences.getBool("otaEnabled", true))
{
server.on("/upload/firmware", HTTP_POST, onFirmwareUpdate, asyncFirmwareUpdateHandler); server.on("/upload/firmware", HTTP_POST, onFirmwareUpdate, asyncFirmwareUpdateHandler);
server.on("/upload/webui", HTTP_POST, onFirmwareUpdate, asyncWebuiUpdateHandler); server.on("/upload/webui", HTTP_POST, onFirmwareUpdate, asyncWebuiUpdateHandler);
} }
@ -229,6 +232,20 @@ JsonDocument getStatusObject()
root["rssi"] = WiFi.RSSI(); root["rssi"] = WiFi.RSSI();
#ifdef HAS_FRONTLIGHT
std::vector<uint16_t> statuses = frontlightGetStatus();
uint16_t arr[NUM_SCREENS];
std::copy(statuses.begin(), statuses.end(), arr);
JsonArray data = root["flStatus"].to<JsonArray>();
copyArray(arr, data);
if (hasLightLevel())
{
root["lightLevel"] = getLightLevel();
}
#endif
return root; return root;
} }
@ -437,7 +454,7 @@ void onApiSettingsPatch(AsyncWebServerRequest *request, JsonVariant &json)
} }
} }
String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness", "flEffectDelay"}; String uintSettings[] = {"minSecPriceUpd", "fullRefreshMin", "ledBrightness", "flMaxBrightness", "flEffectDelay", "luxLightToggle"};
for (String setting : uintSettings) for (String setting : uintSettings)
{ {
@ -586,9 +603,11 @@ void onApiSettingsGet(AsyncWebServerRequest *request)
root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", false); root["flAlwaysOn"] = preferences.getBool("flAlwaysOn", false);
root["flEffectDelay"] = preferences.getUInt("flEffectDelay"); root["flEffectDelay"] = preferences.getUInt("flEffectDelay");
root["flFlashOnUpd"] = preferences.getBool("flFlashOnUpd", false); root["flFlashOnUpd"] = preferences.getBool("flFlashOnUpd", false);
root["hasLightLevel"] = hasLightLevel();
root["luxLightToggle"] = preferences.getUInt("luxLightToggle", 128);
#else #else
root["hasFrontlight"] = false; root["hasFrontlight"] = false;
root["hasLightLevel"] = false;
#endif #endif
root["hwRev"] = getHwRev(); root["hwRev"] = getHwRev();
@ -1133,17 +1152,14 @@ void onApiFrontlightStatus(AsyncWebServerRequest *request)
request->beginResponseStream("application/json"); request->beginResponseStream("application/json");
JsonDocument root; JsonDocument root;
JsonArray ledStates = root["data"].to<JsonArray>();
for (int ledPin = 0; ledPin < NUM_SCREENS; ledPin++) std::vector<uint16_t> statuses = frontlightGetStatus();
{ uint16_t arr[NUM_SCREENS];
uint16_t onTime, offTime; std::copy(statuses.begin(), statuses.end(), arr);
flArray.getPWM(ledPin, &onTime, &offTime);
ledStates.add(onTime); JsonArray data = root["flStatus"].to<JsonArray>();
} copyArray(arr, data);
serializeJson(root, *response);
serializeJson(ledStates, *response);
request->send(response); request->send(response);
} }

View File

@ -24,7 +24,6 @@ uint priceNotifyLostConnection = 0;
uint blockNotifyLostConnection = 0; uint blockNotifyLostConnection = 0;
// char ptrTaskList[1500]; // char ptrTaskList[1500];
extern "C" void app_main() extern "C" void app_main()
{ {
initArduino(); initArduino();
@ -46,6 +45,29 @@ extern "C" void app_main()
int64_t currentUptime = esp_timer_get_time() / 1000000; int64_t currentUptime = esp_timer_get_time() / 1000000;
; ;
if (!getIsOTAUpdating())
{
#ifdef HAS_FRONTLIGHT
if (preferences.getUInt("luxLightToggle", 128) != 0)
{
if (hasLightLevel() && getLightLevel() == 0)
{
if (frontlightIsOn()) {
frontlightFadeOutAll();
}
}
else if (hasLightLevel() && getLightLevel() < preferences.getUInt("luxLightToggle", 128) && !frontlightIsOn())
{
frontlightFadeInAll();
}
else if (frontlightIsOn() && getLightLevel() > preferences.getUInt("luxLightToggle", 128))
{
frontlightFadeOutAll();
}
}
#endif
if (!WiFi.isConnected()) if (!WiFi.isConnected())
{ {
if (!wifiLostConnection) if (!wifiLostConnection)
@ -84,7 +106,8 @@ extern "C" void app_main()
// setupPriceNotify(); // setupPriceNotify();
priceNotifyLostConnection = 0; priceNotifyLostConnection = 0;
} }
} else if (priceNotifyLostConnection > 0 && isPriceNotifyConnected()) }
else if (priceNotifyLostConnection > 0 && isPriceNotifyConnected())
{ {
priceNotifyLostConnection = 0; priceNotifyLostConnection = 0;
} }
@ -139,10 +162,12 @@ extern "C" void app_main()
} }
} }
if (currentUptime - getLastTimeSync() > 24 * 60 * 60) { if (currentUptime - getLastTimeSync() > 24 * 60 * 60)
{
Serial.println(F("Last time update is longer than 24 hours ago, sync again")); Serial.println(F("Last time update is longer than 24 hours ago, sync again"));
syncTime(); syncTime();
}; };
}
vTaskDelay(pdMS_TO_TICKS(5000)); vTaskDelay(pdMS_TO_TICKS(5000));
} }