PX4 Firmware
PX4 Autopilot Software http://px4.io
baro.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2017 PX4 Development Team. All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  *
9  * 1. Redistributions of source code must retain the above copyright
10  * notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  * notice, this list of conditions and the following disclaimer in
13  * the documentation and/or other materials provided with the
14  * distribution.
15  * 3. Neither the name PX4 nor the names of its contributors may be
16  * used to endorse or promote products derived from this software
17  * without specific prior written permission.
18  *
19  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
25  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
26  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
27  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
29  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30  * POSSIBILITY OF SUCH DAMAGE.
31  *
32  ****************************************************************************/
33 
34 /**
35  * @file baro.cpp
36  * Implementation of the Baro Temperature Calibration for onboard sensors.
37  *
38  * @author Siddharth Bharat Purohit
39  * @author Paul Riseborough
40  * @author Beat Küng <beat-kueng@gmx.net>
41  */
42 
43 #include "baro.h"
45 #include <mathlib/mathlib.h>
46 #include <drivers/drv_hrt.h>
47 
48 TemperatureCalibrationBaro::TemperatureCalibrationBaro(float min_temperature_rise, float min_start_temperature,
49  float max_start_temperature)
50  : TemperatureCalibrationCommon(min_temperature_rise, min_start_temperature, max_start_temperature)
51 {
52 
53  //init subscriptions
55 
58  }
59 
60  for (unsigned i = 0; i < _num_sensor_instances; i++) {
61  _sensor_subs[i] = orb_subscribe_multi(ORB_ID(sensor_baro), i);
62  }
63 }
64 
66 {
67  for (unsigned i = 0; i < _num_sensor_instances; i++) {
69  }
70 }
71 
73 {
74  //nothing to do
75 }
76 
77 int TemperatureCalibrationBaro::update_sensor_instance(PerSensorData &data, int sensor_sub)
78 {
79  bool finished = data.hot_soaked;
80 
81  bool updated;
82  orb_check(sensor_sub, &updated);
83 
84  if (!updated) {
85  return finished ? 0 : 1;
86  }
87 
88  sensor_baro_s baro_data;
89  orb_copy(ORB_ID(sensor_baro), sensor_sub, &baro_data);
90 
91  if (finished) {
92  // if we're done, return, but we need to return after orb_copy because of poll()
93  return 0;
94  }
95 
96  data.device_id = baro_data.device_id;
97 
98  data.sensor_sample_filt[0] = 100.0f * baro_data.pressure; // convert from hPA to Pa
99  data.sensor_sample_filt[1] = baro_data.temperature;
100 
101 
102  // wait for min start temp to be reached before starting calibration
103  if (data.sensor_sample_filt[1] < _min_start_temperature) {
104  return 1;
105  }
106 
107  if (!data.cold_soaked) {
108  // allow time for sensors and filters to settle
109  if (hrt_absolute_time() > 10E6) {
110  // If intial temperature exceeds maximum declare an error condition and exit
111  if (data.sensor_sample_filt[1] > _max_start_temperature) {
113 
114  } else {
115  data.cold_soaked = true;
116  data.low_temp = data.sensor_sample_filt[1]; // Record the low temperature
117  data.high_temp = data.low_temp; // Initialise the high temperature to the initial temperature
118  data.ref_temp = data.sensor_sample_filt[1] + 0.5f * _min_temperature_rise;
119  return 1;
120  }
121 
122  } else {
123  return 1;
124  }
125  }
126 
127  // check if temperature increased
128  if (data.sensor_sample_filt[1] > data.high_temp) {
129  data.high_temp = data.sensor_sample_filt[1];
130  data.hot_soak_sat = 0;
131 
132  } else {
133  return 1;
134  }
135 
136  //TODO: Detect when temperature has stopped rising for more than TBD seconds
137  if (data.hot_soak_sat == 10 || (data.high_temp - data.low_temp) > _min_temperature_rise) {
138  data.hot_soaked = true;
139  }
140 
141  if (sensor_sub == _sensor_subs[0]) { // debug output, but only for the first sensor
142  TC_DEBUG("\nBaro: %.20f,%.20f,%.20f,%.20f, %.6f, %.6f, %.6f\n\n", (double)data.sensor_sample_filt[0],
143  (double)data.sensor_sample_filt[1], (double)data.low_temp, (double)data.high_temp,
144  (double)(data.high_temp - data.low_temp));
145  }
146 
147  //update linear fit matrices
148  double relative_temperature = (double)data.sensor_sample_filt[1] - (double)data.ref_temp;
149  data.P[0].update(relative_temperature, (double)data.sensor_sample_filt[0]);
150 
151  return 1;
152 }
153 
155 {
156  for (unsigned uorb_index = 0; uorb_index < _num_sensor_instances; uorb_index++) {
157  finish_sensor_instance(_data[uorb_index], uorb_index);
158  }
159 
160  int32_t enabled = 1;
161  int result = param_set_no_notification(param_find("TC_B_ENABLE"), &enabled);
162 
163  if (result != PX4_OK) {
164  PX4_ERR("unable to reset TC_B_ENABLE (%i)", result);
165  }
166 
167  return result;
168 }
169 
170 int TemperatureCalibrationBaro::finish_sensor_instance(PerSensorData &data, int sensor_index)
171 {
172  if (!data.hot_soaked || data.tempcal_complete) {
173  return 0;
174  }
175 
176  double res[POLYFIT_ORDER + 1] = {};
177  data.P[0].fit(res);
178  res[POLYFIT_ORDER] =
179  0.0; // normalise the correction to be zero at the reference temperature by setting the X^0 coefficient to zero
180  PX4_INFO("Result baro %u %.20f %.20f %.20f %.20f %.20f %.20f", sensor_index, (double)res[0],
181  (double)res[1], (double)res[2], (double)res[3], (double)res[4], (double)res[5]);
182  data.tempcal_complete = true;
183 
184  char str[30];
185  float param = 0.0f;
186  int result = PX4_OK;
187 
188  set_parameter("TC_B%d_ID", sensor_index, &data.device_id);
189 
190  for (unsigned coef_index = 0; coef_index <= POLYFIT_ORDER; coef_index++) {
191  sprintf(str, "TC_B%d_X%d", sensor_index, (POLYFIT_ORDER - coef_index));
192  param = (float)res[coef_index];
193  result = param_set_no_notification(param_find(str), &param);
194 
195  if (result != PX4_OK) {
196  PX4_ERR("unable to reset %s", str);
197  }
198  }
199 
200  set_parameter("TC_B%d_TMAX", sensor_index, &data.high_temp);
201  set_parameter("TC_B%d_TMIN", sensor_index, &data.low_temp);
202  set_parameter("TC_B%d_TREF", sensor_index, &data.ref_temp);
203  return 0;
204 }
virtual ~TemperatureCalibrationBaro()
Definition: baro.cpp:65
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
Definition: uORB.cpp:90
TemperatureCalibrationBaro(float min_temperature_rise, float min_start_temperature, float max_start_temperature)
Definition: baro.cpp:48
#define POLYFIT_ORDER
Definition: baro.h:39
__EXPORT int param_set_no_notification(param_t param, const void *val)
Set the value of a parameter, but do not notify the system about the change.
Definition: parameters.cpp:820
float _min_temperature_rise
minimum difference in temperature before the process finishes
Definition: common.h:95
#define TC_ERROR_INITIAL_TEMP_TOO_HIGH
starting temperature was above the configured allowed temperature
Definition: common.h:52
class TemperatureCalibrationCommon Common base class for all sensor types, contains shared code & dat...
Definition: common.h:120
uint32_t device_id
Definition: sensor_baro.h:55
High-resolution timer with callouts and timekeeping.
int set_parameter(const char *format_str, unsigned index, const void *value)
set a system parameter (without system notification) and print an error if it fails ...
Definition: common.h:102
float temperature
Definition: sensor_baro.h:57
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
float pressure
Definition: sensor_baro.h:56
virtual int update_sensor_instance(PerSensorData &data, int sensor_sub)
update a single sensor instance
Definition: baro.cpp:77
uint8_t * data
Definition: dataman.cpp:149
int orb_unsubscribe(int handle)
Definition: uORB.cpp:85
int finish_sensor_instance(PerSensorData &data, int sensor_index)
Definition: baro.cpp:170
int orb_group_count(const struct orb_metadata *meta)
Get the number of published instances of a topic group.
Definition: uORB.cpp:110
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
#define SENSOR_COUNT_MAX
Definition: common.h:49
int orb_check(int handle, bool *updated)
Definition: uORB.cpp:95
int orb_subscribe_multi(const struct orb_metadata *meta, unsigned instance)
Definition: uORB.cpp:80
float _max_start_temperature
maximum temperature above which the process does not start and an error is declared ...
Definition: common.h:97
float _min_start_temperature
minimum temperature before the process starts
Definition: common.h:96
#define TC_DEBUG(fmt,...)
Definition: common.h:40
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
PerSensorData _data[SENSOR_COUNT_MAX]
Definition: common.h:185