mirror of
https://github.com/PX4/PX4-Autopilot.git
synced 2026-05-28 10:46:33 +08:00
drivers: auav, read sensor eeprom to get cal range (#26294)
* drivers: auav, read sensor eeprom to get cal range * added review feedback
This commit is contained in:
@@ -77,6 +77,10 @@ AUAV::~AUAV()
|
|||||||
void AUAV::RunImpl()
|
void AUAV::RunImpl()
|
||||||
{
|
{
|
||||||
switch (_state) {
|
switch (_state) {
|
||||||
|
case STATE::READ_FACTORY_DATA:
|
||||||
|
handle_state_read_factory_data();
|
||||||
|
break;
|
||||||
|
|
||||||
case STATE::READ_CALIBDATA:
|
case STATE::READ_CALIBDATA:
|
||||||
handle_state_read_calibdata();
|
handle_state_read_calibdata();
|
||||||
break;
|
break;
|
||||||
@@ -107,23 +111,6 @@ int AUAV::init()
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t hw_model = 0;
|
|
||||||
param_get(param_find("SENS_EN_AUAVX"), &hw_model);
|
|
||||||
|
|
||||||
switch (hw_model) {
|
|
||||||
case 1: /* AUAV L05D (+- 5 inH20) */
|
|
||||||
_cal_range = 10.0f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 2: /* AUAV L10D (+- 10 inH20) */
|
|
||||||
_cal_range = 20.0f;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 3: /* AUAV L30D (+- 30 inH20) */
|
|
||||||
_cal_range = 60.0f;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
ScheduleClear();
|
ScheduleClear();
|
||||||
ScheduleNow();
|
ScheduleNow();
|
||||||
return PX4_OK;
|
return PX4_OK;
|
||||||
@@ -148,6 +135,20 @@ int AUAV::probe()
|
|||||||
return PX4_ERROR;
|
return PX4_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AUAV::handle_state_read_factory_data()
|
||||||
|
{
|
||||||
|
int status = read_factory_data();
|
||||||
|
|
||||||
|
if (status == PX4_OK) {
|
||||||
|
/* Factory data read or sensor does not have any, move to next state */
|
||||||
|
_state = STATE::READ_CALIBDATA;
|
||||||
|
ScheduleNow();
|
||||||
|
|
||||||
|
} else {
|
||||||
|
ScheduleDelayed(100_ms);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void AUAV::handle_state_read_calibdata()
|
void AUAV::handle_state_read_calibdata()
|
||||||
{
|
{
|
||||||
int status = PX4_OK;
|
int status = PX4_OK;
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ public:
|
|||||||
|
|
||||||
protected:
|
protected:
|
||||||
enum class STATE : uint8_t {
|
enum class STATE : uint8_t {
|
||||||
|
READ_FACTORY_DATA,
|
||||||
READ_CALIBDATA,
|
READ_CALIBDATA,
|
||||||
REQUEST_MEASUREMENT,
|
REQUEST_MEASUREMENT,
|
||||||
GATHER_MEASUREMENT
|
GATHER_MEASUREMENT
|
||||||
@@ -107,7 +108,9 @@ protected:
|
|||||||
virtual int64_t get_conversion_interval() const = 0;
|
virtual int64_t get_conversion_interval() const = 0;
|
||||||
virtual calib_eeprom_addr_t get_calib_eeprom_addr() const = 0;
|
virtual calib_eeprom_addr_t get_calib_eeprom_addr() const = 0;
|
||||||
virtual float process_pressure_dig(const float pressure_dig) const = 0;
|
virtual float process_pressure_dig(const float pressure_dig) const = 0;
|
||||||
|
virtual int read_factory_data() = 0;
|
||||||
|
|
||||||
|
void handle_state_read_factory_data();
|
||||||
void handle_state_read_calibdata();
|
void handle_state_read_calibdata();
|
||||||
void handle_state_request_measurement();
|
void handle_state_request_measurement();
|
||||||
void handle_state_gather_measurement();
|
void handle_state_gather_measurement();
|
||||||
@@ -117,8 +120,7 @@ protected:
|
|||||||
float correct_pressure(const uint32_t pressure_raw, const uint32_t temperature_raw) const;
|
float correct_pressure(const uint32_t pressure_raw, const uint32_t temperature_raw) const;
|
||||||
float process_temperature_raw(const float temperature_raw) const;
|
float process_temperature_raw(const float temperature_raw) const;
|
||||||
|
|
||||||
float _cal_range{10.0f};
|
STATE _state{STATE::READ_FACTORY_DATA};
|
||||||
STATE _state{STATE::READ_CALIBDATA};
|
|
||||||
calib_data_t _calib_data {};
|
calib_data_t _calib_data {};
|
||||||
|
|
||||||
perf_counter_t _sample_perf;
|
perf_counter_t _sample_perf;
|
||||||
|
|||||||
@@ -77,3 +77,9 @@ float AUAV_Absolute::process_pressure_dig(const float pressure_dig) const
|
|||||||
const float pressure_mbar = 250.f + 1.25f * ((pressure_dig - (0.1f * (1 << 24))) / (1 << 24)) * 1000.f;
|
const float pressure_mbar = 250.f + 1.25f * ((pressure_dig - (0.1f * (1 << 24))) / (1 << 24)) * 1000.f;
|
||||||
return pressure_mbar * MBAR_TO_PA;
|
return pressure_mbar * MBAR_TO_PA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AUAV_Absolute::read_factory_data()
|
||||||
|
{
|
||||||
|
/* Absolute sensor doesn't need to read factory data */
|
||||||
|
return PX4_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -68,6 +68,7 @@ private:
|
|||||||
int64_t get_conversion_interval() const override;
|
int64_t get_conversion_interval() const override;
|
||||||
calib_eeprom_addr_t get_calib_eeprom_addr() const override;
|
calib_eeprom_addr_t get_calib_eeprom_addr() const override;
|
||||||
float process_pressure_dig(const float pressure_dig) const override;
|
float process_pressure_dig(const float pressure_dig) const override;
|
||||||
|
int read_factory_data() override;
|
||||||
|
|
||||||
uORB::PublicationMulti<sensor_baro_s> _sensor_baro_pub{ORB_ID(sensor_baro)};
|
uORB::PublicationMulti<sensor_baro_s> _sensor_baro_pub{ORB_ID(sensor_baro)};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -33,10 +33,38 @@
|
|||||||
|
|
||||||
#include "AUAV_Differential.hpp"
|
#include "AUAV_Differential.hpp"
|
||||||
#include <parameters/param.h>
|
#include <parameters/param.h>
|
||||||
|
#include <cctype>
|
||||||
|
|
||||||
AUAV_Differential::AUAV_Differential(const I2CSPIDriverConfig &config) :
|
AUAV_Differential::AUAV_Differential(const I2CSPIDriverConfig &config) :
|
||||||
AUAV(config)
|
AUAV(config)
|
||||||
{
|
{
|
||||||
|
/* Initialize cal_range from parameter as fallback value */
|
||||||
|
int32_t hw_model = 0;
|
||||||
|
param_get(param_find("SENS_EN_AUAVX"), &hw_model);
|
||||||
|
|
||||||
|
switch (hw_model) {
|
||||||
|
case 1: /* AUAV L05D (+- 5 inH20) */
|
||||||
|
_cal_range = 10;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 2: /* AUAV L10D (+- 10 inH20) */
|
||||||
|
_cal_range = 20;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 3: /* AUAV L30D (+- 30 inH20) */
|
||||||
|
_cal_range = 60;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
_cal_range = 10; /* Default fallback */
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AUAV_Differential::print_status()
|
||||||
|
{
|
||||||
|
AUAV::print_status();
|
||||||
|
PX4_INFO("cal range: %" PRId32, _cal_range);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AUAV_Differential::publish_pressure(const float pressure_p, const float temperature_c,
|
void AUAV_Differential::publish_pressure(const float pressure_p, const float temperature_c,
|
||||||
@@ -83,6 +111,52 @@ AUAV::calib_eeprom_addr_t AUAV_Differential::get_calib_eeprom_addr() const
|
|||||||
|
|
||||||
float AUAV_Differential::process_pressure_dig(const float pressure_dig) const
|
float AUAV_Differential::process_pressure_dig(const float pressure_dig) const
|
||||||
{
|
{
|
||||||
const float pressure_in_h = 1.25f * ((pressure_dig - (1 << 23)) / (1 << 24)) * _cal_range;
|
const float pressure_in_h = 1.25f * ((pressure_dig - (1 << 23)) / (1 << 24)) * static_cast<float>(_cal_range);
|
||||||
return pressure_in_h * INH_TO_PA;
|
return pressure_in_h * INH_TO_PA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int AUAV_Differential::read_factory_data()
|
||||||
|
{
|
||||||
|
/* The differential sensor needs the cal_range from the absolute sensor's EEPROM.
|
||||||
|
* Temporarily switch to the absolute sensor's I2C address to read it, then switch back. */
|
||||||
|
|
||||||
|
uint8_t original_address = get_device_address();
|
||||||
|
set_device_address(I2C_ADDRESS_ABSOLUTE);
|
||||||
|
|
||||||
|
/* Read the calibration range from the absolute sensor's EEPROM */
|
||||||
|
uint16_t factory_data = 0;
|
||||||
|
int status = read_calibration_eeprom(EEPROM_ABS_CAL_RNG, factory_data);
|
||||||
|
|
||||||
|
set_device_address(original_address);
|
||||||
|
|
||||||
|
if (status != PX4_OK) {
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If EEPROM data is 0, stop trying (sensor does not have factory data) */
|
||||||
|
if (factory_data == 0) {
|
||||||
|
PX4_INFO("Differential: cal range data is 0, using fallback value");
|
||||||
|
return PX4_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Decode the two bytes as ASCII characters */
|
||||||
|
uint8_t char_high = (factory_data >> 8) & 0xFF;
|
||||||
|
uint8_t char_low = factory_data & 0xFF;
|
||||||
|
|
||||||
|
/* Validate that both characters are ASCII digits (0-9) */
|
||||||
|
if (!isdigit(char_high) || !isdigit(char_low)) {
|
||||||
|
return PX4_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t sensor_type = ((char_high - '0') * 10) + (char_low - '0');
|
||||||
|
|
||||||
|
/* Check if the detected sensor type is valid */
|
||||||
|
if (sensor_type != AUAV_LD_05 && sensor_type != AUAV_LD_10 && sensor_type != AUAV_LD_30) {
|
||||||
|
return PX4_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
|
_cal_range = sensor_type * 2;
|
||||||
|
PX4_INFO("Differential: read cal range %" PRId32 " from absolute sensor EEPROM", _cal_range);
|
||||||
|
|
||||||
|
return PX4_OK;
|
||||||
|
}
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
#include <uORB/topics/differential_pressure.h>
|
#include <uORB/topics/differential_pressure.h>
|
||||||
|
|
||||||
/* AUAV EEPROM addresses for differential channel */
|
/* AUAV EEPROM addresses for differential channel */
|
||||||
|
static constexpr uint8_t EEPROM_ABS_CAL_RNG = 0x25;
|
||||||
static constexpr uint8_t EEPROM_DIFF_AHW = 0x2B;
|
static constexpr uint8_t EEPROM_DIFF_AHW = 0x2B;
|
||||||
static constexpr uint8_t EEPROM_DIFF_ALW = 0x2C;
|
static constexpr uint8_t EEPROM_DIFF_ALW = 0x2C;
|
||||||
static constexpr uint8_t EEPROM_DIFF_BHW = 0x2D;
|
static constexpr uint8_t EEPROM_DIFF_BHW = 0x2D;
|
||||||
@@ -57,17 +58,26 @@ static_assert(DIFF_CONVERSION_INTERVAL >= 7000, "Conversion interval is too fast
|
|||||||
/* Conversions */
|
/* Conversions */
|
||||||
static constexpr float INH_TO_PA = 249.08f;
|
static constexpr float INH_TO_PA = 249.08f;
|
||||||
|
|
||||||
|
/* Valid AUAV types */
|
||||||
|
static constexpr int32_t AUAV_LD_05 = 5;
|
||||||
|
static constexpr int32_t AUAV_LD_10 = 10;
|
||||||
|
static constexpr int32_t AUAV_LD_30 = 30;
|
||||||
|
|
||||||
class AUAV_Differential : public AUAV
|
class AUAV_Differential : public AUAV
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
explicit AUAV_Differential(const I2CSPIDriverConfig &config);
|
explicit AUAV_Differential(const I2CSPIDriverConfig &config);
|
||||||
~AUAV_Differential() = default;
|
~AUAV_Differential() = default;
|
||||||
|
|
||||||
|
void print_status() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void publish_pressure(const float pressure_p, const float temperature_c, const hrt_abstime timestamp_sample) override;
|
void publish_pressure(const float pressure_p, const float temperature_c, const hrt_abstime timestamp_sample) override;
|
||||||
int64_t get_conversion_interval() const override;
|
int64_t get_conversion_interval() const override;
|
||||||
calib_eeprom_addr_t get_calib_eeprom_addr() const override;
|
calib_eeprom_addr_t get_calib_eeprom_addr() const override;
|
||||||
float process_pressure_dig(const float pressure_dig) const override;
|
float process_pressure_dig(const float pressure_dig) const override;
|
||||||
|
int read_factory_data() override;
|
||||||
|
|
||||||
uORB::PublicationMulti<differential_pressure_s> _differential_pressure_pub{ORB_ID(differential_pressure)};
|
uORB::PublicationMulti<differential_pressure_s> _differential_pressure_pub{ORB_ID(differential_pressure)};
|
||||||
|
int32_t _cal_range{10};
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user