Paparazzi UAS  v5.8.2_stable-0-g6260b7c
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
meteo_stick.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Gautier Hattenberger
3  *
4  * This file is part of paparazzi
5 
6  * paparazzi is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2, or (at your option)
9  * any later version.
10  *
11  * paparazzi is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with paparazzi; see the file COPYING. If not, see
18  * <http://www.gnu.org/licenses/>.
19  *
20  */
21 
23 
24 #include "subsystems/abi.h"
25 #include "peripherals/ads1220.h"
26 #include "mcu_periph/pwm_input.h"
27 #include "generated/airframe.h"
28 
32 #ifndef MS_PRESSURE_OFFSET
33 #define MS_PRESSURE_OFFSET 0.0f
34 #endif
35 #ifndef MS_PRESSURE_SCALE
36 #define MS_PRESSURE_SCALE 1.0f
37 #endif
38 #ifndef MS_TEMPERATURE_OFFSET
39 #define MS_TEMPERATURE_OFFSET 0.0f
40 #endif
41 #ifndef MS_TEMPERATURE_SCALE
42 #define MS_TEMPERATURE_SCALE 1.0f
43 #endif
44 #ifndef MS_HUMIDTY_OFFSET
45 #define MS_HUMIDTY_OFFSET 0.0f
46 #endif
47 #ifndef MS_HUMIDTY_SCALE
48 #define MS_HUMIDTY_SCALE 1.0f
49 #endif
50 #ifndef MS_DIFF_PRESSURE_OFFSET
51 #define MS_DIFF_PRESSURE_OFFSET 0.0f
52 #endif
53 #ifndef MS_DIFF_PRESSURE_SCALE
54 #define MS_DIFF_PRESSURE_SCALE 1.0f
55 #endif
56 
57 // Test if pressure sensor is configured and/or should send ABI message
58 #ifdef MS_PRESSURE_SLAVE_IDX
59 #ifndef USE_MS_PRESSURE
60 #define USE_MS_PRESSURE TRUE
61 #endif
62 #endif
63 
64 // Test if diff pressure sensor is configured and/or should send ABI message
65 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
66 #ifndef USE_MS_DIFF_PRESSURE
67 #define USE_MS_DIFF_PRESSURE TRUE
68 #endif
69 #endif
70 
71 // Test if temperature sensor is configured and/or should send ABI message
72 #ifdef MS_TEMPERATURE_SLAVE_IDX
73 #ifndef USE_MS_TEMPERATURE
74 #define USE_MS_TEMPERATURE TRUE
75 #endif
76 #endif
77 
78 // Test if EEPROM slave index is configured
79 // if not, don't use EEPROM
80 #ifndef MS_EEPROM_SLAVE_IDX
81 #undef USE_MS_EEPROM
82 #endif
83 
86 
87 
91 static const float maxAdc = 8388608.0f; // 2 ** 23
92 
93 static inline float get_pressure(uint32_t raw)
94 {
95  const float uncal_abs = ((raw / maxAdc) + 0.095f) / 0.0009f;
96 
97 #if USE_MS_EEPROM
99 #else
100  return (MS_PRESSURE_SCALE * uncal_abs) + MS_PRESSURE_OFFSET;
101 #endif
102 }
103 
104 static inline float get_temp(uint32_t raw)
105 {
106  const float coeff_A = 3.9083e-3f;
107  const float coeff_B = -5.775e-7f;
108  const float R0 = 1000.0f;
109  const float gain_factor = Ads1220GainTable[ADS1220_GAIN_4];
110  const float pga_factor = 1.0f;
111  const float Rref = 6.8e3f;
112  const float Rt = (raw * Rref) / (gain_factor * pga_factor * maxAdc);
113  const float uncal_temp = ((-R0 * coeff_A) + (sqrtf(powf((R0 * coeff_A), 2.0f) +
114  (4.0f * R0 * coeff_B * (Rt - R0))))) / (2.0f * R0 * coeff_B);
115 
116 #if USE_MS_EEPROM
117  return mtostk_get_calibrated_value(&meteo_stick.calib, MTOSTK_TEMP, uncal_temp, 0.);
118 #else
119  return (MS_TEMPERATURE_SCALE * uncal_temp) + MS_TEMPERATURE_OFFSET;
120 #endif
121 }
122 
123 static float pitot_offset;
124 static int pitot_counter;
125 // number of measures for averaging initial offset
126 #define MS_PITOT_COUNTER 20
127 // filtering coefficient (0 no filter, 1 constant value)
128 #define MS_PITOT_FILTER 0.6
129 
130 static inline float get_diff(uint32_t raw)
131 {
132  const float gain_factor = Ads1220GainTable[ADS1220_GAIN_2];
133  const uint32_t raw_diff = raw > pitot_offset ? raw - pitot_offset : 0;
134  const float uncal_diff = ((raw_diff / maxAdc) * 5000.f / gain_factor);
135 
136 #if USE_MS_EEPROM
138 #else
139  return (MS_DIFF_PRESSURE_SCALE * uncal_diff) + MS_DIFF_PRESSURE_OFFSET;
140 #endif
141 }
142 
143 static inline float get_pitot(uint32_t raw)
144 {
145  return sqrtf((2.0f * get_diff(raw)) / 1.293f);
146 }
147 
148 static inline float get_humidity(uint32_t raw)
149 {
150  const float icu_freq = 42e6f; // Freq
151  const float Ra = 390e3f;
152  const float Rb = 680e3f;
153  const float S1 = 0.3e-12f; // pico farad by % of relative humidity
154  const float calib_raw_period = 17800.f;
155  const float calib_humidity = 45.f;
156  const float k = 2.f * logf(2.f) * (Ra + Rb + Rb);
157  const float uncal_hum = calib_humidity + ((raw - calib_raw_period) / (k * icu_freq * S1));
158 
159 #if USE_MS_EEPROM
161 #else
162  return (MS_HUMIDTY_SCALE * uncal_hum) + MS_HUMIDTY_OFFSET;
163 #endif
164 }
165 
166 
171 #ifndef LOG_MS
172 #define LOG_MS TRUE
173 #endif
174 
175 #if LOG_MS
176 #include "sdLog.h"
177 #include "subsystems/chibios-libopencm3/chibios_sdlog.h"
178 bool_t log_ptu_started;
179 #endif
180 
181 /* Includes and function to send over telemetry
182  *
183  * TRUE by default
184  */
185 #ifndef SEND_MS
186 #define SEND_MS TRUE
187 #endif
188 
189 #if SEND_MS
190 #include "mcu_periph/uart.h"
191 #include "messages.h"
193 #include "subsystems/gps.h"
194 
195 #define MS_DATA_SIZE 4
196 
197 static inline void meteo_stick_send_data(void)
198 {
199  float ptu_data[MS_DATA_SIZE];
200  ptu_data[0] = meteo_stick.current_pressure;
201  ptu_data[1] = meteo_stick.current_temperature;
202  ptu_data[2] = meteo_stick.current_humidity;
203  ptu_data[3] = meteo_stick.current_airspeed;
204  DOWNLINK_SEND_PAYLOAD_FLOAT(DefaultChannel, DefaultDevice, MS_DATA_SIZE, ptu_data);
205 }
206 
207 #endif
208 
209 
210 
214 {
215 #ifdef MS_PRESSURE_SLAVE_IDX
216  // Init absolute pressure
226  ads1220_init(&meteo_stick.pressure, &(MS_SPI_DEV), MS_PRESSURE_SLAVE_IDX);
227 #endif
228 
229 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
230  // Init differential pressure
240  ads1220_init(&meteo_stick.diff_pressure, &(MS_SPI_DEV), MS_DIFF_PRESSURE_SLAVE_IDX);
241 #endif
242 
243 #ifdef MS_TEMPERATURE_SLAVE_IDX
244  // Init temperature
254  ads1220_init(&meteo_stick.temperature, &(MS_SPI_DEV), MS_TEMPERATURE_SLAVE_IDX);
255 #endif
256 
257  // Init humidity
259 
260  // Initial conditions
265 
266 #if USE_MS_EEPROM
267  // Set number of calibration to 0 for all sensors
268  int i;
269  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
271  }
272  // Init eeprom
273  eeprom25AA256_init(&meteo_stick.eeprom, &(MS_SPI_DEV), MS_EEPROM_SLAVE_IDX);
274 #endif
275 
276  // Number of measurements before setting pitot offset
279 
280 #if LOG_MS
281  log_ptu_started = FALSE;
282 #endif
283 }
284 
288 {
289  // Read ADC
290 #ifdef MS_PRESSURE_SLAVE_IDX
292 #endif
293 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
295 #endif
296 #ifdef MS_TEMPERATURE_SLAVE_IDX
298 #endif
299  // Read PWM
300 #ifdef MS_HUMIDITY_PWM_INPUT
301  meteo_stick.humidity_period = pwm_input_period_tics[MS_HUMIDITY_PWM_INPUT];
303 #endif
304 
305 #if USE_MS_EEPROM
307  // Extract calibration data
309  // Extraction failed
310  // Force number of calibration to 0 for all sensors
311  int i;
312  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
314  }
315  }
317  // Load reading request (reading 1Kb from address 0x0)
319  }
320 #endif
321 
322  // Log data
323 #if LOG_MS
324  if (pprzLogFile != -1) {
325  if (!log_ptu_started) {
326 #if USE_MS_EEPROM
328  // Print calibration data in the log header
329  sdLogWriteLog(pprzLogFile, "# Calibration data (UUID: %s)\n#\n", meteo_stick.calib.uuid);
330  int i, j, k;
331  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
332  sdLogWriteLog(pprzLogFile, "# Sensor: %d, time: %d, num_temp: %d, num_coeff: %d\n", i,
336  if (meteo_stick.calib.params[i].timestamp == 0) {
337  continue; // No calibration
338  }
339  for (j = 0; j < meteo_stick.calib.params[i].num_temp; j++) {
340  sdLogWriteLog(pprzLogFile, "# Reference temp: %.2f\n", meteo_stick.calib.params[i].temps[j]);
341  sdLogWriteLog(pprzLogFile, "# Coeffs:");
342  for (k = 0; k < meteo_stick.calib.params[i].num_coeff; k++) {
343  sdLogWriteLog(pprzLogFile, " %.5f", meteo_stick.calib.params[i].coeffs[j][k]);
344  }
345  sdLogWriteLog(pprzLogFile, "\n");
346  }
347  }
348  sdLogWriteLog(pprzLogFile, "#\n");
349  sdLogWriteLog(pprzLogFile,
350  "P(adc) T(adc) H(ticks) P_diff(adc) P(hPa) T(C) H(\%) CAS(m/s) FIX TOW(ms) WEEK Lat(1e7rad) Lon(1e7rad) HMSL(mm) GS(cm/s) course(1e7rad) VZ(cm/s)\n");
351  log_ptu_started = TRUE;
352  }
353 #else
354  sdLogWriteLog(pprzLogFile,
355  "P(adc) T(adc) H(ticks) P_diff(adc) P(hPa) T(C) H(\%) CAS(m/s) FIX TOW(ms) WEEK Lat(1e7rad) Lon(1e7rad) HMSL(mm) GS(cm/s) course(1e7rad) VZ(cm/s)\n");
356  log_ptu_started = TRUE;
357 #endif
358  } else {
359  sdLogWriteLog(pprzLogFile, "%d %d %d %d %.2f %.2f %.2f %.2f %d %d %d %d %d %d %d %d %d\n",
364  gps.fix, gps.tow, gps.week,
367  }
368  }
369 #endif
370 
371  // Send data
372 #if SEND_MS
373  meteo_stick_send_data();
374 #endif
375 
376  // Check if DP offset reset is required
380  }
381 }
382 
386 {
387 #ifdef MS_PRESSURE_SLAVE_IDX
389 #endif
390 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
392 #endif
393 #ifdef MS_TEMPERATURE_SLAVE_IDX
395 #endif
396 
397 #ifdef MS_PRESSURE_SLAVE_IDX
398  // send absolute pressure data over ABI as soon as available
401 #if USE_MS_PRESSURE
403 #endif
405  }
406 #endif
407 
408 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
409  // send differential pressure data over ABI as soon as available
411  if (pitot_counter > 0) {
413  // set initial value
415  } else {
417  }
418  pitot_counter--;
419  }
420  else {
421 #if USE_MS_DIFF_PRESSURE
422  float diff = get_diff(meteo_stick.diff_pressure.data);
423  AbiSendMsgBARO_DIFF(METEO_STICK_SENDER_ID, diff);
424 #endif
427  }
428  }
429 #endif
430 
431 #ifdef MS_TEMPERATURE_SLAVE_IDX
432  // send temperature data over ABI as soon as available
435 #if USE_MS_TEMPERATURE
436  AbiSendMsgTEMPERATURE(METEO_STICK_SENDER_ID, meteo_stick.current_temperature);
437 #endif
439  }
440 #endif
441 
442 #if USE_MS_EEPROM
444 #endif
445 }
446 
void meteo_stick_event(void)
Event function.
Definition: meteo_stick.c:385
struct MeteoStick meteo_stick
General structure.
Definition: meteo_stick.c:85
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
enum Ads1220ConvMode conv
conversion mode
Definition: ads1220.h:135
static const float maxAdc
Prescaling of data according to datasheets.
Definition: meteo_stick.c:91
static float get_humidity(uint32_t raw)
Definition: meteo_stick.c:148
bool_t reset_dp_offset
reset differential pressure offset
Definition: meteo_stick.h:72
void eeprom25AA256_init(struct Eeprom25AA256 *eeprom, struct spi_periph *spi_p, uint8_t slave_idx)
Init function.
Definition: eeprom25AA256.c:45
struct spi_transaction spi_trans
spi transaction
Definition: eeprom25AA256.h:59
void eeprom25AA256_read(struct Eeprom25AA256 *eeprom, uint16_t addr, uint16_t length)
Read function.
Definition: eeprom25AA256.c:72
#define MS_PITOT_COUNTER
Definition: meteo_stick.c:126
static int pitot_counter
Definition: meteo_stick.c:124
void ads1220_event(struct Ads1220 *ads)
Definition: ads1220.c:130
enum Ads1220Imux i2mux
IDAC routing 2.
Definition: ads1220.h:139
static float get_pitot(uint32_t raw)
Definition: meteo_stick.c:143
float current_temperature
calibrated temperature
Definition: meteo_stick.h:64
float temps[MTOSTK_MAX_TEMP_ARRAY_SIZE]
enum Ads1220Mux mux
input multiplexer
Definition: ads1220.h:131
#define MS_HUMIDTY_OFFSET
Definition: meteo_stick.c:45
struct Ads1220 pressure
absolute pressure
Definition: meteo_stick.h:60
uint16_t week
GPS week.
Definition: gps.h:83
struct Ads1220 temperature
temperature
Definition: meteo_stick.h:62
arch independent PWM input capture API
#define MS_PITOT_FILTER
Definition: meteo_stick.c:128
Main include for ABI (AirBorneInterface).
bool mtostk_populate_cal_from_buffer(Calibration_params *cp, uint8_t *_eeprom_buffer)
Initializes a Calibration_params structure from memory buffer.
static float pitot_offset
Definition: meteo_stick.c:123
static float get_temp(uint32_t raw)
Definition: meteo_stick.c:104
void eeprom25AA256_event(struct Eeprom25AA256 *eeprom)
Event function.
Definition: eeprom25AA256.c:89
#define METEO_STICK_SENDER_ID
uint32_t humidity_period
humidity (in ticks)
Definition: meteo_stick.h:63
float coeffs[MTOSTK_MAX_TEMP_ARRAY_SIZE][MTOSTK_MAX_POLY_ARRAY_SIZE]
int32_t z
Down.
#define MS_TEMPERATURE_OFFSET
Definition: meteo_stick.c:39
struct Ads1220Config config
configuration
Definition: ads1220.h:158
struct Ads1220 diff_pressure
differential pressure
Definition: meteo_stick.h:61
float mtostk_get_calibrated_value(Calibration_params *cp, Mtostk_sensors type, float uncal, float temp)
get calibrated value for a sensor according to current temperature
#define FALSE
Definition: std.h:5
static float get_pressure(uint32_t raw)
Definition: meteo_stick.c:93
void meteo_stick_periodic(void)
Periodic function.
Definition: meteo_stick.c:287
Driver for the ADS1220 24-bits ADC from TI SPI communication.
#define TRUE
Definition: std.h:4
enum Ads1220Gain gain
gain
Definition: ads1220.h:132
int32_t hmsl
height above mean sea level in mm
Definition: gps.h:71
enum Ads1220VRef vref
voltage ref
Definition: ads1220.h:136
uint32_t tow
GPS time of week in ms.
Definition: gps.h:84
volatile bool_t data_available
data ready flag
Definition: ads1220.h:161
Device independent GPS code (interface)
bool_t pga_bypass
bypass PGA (PGA enabled = 0)
Definition: ads1220.h:133
float current_humidity
calibrated humidity
Definition: meteo_stick.h:66
unsigned long uint32_t
Definition: types.h:18
void meteo_stick_init(void)
Init function.
Definition: meteo_stick.c:213
#define MS_TEMPERATURE_SCALE
Definition: meteo_stick.c:42
#define MS_DIFF_PRESSURE_OFFSET
Definition: meteo_stick.c:51
int32_t lon
in degrees*1e7
float current_airspeed
calibrated airspeed
Definition: meteo_stick.h:67
volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB]
Definition: pwm_input.c:31
float current_pressure
calibrated pressure
Definition: meteo_stick.h:65
#define MS_DIFF_PRESSURE_SCALE
Definition: meteo_stick.c:54
bool_t data_available
data read flag
Definition: eeprom25AA256.h:62
enum Ads1220SampleRate rate
data output rate
Definition: ads1220.h:134
static void ads1220_periodic(struct Ads1220 *ads)
convenience function: read or start configuration if not already initialized
Definition: ads1220.h:171
unsigned char uint8_t
Definition: types.h:14
int32_t course
GPS course over ground in rad*1e7, [0, 2*Pi]*1e7 (CW/north)
Definition: gps.h:76
volatile uint8_t rx_buf[E25_IN_BUFFER_LEN]
receive buffer
Definition: eeprom25AA256.h:61
Sensors_params params[MTOSTK_NUM_SENSORS]
static const float Ads1220GainTable[]
Definition: ads1220.h:78
uint32_t data
raw ADC value
Definition: ads1220.h:160
enum Ads1220Idac idac
IDAC config.
Definition: ads1220.h:137
void ads1220_init(struct Ads1220 *ads, struct spi_periph *spi_p, uint8_t slave_idx)
Definition: ads1220.c:49
#define MS_HUMIDTY_SCALE
Definition: meteo_stick.c:48
struct Eeprom25AA256 eeprom
eeprom with calibration data
Definition: meteo_stick.h:69
Raw sensors structure.
Definition: meteo_stick.h:59
#define MS_PRESSURE_SCALE
Definition: meteo_stick.c:36
uint16_t gspeed
norm of 2d ground speed in cm/s
Definition: gps.h:74
Calibration_params calib
calibration
Definition: meteo_stick.h:70
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:69
enum Ads1220Imux i1mux
IDAC routing 1.
Definition: ads1220.h:138
Data acquisition module for ENAC PTU board.
int32_t lat
in degrees*1e7
static float get_diff(uint32_t raw)
Definition: meteo_stick.c:130
uint8_t fix
status of fix
Definition: gps.h:82
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:73
struct GpsState gps
global GPS state
Definition: gps.c:41
enum SPITransactionStatus status
Definition: spi.h:156
#define MS_PRESSURE_OFFSET
Default scale and offset Only used if calibration from EEPROM is not used/available.
Definition: meteo_stick.c:33