Compare commits

...

7 Commits

Author SHA1 Message Date
Daniel Agar 592b2e9dbe move analog differential pressure to standalone optional driver 2021-02-23 13:28:29 -05:00
Daniel Agar eed060f17b drivers/differential_pressure: split ms4515 and ms4525 2021-02-23 13:28:29 -05:00
Daniel Agar beb51a219f delete drv_airspeed.h (all IOCTLs), airspeed driver lib
- differential pressure now processed downstream like other sensor data (accel/gyro/mag/etc)
 - rename msg differential_pressure -> sensor_differential_pressure
 - add device id and timestamp_sample to all messages
 - calibration performend directly on raw data and SENS_DPRES_OFF parameter updated
 - remove Airspeed base class from existing differential pressure drivers
 - name differential pressure drivers consistently (no _airspeed suffix)
2021-02-23 13:28:29 -05:00
Daniel Agar b79eec5e84 differential_pressure/ets: set invalid temperature to NAN 2021-02-23 13:28:29 -05:00
Daniel Agar 2af6333351 mavlink: HIL publish airspeed with timestamp_sample 2021-02-23 13:28:29 -05:00
Daniel Agar e658ec42b8 ekf2: use airspeed timestamp_sample 2021-02-23 13:28:29 -05:00
Daniel Agar dfb342bdac sensors: move differential pressure aggregation to sensors/airspeed WorkItem 2021-02-23 13:28:29 -05:00
59 changed files with 1861 additions and 1153 deletions
+10 -16
View File
@@ -126,23 +126,19 @@ then
then
if param compare CBRK_AIRSPD_CHK 0
then
sdp3x_airspeed start -X -q
sdp3x_airspeed start -X -a 0x22 -q
sdp3x start -X -q
sdp3x start -X -a 0x22 -q
# Pixhawk 2.1 has a MS5611 on I2C which gets wrongly
# detected as MS5525 because the chip manufacturer was so
# clever to assign the same I2C address and skip a WHO_AM_I
# register.
if [ $BOARD_FMUV3 = 21 ]
then
ms5525_airspeed start -X -b 2 -q
else
ms5525_airspeed start -X -q
fi
ms4525_airspeed start -X -q
ms4525 start -X -q
ms5525 start -X -q
ets_airspeed start -X -q
# analog differential pressure
if param greater -s SENS_DPRES_ANSC 0
then
analog_diffpres_main start
fi
fi
fi
fi
@@ -150,5 +146,3 @@ fi
###############################################################################
# End Optional drivers #
###############################################################################
sensors start
+4 -2
View File
@@ -322,11 +322,14 @@ else
# Sensors System (start before Commander so Preflight checks are properly run).
# Commander needs to be this early for in-air-restarts.
#
sensors start
if param greater SYS_HITL 0
then
set OUTPUT_MODE hil
sensors start -h
commander start -h
# disable GPS
param set GPS_1_CONFIG 0
@@ -371,7 +374,6 @@ else
set AUX_MODE pwm4
fi
# Check if ATS is enabled
if param compare FD_EXT_ATS_EN 1
then
+3 -3
View File
@@ -16,15 +16,15 @@ if board_adc start
then
fi
if sdp3x_airspeed start -X
if sdp3x start -X
then
fi
if ms5525_airspeed start -X
if ms5525 start -X
then
fi
if ms4525_airspeed start -X
if ms4525 start -X
then
fi
+1 -1
View File
@@ -11,7 +11,7 @@ lps22hb -s start
lsm303agr -s -R 4 start
ms4525_airspeed -T 4515 -I -b 3 start
ms4515 -I -b 3 start
if ! param greater SENS_EN_PMW3901 0
then
@@ -51,7 +51,5 @@
#define ADC_BATTERY_CURRENT_CHANNEL -1
#define ADC_AIRSPEED_VOLTAGE_CHANNEL 2
#define ADC_DP_V_DIV 1.0f
#include <system_config.h>
#include <px4_platform_common/board_common.h>
@@ -52,7 +52,6 @@
#define ADC_AIRSPEED_VOLTAGE_CHANNEL 2
#define BOARD_BATTERY1_V_DIV 5.7f // 1K + 4.7K
#define ADC_DP_V_DIV 1.0f
#define BOARD_ADC_OPEN_CIRCUIT_V 5.3f // Powered from USB
+1 -1
View File
@@ -51,7 +51,6 @@ set(msg_files
commander_state.msg
control_allocator_status.msg
cpuload.msg
differential_pressure.msg
distance_sensor.msg
ekf2_timestamps.msg
ekf_gps_drift.msg
@@ -127,6 +126,7 @@ set(msg_files
sensor_baro.msg
sensor_combined.msg
sensor_correction.msg
sensor_differential_pressure.msg
sensor_gps.msg
sensor_gyro.msg
sensor_gyro_fft.msg
+3 -2
View File
@@ -1,9 +1,10 @@
uint64 timestamp # time since system start (microseconds)
uint64 timestamp # time since system start (microseconds)
uint64 timestamp_sample # the timestamp of the raw data (microseconds)
float32 indicated_airspeed_m_s # indicated airspeed in m/s
float32 true_airspeed_m_s # true filtered airspeed in m/s
float32 air_temperature_celsius # air temperature in degrees celsius, -1000 if unknown
float32 air_temperature_celsius # air temperature in degrees celsius, NAN if unknown
float32 confidence # confidence value from 0 to 1 for this sensor
+4 -1
View File
@@ -1,4 +1,7 @@
uint64 timestamp # time since system start (microseconds)
uint64 timestamp # time since system start (microseconds)
uint64 timestamp_sample
uint32 device_id # unique device ID for the sensor that does not change between power cycles
float32 indicated_airspeed_m_s # indicated airspeed in m/s (IAS), set to NAN if invalid
float32 calibrated_airspeed_m_s # calibrated airspeed in m/s (CAS, accounts for instrumentation errors), set to NAN if invalid
-6
View File
@@ -1,6 +0,0 @@
uint64 timestamp # time since system start (microseconds)
uint64 error_count # Number of errors detected by driver
float32 differential_pressure_raw_pa # Raw differential pressure reading (may be negative)
float32 differential_pressure_filtered_pa # Low pass filtered differential pressure reading
float32 temperature # Temperature provided by sensor, -1000.0f if unknown
uint32 device_id # unique device ID for the sensor that does not change between power cycles
+10
View File
@@ -0,0 +1,10 @@
uint64 timestamp # time since system start (microseconds)
uint64 timestamp_sample
uint32 device_id # unique device ID for the sensor that does not change between power cycles
float32 differential_pressure_pa # differential pressure reading
float32 temperature # temperature in degrees Celsius
uint32 error_count
+1 -1
View File
@@ -33,7 +33,7 @@ rtps:
- msg: debug_vect
id: 15
receive: true
- msg: differential_pressure
- msg: sensor_differential_pressure
id: 16
- msg: distance_sensor
id: 17
+1 -1
View File
@@ -36,7 +36,7 @@ board_adc start
battery_status start
gps start -d /dev/spidev0.0 -i spi -p ubx
ms4525_airspeed start -X
ms4525 start -X
rc_update start
sensors start
commander start
@@ -31,7 +31,9 @@
#
############################################################################
add_subdirectory(analog_diffpres)
add_subdirectory(ets)
add_subdirectory(ms4515)
add_subdirectory(ms4525)
add_subdirectory(ms5525)
add_subdirectory(sdp3x)
add_subdirectory(sdp3x)
@@ -0,0 +1,205 @@
/****************************************************************************
*
* Copyright (c) 2013-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "AnalogDifferentialPressure.hpp"
#include <px4_platform_common/getopt.h>
AnalogDifferentialPressure::AnalogDifferentialPressure(int16_t adc_channel) :
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::hp_default),
_adc_channel(adc_channel)
{
}
int AnalogDifferentialPressure::init()
{
_adc_report_sub.registerCallback();
ScheduleNow();
return PX4_OK;
}
void AnalogDifferentialPressure::Run()
{
// check for parameter updates
if (_parameter_update_sub.updated()) {
// clear update
parameter_update_s pupdate;
_parameter_update_sub.copy(&pupdate);
// update parameters from storage
updateParams();
}
perf_begin(_sample_perf);
if (_param_sens_dpres_ansc.get() > 0.0f) {
adc_report_s adc;
if (_adc_report_sub.update(&adc)) {
/* Read add channels we got */
for (unsigned i = 0; i < PX4_MAX_ADC_CHANNELS; i++) {
if (_adc_channel == adc.channel_id[i]) {
// The scale factor defined by HW's resistive divider (Rt+Rb)/ Rb
#if defined(ADC_DP_V_DIV)
static constexpr float scale = ADC_DP_V_DIV;
#else
static constexpr float scale = 1.0f;
#endif
/* calculate airspeed, raw is the difference from */
const float voltage = (float)(adc.raw_data[i]) * adc.v_ref / adc.resolution * scale;
/**
* The voltage divider pulls the signal down, only act on
* a valid voltage from a connected sensor. Also assume a non-
* zero offset from the sensor if its connected.
*
* Notice: This won't work on devices which have PGA controlled
* vref. Those devices require no divider at all.
*/
if (voltage > 0.4f) {
const float differential_pressure_pa = voltage * _param_sens_dpres_ansc.get();
if (fabsf(differential_pressure_pa - _differential_pressure_pa_last) > 0.01f) {
// only publish changes
sensor_differential_pressure_s diff_pres{};
diff_pres.device_id = 0xAA; // TODO DRV_DIFF_PRESS_DEVTYPE_MS4525
diff_pres.timestamp_sample = adc.timestamp;
diff_pres.differential_pressure_pa = differential_pressure_pa;
diff_pres.temperature = NAN;
diff_pres.timestamp = hrt_absolute_time();
_diff_pres_pub.publish(diff_pres);
_differential_pressure_pa_last = differential_pressure_pa;
}
}
break;
}
}
PX4_DEBUG("ADC channel %d not found", _adc_channel);
}
}
perf_end(_sample_perf);
}
int AnalogDifferentialPressure::custom_command(int argc, char *argv[])
{
return print_usage("unknown command");
}
int AnalogDifferentialPressure::task_spawn(int argc, char *argv[])
{
#if defined(ADC_AIRSPEED_VOLTAGE_CHANNEL)
int16_t adc_channel = ADC_AIRSPEED_VOLTAGE_CHANNEL;
#else
int16_t adc_channel = -1;
#endif
bool error_flag = false;
int myoptind = 1;
int ch;
const char *myoptarg = nullptr;
while ((ch = px4_getopt(argc, argv, "c:", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'c':
adc_channel = strtoul(myoptarg, nullptr, 10);
break;
case '?':
error_flag = true;
break;
default:
PX4_WARN("unrecognized flag");
error_flag = true;
break;
}
}
if (error_flag) {
return PX4_ERROR;
}
AnalogDifferentialPressure *instance = new AnalogDifferentialPressure(adc_channel);
if (instance) {
_object.store(instance);
_task_id = task_id_is_work_queue;
if (instance->init() == PX4_OK) {
return PX4_OK;
}
} else {
PX4_ERR("alloc failed");
}
delete instance;
_object.store(nullptr);
_task_id = -1;
return PX4_ERROR;
}
int AnalogDifferentialPressure::print_usage(const char *reason)
{
if (reason) {
PX4_WARN("%s\n", reason);
}
PRINT_MODULE_DESCRIPTION(
R"DESCR_STR(
### Description
ADC driver.
)DESCR_STR");
PRINT_MODULE_USAGE_NAME("analog_diffpres", "driver");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAM_INT('c', -1, 0, 32, "ADC channel", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
return 0;
}
extern "C" __EXPORT int analog_diffpres_main(int argc, char *argv[])
{
return AnalogDifferentialPressure::main(argc, argv);
}
@@ -0,0 +1,93 @@
/****************************************************************************
*
* Copyright (c) 2013-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
*
* Driver for analog differential pressure sensor
*
*/
#pragma once
#include <drivers/drv_adc.h>
#include <drivers/drv_hrt.h>
#include <lib/perf/perf_counter.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/adc_report.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/sensor_differential_pressure.h>
using namespace time_literals;
class AnalogDifferentialPressure : public ModuleBase<AnalogDifferentialPressure>, public ModuleParams,
public px4::ScheduledWorkItem
{
public:
AnalogDifferentialPressure(int16_t adc_channel = -1);
~AnalogDifferentialPressure() override = default;
/** @see ModuleBase */
static int task_spawn(int argc, char *argv[]);
/** @see ModuleBase */
static int custom_command(int argc, char *argv[]);
/** @see ModuleBase */
static int print_usage(const char *reason = nullptr);
int init();
private:
void Run() override;
uORB::SubscriptionCallbackWorkItem _adc_report_sub{this, ORB_ID(adc_report)};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::PublicationMulti<sensor_differential_pressure_s> _diff_pres_pub{ORB_ID(sensor_differential_pressure)};
DEFINE_PARAMETERS(
(ParamFloat<px4::params::SENS_DPRES_ANSC>) _param_sens_dpres_ansc
)
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
float _differential_pressure_pa_last{0.f};
int16_t _adc_channel{-1};
};
@@ -0,0 +1,42 @@
############################################################################
#
# Copyright (c) 2013-2021 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_module(
MODULE drivers__differential_pressure__analog_diffpres
MAIN analog_diffpres
SRCS
AnalogDifferentialPressure.cpp
AnalogDifferentialPressure.hpp
DEPENDS
px4_work_queue
)
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (C) 2013 PX4 Development Team. All rights reserved.
* Copyright (c) 2013-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -32,41 +32,19 @@
****************************************************************************/
/**
* @file drv_airspeed.h
* Differential pressure sensor analog scaling
*
* Airspeed driver interface.
* Pick the appropriate scaling from the datasheet.
* this number defines the (linear) conversion from voltage
* to Pascal (pa). For the MPXV7002DP this is 1000.
*
* @author Simon Wilks
* NOTE: If the sensor always registers zero, try switching
* the static and dynamic tubes.
*
* @group Sensor Calibration
*/
PARAM_DEFINE_FLOAT(SENS_DPRES_ANSC, 0);
#ifndef _DRV_AIRSPEED_H
#define _DRV_AIRSPEED_H
#include <stdint.h>
#include <sys/ioctl.h>
#include "drv_sensor.h"
#include "drv_orb_dev.h"
#define AIRSPEED_BASE_DEVICE_PATH "/dev/airspeed"
#define AIRSPEED0_DEVICE_PATH "/dev/airspeed0"
/*
* ioctl() definitions
*
* Airspeed drivers also implement the generic sensor driver
* interfaces from drv_sensor.h
*/
#define _AIRSPEEDIOCBASE (0x7700)
#define __AIRSPEEDIOC(_n) (_PX4_IOC(_AIRSPEEDIOCBASE, _n))
#define AIRSPEEDIOCSSCALE __AIRSPEEDIOC(0)
/** airspeed scaling factors; out = (in * Vscale) + offset */
struct airspeed_scale {
float offset_pa;
float scale;
};
#endif /* _DRV_AIRSPEED_H */
// SENS_DPRES_ANLG_EN
// SENS_DPRES_ANLG_CHANNEL?
@@ -31,11 +31,11 @@
#
############################################################################
px4_add_module(
MODULE drivers__ets_airspeed
MODULE drivers__differential_pressure__ets_airspeed
MAIN ets_airspeed
COMPILE_FLAGS
SRCS
ets_airspeed.cpp
DEPENDS
drivers__airspeed
px4_work_queue
)
@@ -37,13 +37,14 @@
*
* Driver for the Eagle Tree Airspeed V3 connected via I2C.
*/
#include <float.h>
#include <drivers/airspeed/airspeed.h>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/device/i2c.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/PublicationMulti.hpp>
#include <float.h>
/* I2C bus address */
#define I2C_ADDRESS 0x75 /* 7-bit address. 8-bit address is 0xEA */
@@ -60,45 +61,63 @@
/* Measurement rate is 100Hz */
#define CONVERSION_INTERVAL (1000000 / 100) /* microseconds */
class ETSAirspeed : public Airspeed, public I2CSPIDriver<ETSAirspeed>
class ETSAirspeed : public device::I2C, public I2CSPIDriver<ETSAirspeed>
{
public:
ETSAirspeed(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS);
virtual ~ETSAirspeed() = default;
virtual ~ETSAirspeed();
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void RunImpl();
protected:
int measure() override;
int collect() override;
private:
int probe() override;
int measure();
int collect();
bool _sensor_ok{false};
int _measure_interval{0};
bool _collect_phase{false};
unsigned _conversion_interval{0};
uORB::PublicationMulti<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
};
/*
* Driver 'main' command.
*/
extern "C" __EXPORT int ets_airspeed_main(int argc, char *argv[]);
ETSAirspeed::ETSAirspeed(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address)
: Airspeed(bus, bus_frequency, address, CONVERSION_INTERVAL),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
ETSAirspeed::ETSAirspeed(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address) :
I2C(DRV_DIFF_PRESS_DEVTYPE_ETS3, MODULE_NAME, bus, address, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
{
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_MS4525;
}
int
ETSAirspeed::measure()
ETSAirspeed::~ETSAirspeed()
{
int ret;
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int ETSAirspeed::probe()
{
uint8_t cmd = READ_CMD;
int ret = transfer(&cmd, 1, nullptr, 0);
return ret;
}
int ETSAirspeed::measure()
{
/*
* Send the command to begin a measurement.
*/
uint8_t cmd = READ_CMD;
ret = transfer(&cmd, 1, nullptr, 0);
int ret = transfer(&cmd, 1, nullptr, 0);
if (OK != ret) {
perf_count(_comms_errors);
@@ -107,59 +126,46 @@ ETSAirspeed::measure()
return ret;
}
int
ETSAirspeed::collect()
int ETSAirspeed::collect()
{
int ret = -EIO;
/* read from the sensor */
uint8_t val[2] = {0, 0};
perf_begin(_sample_perf);
ret = transfer(nullptr, 0, &val[0], 2);
const hrt_abstime timestamp_sample = hrt_absolute_time();
uint8_t val[2] {};
int ret = transfer(nullptr, 0, &val[0], 2);
if (ret < 0) {
perf_count(_comms_errors);
return ret;
}
float diff_pres_pa_raw = (float)(val[1] << 8 | val[0]);
float diff_press_pa_raw = (float)(val[1] << 8 | val[0]);
differential_pressure_s report{};
report.timestamp = hrt_absolute_time();
if (diff_pres_pa_raw < FLT_EPSILON) {
if (diff_press_pa_raw < FLT_EPSILON) {
// a zero value indicates no measurement
// since the noise floor has been arbitrarily killed
// it defeats our stuck sensor detection - the best we
// can do is to output some numerical noise to show
// that we are still correctly sampling.
diff_pres_pa_raw = 0.001f * (report.timestamp & 0x01);
diff_press_pa_raw = 0.001f * (hrt_absolute_time() & 0x01);
}
// The raw value still should be compensated for the known offset
diff_pres_pa_raw -= _diff_pres_offset;
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp_sample;
report.device_id = get_device_id();
report.differential_pressure_pa = diff_press_pa_raw;
report.temperature = NAN;
report.error_count = perf_event_count(_comms_errors);
// XXX we may want to smooth out the readings to remove noise.
report.differential_pressure_filtered_pa = diff_pres_pa_raw;
report.differential_pressure_raw_pa = diff_pres_pa_raw;
report.temperature = -1000.0f;
report.device_id = _device_id.devid;
_airspeed_pub.publish(report);
ret = OK;
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
perf_end(_sample_perf);
return ret;
return PX4_OK;
}
void
ETSAirspeed::RunImpl()
void ETSAirspeed::RunImpl()
{
int ret;
@@ -228,9 +234,7 @@ I2CSPIDriverBase *ETSAirspeed::instantiate(const BusCLIArguments &cli, const Bus
return instance;
}
void
ETSAirspeed::print_usage()
void ETSAirspeed::print_usage()
{
PRINT_MODULE_USAGE_NAME("ets_airspeed", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("airspeed_sensor");
@@ -239,8 +243,7 @@ ETSAirspeed::print_usage()
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
int
ets_airspeed_main(int argc, char *argv[])
extern "C" __EXPORT int ets_airspeed_main(int argc, char *argv[])
{
using ThisDriver = ETSAirspeed;
BusCLIArguments cli{true, false};
@@ -0,0 +1,43 @@
############################################################################
#
# Copyright (c) 2015-2021 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
# are met:
#
# 1. Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# 2. Redistributions in binary form must reproduce the above copyright
# notice, this list of conditions and the following disclaimer in
# the documentation and/or other materials provided with the
# distribution.
# 3. Neither the name PX4 nor the names of its contributors may be
# used to endorse or promote products derived from this software
# without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
# POSSIBILITY OF SUCH DAMAGE.
#
############################################################################
px4_add_module(
MODULE drivers__differential_pressure__ms4515
MAIN ms4515
COMPILE_FLAGS
SRCS
MS4515.cpp
MS4515.hpp
DEPENDS
mathlib
px4_work_queue
)
@@ -0,0 +1,275 @@
/****************************************************************************
*
* Copyright (c) 2013-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "MS4515.hpp"
/* Register address */
#define ADDR_READ_MR 0x00 /* write to this address to start conversion */
/* Measurement rate is 100Hz */
#define MEAS_RATE 100
#define CONVERSION_INTERVAL (1000000 / MEAS_RATE) /* microseconds */
MS4515::MS4515(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address) :
I2C(DRV_DIFF_PRESS_DEVTYPE_MS4515, MODULE_NAME, bus, address, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
{
}
MS4515::~MS4515()
{
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int MS4515::probe()
{
uint8_t cmd = 0;
int ret = transfer(&cmd, 1, nullptr, 0);
return ret;
}
int MS4515::measure()
{
// Send the command to begin a measurement.
uint8_t cmd = 0;
int ret = transfer(&cmd, 1, nullptr, 0);
if (OK != ret) {
perf_count(_comms_errors);
}
return ret;
}
int MS4515::collect()
{
/* read from the sensor */
perf_begin(_sample_perf);
const hrt_abstime timestamp_sample = hrt_absolute_time();
uint8_t val[4] {};
int ret = transfer(nullptr, 0, &val[0], 4);
if (ret < 0) {
perf_count(_comms_errors);
perf_end(_sample_perf);
return ret;
}
uint8_t status = (val[0] & 0xC0) >> 6;
switch (status) {
case 0:
// Normal Operation. Good Data Packet
break;
case 1:
// Reserved
return -EAGAIN;
case 2:
// Stale Data. Data has been fetched since last measurement cycle.
return -EAGAIN;
case 3:
// Fault Detected
perf_count(_comms_errors);
perf_end(_sample_perf);
return -EAGAIN;
}
/* mask the used bits */
int16_t dp_raw = (0x3FFF & ((val[0] << 8) + val[1]));
int16_t dT_raw = (0xFFE0 & ((val[2] << 8) + val[3])) >> 5;
// dT max is almost certainly an invalid reading
if (dT_raw == 2047) {
perf_count(_comms_errors);
return -EAGAIN;
}
// only publish changes
if ((dp_raw != _dp_raw_prev) || (dT_raw != _dT_raw_prev)) {
_dp_raw_prev = dp_raw;
_dT_raw_prev = dT_raw;
float temperature = ((200.0f * dT_raw) / 2047) - 50;
// Calculate differential pressure. As its centered around 8000
// and can go positive or negative
const float P_min = -1.0f;
const float P_max = 1.0f;
const float IN_H20_to_Pa = 248.84f;
/*
this equation is an inversion of the equation in the
pressure transfer function figure on page 4 of the datasheet
We negate the result so that positive differential pressures
are generated when the bottom port is used as the static
port on the pitot and top port is used as the dynamic port
*/
float diff_press_PSI = -((dp_raw - 0.1f * 16383) * (P_max - P_min) / (0.8f * 16383) + P_min);
float diff_press_pa_raw = diff_press_PSI * IN_H20_to_Pa;
/*
With the above calculation the MS4525 sensor will produce a
positive number when the top port is used as a dynamic port
and bottom port is used as the static port
*/
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp_sample;
report.device_id = get_device_id();
report.differential_pressure_pa = diff_press_pa_raw;
report.temperature = temperature;
report.error_count = perf_event_count(_comms_errors);
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
}
perf_end(_sample_perf);
return PX4_OK;
}
void MS4515::RunImpl()
{
int ret;
/* collection phase? */
if (_collect_phase) {
/* perform collection */
ret = collect();
if (OK != ret) {
/* restart the measurement state machine */
_collect_phase = false;
_sensor_ok = false;
ScheduleNow();
return;
}
/* next phase is measurement */
_collect_phase = false;
/*
* Is there a collect->measure gap?
*/
if (_measure_interval > CONVERSION_INTERVAL) {
/* schedule a fresh cycle call when we are ready to measure again */
ScheduleDelayed(_measure_interval - CONVERSION_INTERVAL);
return;
}
}
/* measurement phase */
ret = measure();
if (PX4_OK != ret) {
DEVICE_DEBUG("measure error");
}
_sensor_ok = (ret == OK);
/* next phase is collection */
_collect_phase = true;
/* schedule a fresh cycle call when the measurement is done */
ScheduleDelayed(CONVERSION_INTERVAL);
}
I2CSPIDriverBase *MS4515::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
{
MS4515 *instance = new MS4515(iterator.configuredBusOption(), iterator.bus(), cli.bus_frequency, cli.i2c_address);
if (instance == nullptr) {
PX4_ERR("alloc failed");
return nullptr;
}
if (instance->init() != PX4_OK) {
delete instance;
return nullptr;
}
instance->ScheduleNow();
return instance;
}
void MS4515::print_usage()
{
PRINT_MODULE_USAGE_NAME("ms4515", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("airspeed_sensor");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
extern "C" __EXPORT int ms4515_main(int argc, char *argv[])
{
using ThisDriver = MS4515;
BusCLIArguments cli{true, false};
cli.default_i2c_frequency = 100000;
cli.i2c_address = I2C_ADDRESS_MS4515DO;
const char *verb = cli.optarg();
if (!verb) {
ThisDriver::print_usage();
return -1;
}
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_DIFF_PRESS_DEVTYPE_MS4515);
if (!strcmp(verb, "start")) {
return ThisDriver::module_start(cli, iterator);
}
if (!strcmp(verb, "stop")) {
return ThisDriver::module_stop(iterator);
}
if (!strcmp(verb, "status")) {
return ThisDriver::module_status(iterator);
}
ThisDriver::print_usage();
return -1;
}
@@ -31,57 +31,59 @@
*
****************************************************************************/
/**
*
* Driver for the MEAS Spec series connected via I2C.
*
* Supported sensors:
*
* - MS4515DO
*
* Interface application notes:
*
* - Interfacing to MEAS Digital Pressure Modules (http://www.meas-spec.com/downloads/Interfacing_to_MEAS_Digital_Pressure_Modules.pdf)
*/
#pragma once
#include <string.h>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/device/i2c.h>
#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/defines.h>
#include <perf/perf_counter.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/PublicationMulti.hpp>
class __EXPORT Airspeed : public device::I2C
#define I2C_ADDRESS_MS4515DO 0x46 /* I2C bus address is 1010001x */
class MS4515 : public device::I2C, public I2CSPIDriver<MS4515>
{
public:
Airspeed(int bus, int bus_frequency, int address, unsigned conversion_interval);
virtual ~Airspeed();
MS4515(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS_MS4515DO);
int init() override;
virtual ~MS4515();
int ioctl(device::file_t *filp, int cmd, unsigned long arg) override;
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void RunImpl();
private:
Airspeed(const Airspeed &) = delete;
Airspeed &operator=(const Airspeed &) = delete;
protected:
int probe() override;
/**
* Perform a poll cycle; collect from the previous measurement
* and start a new one.
*/
virtual int measure() = 0;
virtual int collect() = 0;
int measure();
int collect();
bool _sensor_ok;
int _measure_interval;
bool _collect_phase;
float _diff_pres_offset;
bool _sensor_ok{false};
int _measure_interval{0};
bool _collect_phase{false};
unsigned _conversion_interval{0};
uORB::PublicationMulti<differential_pressure_s> _airspeed_pub{ORB_ID(differential_pressure)};
int16_t _dp_raw_prev{0};
int16_t _dT_raw_prev{0};
int _airspeed_orb_class_instance;
uORB::PublicationMulti<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
int _class_instance;
unsigned _conversion_interval;
perf_counter_t _sample_perf;
perf_counter_t _comms_errors;
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
};
@@ -31,12 +31,13 @@
#
############################################################################
px4_add_module(
MODULE drivers__ms4525_airspeed
MAIN ms4525_airspeed
MODULE drivers__differential_pressure__ms4525
MAIN ms4525
COMPILE_FLAGS
SRCS
ms4525_airspeed.cpp
MS4525.cpp
MS4525.hpp
DEPENDS
drivers__airspeed
mathlib
px4_work_queue
)
@@ -31,84 +31,36 @@
*
****************************************************************************/
/**
* @file meas_airspeed.cpp
* @author Lorenz Meier
* @author Sarthak Kaingade
* @author Simon Wilks
* @author Thomas Gubler
*
* Driver for the MEAS Spec series connected via I2C.
*
* Supported sensors:
*
* - MS4525DO (http://www.meas-spec.com/downloads/MS4525DO.pdf)
*
* Interface application notes:
*
* - Interfacing to MEAS Digital Pressure Modules (http://www.meas-spec.com/downloads/Interfacing_to_MEAS_Digital_Pressure_Modules.pdf)
*/
#include <mathlib/math/filter/LowPassFilter2p.hpp>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/airspeed/airspeed.h>
enum MS_DEVICE_TYPE {
DEVICE_TYPE_MS4515 = 4515,
DEVICE_TYPE_MS4525 = 4525
};
/* I2C bus address is 1010001x */
#define I2C_ADDRESS_MS4515DO 0x46
#define I2C_ADDRESS_MS4525DO 0x28 /**< 7-bit address. Depends on the order code (this is for code "I") */
#include "MS4525.hpp"
/* Register address */
#define ADDR_READ_MR 0x00 /* write to this address to start conversion */
/* Measurement rate is 100Hz */
#define MEAS_RATE 100
#define MEAS_DRIVER_FILTER_FREQ 1.2f
#define CONVERSION_INTERVAL (1000000 / MEAS_RATE) /* microseconds */
class MEASAirspeed : public Airspeed, public I2CSPIDriver<MEASAirspeed>
MS4525::MS4525(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address) :
I2C(DRV_DIFF_PRESS_DEVTYPE_MS4525, MODULE_NAME, bus, address, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
{
public:
MEASAirspeed(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS_MS4525DO);
virtual ~MEASAirspeed() = default;
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void RunImpl();
protected:
int measure() override;
int collect() override;
math::LowPassFilter2p _filter{MEAS_RATE, MEAS_DRIVER_FILTER_FREQ};
};
/*
* Driver 'main' command.
*/
extern "C" __EXPORT int ms4525_airspeed_main(int argc, char *argv[]);
MEASAirspeed::MEASAirspeed(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address)
: Airspeed(bus, bus_frequency, address, CONVERSION_INTERVAL),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
{
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_MS4525;
}
int
MEASAirspeed::measure()
MS4525::~MS4525()
{
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int MS4525::probe()
{
uint8_t cmd = 0;
int ret = transfer(&cmd, 1, nullptr, 0);
return ret;
}
int MS4525::measure()
{
// Send the command to begin a measurement.
uint8_t cmd = 0;
@@ -121,14 +73,14 @@ MEASAirspeed::measure()
return ret;
}
int
MEASAirspeed::collect()
int MS4525::collect()
{
/* read from the sensor */
uint8_t val[4] = {0, 0, 0, 0};
perf_begin(_sample_perf);
const hrt_abstime timestamp_sample = hrt_absolute_time();
uint8_t val[4] {};
int ret = transfer(nullptr, 0, &val[0], 4);
if (ret < 0) {
@@ -159,12 +111,9 @@ MEASAirspeed::collect()
return -EAGAIN;
}
int16_t dp_raw = 0, dT_raw = 0;
dp_raw = (val[0] << 8) + val[1];
/* mask the used bits */
dp_raw = 0x3FFF & dp_raw;
dT_raw = (val[2] << 8) + val[3];
dT_raw = (0xFFE0 & dT_raw) >> 5;
int16_t dp_raw = (0x3FFF & ((val[0] << 8) + val[1]));
int16_t dT_raw = (0xFFE0 & ((val[2] << 8) + val[3])) >> 5;
// dT max is almost certainly an invalid reading
if (dT_raw == 2047) {
@@ -172,50 +121,51 @@ MEASAirspeed::collect()
return -EAGAIN;
}
float temperature = ((200.0f * dT_raw) / 2047) - 50;
// only publish changes
if ((dp_raw != _dp_raw_prev) || (dT_raw != _dT_raw_prev)) {
// Calculate differential pressure. As its centered around 8000
// and can go positive or negative
const float P_min = -1.0f;
const float P_max = 1.0f;
const float PSI_to_Pa = 6894.757f;
/*
this equation is an inversion of the equation in the
pressure transfer function figure on page 4 of the datasheet
_dp_raw_prev = dp_raw;
_dT_raw_prev = dT_raw;
We negate the result so that positive differential pressures
are generated when the bottom port is used as the static
port on the pitot and top port is used as the dynamic port
*/
float diff_press_PSI = -((dp_raw - 0.1f * 16383) * (P_max - P_min) / (0.8f * 16383) + P_min);
float diff_press_pa_raw = diff_press_PSI * PSI_to_Pa;
float temperature = ((200.0f * dT_raw) / 2047) - 50;
/*
With the above calculation the MS4525 sensor will produce a
positive number when the top port is used as a dynamic port
and bottom port is used as the static port
*/
// Calculate differential pressure. As its centered around 8000
// and can go positive or negative
const float P_min = -1.0f;
const float P_max = 1.0f;
const float PSI_to_Pa = 6894.757f;
/*
this equation is an inversion of the equation in the
pressure transfer function figure on page 4 of the datasheet
differential_pressure_s report{};
We negate the result so that positive differential pressures
are generated when the bottom port is used as the static
port on the pitot and top port is used as the dynamic port
*/
float diff_press_PSI = -((dp_raw - 0.1f * 16383) * (P_max - P_min) / (0.8f * 16383) + P_min);
float diff_press_pa_raw = diff_press_PSI * PSI_to_Pa;
report.timestamp = hrt_absolute_time();
report.error_count = perf_event_count(_comms_errors);
report.temperature = temperature;
report.differential_pressure_filtered_pa = _filter.apply(diff_press_pa_raw) - _diff_pres_offset;
report.differential_pressure_raw_pa = diff_press_pa_raw - _diff_pres_offset;
report.device_id = _device_id.devid;
_airspeed_pub.publish(report);
ret = OK;
/*
With the above calculation the MS4525 sensor will produce a
positive number when the top port is used as a dynamic port
and bottom port is used as the static port
*/
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp_sample;
report.device_id = get_device_id();
report.differential_pressure_pa = diff_press_pa_raw;
report.temperature = temperature;
report.error_count = perf_event_count(_comms_errors);
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
}
perf_end(_sample_perf);
return ret;
return PX4_OK;
}
void
MEASAirspeed::RunImpl()
void MS4525::RunImpl()
{
int ret;
@@ -251,7 +201,7 @@ MEASAirspeed::RunImpl()
/* measurement phase */
ret = measure();
if (OK != ret) {
if (PX4_OK != ret) {
DEVICE_DEBUG("measure error");
}
@@ -264,11 +214,10 @@ MEASAirspeed::RunImpl()
ScheduleDelayed(CONVERSION_INTERVAL);
}
I2CSPIDriverBase *MEASAirspeed::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
I2CSPIDriverBase *MS4525::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
{
MEASAirspeed *instance = new MEASAirspeed(iterator.configuredBusOption(), iterator.bus(), cli.bus_frequency,
cli.i2c_address);
MS4525 *instance = new MS4525(iterator.configuredBusOption(), iterator.bus(), cli.bus_frequency, cli.i2c_address);
if (instance == nullptr) {
PX4_ERR("alloc failed");
@@ -284,51 +233,30 @@ I2CSPIDriverBase *MEASAirspeed::instantiate(const BusCLIArguments &cli, const Bu
return instance;
}
void
MEASAirspeed::print_usage()
void MS4525::print_usage()
{
PRINT_MODULE_USAGE_NAME("ms4525_airspeed", "driver");
PRINT_MODULE_USAGE_NAME("ms4525", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("airspeed_sensor");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_PARAM_STRING('T', "4525", "4525|4515", "Device type", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
int
ms4525_airspeed_main(int argc, char *argv[])
extern "C" __EXPORT int ms4525_main(int argc, char *argv[])
{
int ch;
using ThisDriver = MEASAirspeed;
using ThisDriver = MS4525;
BusCLIArguments cli{true, false};
cli.default_i2c_frequency = 100000;
int device_type = DEVICE_TYPE_MS4525;
cli.i2c_address = I2C_ADDRESS_MS4525DO;
while ((ch = cli.getopt(argc, argv, "T:")) != EOF) {
switch (ch) {
case 'T':
device_type = atoi(cli.optarg());
break;
}
}
const char *verb = cli.optarg();
const char *verb = cli.parseDefaultArguments(argc, argv);
if (!verb) {
ThisDriver::print_usage();
return -1;
}
if (device_type == DEVICE_TYPE_MS4525) {
cli.i2c_address = I2C_ADDRESS_MS4525DO;
} else {
cli.i2c_address = I2C_ADDRESS_MS4515DO;
}
BusInstanceIterator iterator(MODULE_NAME, cli,
DRV_DIFF_PRESS_DEVTYPE_MS4525);
BusInstanceIterator iterator(MODULE_NAME, cli, DRV_DIFF_PRESS_DEVTYPE_MS4525);
if (!strcmp(verb, "start")) {
return ThisDriver::module_start(cli, iterator);
@@ -0,0 +1,94 @@
/****************************************************************************
*
* Copyright (c) 2013, 2014 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file MS4525.hpp
* @author Lorenz Meier
* @author Sarthak Kaingade
* @author Simon Wilks
* @author Thomas Gubler
*
* Driver for the MEAS Spec series connected via I2C.
*
* Supported sensors:
*
* - MS4525DO (http://www.meas-spec.com/downloads/MS4525DO.pdf)
*
* Interface application notes:
*
* - Interfacing to MEAS Digital Pressure Modules (http://www.meas-spec.com/downloads/Interfacing_to_MEAS_Digital_Pressure_Modules.pdf)
*/
#pragma once
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/device/i2c.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/PublicationMulti.hpp>
#define I2C_ADDRESS_MS4525DO 0x28 /**< 7-bit address. Depends on the order code (this is for code "I") */
class MS4525 : public device::I2C, public I2CSPIDriver<MS4525>
{
public:
MS4525(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS_MS4525DO);
virtual ~MS4525();
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void RunImpl();
private:
int probe() override;
int measure();
int collect();
bool _sensor_ok{false};
int _measure_interval{0};
bool _collect_phase{false};
unsigned _conversion_interval{0};
int16_t _dp_raw_prev{0};
int16_t _dT_raw_prev{0};
uORB::PublicationMulti<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
};
@@ -31,13 +31,14 @@
#
############################################################################
px4_add_module(
MODULE drivers__ms5525_airspeed
MAIN ms5525_airspeed
MODULE drivers__differential_pressure__ms5525
MAIN ms5525
COMPILE_FLAGS
SRCS
ms5525_main.cpp
MS5525.cpp
MS5525_main.cpp
MS5525.hpp
DEPENDS
drivers__airspeed
mathlib
px4_work_queue
)
@@ -33,8 +33,18 @@
#include "MS5525.hpp"
int
MS5525::measure()
MS5525::~MS5525()
{
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int MS5525::probe()
{
return init_ms5525() ? PX4_OK : PX4_ERROR;
}
int MS5525::measure()
{
int ret = PX4_ERROR;
@@ -58,8 +68,7 @@ MS5525::measure()
return ret;
}
bool
MS5525::init_ms5525()
bool MS5525::init_ms5525()
{
// Step 1 - reset
uint8_t cmd = CMD_RESET;
@@ -128,8 +137,7 @@ MS5525::init_ms5525()
}
}
uint8_t
MS5525::prom_crc4(uint16_t n_prom[]) const
uint8_t MS5525::prom_crc4(uint16_t n_prom[]) const
{
// see Measurement Specialties AN520
@@ -166,11 +174,12 @@ MS5525::prom_crc4(uint16_t n_prom[]) const
return (n_rem ^ 0x00);
}
int
MS5525::collect()
int MS5525::collect()
{
perf_begin(_sample_perf);
const hrt_abstime timestamp_sample = hrt_absolute_time();
// read ADC
uint8_t cmd = CMD_ADC_READ;
int ret = transfer(&cmd, 1, nullptr, 0);
@@ -181,7 +190,7 @@ MS5525::collect()
}
// read 24 bits from the sensor
uint8_t val[3];
uint8_t val[3] {};
ret = transfer(nullptr, 0, &val[0], 3);
if (ret != PX4_OK) {
@@ -248,28 +257,23 @@ MS5525::collect()
static constexpr float PSI_to_Pa = 6894.757f;
const float diff_press_pa_raw = diff_press_PSI * PSI_to_Pa;
const float temperature_c = TEMP * 0.01f;
const float temperature = TEMP * 0.01f;
differential_pressure_s diff_pressure = {
.timestamp = hrt_absolute_time(),
.error_count = perf_event_count(_comms_errors),
.differential_pressure_raw_pa = diff_press_pa_raw - _diff_pres_offset,
.differential_pressure_filtered_pa = _filter.apply(diff_press_pa_raw) - _diff_pres_offset,
.temperature = temperature_c,
.device_id = _device_id.devid
};
_airspeed_pub.publish(diff_pressure);
ret = OK;
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp_sample;
report.device_id = get_device_id();
report.differential_pressure_pa = diff_press_pa_raw;
report.temperature = temperature;
report.error_count = perf_event_count(_comms_errors);
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
perf_end(_sample_perf);
return ret;
return PX4_OK;
}
void
MS5525::RunImpl()
void MS5525::RunImpl()
{
int ret = PX4_ERROR;
@@ -33,31 +33,29 @@
#pragma once
#include <drivers/airspeed/airspeed.h>
#include <math.h>
#include <mathlib/math/filter/LowPassFilter2p.hpp>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/device/i2c.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/PublicationMulti.hpp>
/* The MS5525DSO address is 111011Cx, where C is the complementary value of the pin CSB */
static constexpr uint8_t I2C_ADDRESS_1_MS5525DSO = 0x76;
/* Measurement rate is 100Hz */
static constexpr unsigned MEAS_RATE = 100;
static constexpr float MEAS_DRIVER_FILTER_FREQ = 1.2f;
static constexpr int64_t CONVERSION_INTERVAL = (1000000 / MEAS_RATE); /* microseconds */
class MS5525 : public Airspeed, public I2CSPIDriver<MS5525>
class MS5525 : public device::I2C, public I2CSPIDriver<MS5525>
{
public:
MS5525(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS_1_MS5525DSO) :
Airspeed(bus, bus_frequency, address, CONVERSION_INTERVAL),
I2C(DRV_DIFF_PRESS_DEVTYPE_MS5525, MODULE_NAME, bus, address, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address)
{
}
{}
virtual ~MS5525() = default;
virtual ~MS5525();
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
@@ -66,12 +64,14 @@ public:
void RunImpl();
private:
int probe() override;
int measure() override;
int collect() override;
bool init_ms5525();
// temperature is read once every 10 cycles
math::LowPassFilter2p _filter{MEAS_RATE * 0.9, MEAS_DRIVER_FILTER_FREQ};
uint8_t prom_crc4(uint16_t n_prom[]) const;
int measure();
int collect();
static constexpr uint8_t CMD_RESET = 0x1E; // ADC reset command
static constexpr uint8_t CMD_ADC_READ = 0x00; // ADC read command
@@ -121,9 +121,16 @@ private:
uint32_t D1{0};
uint32_t D2{0};
bool init_ms5525();
bool _inited{false};
uint8_t prom_crc4(uint16_t n_prom[]) const;
bool _sensor_ok{false};
int _measure_interval{0};
bool _collect_phase{false};
unsigned _conversion_interval{0};
uORB::PublicationMulti<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
};
@@ -33,8 +33,6 @@
#include "MS5525.hpp"
extern "C" __EXPORT int ms5525_airspeed_main(int argc, char *argv[]);
I2CSPIDriverBase *MS5525::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
{
@@ -54,19 +52,16 @@ I2CSPIDriverBase *MS5525::instantiate(const BusCLIArguments &cli, const BusInsta
return instance;
}
void
MS5525::print_usage()
void MS5525::print_usage()
{
PRINT_MODULE_USAGE_NAME("ms5525_airspeed", "driver");
PRINT_MODULE_USAGE_NAME("ms5525", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("airspeed_sensor");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
int
ms5525_airspeed_main(int argc, char *argv[])
extern "C" __EXPORT int ms5525_main(int argc, char *argv[])
{
using ThisDriver = MS5525;
BusCLIArguments cli{true, false};
@@ -31,13 +31,14 @@
#
############################################################################
px4_add_module(
MODULE drivers__sdp3x_airspeed
MAIN sdp3x_airspeed
MODULE drivers__differential_pressure__sdp3x
MAIN sdp3x
COMPILE_FLAGS
SRCS
sdp3x_main.cpp
SDP3X.cpp
SDP3X_main.cpp
SDP3X.hpp
DEPENDS
drivers__airspeed
mathlib
px4_work_queue
)
@@ -42,8 +42,13 @@
using namespace time_literals;
int
SDP3X::probe()
SDP3X::~SDP3X()
{
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int SDP3X::probe()
{
bool require_initialization = !init_sdp3x();
@@ -63,14 +68,12 @@ int SDP3X::write_command(uint16_t command)
return transfer(&cmd[0], 2, nullptr, 0);
}
bool
SDP3X::init_sdp3x()
bool SDP3X::init_sdp3x()
{
return configure() == 0;
}
int
SDP3X::configure()
int SDP3X::configure()
{
int ret = write_command(SDP3X_CONT_MEAS_AVG_MODE);
@@ -86,8 +89,7 @@ SDP3X::configure()
return ret;
}
int
SDP3X::read_scale()
int SDP3X::read_scale()
{
// get scale
uint8_t val[9];
@@ -109,15 +111,15 @@ SDP3X::read_scale()
switch (_scale) {
case SDP3X_SCALE_PRESSURE_SDP31:
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_SDP31;
set_device_type(DRV_DIFF_PRESS_DEVTYPE_SDP31);
break;
case SDP3X_SCALE_PRESSURE_SDP32:
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_SDP32;
set_device_type(DRV_DIFF_PRESS_DEVTYPE_SDP32);
break;
case SDP3X_SCALE_PRESSURE_SDP33:
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_SDP33;
set_device_type(DRV_DIFF_PRESS_DEVTYPE_SDP33);
break;
}
@@ -130,13 +132,14 @@ void SDP3X::start()
ScheduleDelayed(10_ms);
}
int
SDP3X::collect()
int SDP3X::collect()
{
perf_begin(_sample_perf);
const hrt_abstime timestamp_sample = hrt_absolute_time();
// read 6 bytes from the sensor
uint8_t val[6];
uint8_t val[6] {};
int ret = transfer(nullptr, 0, &val[0], sizeof(val));
if (ret != PX4_OK) {
@@ -154,26 +157,23 @@ SDP3X::collect()
int16_t temp = (((int16_t)val[3]) << 8) | val[4];
float diff_press_pa_raw = static_cast<float>(P) / static_cast<float>(_scale);
float temperature_c = temp / static_cast<float>(SDP3X_SCALE_TEMPERATURE);
float temperature = temp / static_cast<float>(SDP3X_SCALE_TEMPERATURE);
differential_pressure_s report{};
report.timestamp = hrt_absolute_time();
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp_sample;
report.device_id = get_device_id();
report.differential_pressure_pa = diff_press_pa_raw;
report.temperature = temperature;
report.error_count = perf_event_count(_comms_errors);
report.temperature = temperature_c;
report.differential_pressure_filtered_pa = _filter.apply(diff_press_pa_raw) - _diff_pres_offset;
report.differential_pressure_raw_pa = diff_press_pa_raw - _diff_pres_offset;
report.device_id = _device_id.devid;
_airspeed_pub.publish(report);
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
perf_end(_sample_perf);
return ret;
return PX4_OK;
}
void
SDP3X::RunImpl()
void SDP3X::RunImpl()
{
switch (_state) {
case State::RequireConfig:
@@ -36,17 +36,17 @@
*
* Driver for Sensirion SDP3X Differential Pressure Sensor
*
* Datasheet: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/8_Differential_Pressure/Sensirion_Differential_Pressure_Sensors_SDP3x_Digital_Datasheet_V0.8.pdf
* Datasheet: https://www.sensirion.com/fileadmin/user_upload/customers/sensirion/Dokumente/8_Differential_Pressure/Sensirion_sensor_differential_pressure_sensors_SDP3x_Digital_Datasheet_V0.8.pdf
*/
#pragma once
#include <drivers/airspeed/airspeed.h>
#include <math.h>
#include <mathlib/math/filter/LowPassFilter2p.hpp>
#include <px4_platform_common/getopt.h>
#include <px4_platform_common/module.h>
#include <px4_platform_common/i2c_spi_buses.h>
#include <drivers/device/i2c.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/PublicationMulti.hpp>
#define I2C_ADDRESS_1_SDP3X 0x21
#define I2C_ADDRESS_2_SDP3X 0x22
@@ -63,27 +63,26 @@
// Measurement rate is 20Hz
#define SPD3X_MEAS_RATE 100
#define SDP3X_MEAS_DRIVER_FILTER_FREQ 3.0f
#define CONVERSION_INTERVAL (1000000 / SPD3X_MEAS_RATE) /* microseconds */
class SDP3X : public Airspeed, public I2CSPIDriver<SDP3X>
class SDP3X : public device::I2C, public I2CSPIDriver<SDP3X>
{
public:
SDP3X(I2CSPIBusOption bus_option, const int bus, int bus_frequency, int address = I2C_ADDRESS_1_SDP3X,
bool keep_retrying = false) :
Airspeed(bus, bus_frequency, address, CONVERSION_INTERVAL),
I2C(DRV_DIFF_PRESS_DEVTYPE_SDP33, MODULE_NAME, bus, address, bus_frequency),
I2CSPIDriver(MODULE_NAME, px4::device_bus_to_wq(get_device_id()), bus_option, bus, address),
_keep_retrying{keep_retrying}
{
}
virtual ~SDP3X() = default;
virtual ~SDP3X();
static I2CSPIDriverBase *instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance);
static void print_usage();
void RunImpl();
void RunImpl();
void start();
@@ -94,14 +93,13 @@ private:
Running
};
int measure() override { return 0; }
int collect() override;
int measure() { return 0; }
int collect();
int probe() override;
int configure();
int read_scale();
math::LowPassFilter2p _filter{SPD3X_MEAS_RATE, SDP3X_MEAS_DRIVER_FILTER_FREQ};
bool init_sdp3x();
/**
@@ -114,7 +112,17 @@ private:
*/
int write_command(uint16_t command);
bool _sensor_ok{false};
int _measure_interval{0};
bool _collect_phase{false};
unsigned _conversion_interval{0};
uint16_t _scale{0};
const bool _keep_retrying;
State _state{State::RequireConfig};
uORB::PublicationMulti<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
perf_counter_t _sample_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": read")};
perf_counter_t _comms_errors{perf_alloc(PC_COUNT, MODULE_NAME": com err")};
};
@@ -33,8 +33,6 @@
#include "SDP3X.hpp"
extern "C" __EXPORT int sdp3x_airspeed_main(int argc, char *argv[]);
I2CSPIDriverBase *SDP3X::instantiate(const BusCLIArguments &cli, const BusInstanceIterator &iterator,
int runtime_instance)
{
@@ -55,11 +53,9 @@ I2CSPIDriverBase *SDP3X::instantiate(const BusCLIArguments &cli, const BusInstan
return instance;
}
void
SDP3X::print_usage()
void SDP3X::print_usage()
{
PRINT_MODULE_USAGE_NAME("sdp3x_airspeed", "driver");
PRINT_MODULE_USAGE_NAME("sdp3x", "driver");
PRINT_MODULE_USAGE_SUBCATEGORY("airspeed_sensor");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAMS_I2C_SPI_DRIVER(true, false);
@@ -68,8 +64,7 @@ SDP3X::print_usage()
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
}
int
sdp3x_airspeed_main(int argc, char *argv[])
extern "C" __EXPORT int sdp3x_main(int argc, char *argv[])
{
using ThisDriver = SDP3X;
BusCLIArguments cli{true, false};
+7 -6
View File
@@ -101,13 +101,14 @@
#define DRV_IMU_DEVTYPE_ST_LSM9DS1_AG 0x44
#define DRV_MAG_DEVTYPE_ST_LSM9DS1_M 0x45
#define DRV_DIFF_PRESS_DEVTYPE_ETS3 0x46
#define DRV_DIFF_PRESS_DEVTYPE_MS4525 0x47
#define DRV_DIFF_PRESS_DEVTYPE_MS5525 0x48
#define DRV_DIFF_PRESS_DEVTYPE_SDP31 0x49
#define DRV_DIFF_PRESS_DEVTYPE_SDP32 0x4A
#define DRV_DIFF_PRESS_DEVTYPE_SDP33 0x4B
#define DRV_BARO_DEVTYPE_LPS33HW 0x4C
#define DRV_DIFF_PRESS_DEVTYPE_MS4515 0x47
#define DRV_DIFF_PRESS_DEVTYPE_MS4525 0x48
#define DRV_DIFF_PRESS_DEVTYPE_MS5525 0x49
#define DRV_DIFF_PRESS_DEVTYPE_SDP31 0x4A
#define DRV_DIFF_PRESS_DEVTYPE_SDP32 0x4B
#define DRV_DIFF_PRESS_DEVTYPE_SDP33 0x4C
#define DRV_BARO_DEVTYPE_LPS33HW 0x50
#define DRV_BARO_DEVTYPE_MPL3115A2 0x51
#define DRV_ACC_DEVTYPE_FXOS8701C 0x52
+10 -20
View File
@@ -47,7 +47,7 @@ UavcanAirspeedBridge::UavcanAirspeedBridge(uavcan::INode &node) :
_sub_ias_data(node),
_sub_tas_data(node),
_sub_oat_data(node)
{ }
{}
int UavcanAirspeedBridge::init()
{
@@ -75,36 +75,26 @@ int UavcanAirspeedBridge::init()
return 0;
}
void
UavcanAirspeedBridge::oat_sub_cb(const
uavcan::ReceivedDataStructure<uavcan::equipment::air_data::StaticTemperature> &msg)
void UavcanAirspeedBridge::oat_sub_cb(const
uavcan::ReceivedDataStructure<uavcan::equipment::air_data::StaticTemperature> &msg)
{
_last_outside_air_temp_k = msg.static_temperature;
}
void
UavcanAirspeedBridge::tas_sub_cb(const
uavcan::ReceivedDataStructure<uavcan::equipment::air_data::TrueAirspeed> &msg)
void UavcanAirspeedBridge::tas_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::air_data::TrueAirspeed>
&msg)
{
_last_tas_m_s = msg.true_airspeed;
}
void
UavcanAirspeedBridge::ias_sub_cb(const
uavcan::ReceivedDataStructure<uavcan::equipment::air_data::IndicatedAirspeed> &msg)
void UavcanAirspeedBridge::ias_sub_cb(const
uavcan::ReceivedDataStructure<uavcan::equipment::air_data::IndicatedAirspeed> &msg)
{
airspeed_s report{};
/*
* FIXME HACK
* This code used to rely on msg.getMonotonicTimestamp().toUSec() instead of HRT.
* It stopped working when the time sync feature has been introduced, because it caused libuavcan
* to use an independent time source (based on hardware TIM5) instead of HRT.
* The proper solution is to be developed.
*/
report.timestamp = hrt_absolute_time();
report.timestamp_sample = hrt_absolute_time();
report.indicated_airspeed_m_s = msg.indicated_airspeed;
report.true_airspeed_m_s = _last_tas_m_s;
report.air_temperature_celsius = _last_outside_air_temp_k + CONSTANTS_ABSOLUTE_NULL_CELSIUS;
report.timestamp = hrt_absolute_time();
publish(msg.getSrcNodeID().get(), &report);
}
-1
View File
@@ -38,7 +38,6 @@
#pragma once
#include "sensor_bridge.hpp"
#include <drivers/drv_airspeed.h>
#include <uORB/topics/airspeed.h>
#include <uavcan/equipment/air_data/IndicatedAirspeed.hpp>
@@ -37,7 +37,6 @@
#include "differential_pressure.hpp"
#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <lib/ecl/geo/geo.h>
#include <parameters/param.h>
@@ -46,16 +45,13 @@
const char *const UavcanDifferentialPressureBridge::NAME = "differential_pressure";
UavcanDifferentialPressureBridge::UavcanDifferentialPressureBridge(uavcan::INode &node) :
UavcanSensorBridgeBase("uavcan_differential_pressure", ORB_ID(differential_pressure)),
UavcanSensorBridgeBase("uavcan_differential_pressure", ORB_ID(sensor_differential_pressure)),
_sub_air(node)
{
}
int UavcanDifferentialPressureBridge::init()
{
// Initialize the calibration offset
param_get(param_find("SENS_DPRES_OFF"), &_diff_pres_offset);
int res = _sub_air.start(AirCbBinder(this, &UavcanDifferentialPressureBridge::air_sub_cb));
if (res < 0) {
@@ -72,17 +68,13 @@ void UavcanDifferentialPressureBridge::air_sub_cb(const
_device_id.devid_s.devtype = DRV_DIFF_PRESS_DEVTYPE_UAVCAN;
_device_id.devid_s.address = msg.getSrcNodeID().get() & 0xFF;
float diff_press_pa = msg.differential_pressure;
float temperature_c = msg.static_air_temperature + CONSTANTS_ABSOLUTE_NULL_CELSIUS;
differential_pressure_s report = {
.timestamp = hrt_absolute_time(),
.error_count = 0,
.differential_pressure_raw_pa = diff_press_pa - _diff_pres_offset,
.differential_pressure_filtered_pa = _filter.apply(diff_press_pa) - _diff_pres_offset, /// TODO: Create filter
.temperature = temperature_c,
.device_id = _device_id.devid
};
sensor_differential_pressure_s report{};
report.timestamp_sample = hrt_absolute_time();
report.device_id = get_device_id();
report.differential_pressure_pa = msg.differential_pressure;
report.temperature = msg.static_air_temperature + CONSTANTS_ABSOLUTE_NULL_CELSIUS;
report.error_count = 0;
report.timestamp = hrt_absolute_time();
publish(msg.getSrcNodeID().get(), &report);
}
@@ -37,9 +37,7 @@
#pragma once
#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <mathlib/math/filter/LowPassFilter2p.hpp>
#include <uORB/topics/sensor_differential_pressure.h>
#include "sensor_bridge.hpp"
@@ -57,10 +55,6 @@ public:
int init() override;
private:
float _diff_pres_offset{0.f};
math::LowPassFilter2p _filter{10.f, 1.1f}; /// Adapted from MS5525 driver
void air_sub_cb(const uavcan::ReceivedDataStructure<uavcan::equipment::air_data::RawAirData> &msg);
typedef uavcan::MethodBinder < UavcanDifferentialPressureBridge *,
@@ -38,7 +38,7 @@
#include <uavcan/equipment/air_data/RawAirData.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/sensor_differential_pressure.h>
namespace uavcannode
{
@@ -51,7 +51,7 @@ class RawAirData :
public:
RawAirData(px4::WorkItem *work_item, uavcan::INode &node) :
UavcanPublisherBase(uavcan::equipment::air_data::RawAirData::DefaultDataTypeID),
uORB::SubscriptionCallbackWorkItem(work_item, ORB_ID(differential_pressure)),
uORB::SubscriptionCallbackWorkItem(work_item, ORB_ID(sensor_differential_pressure)),
uavcan::Publisher<uavcan::equipment::air_data::RawAirData>(node)
{}
@@ -68,13 +68,13 @@ public:
void BroadcastAnyUpdates() override
{
// differential_pressure -> uavcan::equipment::air_data::RawAirData
differential_pressure_s diff_press;
sensor_differential_pressure_s diff_press;
if (uORB::SubscriptionCallbackWorkItem::update(&diff_press)) {
uavcan::equipment::air_data::RawAirData raw_air_data{};
// raw_air_data.static_pressure =
raw_air_data.differential_pressure = diff_press.differential_pressure_raw_pa;
raw_air_data.differential_pressure = diff_press.differential_pressure_pa;
// raw_air_data.static_pressure_sensor_temperature =
raw_air_data.differential_pressure_sensor_temperature = diff_press.temperature - CONSTANTS_ABSOLUTE_NULL_CELSIUS;
raw_air_data.static_air_temperature = diff_press.temperature - CONSTANTS_ABSOLUTE_NULL_CELSIUS;
-1
View File
@@ -183,7 +183,6 @@ float calc_IAS(float differential_pressure)
} else {
return -sqrtf((2.0f * fabsf(differential_pressure)) / CONSTANTS_AIR_DENSITY_SEA_LEVEL_15C);
}
}
float calc_TAS_from_CAS(float speed_calibrated, float pressure_ambient, float temperature_celsius)
-1
View File
@@ -32,7 +32,6 @@
############################################################################
add_subdirectory(accelerometer)
add_subdirectory(airspeed)
add_subdirectory(barometer)
add_subdirectory(device)
add_subdirectory(gyroscope)
-130
View File
@@ -1,130 +0,0 @@
/****************************************************************************
*
* Copyright (c) 2013-2015 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* @file airspeed.cpp
* @author Simon Wilks <simon@px4.io>
* @author Lorenz Meier <lorenz@px4.io>
*
*/
#include <px4_platform_common/px4_config.h>
#include <drivers/device/device.h>
#include <drivers/device/i2c.h>
#include <systemlib/err.h>
#include <parameters/param.h>
#include <perf/perf_counter.h>
#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <uORB/uORB.h>
#include <uORB/topics/differential_pressure.h>
#include <drivers/airspeed/airspeed.h>
Airspeed::Airspeed(int bus, int bus_frequency, int address, unsigned conversion_interval) :
I2C(0, "Airspeed", bus, address, bus_frequency),
_sensor_ok(false),
_measure_interval(conversion_interval),
_collect_phase(false),
_diff_pres_offset(0.0f),
_airspeed_orb_class_instance(-1),
_class_instance(-1),
_conversion_interval(conversion_interval),
_sample_perf(perf_alloc(PC_ELAPSED, "aspd_read")),
_comms_errors(perf_alloc(PC_COUNT, "aspd_com_err"))
{
}
Airspeed::~Airspeed()
{
if (_class_instance != -1) {
unregister_class_devname(AIRSPEED_BASE_DEVICE_PATH, _class_instance);
}
// free perf counters
perf_free(_sample_perf);
perf_free(_comms_errors);
}
int
Airspeed::init()
{
/* do I2C init (and probe) first */
if (I2C::init() != PX4_OK) {
return PX4_ERROR;
}
/* register alternate interfaces if we have to */
_class_instance = register_class_devname(AIRSPEED_BASE_DEVICE_PATH);
/* advertise sensor topic, measure manually to initialize valid report */
measure();
return PX4_OK;
}
int
Airspeed::probe()
{
/* on initial power up the device may need more than one retry
for detection. Once it is running the number of retries can
be reduced
*/
_retries = 4;
int ret = measure();
// drop back to 2 retries once initialised
_retries = 2;
return ret;
}
int
Airspeed::ioctl(device::file_t *filp, int cmd, unsigned long arg)
{
switch (cmd) {
case AIRSPEEDIOCSSCALE: {
struct airspeed_scale *s = (struct airspeed_scale *)arg;
_diff_pres_offset = s->offset_pa;
return OK;
}
default:
/* give it to the superclass */
return I2C::ioctl(filp, cmd, arg);
}
}
+57 -138
View File
@@ -44,18 +44,16 @@
#include <px4_platform_common/defines.h>
#include <px4_platform_common/posix.h>
#include <px4_platform_common/time.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <math.h>
#include <drivers/drv_hrt.h>
#include <drivers/drv_airspeed.h>
#include <uORB/topics/differential_pressure.h>
#include <systemlib/mavlink_log.h>
#include <parameters/param.h>
#include <systemlib/err.h>
#include <lib/ecl/AlphaFilter/AlphaFilter.hpp>
#include <lib/systemlib/mavlink_log.h>
#include <lib/parameters/param.h>
#include <uORB/SubscriptionBlocking.hpp>
#include <uORB/topics/sensor_differential_pressure.h>
static const char *sensor_name = "airspeed";
using namespace time_literals;
static constexpr char sensor_name[] {"airspeed"};
static void feedback_calibration_failed(orb_advert_t *mavlink_log_pub)
{
@@ -67,114 +65,58 @@ int do_airspeed_calibration(orb_advert_t *mavlink_log_pub)
{
const hrt_abstime calibration_started = hrt_absolute_time();
int result = PX4_OK;
unsigned calibration_counter = 0;
const unsigned maxcount = 2400;
static constexpr unsigned MAX_COUNT = 2400;
static constexpr unsigned CALIBRATION_COUNT = (MAX_COUNT * 2) / 3;
/* give directions */
calibration_log_info(mavlink_log_pub, CAL_QGC_STARTED_MSG, sensor_name);
const unsigned calibration_count = (maxcount * 2) / 3;
uORB::SubscriptionBlocking<sensor_differential_pressure_s> diff_pres_sub{ORB_ID(sensor_differential_pressure)};
sensor_differential_pressure_s diff_pres{};
diff_pres_sub.copy(&diff_pres);
int diff_pres_sub = orb_subscribe(ORB_ID(differential_pressure));
struct differential_pressure_s diff_pres;
// store initial error count
uint32_t error_count = diff_pres.error_count;
float diff_pres_offset = 0.0f;
float diff_pres_total = 0.0f;
unsigned calibration_counter = 0;
/* Reset sensor parameters */
struct airspeed_scale airscale = {
diff_pres_offset,
1.0f,
};
bool paramreset_successful = false;
int fd = px4_open(AIRSPEED0_DEVICE_PATH, 0);
if (fd >= 0) {
if (PX4_OK == px4_ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
paramreset_successful = true;
} else {
calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset zero failed");
}
px4_close(fd);
}
if (!paramreset_successful) {
/* only warn if analog scaling is zero */
float analog_scaling = 0.0f;
param_get(param_find("SENS_DPRES_ANSC"), &(analog_scaling));
if (fabsf(analog_scaling) < 0.1f) {
calibration_log_critical(mavlink_log_pub, "[cal] No airspeed sensor found");
goto error_return;
}
/* set scaling offset parameter */
if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG);
goto error_return;
}
}
calibration_log_critical(mavlink_log_pub, "[cal] Ensure sensor is not measuring wind");
px4_usleep(500 * 1000);
calibration_log_critical(mavlink_log_pub, "[cal] Ensure sensor is not measuring wind");
while (calibration_counter < calibration_count) {
while (calibration_counter < CALIBRATION_COUNT) {
if (calibrate_cancel_check(mavlink_log_pub, calibration_started)) {
goto error_return;
return PX4_ERROR;
}
/* wait blocking for new data */
px4_pollfd_struct_t fds[1];
fds[0].fd = diff_pres_sub;
fds[0].events = POLLIN;
if (diff_pres_sub.updateBlocking(diff_pres, 1_s)) {
int poll_ret = px4_poll(fds, 1, 1000);
if (poll_ret) {
orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);
diff_pres_offset += diff_pres.differential_pressure_raw_pa;
diff_pres_total += diff_pres.differential_pressure_pa;
calibration_counter++;
/* any differential pressure failure a reason to abort */
if (diff_pres.error_count != 0) {
calibration_log_critical(mavlink_log_pub, "[cal] Airspeed sensor is reporting errors (%" PRIu64 ")",
diff_pres.error_count);
if (diff_pres.error_count > error_count) {
calibration_log_critical(mavlink_log_pub, "[cal] Airspeed sensor is reporting errors (%d)", diff_pres.error_count);
calibration_log_critical(mavlink_log_pub, "[cal] Check wiring, reboot vehicle, and try again");
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
if (calibration_counter % (calibration_count / 20) == 0) {
calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, (calibration_counter * 80) / calibration_count);
if (calibration_counter % (CALIBRATION_COUNT / 20) == 0) {
calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, (calibration_counter * 80) / CALIBRATION_COUNT);
}
} else if (poll_ret == 0) {
} else {
/* any poll failure for 1s is a reason to abort */
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
}
diff_pres_offset = diff_pres_offset / calibration_count;
float diff_pres_offset = diff_pres_total / calibration_counter;
if (PX4_ISFINITE(diff_pres_offset)) {
int fd_scale = px4_open(AIRSPEED0_DEVICE_PATH, 0);
airscale.offset_pa = diff_pres_offset;
if (fd_scale >= 0) {
if (PX4_OK != px4_ioctl(fd_scale, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
calibration_log_critical(mavlink_log_pub, "[cal] airspeed offset update failed");
}
px4_close(fd_scale);
}
if ((calibration_counter > 0) && PX4_ISFINITE(diff_pres_offset)) {
// Prevent a completely zero param
// since this is used to detect a missing calibration
@@ -184,89 +126,80 @@ int do_airspeed_calibration(orb_advert_t *mavlink_log_pub)
diff_pres_offset = 0.00000001f;
}
if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
if (param_set(param_find("SENS_DPRES_OFF"), &diff_pres_offset)) {
calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG);
goto error_return;
return PX4_ERROR;
}
} else {
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
calibration_log_info(mavlink_log_pub, "[cal] Offset of %d Pascal", (int)diff_pres_offset);
calibration_log_info(mavlink_log_pub, "[cal] Offset of %.1f Pascal", (double)diff_pres_offset);
/* wait 500 ms to ensure parameter propagated through the system */
px4_usleep(500 * 1000);
/* wait 100 ms to ensure parameter propagated through the system */
px4_usleep(100 * 1000);
calibration_log_critical(mavlink_log_pub, "[cal] Blow across front of pitot without touching");
AlphaFilter<float> diff_pres_filtered{0.1f};
calibration_counter = 0;
/* just take a few samples and make sure pitot tubes are not reversed, timeout after ~30 seconds */
while (calibration_counter < maxcount) {
while (calibration_counter < MAX_COUNT) {
if (calibrate_cancel_check(mavlink_log_pub, calibration_started)) {
goto error_return;
return PX4_ERROR;
}
/* wait blocking for new data */
px4_pollfd_struct_t fds[1];
fds[0].fd = diff_pres_sub;
fds[0].events = POLLIN;
if (diff_pres_sub.updateBlocking(diff_pres, 1_s)) {
int poll_ret = px4_poll(fds, 1, 1000);
diff_pres_filtered.update(diff_pres.differential_pressure_pa - diff_pres_offset);
if (poll_ret) {
orb_copy(ORB_ID(differential_pressure), diff_pres_sub, &diff_pres);
if (fabsf(diff_pres.differential_pressure_filtered_pa) > 50.0f) {
if (diff_pres.differential_pressure_filtered_pa > 0) {
calibration_log_info(mavlink_log_pub, "[cal] Positive pressure: OK (%d Pa)",
(int)diff_pres.differential_pressure_filtered_pa);
if (fabsf(diff_pres_filtered.getState()) > 50.0f) {
if (diff_pres_filtered.getState() > 0) {
calibration_log_info(mavlink_log_pub, "[cal] Positive pressure: OK (%.1f Pa)", (double)diff_pres_filtered.getState());
break;
} else {
/* do not allow negative values */
calibration_log_critical(mavlink_log_pub, "[cal] Negative pressure difference detected (%d Pa)",
(int)diff_pres.differential_pressure_filtered_pa);
calibration_log_critical(mavlink_log_pub, "[cal] Negative pressure difference detected (%.1f Pa)",
(double)diff_pres_filtered.getState());
calibration_log_critical(mavlink_log_pub, "[cal] Swap static and dynamic ports!");
/* the user setup is wrong, wipe the calibration to force a proper re-calibration */
diff_pres_offset = 0.0f;
if (param_set(param_find("SENS_DPRES_OFF"), &(diff_pres_offset))) {
if (param_reset(param_find("SENS_DPRES_OFF")) != PX4_OK) {
calibration_log_critical(mavlink_log_pub, CAL_ERROR_SET_PARAMS_MSG);
goto error_return;
return PX4_ERROR;
}
/* save */
calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 0);
param_save_default();
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
}
if (calibration_counter % 500 == 0) {
calibration_log_info(mavlink_log_pub, "[cal] Create air pressure! (got %d, wanted: 50 Pa)",
(int)diff_pres.differential_pressure_filtered_pa);
calibration_log_info(mavlink_log_pub, "[cal] Create air pressure! (got %.1f, wanted: 50 Pa)",
(double)diff_pres_filtered.getState());
tune_neutral(true);
}
calibration_counter++;
} else if (poll_ret == 0) {
} else {
/* any poll failure for 1s is a reason to abort */
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
}
if (calibration_counter == maxcount) {
if (calibration_counter == MAX_COUNT) {
feedback_calibration_failed(mavlink_log_pub);
goto error_return;
return PX4_ERROR;
}
calibration_log_info(mavlink_log_pub, CAL_QGC_PROGRESS_MSG, 100);
@@ -274,19 +207,5 @@ int do_airspeed_calibration(orb_advert_t *mavlink_log_pub)
calibration_log_info(mavlink_log_pub, CAL_QGC_DONE_MSG, sensor_name);
tune_neutral(true);
/* Wait 2sec for the airflow to stop and ensure the driver filter has caught up, otherwise
* the followup preflight checks might fail. */
px4_usleep(2e6);
normal_return:
px4_close(diff_pres_sub);
// This give a chance for the log messages to go out of the queue before someone else stomps on then
px4_sleep(1);
return result;
error_return:
result = PX4_ERROR;
goto normal_return;
return PX4_OK;
}
+1 -1
View File
@@ -1186,7 +1186,7 @@ void EKF2::UpdateAirspeedSample(ekf2_timestamps_s &ekf2_timestamps)
if ((_param_ekf2_arsp_thr.get() > FLT_EPSILON) && (true_airspeed_m_s > _param_ekf2_arsp_thr.get())) {
airspeedSample airspeed_sample {
.time_us = airspeed.timestamp,
.time_us = airspeed.timestamp_sample,
.true_airspeed = true_airspeed_m_s,
.eas2tas = airspeed.true_airspeed_m_s / airspeed.indicated_airspeed_m_s,
};
+11 -11
View File
@@ -63,7 +63,7 @@
#include <uORB/topics/camera_capture.h>
#include <uORB/topics/camera_trigger.h>
#include <uORB/topics/cpuload.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/topics/distance_sensor.h>
#include <uORB/topics/estimator_selector_status.h>
#include <uORB/topics/estimator_sensor_bias.h>
@@ -923,7 +923,7 @@ private:
uORB::Subscription _estimator_sensor_bias_sub{ORB_ID(estimator_sensor_bias)};
uORB::Subscription _estimator_selector_status_sub{ORB_ID(estimator_selector_status)};
uORB::Subscription _sensor_selection_sub{ORB_ID(sensor_selection)};
uORB::Subscription _differential_pressure_sub{ORB_ID(differential_pressure)};
uORB::Subscription _sensor_differential_pressure_sub{ORB_ID(sensor_differential_pressure)};
uORB::Subscription _magnetometer_sub{ORB_ID(vehicle_magnetometer)};
uORB::Subscription _air_data_sub{ORB_ID(vehicle_air_data)};
@@ -1026,14 +1026,14 @@ protected:
_air_data_sub.copy(&air_data);
}
differential_pressure_s differential_pressure{};
sensor_differential_pressure_s differential_pressure{};
if (_differential_pressure_sub.update(&differential_pressure)) {
if (_sensor_differential_pressure_sub.update(&differential_pressure)) {
/* mark fourth group (dpres field) dimensions as changed */
fields_updated |= (1 << 10);
} else {
_differential_pressure_sub.copy(&differential_pressure);
_sensor_differential_pressure_sub.copy(&differential_pressure);
}
const float accel_dt_inv = 1.e6f / (float)imu.delta_velocity_dt;
@@ -1055,7 +1055,7 @@ protected:
msg.ymag = mag(1);
msg.zmag = mag(2);
msg.abs_pressure = air_data.baro_pressure_pa;
msg.diff_pressure = differential_pressure.differential_pressure_raw_pa;
msg.diff_pressure = differential_pressure.differential_pressure_pa;
msg.pressure_alt = air_data.baro_alt_meter;
msg.temperature = air_data.baro_temp_celcius;
msg.fields_updated = fields_updated;
@@ -1089,7 +1089,7 @@ public:
}
private:
uORB::Subscription _differential_pressure_sub{ORB_ID(differential_pressure)};
uORB::Subscription _sensor_differential_pressure_sub{ORB_ID(sensor_differential_pressure)};
uORB::Subscription _sensor_baro_sub{ORB_ID(sensor_baro), N};
/* do not allow top copying this class */
@@ -1102,16 +1102,16 @@ protected:
bool send() override
{
if (_sensor_baro_sub.updated() || _differential_pressure_sub.updated()) {
if (_sensor_baro_sub.updated() || _sensor_differential_pressure_sub.updated()) {
sensor_baro_s sensor_baro{};
differential_pressure_s differential_pressure{};
sensor_differential_pressure_s differential_pressure{};
_sensor_baro_sub.copy(&sensor_baro);
_differential_pressure_sub.copy(&differential_pressure);
_sensor_differential_pressure_sub.copy(&differential_pressure);
typename Derived::mav_msg_type msg{};
msg.time_boot_ms = sensor_baro.timestamp / 1000;
msg.press_abs = sensor_baro.pressure;
msg.press_diff = differential_pressure.differential_pressure_raw_pa;
msg.press_diff = differential_pressure.differential_pressure_pa;
msg.temperature = sensor_baro.temperature;
Derived::send(_mavlink->get_channel(), &msg);
+6 -8
View File
@@ -2345,12 +2345,11 @@ MavlinkReceiver::handle_message_hil_sensor(mavlink_message_t *msg)
// differential pressure
if ((hil_sensor.fields_updated & SensorSource::DIFF_PRESS) == SensorSource::DIFF_PRESS) {
differential_pressure_s report{};
report.timestamp = timestamp;
sensor_differential_pressure_s report{};
report.timestamp_sample = timestamp;
report.temperature = hil_sensor.temperature;
report.differential_pressure_filtered_pa = hil_sensor.diff_pressure * 100.0f; // convert from millibar to bar;
report.differential_pressure_raw_pa = hil_sensor.diff_pressure * 100.0f; // convert from millibar to bar;
report.differential_pressure_pa = hil_sensor.diff_pressure * 100.0f; // convert from millibar to bar;
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
}
@@ -2641,11 +2640,10 @@ MavlinkReceiver::handle_message_hil_state_quaternion(mavlink_message_t *msg)
/* airspeed */
{
airspeed_s airspeed{};
airspeed.timestamp = timestamp;
airspeed.timestamp_sample = timestamp;
airspeed.indicated_airspeed_m_s = hil_state.ind_airspeed * 1e-2f;
airspeed.true_airspeed_m_s = hil_state.true_airspeed * 1e-2f;
airspeed.timestamp = hrt_absolute_time();
_airspeed_pub.publish(airspeed);
}
+2 -2
View File
@@ -63,7 +63,7 @@
#include <uORB/topics/battery_status.h>
#include <uORB/topics/cellular_status.h>
#include <uORB/topics/collision_report.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/topics/distance_sensor.h>
#include <uORB/topics/follow_target.h>
#include <uORB/topics/generator_status.h>
@@ -356,7 +356,7 @@ private:
uORB::Publication<battery_status_s> _battery_pub{ORB_ID(battery_status)};
uORB::Publication<cellular_status_s> _cellular_status_pub{ORB_ID(cellular_status)};
uORB::Publication<collision_report_s> _collision_report_pub{ORB_ID(collision_report)};
uORB::Publication<differential_pressure_s> _differential_pressure_pub{ORB_ID(differential_pressure)};
uORB::Publication<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
uORB::Publication<follow_target_s> _follow_target_pub{ORB_ID(follow_target)};
uORB::Publication<gimbal_manager_set_attitude_s> _gimbal_manager_set_attitude_pub{ORB_ID(gimbal_manager_set_attitude)};
uORB::Publication<gimbal_manager_set_manual_control_s> _gimbal_manager_set_manual_control_pub{ORB_ID(gimbal_manager_set_manual_control)};
+2
View File
@@ -34,6 +34,7 @@
add_subdirectory(data_validator)
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(airspeed)
add_subdirectory(vehicle_acceleration)
add_subdirectory(vehicle_angular_velocity)
add_subdirectory(vehicle_air_data)
@@ -55,6 +56,7 @@ px4_add_module(
git_ecl
mathlib
sensor_calibration
sensors_airspeed
vehicle_acceleration
vehicle_angular_velocity
vehicle_air_data
+338
View File
@@ -0,0 +1,338 @@
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#include "Airspeed.hpp"
#include <px4_platform_common/log.h>
#include <lib/ecl/geo/geo.h>
#include <lib/airspeed/airspeed.h>
#include <drivers/drv_sensor.h>
namespace sensors
{
using namespace matrix;
using namespace time_literals;
static constexpr uint32_t SENSOR_TIMEOUT{300_ms};
/**
* HACK - true temperature is much less than indicated temperature in baro,
* subtract 5 degrees in an attempt to account for the electrical upheating of the PCB
*/
#define PCB_TEMP_ESTIMATE_DEG 5.0f
Airspeed::Airspeed() :
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::nav_and_controllers)
{
_voter.set_timeout(SENSOR_TIMEOUT);
_voter.set_equal_value_threshold(100);
ParametersUpdate(true);
}
Airspeed::~Airspeed()
{
Stop();
perf_free(_cycle_perf);
}
bool Airspeed::Start()
{
ScheduleNow();
return true;
}
void Airspeed::Stop()
{
Deinit();
// clear all registered callbacks
for (auto &sub : _sensor_sub) {
sub.unregisterCallback();
}
}
void Airspeed::ParametersUpdate(bool force)
{
// Check if parameters have changed
if (_parameter_update_sub.updated() || force) {
// clear update
parameter_update_s param_update;
_parameter_update_sub.copy(&param_update);
updateParams();
}
}
void Airspeed::Run()
{
perf_begin(_cycle_perf);
ParametersUpdate();
if (_vehicle_air_data_sub.updated()) {
vehicle_air_data_s air_data;
if (_vehicle_air_data_sub.copy(&air_data)) {
if ((air_data.timestamp != 0) && PX4_ISFINITE(air_data.baro_temp_celcius)
&& (air_data.baro_temp_celcius >= -40.f) && (air_data.baro_temp_celcius <= 125.f)) {
// TODO: review PCB_TEMP_ESTIMATE_DEG, ignore for external baro
_baro_air_temperature = air_data.baro_temp_celcius - PCB_TEMP_ESTIMATE_DEG;
}
}
}
bool updated[MAX_SENSOR_COUNT] {};
for (int uorb_index = 0; uorb_index < MAX_SENSOR_COUNT; uorb_index++) {
if (!_advertised[uorb_index]) {
// use data's timestamp to throttle advertisement checks
if ((_last_data[uorb_index].timestamp == 0) || (hrt_elapsed_time(&_last_data[uorb_index].timestamp) > 1_s)) {
if (_sensor_sub[uorb_index].advertised()) {
if (uorb_index > 0) {
/* the first always exists, but for each further sensor, add a new validator */
if (!_voter.add_new_validator()) {
PX4_ERR("failed to add validator for %s %i", "DPRES", uorb_index);
}
}
_advertised[uorb_index] = true;
// advertise outputs in order if publishing all
if (!_param_sens_dpres_mode.get()) {
for (int instance = 0; instance < uorb_index; instance++) {
_airspeed_multi_pub[instance].advertise();
}
}
if (_selected_sensor_sub_index < 0) {
_sensor_sub[uorb_index].registerCallback();
}
} else {
_last_data[uorb_index].timestamp = hrt_absolute_time();
}
}
}
if (_advertised[uorb_index]) {
sensor_differential_pressure_s diff_pres;
while (_sensor_sub[uorb_index].update(&diff_pres)) {
updated[uorb_index] = true;
_device_id[uorb_index] = diff_pres.device_id;
float differential_pressure_pa = diff_pres.differential_pressure_pa - _param_sens_dpres_off.get();
float vect[3] {differential_pressure_pa, diff_pres.temperature, 0.f};
_voter.put(uorb_index, diff_pres.timestamp_sample, vect, diff_pres.error_count, _priority[uorb_index]);
float air_temperature_celsius = NAN;
// assume anything outside of a (generous) operating range of -40C to 125C is invalid
if (PX4_ISFINITE(diff_pres.temperature) && (diff_pres.temperature >= -40.f) && (diff_pres.temperature <= 125.f)) {
air_temperature_celsius = diff_pres.temperature;
} else {
// differential pressure temperature invalid, use barometer temperature if available
if (PX4_ISFINITE(_baro_air_temperature)) {
air_temperature_celsius = _baro_air_temperature;
}
}
// average raw data for all instances
_timestamp_sample_sum[uorb_index] += diff_pres.timestamp_sample;
_sensor_differential_pressure_sum[uorb_index] += differential_pressure_pa;
_temperature_sum[uorb_index] += air_temperature_celsius;
_sum_count[uorb_index]++;
}
}
}
// check for the current best sensor
int best_index = 0;
_voter.get_best(hrt_absolute_time(), &best_index);
if (best_index >= 0) {
if (_selected_sensor_sub_index != best_index) {
// clear all registered callbacks
for (auto &sub : _sensor_sub) {
sub.unregisterCallback();
}
if (_param_sens_dpres_mode.get()) {
if (_selected_sensor_sub_index >= 0) {
PX4_INFO("%s switch from #%u -> #%d", "DPRES", _selected_sensor_sub_index, best_index);
}
}
_selected_sensor_sub_index = best_index;
_sensor_sub[_selected_sensor_sub_index].registerCallback();
}
}
// Publish
if (_param_sens_dpres_mode.get()) {
// publish only best sensor
if ((_selected_sensor_sub_index >= 0)
&& (_voter.get_sensor_state(_selected_sensor_sub_index) == DataValidator::ERROR_FLAG_NO_ERROR)
&& updated[_selected_sensor_sub_index]) {
Publish(_selected_sensor_sub_index);
}
} else {
// publish all
for (int uorb_index = 0; uorb_index < MAX_SENSOR_COUNT; uorb_index++) {
// publish all sensors as separate instances
if (updated[uorb_index] && (_device_id[uorb_index] != 0)) {
Publish(uorb_index, true);
}
}
}
// check failover and report
if (_param_sens_dpres_mode.get()) {
if (_last_failover_count != _voter.failover_count()) {
uint32_t flags = _voter.failover_state();
int failover_index = _voter.failover_index();
if (flags != DataValidator::ERROR_FLAG_NO_ERROR) {
if (failover_index != -1) {
const hrt_abstime now = hrt_absolute_time();
if (now - _last_error_message > 3_s) {
mavlink_log_emergency(&_mavlink_log_pub, "%s #%i failed: %s%s%s%s%s!",
"DPRES",
failover_index,
((flags & DataValidator::ERROR_FLAG_NO_DATA) ? " OFF" : ""),
((flags & DataValidator::ERROR_FLAG_STALE_DATA) ? " STALE" : ""),
((flags & DataValidator::ERROR_FLAG_TIMEOUT) ? " TIMEOUT" : ""),
((flags & DataValidator::ERROR_FLAG_HIGH_ERRCOUNT) ? " ERR CNT" : ""),
((flags & DataValidator::ERROR_FLAG_HIGH_ERRDENSITY) ? " ERR DNST" : ""));
_last_error_message = now;
}
// reduce priority of failed sensor to the minimum
_priority[failover_index] = 1;
}
}
_last_failover_count = _voter.failover_count();
}
}
// reschedule timeout
ScheduleDelayed(100_ms);
perf_end(_cycle_perf);
}
void Airspeed::Publish(uint8_t instance, bool multi)
{
if ((_param_sens_dpres_rate.get() > 0)
&& hrt_elapsed_time(&_last_publication_timestamp[instance]) >= (1e6f / _param_sens_dpres_rate.get())) {
const float differential_pressure = _sensor_differential_pressure_sum[instance] / _sum_count[instance];
const float temperature = _temperature_sum[instance] / _sum_count[instance];
const hrt_abstime timestamp_sample = _timestamp_sample_sum[instance] / _sum_count[instance];
// reset
_timestamp_sample_sum[instance] = 0;
_sensor_differential_pressure_sum[instance] = 0;
_temperature_sum[instance] = 0;
_sum_count[instance] = 0;
airspeed_s out{};
out.timestamp_sample = timestamp_sample;
out.air_temperature_celsius = temperature;
out.confidence = 1.f; // TODO
switch ((_device_id[instance] >> 16) & 0xFF) {
case DRV_DIFF_PRESS_DEVTYPE_SDP31:
// fallthrough
case DRV_DIFF_PRESS_DEVTYPE_SDP32:
// fallthrough
case DRV_DIFF_PRESS_DEVTYPE_SDP33:
out.indicated_airspeed_m_s = calc_IAS_corrected((enum AIRSPEED_COMPENSATION_MODEL) _param_cal_air_cmodel.get(),
AIRSPEED_SENSOR_MODEL_SDP3X, _param_cal_air_tubelen.get(), _param_cal_air_tubed_mm.get(),
differential_pressure, _baro_pressure_pa, temperature);
break;
default:
out.indicated_airspeed_m_s = calc_IAS(differential_pressure);
break;
}
// assume that CAS = IAS as we don't have an CAS-scale here
out.true_airspeed_m_s = calc_TAS_from_CAS(out.indicated_airspeed_m_s, _baro_pressure_pa, temperature);
if (PX4_ISFINITE(out.indicated_airspeed_m_s) && PX4_ISFINITE(out.true_airspeed_m_s)) {
out.timestamp = hrt_absolute_time();
if (multi) {
_airspeed_multi_pub[instance].publish(out);
} else {
// otherwise only ever publish the first instance
_airspeed_multi_pub[0].publish(out);
}
_last_publication_timestamp[instance] = out.timestamp;
}
}
}
void Airspeed::PrintStatus()
{
if (_selected_sensor_sub_index >= 0) {
PX4_INFO("selected differential pressure: %d (%d)", _device_id[_selected_sensor_sub_index], _selected_sensor_sub_index);
}
_voter.print();
}
}; // namespace sensors
+131
View File
@@ -0,0 +1,131 @@
/****************************************************************************
*
* Copyright (c) 2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
#pragma once
#include "data_validator/DataValidatorGroup.hpp"
#include <lib/mathlib/math/Limits.hpp>
#include <lib/matrix/matrix/math.hpp>
#include <lib/perf/perf_counter.h>
#include <lib/systemlib/mavlink_log.h>
#include <px4_platform_common/log.h>
#include <px4_platform_common/module_params.h>
#include <px4_platform_common/px4_config.h>
#include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
#include <uORB/Publication.hpp>
#include <uORB/PublicationMulti.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/airspeed.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/vehicle_air_data.h>
using namespace time_literals;
namespace sensors
{
class Airspeed : public ModuleParams, public px4::ScheduledWorkItem
{
public:
Airspeed();
~Airspeed() override;
bool Start();
void Stop();
void PrintStatus();
private:
void Run() override;
void ParametersUpdate(bool force = false);
void Publish(uint8_t instance, bool multi = false);
static constexpr int MAX_SENSOR_COUNT = 4;
uORB::PublicationMulti<airspeed_s> _airspeed_multi_pub[MAX_SENSOR_COUNT] {
{ORB_ID(airspeed)},
{ORB_ID(airspeed)},
{ORB_ID(airspeed)},
{ORB_ID(airspeed)},
};
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::Subscription _vehicle_air_data_sub{ORB_ID(vehicle_air_data)};
uORB::SubscriptionCallbackWorkItem _sensor_sub[MAX_SENSOR_COUNT] {
{this, ORB_ID(sensor_differential_pressure), 0},
{this, ORB_ID(sensor_differential_pressure), 1},
{this, ORB_ID(sensor_differential_pressure), 2},
{this, ORB_ID(sensor_differential_pressure), 3},
};
perf_counter_t _cycle_perf{perf_alloc(PC_ELAPSED, MODULE_NAME": cycle")};
hrt_abstime _last_error_message{0};
orb_advert_t _mavlink_log_pub{nullptr};
DataValidatorGroup _voter{1};
unsigned _last_failover_count{0};
uint32_t _device_id[MAX_SENSOR_COUNT] {};
uint64_t _timestamp_sample_sum[MAX_SENSOR_COUNT] {0};
hrt_abstime _last_publication_timestamp[MAX_SENSOR_COUNT] {};
float _sensor_differential_pressure_sum[MAX_SENSOR_COUNT] {};
float _temperature_sum[MAX_SENSOR_COUNT] {};
int _sum_count[MAX_SENSOR_COUNT] {};
sensor_differential_pressure_s _last_data[MAX_SENSOR_COUNT] {};
bool _advertised[MAX_SENSOR_COUNT] {};
uint8_t _priority[MAX_SENSOR_COUNT] {100, 100, 100, 100};
int8_t _selected_sensor_sub_index{-1};
float _baro_pressure_pa{101325.f}; // Sea level standard atmospheric pressure
float _baro_air_temperature{15.f};
DEFINE_PARAMETERS(
(ParamInt<px4::params::SENS_DPRES_MODE>) _param_sens_dpres_mode,
(ParamFloat<px4::params::SENS_DPRES_OFF>) _param_sens_dpres_off,
(ParamFloat<px4::params::SENS_DPRES_RATE>) _param_sens_dpres_rate,
(ParamInt<px4::params::CAL_AIR_CMODEL>) _param_cal_air_cmodel,
(ParamFloat<px4::params::CAL_AIR_TUBELEN>) _param_cal_air_tubelen,
(ParamFloat<px4::params::CAL_AIR_TUBED_MM>) _param_cal_air_tubed_mm
)
};
}; // namespace sensors
@@ -1,6 +1,6 @@
############################################################################
#
# Copyright (c) 2015 PX4 Development Team. All rights reserved.
# Copyright (c) 2020 PX4 Development Team. All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions
@@ -31,5 +31,12 @@
#
############################################################################
px4_add_library(drivers__airspeed airspeed.cpp)
target_link_libraries(drivers__airspeed PRIVATE drivers__device)
px4_add_library(sensors_airspeed
Airspeed.cpp
Airspeed.hpp
)
target_link_libraries(sensors_airspeed
PRIVATE
airspeed
px4_work_queue
)
+115
View File
@@ -0,0 +1,115 @@
/****************************************************************************
*
* Copyright (c) 2012-2020 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* 3. Neither the name PX4 nor the names of its contributors may be
* used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
* OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
****************************************************************************/
/**
* Airspeed sensor compensation model for the SDP3x
*
* Model with Pitot
* CAL_AIR_TUBED_MM: Not used, 1.5 mm tubes assumed.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor.
* Model without Pitot (1.5 mm tubes)
* CAL_AIR_TUBED_MM: Not used, 1.5 mm tubes assumed.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor.
* Tube Pressure Drop
* CAL_AIR_TUBED_MM: Diameter in mm of the pitot and tubes, must have the same diameter.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor and the static + dynamic port length of the pitot.
*
* @value 0 Model with Pitot
* @value 1 Model without Pitot (1.5 mm tubes)
* @value 2 Tube Pressure Drop
*
* @group Sensors
*/
PARAM_DEFINE_INT32(CAL_AIR_CMODEL, 0);
/**
* Airspeed sensor tube length.
*
* See the CAL_AIR_CMODEL explanation on how this parameter should be set.
*
* @min 0.01
* @max 2.00
* @unit m
*
* @group Sensors
*/
PARAM_DEFINE_FLOAT(CAL_AIR_TUBELEN, 0.2f);
/**
* Airspeed sensor tube diameter. Only used for the Tube Pressure Drop Compensation.
*
* @min 0.1
* @max 100
* @unit mm
*
* @group Sensors
*/
PARAM_DEFINE_FLOAT(CAL_AIR_TUBED_MM, 1.5f);
/**
* Differential pressure sensor offset
*
* The offset (zero-reading) in Pascal
*
* @category system
* @group Sensor Calibration
*/
PARAM_DEFINE_FLOAT(SENS_DPRES_OFF, 0.0f);
/**
* Sensors hub differential pressure mode
*
* @value 0 Publish all airspeeds
* @value 1 Publish primary airspeed
*
* @category system
* @reboot_required true
* @group Sensors
*/
PARAM_DEFINE_INT32(SENS_DPRES_MODE, 1);
/**
* Differential pressure (airspeed) max rate.
*
* Airspeed data maximum publication rate. This is an upper bound,
* actual differential pressure data rate is still dependant on the sensor.
*
* @min 1
* @max 100
* @group Sensors
* @unit Hz
*
* @reboot_required true
*
*/
PARAM_DEFINE_FLOAT(SENS_DPRES_RATE, 10.0f);
+1 -71
View File
@@ -1,6 +1,6 @@
/****************************************************************************
*
* Copyright (c) 2012-2019 PX4 Development Team. All rights reserved.
* Copyright (c) 2012-2021 PX4 Development Team. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
@@ -31,76 +31,6 @@
*
****************************************************************************/
/**
* Airspeed sensor compensation model for the SDP3x
*
* Model with Pitot
* CAL_AIR_TUBED_MM: Not used, 1.5 mm tubes assumed.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor.
* Model without Pitot (1.5 mm tubes)
* CAL_AIR_TUBED_MM: Not used, 1.5 mm tubes assumed.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor.
* Tube Pressure Drop
* CAL_AIR_TUBED_MM: Diameter in mm of the pitot and tubes, must have the same diameter.
* CAL_AIR_TUBELEN: Length of the tubes connecting the pitot to the sensor and the static + dynamic port length of the pitot.
*
* @value 0 Model with Pitot
* @value 1 Model without Pitot (1.5 mm tubes)
* @value 2 Tube Pressure Drop
*
* @group Sensors
*/
PARAM_DEFINE_INT32(CAL_AIR_CMODEL, 0);
/**
* Airspeed sensor tube length.
*
* See the CAL_AIR_CMODEL explanation on how this parameter should be set.
*
* @min 0.01
* @max 2.00
* @unit m
*
* @group Sensors
*/
PARAM_DEFINE_FLOAT(CAL_AIR_TUBELEN, 0.2f);
/**
* Airspeed sensor tube diameter. Only used for the Tube Pressure Drop Compensation.
*
* @min 0.1
* @max 100
* @unit mm
*
* @group Sensors
*/
PARAM_DEFINE_FLOAT(CAL_AIR_TUBED_MM, 1.5f);
/**
* Differential pressure sensor offset
*
* The offset (zero-reading) in Pascal
*
* @category system
* @group Sensor Calibration
* @volatile
*/
PARAM_DEFINE_FLOAT(SENS_DPRES_OFF, 0.0f);
/**
* Differential pressure sensor analog scaling
*
* Pick the appropriate scaling from the datasheet.
* this number defines the (linear) conversion from voltage
* to Pascal (pa). For the MPXV7002DP this is 1000.
*
* NOTE: If the sensor always registers zero, try switching
* the static and dynamic tubes.
*
* @group Sensor Calibration
*/
PARAM_DEFINE_FLOAT(SENS_DPRES_ANSC, 0);
/**
* Board rotation
*
+43 -296
View File
@@ -41,10 +41,7 @@
* @author Beat Küng <beat-kueng@gmx.net>
*/
#include <drivers/drv_adc.h>
#include <drivers/drv_airspeed.h>
#include <drivers/drv_hrt.h>
#include <lib/airspeed/airspeed.h>
#include <lib/mathlib/mathlib.h>
#include <lib/parameters/param.h>
#include <lib/perf/perf_counter.h>
@@ -60,16 +57,14 @@
#include <uORB/PublicationMulti.hpp>
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionCallback.hpp>
#include <uORB/topics/actuator_controls.h>
#include <uORB/topics/airspeed.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/parameter_update.h>
#include <uORB/topics/sensors_status_imu.h>
#include <uORB/topics/vehicle_air_data.h>
#include <uORB/topics/vehicle_control_mode.h>
#include <uORB/topics/vehicle_imu.h>
#include <uORB/topics/vehicle_status.h>
#include "voted_sensors_update.h"
#include "airspeed/Airspeed.hpp"
#include "vehicle_acceleration/VehicleAcceleration.hpp"
#include "vehicle_angular_velocity/VehicleAngularVelocity.hpp"
#include "vehicle_air_data/VehicleAirData.hpp"
@@ -80,15 +75,10 @@
using namespace sensors;
using namespace time_literals;
/**
* HACK - true temperature is much less than indicated temperature in baro,
* subtract 5 degrees in an attempt to account for the electrical upheating of the PCB
*/
#define PCB_TEMP_ESTIMATE_DEG 5.0f
class Sensors : public ModuleBase<Sensors>, public ModuleParams, public px4::ScheduledWorkItem
{
public:
explicit Sensors(bool hil_enabled);
explicit Sensors();
~Sensors() override;
/** @see ModuleBase */
@@ -109,8 +99,8 @@ public:
bool init();
private:
const bool _hil_enabled; /**< if true, HIL is active */
bool _armed{false}; /**< arming status of the vehicle */
bool _armed{false}; /**< arming status of the vehicle */
bool _hil_enabled{false}; /**< if true, HIL is active */
hrt_abstime _last_config_update{0};
hrt_abstime _sensor_combined_prev_timestamp{0};
@@ -126,85 +116,30 @@ private:
uORB::SubscriptionInterval _parameter_update_sub{ORB_ID(parameter_update), 1_s};
uORB::Subscription _diff_pres_sub{ORB_ID(differential_pressure)};
uORB::Subscription _vcontrol_mode_sub{ORB_ID(vehicle_control_mode)};
uORB::Subscription _vehicle_air_data_sub{ORB_ID(vehicle_air_data)};
uORB::Subscription _vehicle_status_sub{ORB_ID(vehicle_status)};
uORB::Publication<airspeed_s> _airspeed_pub{ORB_ID(airspeed)};
uORB::Publication<sensor_combined_s> _sensor_pub{ORB_ID(sensor_combined)};
perf_counter_t _loop_perf; /**< loop performance counter */
DataValidator _airspeed_validator; /**< data validator to monitor airspeed */
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
hrt_abstime _last_adc{0}; /**< last time we took input from the ADC */
uORB::Subscription _adc_report_sub{ORB_ID(adc_report)}; /**< adc_report sub */
differential_pressure_s _diff_pres {};
uORB::PublicationMulti<differential_pressure_s> _diff_pres_pub{ORB_ID(differential_pressure)}; /**< differential_pressure */
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
struct Parameters {
float diff_pres_offset_pa;
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
float diff_pres_analog_scale;
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
int32_t air_cmodel;
float air_tube_length;
float air_tube_diameter_mm;
} _parameters{}; /**< local copies of interesting parameters */
struct ParameterHandles {
param_t diff_pres_offset_pa;
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
param_t diff_pres_analog_scale;
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
param_t air_cmodel;
param_t air_tube_length;
param_t air_tube_diameter_mm;
} _parameter_handles{}; /**< handles for interesting parameters */
VotedSensorsUpdate _voted_sensors_update;
VehicleAcceleration _vehicle_acceleration;
VehicleAngularVelocity _vehicle_angular_velocity;
Airspeed *_airspeed{nullptr};
VehicleAirData *_vehicle_air_data{nullptr};
VehicleMagnetometer *_vehicle_magnetometer{nullptr};
VehicleGPSPosition *_vehicle_gps_position{nullptr};
VehicleIMU *_vehicle_imu_list[MAX_SENSOR_COUNT] {};
/**
* Update our local parameter cache.
*/
int parameters_update();
/**
* Poll the differential pressure sensor for updated data.
*
* @param raw Combined sensor data structure into which
* data should be returned.
*/
void diff_pres_poll();
/**
* Check for changes in parameters.
*/
void parameter_update_poll(bool forced = false);
/**
* Poll the ADC and update readings to suit.
*
* @param raw Combined sensor data structure into which
* data should be returned.
*/
void adc_poll();
void InitializeAirspeed();
void InitializeVehicleAirData();
void InitializeVehicleGPSPosition();
void InitializeVehicleIMU();
@@ -217,23 +152,12 @@ private:
)
};
Sensors::Sensors(bool hil_enabled) :
Sensors::Sensors() :
ModuleParams(nullptr),
ScheduledWorkItem(MODULE_NAME, px4::wq_configurations::nav_and_controllers),
_hil_enabled(hil_enabled),
_loop_perf(perf_alloc(PC_ELAPSED, "sensors")),
_voted_sensors_update(hil_enabled, _vehicle_imu_sub)
_voted_sensors_update(_vehicle_imu_sub)
{
/* Differential pressure offset */
_parameter_handles.diff_pres_offset_pa = param_find("SENS_DPRES_OFF");
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
_parameter_handles.diff_pres_analog_scale = param_find("SENS_DPRES_ANSC");
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
_parameter_handles.air_cmodel = param_find("CAL_AIR_CMODEL");
_parameter_handles.air_tube_length = param_find("CAL_AIR_TUBELEN");
_parameter_handles.air_tube_diameter_mm = param_find("CAL_AIR_TUBED_MM");
param_find("SYS_FAC_CAL_MODE");
// Parameters controlling the on-board sensor thermal calibrator
@@ -241,9 +165,6 @@ Sensors::Sensors(bool hil_enabled) :
param_find("SYS_CAL_TMAX");
param_find("SYS_CAL_TMIN");
_airspeed_validator.set_timeout(300000);
_airspeed_validator.set_equal_value_threshold(100);
_vehicle_acceleration.Start();
_vehicle_angular_velocity.Start();
}
@@ -258,6 +179,11 @@ Sensors::~Sensors()
_vehicle_acceleration.Stop();
_vehicle_angular_velocity.Stop();
if (_airspeed) {
_airspeed->Stop();
delete _airspeed;
}
if (_vehicle_air_data) {
_vehicle_air_data->Stop();
delete _vehicle_air_data;
@@ -290,102 +216,7 @@ bool Sensors::init()
return true;
}
int Sensors::parameters_update()
{
if (_armed) {
return 0;
}
/* Airspeed offset */
param_get(_parameter_handles.diff_pres_offset_pa, &(_parameters.diff_pres_offset_pa));
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
param_get(_parameter_handles.diff_pres_analog_scale, &(_parameters.diff_pres_analog_scale));
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
param_get(_parameter_handles.air_cmodel, &_parameters.air_cmodel);
param_get(_parameter_handles.air_tube_length, &_parameters.air_tube_length);
param_get(_parameter_handles.air_tube_diameter_mm, &_parameters.air_tube_diameter_mm);
_voted_sensors_update.parametersUpdate();
return PX4_OK;
}
void Sensors::diff_pres_poll()
{
differential_pressure_s diff_pres{};
if (_diff_pres_sub.update(&diff_pres)) {
vehicle_air_data_s air_data{};
_vehicle_air_data_sub.copy(&air_data);
float air_temperature_celsius = NAN;
// assume anything outside of a (generous) operating range of -40C to 125C is invalid
if (PX4_ISFINITE(diff_pres.temperature) && (diff_pres.temperature >= -40.f) && (diff_pres.temperature <= 125.f)) {
air_temperature_celsius = diff_pres.temperature;
} else {
// differential pressure temperature invalid, check barometer
if ((air_data.timestamp != 0) && PX4_ISFINITE(air_data.baro_temp_celcius)
&& (air_data.baro_temp_celcius >= -40.f) && (air_data.baro_temp_celcius <= 125.f)) {
// TODO: review PCB_TEMP_ESTIMATE_DEG, ignore for external baro
air_temperature_celsius = air_data.baro_temp_celcius - PCB_TEMP_ESTIMATE_DEG;
}
}
airspeed_s airspeed{};
airspeed.timestamp = diff_pres.timestamp;
/* push data into validator */
float airspeed_input[3] = { diff_pres.differential_pressure_raw_pa, diff_pres.temperature, 0.0f };
_airspeed_validator.put(airspeed.timestamp, airspeed_input, diff_pres.error_count, 100); // TODO: real priority?
airspeed.confidence = _airspeed_validator.confidence(hrt_absolute_time());
enum AIRSPEED_SENSOR_MODEL smodel;
switch ((diff_pres.device_id >> 16) & 0xFF) {
case DRV_DIFF_PRESS_DEVTYPE_SDP31:
/* fallthrough */
case DRV_DIFF_PRESS_DEVTYPE_SDP32:
/* fallthrough */
case DRV_DIFF_PRESS_DEVTYPE_SDP33:
/* fallthrough */
smodel = AIRSPEED_SENSOR_MODEL_SDP3X;
break;
default:
smodel = AIRSPEED_SENSOR_MODEL_MEMBRANE;
break;
}
/* don't risk to feed negative airspeed into the system */
airspeed.indicated_airspeed_m_s = calc_IAS_corrected((enum AIRSPEED_COMPENSATION_MODEL)
_parameters.air_cmodel,
smodel, _parameters.air_tube_length, _parameters.air_tube_diameter_mm,
diff_pres.differential_pressure_filtered_pa, air_data.baro_pressure_pa,
air_temperature_celsius);
airspeed.true_airspeed_m_s = calc_TAS_from_CAS(airspeed.indicated_airspeed_m_s, air_data.baro_pressure_pa,
air_temperature_celsius); // assume that CAS = IAS as we don't have an CAS-scale here
airspeed.air_temperature_celsius = air_temperature_celsius;
if (PX4_ISFINITE(airspeed.indicated_airspeed_m_s) && PX4_ISFINITE(airspeed.true_airspeed_m_s)) {
_airspeed_pub.publish(airspeed);
}
}
}
void
Sensors::parameter_update_poll(bool forced)
void Sensors::parameter_update_poll(bool forced)
{
// check for parameter updates
if (_parameter_update_sub.updated() || forced) {
@@ -394,85 +225,25 @@ Sensors::parameter_update_poll(bool forced)
_parameter_update_sub.copy(&pupdate);
// update parameters from storage
parameters_update();
updateParams();
/* update airspeed scale */
int fd = px4_open(AIRSPEED0_DEVICE_PATH, 0);
/* this sensor is optional, abort without error */
if (fd >= 0) {
struct airspeed_scale airscale = {
_parameters.diff_pres_offset_pa,
1.0f,
};
if (OK != px4_ioctl(fd, AIRSPEEDIOCSSCALE, (long unsigned int)&airscale)) {
warn("WARNING: failed to set scale / offsets for airspeed sensor");
}
px4_close(fd);
if (!_armed) {
_voted_sensors_update.parametersUpdate();
}
}
}
void Sensors::adc_poll()
void Sensors::InitializeAirspeed()
{
/* only read if not in HIL mode */
if (_hil_enabled) {
return;
}
if (_airspeed == nullptr) {
if (orb_exists(ORB_ID(sensor_differential_pressure), 0) == PX4_OK) {
_airspeed = new Airspeed();
#ifdef ADC_AIRSPEED_VOLTAGE_CHANNEL
if (_parameters.diff_pres_analog_scale > 0.0f) {
hrt_abstime t = hrt_absolute_time();
/* rate limit to 100 Hz */
if (t - _last_adc >= 10000) {
adc_report_s adc;
if (_adc_report_sub.update(&adc)) {
/* Read add channels we got */
for (unsigned i = 0; i < PX4_MAX_ADC_CHANNELS; i++) {
if (adc.channel_id[i] == -1) {
continue; // skip non-exist channels
}
if (ADC_AIRSPEED_VOLTAGE_CHANNEL == adc.channel_id[i]) {
/* calculate airspeed, raw is the difference from */
const float voltage = (float)(adc.raw_data[i]) * adc.v_ref / adc.resolution * ADC_DP_V_DIV;
/**
* The voltage divider pulls the signal down, only act on
* a valid voltage from a connected sensor. Also assume a non-
* zero offset from the sensor if its connected.
*
* Notice: This won't work on devices which have PGA controlled
* vref. Those devices require no divider at all.
*/
if (voltage > 0.4f) {
const float diff_pres_pa_raw = voltage * _parameters.diff_pres_analog_scale - _parameters.diff_pres_offset_pa;
_diff_pres.timestamp = t;
_diff_pres.differential_pressure_raw_pa = diff_pres_pa_raw;
_diff_pres.differential_pressure_filtered_pa = (_diff_pres.differential_pressure_filtered_pa * 0.9f) +
(diff_pres_pa_raw * 0.1f);
_diff_pres.temperature = -1000.0f;
_diff_pres_pub.publish(_diff_pres);
}
}
}
if (_airspeed) {
_airspeed->Start();
}
_last_adc = t;
}
}
#endif /* ADC_AIRSPEED_VOLTAGE_CHANNEL */
}
void Sensors::InitializeVehicleAirData()
@@ -572,6 +343,7 @@ void Sensors::Run()
// run once
if (_last_config_update == 0) {
InitializeAirspeed();
InitializeVehicleAirData();
InitializeVehicleIMU();
InitializeVehicleGPSPosition();
@@ -586,21 +358,23 @@ void Sensors::Run()
ScheduleDelayed(10_ms);
// check vehicle status for changes to publication state
if (_vcontrol_mode_sub.updated()) {
vehicle_control_mode_s vcontrol_mode{};
if (_vehicle_status_sub.updated()) {
vehicle_status_s vehicle_status;
if (_vcontrol_mode_sub.copy(&vcontrol_mode)) {
_armed = vcontrol_mode.flag_armed;
if (_vehicle_status_sub.copy(&vehicle_status)) {
const bool hil_prev = _hil_enabled;
_armed = (vehicle_status.arming_state == vehicle_status_s::ARMING_STATE_ARMED);
_hil_enabled = (vehicle_status.hil_state == vehicle_status_s::HIL_STATE_ON);
if (!hil_prev && _hil_enabled) {
_voted_sensors_update.set_hil_enabled();
}
}
}
_voted_sensors_update.sensorsPoll(_sensor_combined);
// check analog airspeed
adc_poll();
diff_pres_poll();
if (_sensor_combined.timestamp != _sensor_combined_prev_timestamp) {
_voted_sensors_update.setRelativeTimestamps(_sensor_combined);
@@ -612,6 +386,7 @@ void Sensors::Run()
// when not adding sensors poll for param updates
if (!_armed && hrt_elapsed_time(&_last_config_update) > 500_ms) {
_voted_sensors_update.initializeSensors();
InitializeAirspeed();
InitializeVehicleAirData();
InitializeVehicleIMU();
InitializeVehicleGPSPosition();
@@ -628,35 +403,7 @@ void Sensors::Run()
int Sensors::task_spawn(int argc, char *argv[])
{
bool hil_enabled = false;
bool error_flag = false;
int myoptind = 1;
int ch;
const char *myoptarg = nullptr;
while ((ch = px4_getopt(argc, argv, "h", &myoptind, &myoptarg)) != EOF) {
switch (ch) {
case 'h':
hil_enabled = true;
break;
case '?':
error_flag = true;
break;
default:
PX4_WARN("unrecognized flag");
error_flag = true;
break;
}
}
if (error_flag) {
return PX4_ERROR;
}
Sensors *instance = new Sensors(hil_enabled);
Sensors *instance = new Sensors();
if (instance) {
_object.store(instance);
@@ -691,9 +438,10 @@ int Sensors::print_status()
_vehicle_air_data->PrintStatus();
}
PX4_INFO_RAW("\n");
PX4_INFO("Airspeed status:");
_airspeed_validator.print();
if (_airspeed) {
PX4_INFO_RAW("\n");
_airspeed->PrintStatus();
}
PX4_INFO_RAW("\n");
_vehicle_acceleration.PrintStatus();
@@ -752,7 +500,6 @@ It runs in its own thread and polls on the currently selected gyro topic.
PRINT_MODULE_USAGE_NAME("sensors", "system");
PRINT_MODULE_USAGE_COMMAND("start");
PRINT_MODULE_USAGE_PARAM_FLAG('h', "Start in HIL mode", true);
PRINT_MODULE_USAGE_DEFAULT_COMMANDS();
return 0;
+3 -10
View File
@@ -46,18 +46,11 @@
using namespace sensors;
using namespace matrix;
using namespace time_literals;
VotedSensorsUpdate::VotedSensorsUpdate(bool hil_enabled,
uORB::SubscriptionCallbackWorkItem(&vehicle_imu_sub)[MAX_SENSOR_COUNT]) :
VotedSensorsUpdate::VotedSensorsUpdate(uORB::SubscriptionCallbackWorkItem(&vehicle_imu_sub)[MAX_SENSOR_COUNT]) :
ModuleParams(nullptr),
_vehicle_imu_sub(vehicle_imu_sub),
_hil_enabled(hil_enabled)
_vehicle_imu_sub(vehicle_imu_sub)
{
if (_hil_enabled) { // HIL has less accurate timing so increase the timeouts a bit
_gyro.voter.set_timeout(500000);
_accel.voter.set_timeout(500000);
}
}
int VotedSensorsUpdate::init(sensor_combined_s &raw)
@@ -259,7 +252,7 @@ void VotedSensorsUpdate::imuPoll(struct sensor_combined_s &raw)
bool VotedSensorsUpdate::checkFailover(SensorData &sensor, const char *sensor_name)
{
if (sensor.last_failover_count != sensor.voter.failover_count() && !_hil_enabled) {
if (sensor.last_failover_count != sensor.voter.failover_count()) {
uint32_t flags = sensor.voter.failover_state();
int failover_index = sensor.voter.failover_index();
+10 -3
View File
@@ -58,6 +58,8 @@
#include <uORB/topics/vehicle_imu.h>
#include <uORB/topics/vehicle_imu_status.h>
using namespace time_literals;
namespace sensors
{
@@ -75,7 +77,7 @@ public:
* @param parameters parameter values. These do not have to be initialized when constructing this object.
* Only when calling init(), they have to be initialized.
*/
VotedSensorsUpdate(bool hil_enabled, uORB::SubscriptionCallbackWorkItem(&vehicle_imu_sub)[MAX_SENSOR_COUNT]);
VotedSensorsUpdate(uORB::SubscriptionCallbackWorkItem(&vehicle_imu_sub)[MAX_SENSOR_COUNT]);
/**
* initialize subscriptions etc.
@@ -107,6 +109,13 @@ public:
*/
void setRelativeTimestamps(sensor_combined_s &raw);
void set_hil_enabled()
{
// HIL has less accurate timing so increase the timeouts a bit
_gyro.voter.set_timeout(1_s);
_accel.voter.set_timeout(1_s);
}
private:
static constexpr uint8_t DEFAULT_PRIORITY = 50;
@@ -167,8 +176,6 @@ private:
sensor_combined_s _last_sensor_data[MAX_SENSOR_COUNT] {}; /**< latest sensor data from all sensors instances */
const bool _hil_enabled{false}; /**< is hardware-in-the-loop mode enabled? */
bool _selection_changed{true}; /**< true when a sensor selection has changed and not been published */
matrix::Vector3f _accel_diff[MAX_SENSOR_COUNT] {}; /**< filtered accel differences between IMU units (m/s/s) */
+2 -2
View File
@@ -58,7 +58,7 @@
#include <uORB/Subscription.hpp>
#include <uORB/SubscriptionInterval.hpp>
#include <uORB/topics/actuator_outputs.h>
#include <uORB/topics/differential_pressure.h>
#include <uORB/topics/sensor_differential_pressure.h>
#include <uORB/topics/distance_sensor.h>
#include <uORB/topics/irlock_report.h>
#include <uORB/topics/manual_control_setpoint.h>
@@ -189,7 +189,7 @@ private:
perf_counter_t _perf_sim_interval{perf_alloc(PC_INTERVAL, MODULE_NAME": network interval")};
// uORB publisher handlers
uORB::Publication<differential_pressure_s> _differential_pressure_pub{ORB_ID(differential_pressure)};
uORB::Publication<sensor_differential_pressure_s> _differential_pressure_pub{ORB_ID(sensor_differential_pressure)};
uORB::PublicationMulti<optical_flow_s> _flow_pub{ORB_ID(optical_flow)};
uORB::Publication<irlock_report_s> _irlock_report_pub{ORB_ID(irlock_report)};
uORB::Publication<vehicle_odometry_s> _visual_odometry_pub{ORB_ID(vehicle_visual_odometry)};
+4 -5
View File
@@ -265,12 +265,11 @@ void Simulator::update_sensors(const hrt_abstime &time, const mavlink_hil_sensor
// differential pressure
if ((sensors.fields_updated & SensorSource::DIFF_PRESS) == SensorSource::DIFF_PRESS && !_airspeed_blocked) {
differential_pressure_s report{};
report.timestamp = time;
sensor_differential_pressure_s report{};
report.timestamp_sample = time;
report.temperature = _sensors_temperature;
report.differential_pressure_filtered_pa = sensors.diff_pressure * 100.0f; // convert from millibar to bar;
report.differential_pressure_raw_pa = sensors.diff_pressure * 100.0f; // convert from millibar to bar;
report.differential_pressure_pa = sensors.diff_pressure * 100.0f; // convert from millibar to bar;
report.timestamp = hrt_absolute_time();
_differential_pressure_pub.publish(report);
}
}