Skip to content

Commit

Permalink
AP_Airspeed: fixed timing errors in MS5525 driver
Browse files Browse the repository at this point in the history
this fixes issue #7188, where we could read from the MS5525 sensor too
soon after requesting data and the result coming back would be garbage
  • Loading branch information
tridge authored and magicrub committed Dec 27, 2017
1 parent 6c65157 commit 55f73f4
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 9 deletions.
43 changes: 34 additions & 9 deletions libraries/AP_Airspeed/AP_Airspeed_MS5525.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ bool AP_Airspeed_MS5525::init()
uint8_t reg = REG_CONVERT_TEMPERATURE;
dev->transfer(&reg, 1, nullptr, 0);
state = 0;
command_send_us = AP_HAL::micros();

// drop to 2 retries for runtime
dev->set_retries(2);
Expand Down Expand Up @@ -226,30 +227,54 @@ void AP_Airspeed_MS5525::calculate(void)
// 50Hz timer
void AP_Airspeed_MS5525::timer()
{
if (AP_HAL::micros() - command_send_us < 10000) {
// we should avoid trying to read the ADC too soon after
// sending the command
return;
}

uint32_t adc_val = read_adc();

if (adc_val == 0) {
// we have either done a read too soon after sending the
// request or we have tried to read the same sample twice. We
// re-send the command now as we don't know what state the
// sensor is in, and we do want to trigger it sending a value,
// which we will discard
if (dev->transfer(&cmd_sent, 1, nullptr, 0)) {
command_send_us = AP_HAL::micros();
}
// when we get adc_val == 0 then then both the current value and
// the next value we read from the sensor are invalid
ignore_next = true;
return;
}

/*
* If read fails, re-initiate a read command for current state or we are
* stuck
*/
uint8_t next_state = state;
if (adc_val != 0) {
next_state = (state + 1) % 5;

if (state == 0) {
if (!ignore_next) {
if (cmd_sent == REG_CONVERT_TEMPERATURE) {
D2 = adc_val;
} else {
} else if (cmd_sent == REG_CONVERT_PRESSURE) {
D1 = adc_val;
calculate();
}
}

uint8_t next_cmd = next_state == 0 ? REG_CONVERT_TEMPERATURE : REG_CONVERT_PRESSURE;
if (!dev->transfer(&next_cmd, 1, nullptr, 0)) {
ignore_next = false;

cmd_sent = (state == 0) ? REG_CONVERT_TEMPERATURE : REG_CONVERT_PRESSURE;
if (!dev->transfer(&cmd_sent, 1, nullptr, 0)) {
// we don't know for sure what state the sensor is in when we
// fail to send the command, so ignore the next response
ignore_next = true;
return;
}
command_send_us = AP_HAL::micros();

state = next_state;
state = (state + 1) % 5;
}

// return the current differential_pressure in Pascal
Expand Down
3 changes: 3 additions & 0 deletions libraries/AP_Airspeed/AP_Airspeed_MS5525.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ class AP_Airspeed_MS5525 : public AP_Airspeed_Backend
uint8_t state;
int32_t D1;
int32_t D2;
uint32_t command_send_us;
bool ignore_next;
uint8_t cmd_sent;

AP_HAL::OwnPtr<AP_HAL::I2CDevice> dev;
};

0 comments on commit 55f73f4

Please sign in to comment.