mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-05-28 14:10:06 +08:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 592b2e9dbe | |||
| eed060f17b | |||
| beb51a219f | |||
| b79eec5e84 | |||
| 2af6333351 | |||
| e658ec42b8 | |||
| dfb342bdac |
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
@@ -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
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
)
|
||||
+12
-34
@@ -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;
|
||||
}
|
||||
+38
-36
@@ -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
|
||||
)
|
||||
|
||||
+71
-143
@@ -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")};
|
||||
|
||||
};
|
||||
|
||||
+3
-8
@@ -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")};
|
||||
};
|
||||
|
||||
+3
-8
@@ -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};
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -32,7 +32,6 @@
|
||||
############################################################################
|
||||
|
||||
add_subdirectory(accelerometer)
|
||||
add_subdirectory(airspeed)
|
||||
add_subdirectory(barometer)
|
||||
add_subdirectory(device)
|
||||
add_subdirectory(gyroscope)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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)};
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(¶m_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
|
||||
@@ -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
|
||||
+10
-3
@@ -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
|
||||
)
|
||||
@@ -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,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
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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) */
|
||||
|
||||
@@ -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)};
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user