tfmini : fix scheduling and modernize output

This reduces the scheduling interval to 9ms, such that the driver is always ready to read new data. Running it at exactly 100Hz is not correct since the driver and sensor measurement intervals are not "in sync", causing the driver to miss data. This causes a fill-up of the UART buffer.
This commit is contained in:
Mohammed Kabir
2018-08-24 11:19:31 -04:00
committed by Lorenz Meier
parent e4088204ee
commit 3afa018954
+32 -81
View File
@@ -118,16 +118,11 @@ private:
orb_advert_t _distance_sensor_topic; orb_advert_t _distance_sensor_topic;
unsigned _consecutive_fail_count;
perf_counter_t _sample_perf; perf_counter_t _sample_perf;
perf_counter_t _comms_errors; perf_counter_t _comms_errors;
/** /**
* Initialise the automatic measurement state machine and start it. * Initialise the automatic measurement state machine and start it.
*
* @note This function is called at open and error time. It might make sense
* to make it more aggressive about resetting the bus in case of errors.
*/ */
void start(); void start();
@@ -174,7 +169,7 @@ TFMINI::TFMINI(const char *port, uint8_t rotation) :
_rotation(rotation), _rotation(rotation),
_min_distance(0.30f), _min_distance(0.30f),
_max_distance(12.0f), _max_distance(12.0f),
_conversion_interval(10000), _conversion_interval(9000),
_reports(nullptr), _reports(nullptr),
_measure_ticks(0), _measure_ticks(0),
_collect_phase(false), _collect_phase(false),
@@ -185,7 +180,6 @@ TFMINI::TFMINI(const char *port, uint8_t rotation) :
_class_instance(-1), _class_instance(-1),
_orb_class_instance(-1), _orb_class_instance(-1),
_distance_sensor_topic(nullptr), _distance_sensor_topic(nullptr),
_consecutive_fail_count(0),
_sample_perf(perf_alloc(PC_ELAPSED, "tfmini_read")), _sample_perf(perf_alloc(PC_ELAPSED, "tfmini_read")),
_comms_errors(perf_alloc(PC_COUNT, "tfmini_com_err")) _comms_errors(perf_alloc(PC_COUNT, "tfmini_com_err"))
{ {
@@ -233,7 +227,7 @@ TFMINI::init()
case 1: /* TFMINI (12m, 100 Hz)*/ case 1: /* TFMINI (12m, 100 Hz)*/
_min_distance = 0.3f; _min_distance = 0.3f;
_max_distance = 12.0f; _max_distance = 12.0f;
_conversion_interval = 10000; _conversion_interval = 9000;
break; break;
default: default:
@@ -247,10 +241,10 @@ TFMINI::init()
do { /* create a scope to handle exit conditions using break */ do { /* create a scope to handle exit conditions using break */
/* open fd */ /* open fd */
_fd = ::open(_port, O_RDWR | O_NOCTTY | O_SYNC); _fd = ::open(_port, O_RDWR | O_NOCTTY);
if (_fd < 0) { if (_fd < 0) {
warnx("Error opening fd"); PX4_ERR("Error opening fd");
return -1; return -1;
} }
@@ -268,19 +262,19 @@ TFMINI::init()
/* set baud rate */ /* set baud rate */
if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) { if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
warnx("ERR CFG: %d ISPD", termios_state); PX4_ERR("CFG: %d ISPD", termios_state);
ret = -1; ret = -1;
break; break;
} }
if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) { if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
warnx("ERR CFG: %d OSPD\n", termios_state); PX4_ERR("CFG: %d OSPD\n", termios_state);
ret = -1; ret = -1;
break; break;
} }
if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) { if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) {
warnx("ERR baud %d ATTR", termios_state); PX4_ERR("baud %d ATTR", termios_state);
ret = -1; ret = -1;
break; break;
} }
@@ -302,7 +296,7 @@ TFMINI::init()
uart_config.c_cc[VTIME] = 1; uart_config.c_cc[VTIME] = 1;
if (_fd < 0) { if (_fd < 0) {
warnx("FAIL: laser fd"); PX4_ERR("FAIL: laser fd");
ret = -1; ret = -1;
break; break;
} }
@@ -316,7 +310,7 @@ TFMINI::init()
_reports = new ringbuffer::RingBuffer(2, sizeof(distance_sensor_s)); _reports = new ringbuffer::RingBuffer(2, sizeof(distance_sensor_s));
if (_reports == nullptr) { if (_reports == nullptr) {
warnx("mem err"); PX4_ERR("mem err");
ret = -1; ret = -1;
break; break;
} }
@@ -538,7 +532,7 @@ TFMINI::collect()
ret = ::read(_fd, &readbuf[0], readlen); ret = ::read(_fd, &readbuf[0], readlen);
if (ret < 0) { if (ret < 0) {
DEVICE_DEBUG("read err: %d", ret); PX4_ERR("read err: %d", ret);
perf_count(_comms_errors); perf_count(_comms_errors);
perf_end(_sample_perf); perf_end(_sample_perf);
@@ -629,7 +623,7 @@ TFMINI::cycle()
/* fds initialized? */ /* fds initialized? */
if (_fd < 0) { if (_fd < 0) {
/* open fd */ /* open fd */
_fd = ::open(_port, O_RDWR | O_NOCTTY | O_SYNC); _fd = ::open(_port, O_RDWR | O_NOCTTY);
} }
/* collection phase? */ /* collection phase? */
@@ -639,33 +633,15 @@ TFMINI::cycle()
int collect_ret = collect(); int collect_ret = collect();
if (collect_ret == -EAGAIN) { if (collect_ret == -EAGAIN) {
/* reschedule to grab the missing bits, time to transmit 8 bytes @ 9600 bps */ /* reschedule to grab the missing bits, time to transmit 9 bytes @ 115200 bps */
work_queue(HPWORK, work_queue(HPWORK,
&_work, &_work,
(worker_t)&TFMINI::cycle_trampoline, (worker_t)&TFMINI::cycle_trampoline,
this, this,
USEC2TICK(1042 * 8)); USEC2TICK(87 * 9));
return; return;
} }
if (OK != collect_ret) {
/* we know the sensor needs about four seconds to initialize */
if (hrt_absolute_time() > 5 * 1000 * 1000LL && _consecutive_fail_count < 5) {
DEVICE_LOG("collection error #%u", _consecutive_fail_count);
}
_consecutive_fail_count++;
/* restart the measurement state machine */
start();
return;
} else {
/* apparently success */
_consecutive_fail_count = 0;
}
/* next phase is measurement */ /* next phase is measurement */
_collect_phase = false; _collect_phase = false;
@@ -717,7 +693,6 @@ TFMINI *g_dev;
void start(const char *port, uint8_t rotation); void start(const char *port, uint8_t rotation);
void stop(); void stop();
void test(); void test();
void reset();
void info(); void info();
void usage(); void usage();
@@ -730,7 +705,8 @@ start(const char *port, uint8_t rotation)
int fd; int fd;
if (g_dev != nullptr) { if (g_dev != nullptr) {
errx(1, "already started"); PX4_ERR("already started");
exit(1);
} }
/* create the driver */ /* create the driver */
@@ -748,7 +724,7 @@ start(const char *port, uint8_t rotation)
fd = px4_open(RANGE_FINDER0_DEVICE_PATH, O_RDONLY); fd = px4_open(RANGE_FINDER0_DEVICE_PATH, O_RDONLY);
if (fd < 0) { if (fd < 0) {
warnx("Opening device '%s' failed"); PX4_ERR("Opening device '%s' failed");
goto fail; goto fail;
} }
@@ -765,7 +741,8 @@ fail:
g_dev = nullptr; g_dev = nullptr;
} }
errx(1, "driver start failed"); PX4_ERR("driver start failed");
exit(1);
} }
/** /**
@@ -774,13 +751,14 @@ fail:
void stop() void stop()
{ {
if (g_dev != nullptr) { if (g_dev != nullptr) {
warnx("stopping driver"); PX4_INFO("stopping driver");
delete g_dev; delete g_dev;
g_dev = nullptr; g_dev = nullptr;
warnx("driver stopped"); PX4_INFO("driver stopped");
} else { } else {
errx(1, "driver not running"); PX4_ERR("driver not running");
exit(1);
} }
exit(0); exit(0);
@@ -814,7 +792,8 @@ test()
/* start the sensor polling at 2 Hz rate */ /* start the sensor polling at 2 Hz rate */
if (OK != px4_ioctl(fd, SENSORIOCSPOLLRATE, 2)) { if (OK != px4_ioctl(fd, SENSORIOCSPOLLRATE, 2)) {
errx(1, "failed to set 2Hz poll rate"); PX4_ERR("failed to set 2Hz poll rate");
exit(1);
} }
/* read the sensor 5x and report each value */ /* read the sensor 5x and report each value */
@@ -827,7 +806,7 @@ test()
int ret = px4_poll(&fds, 1, 2000); int ret = px4_poll(&fds, 1, 2000);
if (ret != 1) { if (ret != 1) {
warnx("timed out"); PX4_ERR("timed out");
break; break;
} }
@@ -835,7 +814,7 @@ test()
sz = px4_read(fd, &report, sizeof(report)); sz = px4_read(fd, &report, sizeof(report));
if (sz != sizeof(report)) { if (sz != sizeof(report)) {
warnx("read failed: got %d vs exp. %d", sz, sizeof(report)); PX4_ERR("read failed: got %d vs exp. %d", sz, sizeof(report));
break; break;
} }
@@ -844,33 +823,11 @@ test()
/* reset the sensor polling to the default rate */ /* reset the sensor polling to the default rate */
if (OK != px4_ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) { if (OK != px4_ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) {
errx(1, "ERR: DEF RATE"); PX4_ERR("failed to set default poll rate");
exit(1);
} }
errx(0, "PASS"); PX4_INFO("PASS");
}
/**
* Reset the driver.
*/
void
reset()
{
int fd = px4_open(RANGE_FINDER0_DEVICE_PATH, O_RDONLY);
if (fd < 0) {
err(1, "failed ");
}
if (px4_ioctl(fd, SENSORIOCRESET, 0) < 0) {
err(1, "driver reset failed");
}
if (px4_ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT) < 0) {
err(1, "driver poll restart failed");
}
exit(0);
} }
/** /**
@@ -880,7 +837,8 @@ void
info() info()
{ {
if (g_dev == nullptr) { if (g_dev == nullptr) {
errx(1, "driver not running"); PX4_ERR("driver not running");
exit(1);
} }
printf("state @ %p\n", g_dev); printf("state @ %p\n", g_dev);
@@ -958,13 +916,6 @@ tfmini_main(int argc, char *argv[])
tfmini::test(); tfmini::test();
} }
/*
* Reset the driver.
*/
if (!strcmp(argv[myoptind], "reset")) {
tfmini::reset();
}
/* /*
* Print driver information. * Print driver information.
*/ */
@@ -973,6 +924,6 @@ tfmini_main(int argc, char *argv[])
} }
out_error: out_error:
PX4_ERR("unrecognized command, try 'start', 'test', 'reset' or 'info'"); PX4_ERR("unrecognized command, try 'start', 'test', or 'info'");
return -1; return -1;
} }