diff --git a/lib/Adafruit_TSL2591/Adafruit_TSL2591.cpp b/lib/Adafruit_TSL2591/Adafruit_TSL2591.cpp index d02eeffe4..52e71971f 100644 --- a/lib/Adafruit_TSL2591/Adafruit_TSL2591.cpp +++ b/lib/Adafruit_TSL2591/Adafruit_TSL2591.cpp @@ -250,6 +250,29 @@ uint32_t Adafruit_TSL2591::calculateLux(uint16_t ch0, uint16_t ch1) return (uint32_t) calculateLuxf(ch0, ch1); } +uint32_t Adafruit_TSL2591::getFullLuminosity (bool& finished) +{ + const uint8_t status = read8(TSL2591_COMMAND_BIT | TSL2591_REGISTER_DEVICE_STATUS); + + // ALS Valid. Indicates that the ADC channels have completed an + // integration cycle since the AEN bit was asserted. + finished = status & 0x01; + if (!finished) { + return 0; + } + + uint32_t x; + uint16_t y = 0; + y |= read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN0_LOW); + x = read16(TSL2591_COMMAND_BIT | TSL2591_REGISTER_CHAN1_LOW); + x <<= 16; + x |= y; + + disable(); + + return x; +} + uint32_t Adafruit_TSL2591::getFullLuminosity (void) { if (!_initialized) diff --git a/lib/Adafruit_TSL2591/Adafruit_TSL2591.h b/lib/Adafruit_TSL2591/Adafruit_TSL2591.h index a780fb245..8530b356c 100644 --- a/lib/Adafruit_TSL2591/Adafruit_TSL2591.h +++ b/lib/Adafruit_TSL2591/Adafruit_TSL2591.h @@ -163,6 +163,7 @@ class Adafruit_TSL2591 : public Adafruit_Sensor void setTiming ( tsl2591IntegrationTime_t integration ); uint16_t getLuminosity (uint8_t channel ); uint32_t getFullLuminosity ( ); + uint32_t getFullLuminosity (bool& finished); tsl2591IntegrationTime_t getTiming(); tsl2591Gain_t getGain(); diff --git a/src/_P074_TSL2591.ino b/src/_P074_TSL2591.ino index 6d8316f75..1c97891da 100644 --- a/src/_P074_TSL2591.ino +++ b/src/_P074_TSL2591.ino @@ -61,7 +61,49 @@ struct P074_data_struct : public PluginTaskData_base { } } + // Return true when value is present. + bool getFullLuminosity(uint32_t & value) { + value = 0; + if (newValuePresent) { + // don't try to read a new value until the last one was processed. + return false; + } + if (!integrationActive) { + if (startIntegrationNeeded) { + // Fix to re-set the gain/timing before every read. + // See https://github.com/letscontrolit/ESPEasy/issues/3347 + if (tsl.begin()) { + tsl.enable(); + integrationStart = millis(); + integrationActive = true; + startIntegrationNeeded = false; + } + } + return false; // Started integration, so no value possible yet. + } + bool finished = false; + value = tsl.getFullLuminosity(finished); + if (finished) { + integrationActive = false; + integrationStart = 0; + newValuePresent = true; + } else { + if (timePassedSince(integrationStart) > 1000) { + // Max integration time is 600 msec, so if we still have no value, reset the current state + integrationStart = 0; + integrationActive = false; + newValuePresent = false; + startIntegrationNeeded = true; // Apparently a value was needed + } + } + return finished; + } + Adafruit_TSL2591 tsl; + unsigned long integrationStart = 0; + bool integrationActive = false; + bool newValuePresent = false; + bool startIntegrationNeeded = false; }; boolean Plugin_074(byte function, struct EventStruct *event, String& string) { @@ -192,24 +234,14 @@ boolean Plugin_074(byte function, struct EventStruct *event, String& string) { break; } - case PLUGIN_READ: { + case PLUGIN_TEN_PER_SECOND: { P074_data_struct *P074_data = static_cast(getPluginTaskData(event->TaskIndex)); if (nullptr != P074_data) { - - // Fix to re-set the gain/timing before every read. - // See https://github.com/letscontrolit/ESPEasy/issues/3347 - if (!P074_data->tsl.begin()) { - break; - } - - // Simple data read example. Just read the infrared, fullspecrtrum diode - // or 'visible' (difference between the two) channels. - float lux, full, visible, ir; - { - uint32_t fullLuminosity = P074_data->tsl.getFullLuminosity(); - + uint32_t fullLuminosity; + if (P074_data->getFullLuminosity(fullLuminosity)) { + float lux, full, visible, ir; // TSL2591_FULLSPECTRUM: Reads two byte value from channel 0 (visible + infrared) full = (fullLuminosity & 0xFFFF); @@ -220,25 +252,48 @@ boolean Plugin_074(byte function, struct EventStruct *event, String& string) { visible = ( (fullLuminosity & 0xFFFF) - (fullLuminosity >> 16)); lux = P074_data->tsl.calculateLuxf(full, ir); // get LUX - } - UserVar[event->BaseVarIndex + 0] = lux; - UserVar[event->BaseVarIndex + 1] = full; - UserVar[event->BaseVarIndex + 2] = visible; - UserVar[event->BaseVarIndex + 3] = ir; + UserVar[event->BaseVarIndex + 0] = lux; + UserVar[event->BaseVarIndex + 1] = full; + UserVar[event->BaseVarIndex + 2] = visible; + UserVar[event->BaseVarIndex + 3] = ir; - if (loglevelActiveFor(LOG_LEVEL_INFO)) { - String log = F("TSL2591: Lux: "); - log += String(lux); - log += F(" Full: "); - log += String(full); - log += F(" Visible: "); - log += String(visible); - log += F(" IR: "); - log += String(ir); - addLog(LOG_LEVEL_INFO, log); + if (loglevelActiveFor(LOG_LEVEL_INFO)) { + String log = F("TSL2591: Lux: "); + log += String(lux); + log += F(" Full: "); + log += String(full); + log += F(" Visible: "); + log += String(visible); + log += F(" IR: "); + log += String(ir); + addLog(LOG_LEVEL_INFO, log); + } + + // Update was succesfull, schedule a read. + Scheduler.schedule_task_device_timer(event->TaskIndex, millis() + 10); + } + } + break; + } + + case PLUGIN_READ: { + P074_data_struct *P074_data = + static_cast(getPluginTaskData(event->TaskIndex)); + + if (nullptr != P074_data) { + // PLUGIN_READ is either triggered by the task interval timer, or re-scheduled + // from PLUGIN_TEN_PER_SECOND when there is new data. + if (P074_data->newValuePresent) { + // Value was read in the PLUGIN_TEN_PER_SECOND call, just notify controllers. + P074_data->newValuePresent = false; + success = true; + } else { + if (!P074_data->integrationActive) { + // No reading in progress and no new value present, so must trigger a new reading. + P074_data->startIntegrationNeeded = true; + } } - success = true; } else { addLog(LOG_LEVEL_ERROR, F("TSL2591: Sensor not initialized!?")); }