Skip to content

Commit 01b61c4

Browse files
authored
Merge branch 'master' into ducle/patch-airspeed-calibration
2 parents dbdef16 + bac78b5 commit 01b61c4

File tree

8 files changed

+333
-1
lines changed

8 files changed

+333
-1
lines changed

Tools/scripts/build_options.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,7 @@ def config_option(self):
407407
Feature('Airspeed Drivers', 'NMEA_AIRSPEED', 'AP_AIRSPEED_NMEA_ENABLED', 'Enable NMEA AIRSPEED', 0, 'AIRSPEED'),
408408
Feature('Airspeed Drivers', 'SDP3X', 'AP_AIRSPEED_SDP3X_ENABLED', 'Enable SDP3X AIRSPEED', 0, 'AIRSPEED'),
409409
Feature('Airspeed Drivers', 'DRONECAN_ASPD', 'AP_AIRSPEED_DRONECAN_ENABLED', 'Enable DroneCAN AIRSPEED', 0, 'AIRSPEED,DroneCAN'), # NOQA: E501
410+
Feature('Airspeed Drivers', 'AUAV_AIRSPEED', 'AP_AIRSPEED_AUAV_ENABLED', 'ENABLE AUAV AIRSPEED', 0, 'AIRSPEED'),
410411

411412
Feature('Actuators', 'ServoTelem', 'AP_SERVO_TELEM_ENABLED', 'Enable servo telemetry library', 0, None),
412413
Feature('Actuators', 'Volz', 'AP_VOLZ_ENABLED', 'Enable Volz Protocol', 0, None),

libraries/AP_Airspeed/AP_Airspeed.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
#include "AP_Airspeed_DroneCAN.h"
5353
#include "AP_Airspeed_NMEA.h"
5454
#include "AP_Airspeed_MSP.h"
55+
#include "AP_Airspeed_AUAV.h"
5556
#include "AP_Airspeed_External.h"
5657
#include "AP_Airspeed_SITL.h"
5758
extern const AP_HAL::HAL &hal;
@@ -439,6 +440,21 @@ void AP_Airspeed::allocate()
439440
case TYPE_EXTERNAL:
440441
#if AP_AIRSPEED_EXTERNAL_ENABLED
441442
sensor[i] = NEW_NOTHROW AP_Airspeed_External(*this, i);
443+
#endif
444+
break;
445+
case TYPE_AUAV_5IN:
446+
#if AP_AIRSPEED_AUAV_ENABLED
447+
sensor[i] = NEW_NOTHROW AP_Airspeed_AUAV(*this, i, 5);
448+
#endif
449+
break;
450+
case TYPE_AUAV_10IN:
451+
#if AP_AIRSPEED_AUAV_ENABLED
452+
sensor[i] = NEW_NOTHROW AP_Airspeed_AUAV(*this, i, 10);
453+
#endif
454+
break;
455+
case TYPE_AUAV_30IN:
456+
#if AP_AIRSPEED_AUAV_ENABLED
457+
sensor[i] = NEW_NOTHROW AP_Airspeed_AUAV(*this, i, 30);
442458
#endif
443459
break;
444460
}

libraries/AP_Airspeed/AP_Airspeed.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -192,6 +192,9 @@ class AP_Airspeed
192192
TYPE_MSP=14,
193193
TYPE_I2C_ASP5033=15,
194194
TYPE_EXTERNAL=16,
195+
TYPE_AUAV_10IN=17,
196+
TYPE_AUAV_5IN=18,
197+
TYPE_AUAV_30IN=19,
195198
TYPE_SITL=100,
196199
};
197200

Lines changed: 234 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,234 @@
1+
/*
2+
This program is free software: you can redistribute it and/or modify
3+
it under the terms of the GNU General Public License as published by
4+
the Free Software Foundation, either version 3 of the License, or
5+
(at your option) any later version.
6+
7+
This program is distributed in the hope that it will be useful,
8+
but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
GNU General Public License for more details.
11+
12+
You should have received a copy of the GNU General Public License
13+
along with this program. If not, see <http://www.gnu.org/licenses/>.
14+
*/
15+
16+
/*
17+
backend driver for airspeed from a I2C AUAV sensor
18+
*/
19+
#include "AP_Airspeed_AUAV.h"
20+
21+
#if AP_AIRSPEED_AUAV_ENABLED
22+
23+
#define AUAV_AIRSPEED_I2C_ADDR 0x26
24+
25+
// the sensor supports a 2nd channel (2nd I2C address) for absolute pressure
26+
// we could use this as a baro driver but don't yet
27+
#define AUAV_AIRSPEED_I2C_ADDR_ABSOLUTE 0x27
28+
29+
// max measurement time for 8x averaging differential is 16.2ms
30+
#define MEASUREMENT_TIME_MAX_MS 17
31+
32+
#define MEASUREMENT_TIMEOUT_MS 200
33+
34+
#include <AP_Common/AP_Common.h>
35+
#include <AP_HAL/AP_HAL.h>
36+
#include <AP_HAL/I2CDevice.h>
37+
#include <AP_Math/AP_Math.h>
38+
#include <GCS_MAVLink/GCS.h>
39+
40+
extern const AP_HAL::HAL &hal;
41+
42+
43+
AP_Airspeed_AUAV::AP_Airspeed_AUAV(AP_Airspeed &_frontend, uint8_t _instance, const float _range_inH2O) :
44+
AP_Airspeed_Backend(_frontend, _instance),
45+
range_inH2O(_range_inH2O)
46+
{
47+
}
48+
49+
// probe for a sensor
50+
bool AP_Airspeed_AUAV::probe(uint8_t bus, uint8_t address)
51+
{
52+
_dev = hal.i2c_mgr->get_device(bus, address);
53+
if (!_dev) {
54+
return false;
55+
}
56+
57+
WITH_SEMAPHORE(_dev->get_semaphore());
58+
59+
_dev->set_retries(10);
60+
_measure();
61+
hal.scheduler->delay(20);
62+
_collect();
63+
64+
return last_sample_time_ms != 0;
65+
66+
}
67+
68+
// probe and initialise the sensor
69+
bool AP_Airspeed_AUAV::init()
70+
{
71+
const auto bus = get_bus();
72+
if (!probe(bus, AUAV_AIRSPEED_I2C_ADDR)) {
73+
GCS_SEND_TEXT(MAV_SEVERITY_ERROR, "AUAV AIRSPEED[%u]: no sensor found on bus %u", get_instance(), bus);
74+
return false;
75+
}
76+
77+
_dev->set_device_type(uint8_t(DevType::AUAV));
78+
set_bus_id(_dev->get_bus_id());
79+
80+
GCS_SEND_TEXT(MAV_SEVERITY_INFO, "AUAV AIRSPEED[%u]: Found bus %u addr 0x%02x", get_instance(), _dev->bus_num(), _dev->get_bus_address());
81+
82+
WITH_SEMAPHORE(_dev->get_semaphore());
83+
84+
// drop to 2 retries for runtime
85+
_read_coefficients();
86+
_dev->set_retries(2);
87+
_dev->register_periodic_callback(20000,
88+
FUNCTOR_BIND_MEMBER(&AP_Airspeed_AUAV::_timer, void));
89+
return true;
90+
}
91+
92+
// start a measurement
93+
void AP_Airspeed_AUAV::_measure()
94+
{
95+
measurement_started_ms = 0;
96+
uint8_t cmd = 0xAE; // start average8, max 16.2ms measurement time
97+
if (_dev->transfer(&cmd, 1, nullptr, 0)) {
98+
measurement_started_ms = AP_HAL::millis();
99+
}
100+
}
101+
102+
// read the values from the sensor
103+
void AP_Airspeed_AUAV::_collect()
104+
{
105+
measurement_started_ms = 0; // It should always get reset by _measure. This is a safety to handle failures of i2c bus
106+
uint8_t inbuf[7];
107+
if (!_dev->read((uint8_t *)&inbuf, sizeof(inbuf))) {
108+
return;
109+
}
110+
const uint8_t status = inbuf[0];
111+
const uint8_t healthy_status = 0x50; // power on, not busy, differential normal, not out of range
112+
if (status != healthy_status) {
113+
// not ready or error
114+
return;
115+
}
116+
const int32_t Tref_Counts = 7576807; // temperature counts at 25C
117+
const float TC50Scale = 100.0f * 100.0f * 167772.2f; // scale TC50 to 1.0% FS0
118+
float Pdiff, TC50;
119+
120+
// Convert unsigned 24-bit pressure value to signed +/- 23-bit:
121+
const int32_t iPraw = (inbuf[1]<<16) + (inbuf[2]<<8) + inbuf[3] - 0x800000;
122+
123+
// Convert signed 23-bit valu11e to float, normalized to +/- 1.0:
124+
const float Pnorm = float(iPraw) / float(0x7FFFFF);
125+
const float AP3 = DLIN_A * Pnorm * Pnorm * Pnorm; // A*Pout^3
126+
const float BP2 = DLIN_B * Pnorm * Pnorm; // B*Pout^2
127+
const float CP = DLIN_C * Pnorm; // C*POut
128+
const float Corr = AP3 + BP2 + CP + DLIN_D; // Linearity correction term
129+
const float Pcorr = Pnorm + Corr; // Corrected P, range +/-1.0.
130+
131+
// Compute difference from reference temperature, in sensor counts:
132+
const int32_t iTemp = (inbuf[4]<<16) + (inbuf[5]<<8) + inbuf[6]; // 24-bit temperature
133+
134+
// get temperature in degrees C
135+
temp_C = (iTemp * 155) / float(1U<<24) - 45;
136+
137+
const int32_t Tdiff = iTemp - Tref_Counts; // see constant defined above.
138+
const float Pnfso = (Pcorr + 1.0f) * 0.5;
139+
140+
//TC50: Select High/Low, based on current temp above/below 25C:
141+
if (Tdiff > 0) {
142+
TC50 = D_TC50H;
143+
} else {
144+
TC50 = D_TC50L;
145+
}
146+
147+
// Find absolute difference between midrange and reading (abs(Pnfso-0.5)):
148+
if (Pnfso > 0.5) {
149+
Pdiff = Pnfso - 0.5;
150+
} else {
151+
Pdiff = 0.5f - Pnfso;
152+
}
153+
154+
const float Tcorr = (1.0f - (D_Es * 2.5f * Pdiff)) * Tdiff * TC50 / TC50Scale;
155+
const float PCorrt = Pnfso - Tcorr; // corrected P: float, [0 to +1.0)
156+
const uint32_t PComp = (uint32_t) (PCorrt * (float)0xFFFFFF);
157+
pressure_digital = PComp;
158+
159+
last_sample_time_ms = AP_HAL::millis();
160+
}
161+
162+
uint32_t AP_Airspeed_AUAV::_read_register(uint8_t cmd)
163+
{
164+
uint8_t raw_bytes1[3];
165+
if (!_dev->transfer(&cmd,1,(uint8_t *)&raw_bytes1, sizeof(raw_bytes1))) {
166+
return 0;
167+
}
168+
uint8_t raw_bytes2[3];
169+
uint8_t cmd2 = cmd + 1;
170+
if (!_dev->transfer(&cmd2,1,(uint8_t *)&raw_bytes2, sizeof(raw_bytes2))) {
171+
return 0;
172+
}
173+
uint32_t result = ((uint32_t)raw_bytes1[1] << 24) | ((uint32_t)raw_bytes1[2] << 16) | ((uint32_t)raw_bytes2[1] << 8) | (uint32_t)raw_bytes2[2];
174+
return result;
175+
}
176+
177+
bool AP_Airspeed_AUAV::_read_coefficients()
178+
{
179+
// Differential Coefficients
180+
int32_t i32A = 0, i32B =0, i32C =0, i32D=0, i32TC50HLE=0;
181+
int8_t i8TC50H = 0, i8TC50L = 0, i8Es = 0;
182+
i32A = _read_register(0x2B);
183+
DLIN_A = ((float)(i32A))/((float)(0x7FFFFFFF));
184+
185+
i32B = _read_register(0x2D);
186+
DLIN_B = (float)(i32B)/(float)(0x7FFFFFFF);
187+
188+
i32C = _read_register(0x2F);
189+
DLIN_C = (float)(i32C)/(float)(0x7FFFFFFF);
190+
191+
i32D = _read_register(0x31);
192+
DLIN_D = (float)(i32D)/(float)(0x7FFFFFFF);
193+
194+
i32TC50HLE = _read_register(0x33);
195+
i8TC50H = (i32TC50HLE >> 24) & 0xFF; // 55 H
196+
i8TC50L = (i32TC50HLE >> 16) & 0xFF; // 55 L
197+
i8Es = (i32TC50HLE ) & 0xFF; // 56 L
198+
D_Es = (float)(i8Es)/(float)(0x7F);
199+
D_TC50H = (float)(i8TC50H)/(float)(0x7F);
200+
D_TC50L = (float)(i8TC50L)/(float)(0x7F);
201+
202+
return true; //Need to actually check
203+
}
204+
205+
// 50Hz timer
206+
void AP_Airspeed_AUAV::_timer()
207+
{
208+
if (measurement_started_ms == 0) {
209+
_measure();
210+
}
211+
if ((AP_HAL::millis() - measurement_started_ms) > MEASUREMENT_TIME_MAX_MS) {
212+
_collect();
213+
// start a new measurement
214+
_measure();
215+
}
216+
}
217+
218+
// return the current differential_pressure in Pascal
219+
bool AP_Airspeed_AUAV::get_differential_pressure(float &_pressure)
220+
{
221+
WITH_SEMAPHORE(sem);
222+
_pressure = 248.8f*1.25f*((pressure_digital-8388608)/16777216.0f) * 2 * range_inH2O;
223+
return AP_HAL::millis() - last_sample_time_ms < MEASUREMENT_TIMEOUT_MS;
224+
}
225+
226+
// return the current temperature in degrees C, if available
227+
bool AP_Airspeed_AUAV::get_temperature(float &_temperature)
228+
{
229+
WITH_SEMAPHORE(sem);
230+
_temperature = temp_C;
231+
return AP_HAL::millis() - last_sample_time_ms < MEASUREMENT_TIMEOUT_MS;
232+
}
233+
234+
#endif // AP_AIRSPEED_AUAV_ENABLED
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
/*
2+
This program is free software: you can redistribute it and/or modify
3+
it under the terms of the GNU General Public License as published by
4+
the Free Software Foundation, either version 3 of the License, or
5+
(at your option) any later version.
6+
7+
This program is distributed in the hope that it will be useful,
8+
but WITHOUT ANY WARRANTY; without even the implied warranty of
9+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10+
GNU General Public License for more details.
11+
12+
You should have received a copy of the GNU General Public License
13+
along with this program. If not, see <http://www.gnu.org/licenses/>.
14+
*/
15+
#pragma once
16+
17+
#include "AP_Airspeed_config.h"
18+
19+
#if AP_AIRSPEED_AUAV_ENABLED
20+
21+
/*
22+
backend driver for airspeed from I2C
23+
*/
24+
25+
#include <AP_HAL/AP_HAL.h>
26+
#include <AP_HAL/utility/OwnPtr.h>
27+
#include <AP_HAL/I2CDevice.h>
28+
#include <utility>
29+
30+
#include "AP_Airspeed_Backend.h"
31+
32+
class AP_Airspeed_AUAV : public AP_Airspeed_Backend
33+
{
34+
public:
35+
AP_Airspeed_AUAV(AP_Airspeed &frontend, uint8_t _instance, const float _range_inH2O);
36+
~AP_Airspeed_AUAV(void) {}
37+
38+
// probe and initialise the sensor
39+
bool init() override;
40+
41+
// return the current differential_pressure in Pascal
42+
bool get_differential_pressure(float &pressure) override;
43+
44+
// return the current temperature in degrees C, if available
45+
bool get_temperature(float &temperature) override;
46+
47+
private:
48+
bool probe(uint8_t bus, uint8_t address);
49+
void _measure();
50+
void _collect();
51+
void _timer();
52+
bool _read_coefficients();
53+
uint32_t _read_register(uint8_t cmd);
54+
55+
uint32_t last_sample_time_ms;
56+
uint32_t measurement_started_ms;
57+
AP_HAL::OwnPtr<AP_HAL::I2CDevice> _dev;
58+
59+
float DLIN_A;
60+
float DLIN_B;
61+
float DLIN_C;
62+
float DLIN_D;
63+
float D_Es;
64+
float D_TC50H;
65+
float D_TC50L; // Diff coeffs
66+
67+
float pressure_digital;
68+
float pressure_abs_L;
69+
float temp_C;
70+
const float range_inH2O;
71+
};
72+
73+
#endif // AP_Airspeed_AUAV_ENABLED

libraries/AP_Airspeed/AP_Airspeed_Backend.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ class AP_Airspeed_Backend {
127127
ANALOG = 0x08,
128128
NMEA = 0x09,
129129
ASP5033 = 0x0A,
130+
AUAV = 0x0B,
130131
};
131132

132133
private:

libraries/AP_Airspeed/AP_Airspeed_Params.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ const AP_Param::GroupInfo AP_Airspeed_Params::var_info[] = {
4646
// @Param: TYPE
4747
// @DisplayName: Airspeed type
4848
// @Description: Type of airspeed sensor
49-
// @Values: 0:None,1:I2C-MS4525D0,2:Analog,3:I2C-MS5525,4:I2C-MS5525 (0x76),5:I2C-MS5525 (0x77),6:I2C-SDP3X,7:I2C-DLVR-5in,8:DroneCAN,9:I2C-DLVR-10in,10:I2C-DLVR-20in,11:I2C-DLVR-30in,12:I2C-DLVR-60in,13:NMEA water speed,14:MSP,15:ASP5033,16:ExternalAHRS,100:SITL
49+
// @Values: 0:None,1:I2C-MS4525D0,2:Analog,3:I2C-MS5525,4:I2C-MS5525 (0x76),5:I2C-MS5525 (0x77),6:I2C-SDP3X,7:I2C-DLVR-5in,8:DroneCAN,9:I2C-DLVR-10in,10:I2C-DLVR-20in,11:I2C-DLVR-30in,12:I2C-DLVR-60in,13:NMEA water speed,14:MSP,15:ASP5033,16:ExternalAHRS,17:AUAV-10in,18:AUAV-5in,19:AUAV-30in,100:SITL
5050
// @User: Standard
5151
AP_GROUPINFO_FLAGS("TYPE", 1, AP_Airspeed_Params, type, 0, AP_PARAM_FLAG_ENABLE),
5252

libraries/AP_Airspeed/AP_Airspeed_config.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@
5555
#define AP_AIRSPEED_SITL_ENABLED AP_AIRSPEED_BACKEND_DEFAULT_ENABLED && AP_SIM_ENABLED
5656
#endif
5757

58+
#ifndef AP_AIRSPEED_AUAV_ENABLED
59+
#define AP_AIRSPEED_AUAV_ENABLED AP_AIRSPEED_BACKEND_DEFAULT_ENABLED
60+
#endif
61+
5862
// other AP_Airspeed options:
5963
#ifndef AIRSPEED_MAX_SENSORS
6064
#define AIRSPEED_MAX_SENSORS 2

0 commit comments

Comments
 (0)