Paparazzi UAS  v5.15_devel-79-g48e7b20
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
177 bool log_ptu_started;
178 #endif
179 
180 /* Includes and function to send over telemetry
181  *
182  * TRUE by default
183  */
184 #ifndef SEND_MS
185 #define SEND_MS TRUE
186 #endif
187 
188 #if SEND_MS
189 #include "mcu_periph/uart.h"
190 #include "pprzlink/messages.h"
192 #include "subsystems/gps.h"
193 
194 #define MS_DATA_SIZE 4
195 
196 static inline void meteo_stick_send_data(void)
197 {
198  float ptu_data[MS_DATA_SIZE];
199  ptu_data[0] = meteo_stick.current_pressure;
200  ptu_data[1] = meteo_stick.current_temperature;
201  ptu_data[2] = meteo_stick.current_humidity;
202  ptu_data[3] = meteo_stick.current_airspeed;
203  DOWNLINK_SEND_PAYLOAD_FLOAT(DefaultChannel, DefaultDevice, MS_DATA_SIZE, ptu_data);
204 }
205 
206 #endif
207 
208 
209 
213 {
214 #ifdef MS_PRESSURE_SLAVE_IDX
215  // Init absolute pressure
225  ads1220_init(&meteo_stick.pressure, &(MS_SPI_DEV), MS_PRESSURE_SLAVE_IDX);
226 #endif
227 
228 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
229  // Init differential pressure
239  ads1220_init(&meteo_stick.diff_pressure, &(MS_SPI_DEV), MS_DIFF_PRESSURE_SLAVE_IDX);
240 #endif
241 
242 #ifdef MS_TEMPERATURE_SLAVE_IDX
243  // Init temperature
253  ads1220_init(&meteo_stick.temperature, &(MS_SPI_DEV), MS_TEMPERATURE_SLAVE_IDX);
254 #endif
255 
256  // Init humidity
258 
259  // Initial conditions
264 
265 #if USE_MS_EEPROM
266  // Set number of calibration to 0 for all sensors
267  int i;
268  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
269  meteo_stick.calib.params[i].num_temp = 0;
270  }
271  // Init eeprom
272  eeprom25AA256_init(&meteo_stick.eeprom, &(MS_SPI_DEV), MS_EEPROM_SLAVE_IDX);
273 #endif
274 
275  // Number of measurements before setting pitot offset
278 
279 #if LOG_MS
280  log_ptu_started = false;
281 #endif
282 }
283 
287 {
288  // Read ADC
289 #ifdef MS_PRESSURE_SLAVE_IDX
291 #endif
292 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
294 #endif
295 #ifdef MS_TEMPERATURE_SLAVE_IDX
297 #endif
298  // Read PWM
299 #ifdef MS_HUMIDITY_PWM_INPUT
300  meteo_stick.humidity_period = pwm_input_period_tics[MS_HUMIDITY_PWM_INPUT];
302 #endif
303 
304 #if USE_MS_EEPROM
305  if (meteo_stick.eeprom.data_available) {
306  // Extract calibration data
307  if (!mtostk_populate_cal_from_buffer(&meteo_stick.calib, (uint8_t *)(meteo_stick.eeprom.rx_buf + 3))) {
308  // Extraction failed
309  // Force number of calibration to 0 for all sensors
310  int i;
311  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
312  meteo_stick.calib.params[i].num_temp = 0;
313  }
314  }
315  } else if (meteo_stick.eeprom.spi_trans.status == SPITransDone) {
316  // Load reading request (reading 1Kb from address 0x0)
317  eeprom25AA256_read(&meteo_stick.eeprom, 0x0, 1024);
318  }
319 #endif
320 
321  // Log data
322 #if LOG_MS
323  if (pprzLogFile != -1) {
324  if (!log_ptu_started) {
325 #if USE_MS_EEPROM
326  if (meteo_stick.eeprom.data_available) {
327  // Print calibration data in the log header
328  sdLogWriteLog(pprzLogFile, "# Calibration data (UUID: %s)\n#\n", meteo_stick.calib.uuid);
329  int i, j, k;
330  for (i = 0; i < MTOSTK_NUM_SENSORS; i++) {
331  sdLogWriteLog(pprzLogFile, "# Sensor: %d, time: %d, num_temp: %d, num_coeff: %d\n", i,
332  meteo_stick.calib.params[i].timestamp,
333  meteo_stick.calib.params[i].num_temp,
334  meteo_stick.calib.params[i].num_coeff);
335  if (meteo_stick.calib.params[i].timestamp == 0) {
336  continue; // No calibration
337  }
338  for (j = 0; j < meteo_stick.calib.params[i].num_temp; j++) {
339  sdLogWriteLog(pprzLogFile, "# Reference temp: %.2f\n", meteo_stick.calib.params[i].temps[j]);
340  sdLogWriteLog(pprzLogFile, "# Coeffs:");
341  for (k = 0; k < meteo_stick.calib.params[i].num_coeff; k++) {
342  sdLogWriteLog(pprzLogFile, " %.5f", meteo_stick.calib.params[i].coeffs[j][k]);
343  }
344  sdLogWriteLog(pprzLogFile, "\n");
345  }
346  }
347  sdLogWriteLog(pprzLogFile, "#\n");
348  sdLogWriteLog(pprzLogFile,
349  "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");
350  log_ptu_started = true;
351  }
352 #else
353  sdLogWriteLog(pprzLogFile,
354  "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");
355  log_ptu_started = true;
356 #endif
357  } else {
358  sdLogWriteLog(pprzLogFile, "%lu %lu %lu %lu %.2f %.2f %.2f %.2f %d %lu %d %lu %lu %lu %d %lu %lu\n",
363  gps.fix, gps.tow, gps.week,
366  }
367  }
368 #endif
369 
370  // Send data
371 #if SEND_MS
372  meteo_stick_send_data();
373 #endif
374 
375  // Check if DP offset reset is required
379  }
380 }
381 
385 {
386 #ifdef MS_PRESSURE_SLAVE_IDX
388 #endif
389 #ifdef MS_DIFF_PRESSURE_SLAVE_IDX
391 #endif
392 #ifdef MS_TEMPERATURE_SLAVE_IDX
394 #endif
395 
396 #ifdef MS_PRESSURE_SLAVE_IDX
397  // send absolute pressure data over ABI as soon as available
399  uint32_t now_ts = get_sys_time_usec();
401 #if USE_MS_PRESSURE
402  AbiSendMsgBARO_ABS(METEO_STICK_SENDER_ID, now_ts, meteo_stick.current_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:384
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
void eeprom25AA256_init(struct Eeprom25AA256 *eeprom, struct spi_periph *spi_p, uint8_t slave_idx)
Init function.
Definition: eeprom25AA256.c:45
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
volatile bool data_available
data ready flag
Definition: ads1220.h:161
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:108
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
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
static float get_pressure(uint32_t raw)
Definition: meteo_stick.c:93
void meteo_stick_periodic(void)
Periodic function.
Definition: meteo_stick.c:286
Driver for the ADS1220 24-bits ADC from TI SPI communication.
enum Ads1220Gain gain
gain
Definition: ads1220.h:132
int32_t hmsl
height above mean sea level (MSL) in mm
Definition: gps.h:94
bool pga_bypass
bypass PGA (PGA enabled = 0)
Definition: ads1220.h:133
enum Ads1220VRef vref
voltage ref
Definition: ads1220.h:136
uint32_t tow
GPS time of week in ms.
Definition: gps.h:109
Device independent GPS code (interface)
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:212
#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
FileDes pprzLogFile
Definition: sdlog_chibios.c:85
volatile uint32_t pwm_input_period_tics[PWM_INPUT_NB]
Definition: pwm_input.c:36
float current_pressure
calibrated pressure
Definition: meteo_stick.h:65
#define MS_DIFF_PRESSURE_SCALE
Definition: meteo_stick.c:54
enum Ads1220SampleRate rate
data output rate
Definition: ads1220.h:134
bool reset_dp_offset
reset differential pressure offset
Definition: meteo_stick.h:72
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:99
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
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:97
struct LlaCoor_i lla_pos
position in LLA (lat,lon: deg*1e7; alt: mm over ellipsoid)
Definition: gps.h:92
enum Ads1220Imux i1mux
IDAC routing 1.
Definition: ads1220.h:138
Data acquisition module for ENAC PTU board.
uint32_t get_sys_time_usec(void)
Get the time in microseconds since startup.
Definition: sys_time_arch.c:68
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:107
struct NedCoor_i ned_vel
speed NED in cm/s
Definition: gps.h:96
struct GpsState gps
global GPS state
Definition: gps.c:69
#define MS_PRESSURE_OFFSET
Default scale and offset Only used if calibration from EEPROM is not used/available.
Definition: meteo_stick.c:33