optical_flow/paw3902: minor improvements

- configure a backup schedule when using motion interrupt otherwise the
sensor will stop publishing entirely in the dark
 - as a precaution issue full reset if sensor is stuck in a bad state
(no vaid data for an extended period)
 - update light mode change criteria to match datasheet exactly
This commit is contained in:
Daniel Agar
2021-07-08 13:40:21 -04:00
parent f5e5794930
commit 62144c6b6b
3 changed files with 48 additions and 17 deletions
+40 -16
View File
@@ -137,7 +137,13 @@ bool PAW3902::DataReadyInterruptConfigure()
} }
// Setup data ready on falling edge // Setup data ready on falling edge
return px4_arch_gpiosetevent(_drdy_gpio, false, true, true, &DataReadyInterruptCallback, this) == 0; if (px4_arch_gpiosetevent(_drdy_gpio, false, true, true, &DataReadyInterruptCallback, this) == 0) {
_data_ready_interrupt_enabled = true;
return true;
}
_data_ready_interrupt_enabled = false;
return false;
} }
bool PAW3902::DataReadyInterruptDisable() bool PAW3902::DataReadyInterruptDisable()
@@ -146,6 +152,8 @@ bool PAW3902::DataReadyInterruptDisable()
return false; return false;
} }
_data_ready_interrupt_enabled = false;
return px4_arch_gpiosetevent(_drdy_gpio, false, false, false, nullptr, nullptr) == 0; return px4_arch_gpiosetevent(_drdy_gpio, false, false, false, nullptr, nullptr) == 0;
} }
@@ -165,25 +173,24 @@ bool PAW3902::ChangeMode(Mode newMode, bool force)
// Issue a soft reset // Issue a soft reset
RegisterWrite(Register::Power_Up_Reset, 0x5A); RegisterWrite(Register::Power_Up_Reset, 0x5A);
px4_usleep(1000); px4_usleep(1000);
_last_reset = hrt_absolute_time();
uint32_t interval_us = 0;
switch (newMode) { switch (newMode) {
case Mode::Bright: case Mode::Bright:
ModeBright(); ModeBright();
interval_us = SAMPLE_INTERVAL_MODE_0; _scheduled_interval_us = SAMPLE_INTERVAL_MODE_0;
perf_count(_mode_change_bright_perf); perf_count(_mode_change_bright_perf);
break; break;
case Mode::LowLight: case Mode::LowLight:
ModeLowLight(); ModeLowLight();
interval_us = SAMPLE_INTERVAL_MODE_1; _scheduled_interval_us = SAMPLE_INTERVAL_MODE_1;
perf_count(_mode_change_low_light_perf); perf_count(_mode_change_low_light_perf);
break; break;
case Mode::SuperLowLight: case Mode::SuperLowLight:
ModeSuperLowLight(); ModeSuperLowLight();
interval_us = SAMPLE_INTERVAL_MODE_2; _scheduled_interval_us = SAMPLE_INTERVAL_MODE_2;
perf_count(_mode_change_super_low_light_perf); perf_count(_mode_change_super_low_light_perf);
break; break;
} }
@@ -195,10 +202,10 @@ bool PAW3902::ChangeMode(Mode newMode, bool force)
if (DataReadyInterruptConfigure()) { if (DataReadyInterruptConfigure()) {
// backup schedule as a watchdog timeout // backup schedule as a watchdog timeout
ScheduleDelayed(500_ms); ScheduleDelayed(_scheduled_interval_us * 2);
} else { } else {
ScheduleOnInterval(interval_us); ScheduleOnInterval(_scheduled_interval_us);
} }
_mode = newMode; _mode = newMode;
@@ -610,6 +617,19 @@ bool PAW3902::RegisterWriteVerified(uint8_t reg, uint8_t data, int retries)
void PAW3902::RunImpl() void PAW3902::RunImpl()
{ {
// backup schedule
if (_data_ready_interrupt_enabled) {
ScheduleDelayed(_scheduled_interval_us * 2);
}
// force reset if there hasn't been valid data for an extended period (sensor could be in a bad state)
static constexpr hrt_abstime RESET_TIMEOUT_US = 5_s;
if ((hrt_elapsed_time(&_last_good_publish) > RESET_TIMEOUT_US) && (hrt_elapsed_time(&_last_reset) > RESET_TIMEOUT_US)) {
ChangeMode(Mode::LowLight, true);
return;
}
perf_begin(_sample_perf); perf_begin(_sample_perf);
perf_count(_interval_perf); perf_count(_interval_perf);
@@ -660,8 +680,8 @@ void PAW3902::RunImpl()
data_valid = false; data_valid = false;
} }
// shutter >= 8190 (0x1FFE), raw data sum <= 60 (0x3C) // shutter >= 8190 (0x1FFE), raw data sum < 60 (0x3C)
if (data_valid && (_valid_count >= 10) && (shutter >= 0x1FFE) && (buf.data.RawData_Sum <= 0x3C)) { if ((shutter >= 0x1FFE) && (buf.data.RawData_Sum < 0x3C)) {
// Bright -> LowLight // Bright -> LowLight
_bright_to_low_counter++; _bright_to_low_counter++;
@@ -684,8 +704,8 @@ void PAW3902::RunImpl()
data_valid = false; data_valid = false;
} }
// shutter >= 8190 (0x1FFE) and raw data sum <= 90 (0x5A) // shutter >= 8190 (0x1FFE) and raw data sum < 90 (0x5A)
if (data_valid && (_valid_count >= 10) && (shutter >= 0x1FFE) && (buf.data.RawData_Sum <= 0x5A)) { if ((shutter >= 0x1FFE) && (buf.data.RawData_Sum < 0x5A)) {
// LowLight -> SuperLowLight // LowLight -> SuperLowLight
_low_to_bright_counter = 0; _low_to_bright_counter = 0;
_low_to_superlow_counter++; _low_to_superlow_counter++;
@@ -694,7 +714,7 @@ void PAW3902::RunImpl()
ChangeMode(Mode::SuperLowLight); ChangeMode(Mode::SuperLowLight);
} }
} else if (data_valid && (_valid_count >= 10) && (shutter < 0x0BB8)) { } else if (shutter < 0x0BB8) {
// LowLight -> Bright // LowLight -> Bright
// shutter < 0x0BB8 (3000) // shutter < 0x0BB8 (3000)
_low_to_bright_counter++; _low_to_bright_counter++;
@@ -721,7 +741,7 @@ void PAW3902::RunImpl()
} }
// shutter < 500 (0x01F4) // shutter < 500 (0x01F4)
if (data_valid && (_valid_count >= 10) && (shutter < 0x01F4)) { if (shutter < 0x01F4) {
// should not operate with Shutter < 0x01F4 in Mode 2 // should not operate with Shutter < 0x01F4 in Mode 2
_superlow_to_low_counter++; _superlow_to_low_counter++;
@@ -729,7 +749,7 @@ void PAW3902::RunImpl()
ChangeMode(Mode::LowLight); ChangeMode(Mode::LowLight);
} }
} else if (data_valid && (_valid_count >= 10) && (shutter < 0x03E8)) { } else if (shutter < 0x03E8) {
// SuperLowLight -> LowLight // SuperLowLight -> LowLight
// shutter < 1000 (0x03E8) // shutter < 1000 (0x03E8)
_superlow_to_low_counter++; _superlow_to_low_counter++;
@@ -783,7 +803,7 @@ void PAW3902::RunImpl()
report.frame_count_since_last_readout = _flow_sample_counter; // number of frames report.frame_count_since_last_readout = _flow_sample_counter; // number of frames
report.integration_timespan = _flow_dt_sum_usec; // microseconds report.integration_timespan = _flow_dt_sum_usec; // microseconds
report.quality = _flow_sample_counter > 0 ? _flow_quality_sum / _flow_sample_counter : 0; report.quality = _flow_quality_sum / _flow_sample_counter;
// No gyro on this board // No gyro on this board
report.gyro_x_rate_integral = NAN; report.gyro_x_rate_integral = NAN;
@@ -813,6 +833,10 @@ void PAW3902::RunImpl()
report.timestamp = hrt_absolute_time(); report.timestamp = hrt_absolute_time();
_optical_flow_pub.publish(report); _optical_flow_pub.publish(report);
if (report.quality > 10) {
_last_good_publish = report.timestamp;
}
ResetAccumulatedData(); ResetAccumulatedData();
} }
@@ -126,10 +126,17 @@ private:
Mode _mode{Mode::LowLight}; Mode _mode{Mode::LowLight};
uint32_t _scheduled_interval_us{SAMPLE_INTERVAL_MODE_1};
int _bright_to_low_counter{0}; int _bright_to_low_counter{0};
int _low_to_superlow_counter{0}; int _low_to_superlow_counter{0};
int _low_to_bright_counter{0}; int _low_to_bright_counter{0};
int _superlow_to_low_counter{0}; int _superlow_to_low_counter{0};
int _valid_count{0}; int _valid_count{0};
bool _data_ready_interrupt_enabled{false};
hrt_abstime _last_good_publish{0};
hrt_abstime _last_reset{0};
}; };
@@ -1,6 +1,6 @@
/**************************************************************************** /****************************************************************************
* *
* Copyright (c) 2019-2020, 2021 PX4 Development Team. All rights reserved. * Copyright (c) 2019-2021 PX4 Development Team. All rights reserved.
* *
* Redistribution and use in source and binary forms, with or without * Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions * modification, are permitted provided that the following conditions