[VL53L0x] Make reading sensor async

This commit is contained in:
TD-er
2024-06-27 13:38:46 +02:00
parent 97060ac321
commit 25bdb676f0
5 changed files with 65 additions and 44 deletions
+21 -13
View File
@@ -832,12 +832,16 @@ uint16_t VL53L0X::readRangeContinuousMillimeters()
start_timeout_ms = millis();
while (!loop(distance)) {
if (VL53L0X_NOT_WAITING == distance) {
return 65535;
return 65535u;
}
}
if (VL53L0X_TIMEOUT == distance)
{
return 65535;
return 65535u;
}
if (VL53L0X_WAITING == distance)
{
return 65534u;
}
return distance;
}
@@ -869,6 +873,11 @@ bool VL53L0X::asyncReadRangeSingleMillimeters(int16_t& distance)
return false;
}
bool VL53L0X::asyncReadRangeContinuousMillimeters(int16_t& distance)
{
return loop(distance);
}
// Performs a single-shot range measurement and returns the reading in
// millimeters
// based on VL53L0X_PerformSingleRangingMeasurement()
@@ -1100,7 +1109,6 @@ bool VL53L0X::loop(int16_t& distance) {
}
case state_e::waitMeasurement:
{
distance = VL53L0X_WAITING;
if ((readReg(RESULT_INTERRUPT_STATUS) & 0x07) == 0) {
if (timePassedSince > io_timeout) {
distance = VL53L0X_TIMEOUT;
@@ -1108,17 +1116,17 @@ bool VL53L0X::loop(int16_t& distance) {
start_timeout_ms = millis();
return true;
}
} else {
// assumptions: Linearity Corrective Gain is 1000 (default);
// fractional ranging is not enabled
distance = readReg16Bit(RESULT_RANGE_STATUS + 10);
writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
did_timeout = false;
start_timeout_ms = millis();
return true;
distance = VL53L0X_WAITING;
return false;
}
return false;
// assumptions: Linearity Corrective Gain is 1000 (default);
// fractional ranging is not enabled
distance = readReg16Bit(RESULT_RANGE_STATUS + 10);
writeReg(SYSTEM_INTERRUPT_CLEAR, 0x01);
did_timeout = false;
start_timeout_ms = millis();
return true;
}
}
return true;
+5
View File
@@ -197,6 +197,11 @@ public:
// Valid distance when distance >= 0
bool asyncReadRangeSingleMillimeters(int16_t& distance);
// Check if new sample is ready.
// Return true when measurement has finished or aborted.
// Valid distance when distance >= 0
bool asyncReadRangeContinuousMillimeters(int16_t& distance);
private:
enum class state_e {
+7 -7
View File
@@ -142,7 +142,10 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string)
initPluginTaskData(event->TaskIndex, new (std::nothrow) P110_data_struct(P110_I2C_ADDRESS, P110_TIMING, P110_RANGE == 1));
P110_data_struct *P110_data = static_cast<P110_data_struct *>(getPluginTaskData(event->TaskIndex));
success = (nullptr != P110_data) && P110_data->begin(); // Start the sensor
if (nullptr != P110_data) {
const uint32_t interval_ms = Settings.TaskDeviceTimer[event->TaskIndex] * 1000;
success = P110_data->begin(interval_ms); // Start the sensor
}
break;
}
case PLUGIN_READ:
@@ -151,8 +154,8 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string)
if (nullptr != P110_data) {
if (P110_data->isReadSuccessful()) {
const uint16_t dist = P110_data->getDistance();
const uint16_t p_dist = UserVar.getFloat(event->TaskIndex, 0);
const int16_t dist = P110_data->getDistance();
const int16_t p_dist = UserVar.getFloat(event->TaskIndex, 0);
const int16_t direct = dist == p_dist ? 0 : (dist < p_dist ? -1 : 1);
const bool triggered = (dist > (p_dist + P110_DELTA)) || (dist < (p_dist - P110_DELTA));
@@ -178,10 +181,7 @@ boolean Plugin_110(uint8_t function, struct EventStruct *event, String& string)
P110_data_struct *P110_data = static_cast<P110_data_struct *>(getPluginTaskData(event->TaskIndex));
if (nullptr != P110_data) {
P110_data->readDistance();
if (P110_data->isReadSuccessful() && (Settings.TaskDeviceTimer[event->TaskIndex] == 0)) { // Trigger as soon as there's a valid
// measurement and 0 interval is set
if (P110_data->readDistance() >= 0) {
Scheduler.schedule_task_device_timer(event->TaskIndex, millis() + 10);
}
}
+25 -19
View File
@@ -10,7 +10,7 @@ P110_data_struct::P110_data_struct(uint8_t i2c_addr, int timing, bool range) :
// **************************************************************************/
// Initialize VL53L0X
// **************************************************************************/
bool P110_data_struct::begin() {
bool P110_data_struct::begin(uint32_t interval_ms) {
_timeToWait = 0;
_initPhase = P110_initPhases::Undefined;
sensor.setAddress(_i2cAddress); // Initialize for configured address
@@ -39,6 +39,8 @@ bool P110_data_struct::begin() {
_initPhase = P110_initPhases::InitDelay;
_timeToWait = millis() + _timing + 50;
sensor.startContinuous(interval_ms);
return true;
}
@@ -52,8 +54,10 @@ bool P110_data_struct::plugin_fifty_per_second() {
return true;
}
int16_t P110_data_struct::getDistance() const {
return _distance;
int16_t P110_data_struct::getDistance() {
const int res = _distance;
_distance = P110_DISTANCE_WAITING;
return res;
}
int16_t P110_data_struct::readDistance() {
@@ -61,6 +65,15 @@ int16_t P110_data_struct::readDistance() {
return P110_DISTANCE_UNINITIALIZED;
}
const uint16_t dist = sensor.readRangeContinuousMillimeters();
if (dist == 65534) {
// Just waiting
// No need to keep sending many logs per second
return P110_DISTANCE_WAITING;
}
# ifdef P110_DEBUG_LOG
if (loglevelActiveFor(LOG_LEVEL_DEBUG)) {
@@ -69,35 +82,28 @@ int16_t P110_data_struct::readDistance() {
}
# endif // P110_DEBUG_LOG
const uint16_t dist = sensor.readRangeSingleMillimeters();
if (sensor.timeoutOccurred()) {
# ifdef P110_DEBUG_LOG
addLog(LOG_LEVEL_DEBUG, F("VL53L0X: TIMEOUT"));
# endif // P110_DEBUG_LOG
_distance = P110_DISTANCE_READ_TIMEOUT;
return P110_DISTANCE_READ_TIMEOUT;
} else if (dist == 0xFFFF) {
# ifdef P110_DEBUG_LOG
addLog(LOG_LEVEL_DEBUG, F("VL53L0X: NO MEASUREMENT: 0xFFFF"));
# endif // P110_DEBUG_LOG
_distance = P110_DISTANCE_READ_ERROR;
return P110_DISTANCE_READ_ERROR;
} else if (dist >= 8190u) {
# ifdef P110_DEBUG_LOG
addLog(LOG_LEVEL_DEBUG, concat(F("VL53L0X: NO MEASUREMENT: "), dist));
# endif // P110_DEBUG_LOG
_distance = P110_DISTANCE_OUT_OF_RANGE;
} else {
_distance = dist;
}
# ifdef P110_INFO_LOG
if (loglevelActiveFor(LOG_LEVEL_INFO)) {
addLogMove(LOG_LEVEL_INFO, strformat(F("VL53L0X: Addr: 0x%02x / Timing: %d / Long Range: %d / success: %d / Distance: %d"),
_i2cAddress, _timing, _range, success, dist));
}
# endif // P110_INFO_LOG
return P110_DISTANCE_OUT_OF_RANGE;
}
// Only keep a copy of actual distance readings.
// Since the distance reading is later called from PLUGIN_READ,
// we might have had a new reading inbetween which could be a "still waiting"
// value and then we lost the actual reading.
_distance = dist;
return _distance;
}
+7 -5
View File
@@ -25,12 +25,14 @@
# define P110_DISTANCE_READ_TIMEOUT -2
# define P110_DISTANCE_READ_ERROR -3
# define P110_DISTANCE_OUT_OF_RANGE -4
# define P110_DISTANCE_WAITING -5
enum class P110_initPhases : uint8_t {
Ready = 0x00,
InitDelay = 0x01,
Undefined = 0xFF
Undefined = 0xFF,
InitDelay = 0x00,
Ready = 0x01,
WaitMeasurement = 0x02
};
struct P110_data_struct : public PluginTaskData_base {
@@ -42,9 +44,9 @@ public:
P110_data_struct() = delete;
virtual ~P110_data_struct() = default;
bool begin();
bool begin(uint32_t interval_ms);
int16_t readDistance();
int16_t getDistance() const;
int16_t getDistance();
bool isReadSuccessful() const;
bool plugin_fifty_per_second();