Browse Source

Merge pull request #785 from PX4/laser_fixes

Robustify SF02/F parsing, adjust health checks and startup routine
sbg
Lorenz Meier 11 years ago
parent
commit
971e1241c8
  1. 131
      src/drivers/sf0x/sf0x.cpp

131
src/drivers/sf0x/sf0x.cpp

@ -276,34 +276,11 @@ SF0X::init()
warnx("advert err"); warnx("advert err");
} }
/* attempt to get a measurement 5 times */
while (ret != OK && i < 5) {
if (measure()) {
ret = ERROR;
_sensor_ok = false;
}
usleep(100000);
if (collect()) {
ret = ERROR;
_sensor_ok = false;
} else {
ret = OK;
/* sensor is ok, but we don't really know if it is within range */
_sensor_ok = true;
}
i++;
}
/* close the fd */ /* close the fd */
::close(_fd); ::close(_fd);
_fd = -1; _fd = -1;
out: out:
return ret; return OK;
} }
int int
@ -376,6 +353,7 @@ SF0X::ioctl(struct file *filp, int cmd, unsigned long arg)
/* adjust to a legal polling interval in Hz */ /* adjust to a legal polling interval in Hz */
default: { default: {
/* do we need to start internal polling? */ /* do we need to start internal polling? */
bool want_start = (_measure_ticks == 0); bool want_start = (_measure_ticks == 0);
@ -544,10 +522,16 @@ SF0X::collect()
if (read_elapsed > (SF0X_CONVERSION_INTERVAL * 2)) { if (read_elapsed > (SF0X_CONVERSION_INTERVAL * 2)) {
_linebuf_index = 0; _linebuf_index = 0;
} else if (_linebuf_index > 0) {
/* increment to next read position */
_linebuf_index++;
} }
/* the buffer for read chars is buflen minus null termination */
unsigned readlen = sizeof(_linebuf) - 1;
/* read from the sensor (uart buffer) */ /* read from the sensor (uart buffer) */
ret = ::read(_fd, &_linebuf[_linebuf_index], sizeof(_linebuf) - _linebuf_index); ret = ::read(_fd, &_linebuf[_linebuf_index], readlen - _linebuf_index);
if (ret < 0) { if (ret < 0) {
_linebuf[sizeof(_linebuf) - 1] = '\0'; _linebuf[sizeof(_linebuf) - 1] = '\0';
@ -562,19 +546,30 @@ SF0X::collect()
} else { } else {
return -EAGAIN; return -EAGAIN;
} }
} else if (ret == 0) {
return -EAGAIN;
} }
_linebuf_index += ret; /* we did increment the index to the next position already, so just add the additional fields */
_linebuf_index += (ret - 1);
if (_linebuf_index >= sizeof(_linebuf)) {
_linebuf_index = 0;
}
_last_read = hrt_absolute_time(); _last_read = hrt_absolute_time();
if (_linebuf[_linebuf_index - 2] != '\r' || _linebuf[_linebuf_index - 1] != '\n') { if (_linebuf_index < 1) {
/* incomplete read, reschedule ourselves */ /* we need at least the two end bytes to make sense of this string */
return -EAGAIN; return -EAGAIN;
} else if (_linebuf[_linebuf_index - 1] != '\r' || _linebuf[_linebuf_index] != '\n') {
if (_linebuf_index >= readlen - 1) {
/* we have a full buffer, but no line ending - abort */
_linebuf_index = 0;
perf_count(_comms_errors);
return -ENOMEM;
} else {
/* incomplete read, reschedule ourselves */
return -EAGAIN;
}
} }
char *end; char *end;
@ -582,22 +577,56 @@ SF0X::collect()
bool valid; bool valid;
/* enforce line ending */ /* enforce line ending */
_linebuf[sizeof(_linebuf) - 1] = '\0'; unsigned lend = (_linebuf_index < (sizeof(_linebuf) - 1)) ? _linebuf_index : (sizeof(_linebuf) - 1);
_linebuf[lend] = '\0';
if (_linebuf[0] == '-' && _linebuf[1] == '-' && _linebuf[2] == '.') { if (_linebuf[0] == '-' && _linebuf[1] == '-' && _linebuf[2] == '.') {
si_units = -1.0f; si_units = -1.0f;
valid = false; valid = false;
} else { } else {
si_units = strtod(_linebuf, &end);
valid = true; /* we need to find a dot in the string, as we're missing the meters part else */
valid = false;
/* wipe out partially read content from last cycle(s), check for dot */
for (int i = 0; i < (lend - 2); i++) {
if (_linebuf[i] == '\n') {
char buf[sizeof(_linebuf)];
memcpy(buf, &_linebuf[i+1], (lend + 1) - (i + 1));
memcpy(_linebuf, buf, (lend + 1) - (i + 1));
}
if (_linebuf[i] == '.') {
valid = true;
}
}
if (valid) {
si_units = strtod(_linebuf, &end);
/* we require at least 3 characters for a valid number */
if (end > _linebuf + 3) {
valid = true;
} else {
si_units = -1.0f;
valid = false;
}
}
} }
debug("val (float): %8.4f, raw: %s\n", si_units, _linebuf); debug("val (float): %8.4f, raw: %s, valid: %s\n", si_units, _linebuf, ((valid) ? "OK" : "NO"));
/* done with this chunk, resetting */ /* done with this chunk, resetting - even if invalid */
_linebuf_index = 0; _linebuf_index = 0;
/* if its invalid, there is no reason to forward the value */
if (!valid) {
perf_count(_comms_errors);
return -EINVAL;
}
struct range_finder_report report; struct range_finder_report report;
/* this should be fairly close to the end of the measurement, so the best approximation of the time */ /* this should be fairly close to the end of the measurement, so the best approximation of the time */
@ -689,7 +718,11 @@ SF0X::cycle()
} }
if (OK != collect_ret) { if (OK != collect_ret) {
log("collection error");
/* we know the sensor needs about four seconds to initialize */
if (hrt_absolute_time() > 5 * 1000 * 1000LL) {
log("collection error");
}
/* restart the measurement state machine */ /* restart the measurement state machine */
start(); start();
return; return;
@ -848,10 +881,10 @@ test()
} }
warnx("single read"); warnx("single read");
warnx("measurement: %0.2f m", (double)report.distance); warnx("val: %0.2f m", (double)report.distance);
warnx("time: %lld", report.timestamp); warnx("time: %lld", report.timestamp);
/* start the sensor polling at 2Hz */ /* start the sensor polling at 2 Hz rate */
if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2)) { if (OK != ioctl(fd, SENSORIOCSPOLLRATE, 2)) {
errx(1, "failed to set 2Hz poll rate"); errx(1, "failed to set 2Hz poll rate");
} }
@ -866,24 +899,26 @@ test()
int ret = poll(&fds, 1, 2000); int ret = poll(&fds, 1, 2000);
if (ret != 1) { if (ret != 1) {
errx(1, "timed out waiting for sensor data"); warnx("timed out");
break;
} }
/* now go get it */ /* now go get it */
sz = read(fd, &report, sizeof(report)); sz = read(fd, &report, sizeof(report));
if (sz != sizeof(report)) { if (sz != sizeof(report)) {
err(1, "periodic read failed"); warnx("read failed: got %d vs exp. %d", sz, sizeof(report));
break;
} }
warnx("periodic read %u", i); warnx("read #%u", i);
warnx("measurement: %0.3f", (double)report.distance); warnx("val: %0.3f m", (double)report.distance);
warnx("time: %lld", report.timestamp); warnx("time: %lld", report.timestamp);
} }
/* reset the sensor polling to default rate */ /* reset the sensor polling to the default rate */
if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) { if (OK != ioctl(fd, SENSORIOCSPOLLRATE, SENSOR_POLLRATE_DEFAULT)) {
errx(1, "failed to set default poll rate"); errx(1, "ERR: DEF RATE");
} }
errx(0, "PASS"); errx(0, "PASS");

Loading…
Cancel
Save