Paparazzi UAS  v5.12_stable-4-g9b43e9b
Paparazzi is a free software Unmanned Aircraft System.
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
airspeed_ms45xx_i2c.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2014 Freek van Tienen <freek.v.tienen@gmail.com>
3  * 2014 Felix Ruess <felix.ruess@gmail.com>
4  *
5  * This file is part of paparazzi
6  *
7  * paparazzi is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2, or (at your option)
10  * any later version.
11  *
12  * paparazzi is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with paparazzi; see the file COPYING. If not, write to
19  * the Free Software Foundation, 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22 
28 #include "std.h"
29 #include "mcu_periph/i2c.h"
32 #include "subsystems/abi.h"
33 
34 #include "mcu_periph/uart.h"
35 #include "pprzlink/messages.h"
37 
38 #if PERIODIC_TELEMETRY
40 #endif
41 
42 #ifndef USE_AIRSPEED_MS45XX
43 #if USE_AIRSPEED
44 #define USE_AIRSPEED_MS45XX TRUE
45 PRINT_CONFIG_MSG("USE_AIRSPEED_MS45XX automatically set to TRUE")
46 #endif
47 #endif
48 
49 #if USE_AIRSPEED_MS45XX
50 #include "state.h"
51 #endif
52 
55 #ifndef MS45XX_I2C_DEV
56 #define MS45XX_I2C_DEV i2c2
57 #endif
58 
60 #ifndef MS45XX_I2C_ADDR
61 #define MS45XX_I2C_ADDR 0x50
62 #endif
63 
68 #ifndef MS45XX_PRESSURE_RANGE
69 #define MS45XX_PRESSURE_RANGE 1
70 #endif
71 
76 #ifndef MS45XX_OUTPUT_TYPE
77 #define MS45XX_OUTPUT_TYPE 0
78 #endif
79 
81 #define PSI_TO_PA 6894.75729
82 
83 #if MS45XX_OUTPUT_TYPE == 0
84 /* Offset and scaling for OUTPUT TYPE A:
85  * p_raw = (0.8*16383)/ (Pmax - Pmin) * (pressure - Pmin) + 0.1*16383
86  * For differential sensors Pmax = MS45XX_PRESSURE_RANGE = -Pmin.
87  *
88  * p_diff = (p_raw - 0.1*16383) * 2*RANGE/(0.8*16383) - RANGE
89  * p_diff = p_raw * 2*RANGE/(0.8*16383) - (RANGE + (0.1 * 16383) * 2*RANGE/(0.8*16383)
90  * p_diff = p_raw * 2*RANGE/(0.8*16383) - (1.25 * RANGE)
91  * p_diff = p_raw * scale - offset
92  * then convert to Pascal
93  */
94 #ifndef MS45XX_PRESSURE_SCALE
95 #define MS45XX_PRESSURE_SCALE (2 * MS45XX_PRESSURE_RANGE / (0.8 * 16383) * PSI_TO_PA)
96 #endif
97 #ifndef MS45XX_PRESSURE_OFFSET
98 #define MS45XX_PRESSURE_OFFSET (1.25 * MS45XX_PRESSURE_RANGE * PSI_TO_PA)
99 #endif
100 #else
101 /* Offset and scaling for OUTPUT TYPE B:
102  * p_raw = (0.9*16383)/ (Pmax - Pmin) * (pressure - Pmin) + 0.05*16383
103  */
104 #ifndef MS45XX_PRESSURE_SCALE
105 #define MS45XX_PRESSURE_SCALE (2 * MS45XX_PRESSURE_RANGE / (0.9 * 16383) * PSI_TO_PA)
106 #endif
107 #ifndef MS45XX_PRESSURE_OFFSET
108 #define MS45XX_PRESSURE_OFFSET ((1.0 + 0.1 / 0.9) * MS45XX_PRESSURE_RANGE * PSI_TO_PA)
109 #endif
110 #endif
111 
115 #ifndef MS45XX_SYNC_SEND
116 #define MS45XX_SYNC_SEND FALSE
117 #endif
118 
124 #ifndef MS45XX_AIRSPEED_SCALE
125 #define MS45XX_AIRSPEED_SCALE 1.6327
126 #endif
127 
131 #ifndef MS45XX_LOWPASS_TAU
132 #define MS45XX_LOWPASS_TAU 0.15
133 #endif
134 
138 
139 
140 static void ms45xx_downlink(struct transport_tx *trans, struct link_device *dev)
141 {
142  pprz_msg_send_AIRSPEED_MS45XX(trans, dev, AC_ID,
145 }
146 
147 void ms45xx_i2c_init(void)
148 {
149  ms45xx.diff_pressure = 0;
150  ms45xx.temperature = 0;
151  ms45xx.airspeed = 0.;
156 
158  // setup low pass filter with time constant and 100Hz sampling freq
160  MS45XX_I2C_PERIODIC_PERIOD, 0);
161 
162 #if PERIODIC_TELEMETRY
163  register_periodic_telemetry(DefaultPeriodic, PPRZ_MSG_ID_AIRSPEED_MS45XX, ms45xx_downlink);
164 #endif
165 }
166 
168 {
169  // Initiate next read
172  }
173 }
174 
176 {
177  /* Check if transaction is succesfull */
179 
180  /* 2 MSB of data are status bits, 0 = good data, 2 = already fetched, 3 = fault */
181  uint8_t status = (0xC0 & ms45xx_trans.buf[0]) >> 6;
182 
183  if (status == 0) {
184  /* 14bit raw pressure */
185  uint16_t p_raw = 0x3FFF & (((uint16_t)(ms45xx_trans.buf[0]) << 8) |
186  (uint16_t)(ms45xx_trans.buf[1]));
187  /* Output is proportional to the difference between Port 1 and Port 2. Output
188  * swings positive when Port 1> Port 2. Output is 50% of total counts
189  * when Port 1=Port 2.
190  * p_diff = p_raw * scale - offset
191  */
192  float p_diff = p_raw * ms45xx.pressure_scale - ms45xx.pressure_offset;
193  ms45xx.diff_pressure = update_butterworth_2_low_pass(&ms45xx_filter, p_diff);
194 
195  /* 11bit raw temperature, 5 LSB bits not used */
196  uint16_t temp_raw = 0xFFE0 & (((uint16_t)(ms45xx_trans.buf[2]) << 8) |
197  (uint16_t)(ms45xx_trans.buf[3]));
198  temp_raw = temp_raw >> 5;
199  /* 0 = -50degC, 20147 = 150degC
200  * ms45xx_temperature in 0.1 deg Celcius
201  */
202  ms45xx.temperature = ((uint32_t)temp_raw * 2000) / 2047 - 500;
203 
204  // Send differential pressure via ABI
205  AbiSendMsgBARO_DIFF(MS45XX_SENDER_ID, ms45xx.diff_pressure);
206  // Send temperature as float in deg Celcius via ABI
207  float temp = ms45xx.temperature / 10.0f;
208  AbiSendMsgTEMPERATURE(MS45XX_SENDER_ID, temp);
209 
210  // Compute airspeed
212 #if USE_AIRSPEED_MS45XX
214 #endif
215  if (ms45xx.sync_send) {
216  ms45xx_downlink(&(DefaultChannel).trans_tx, &(DefaultDevice).device);
217  }
218  }
219 
220  // Set to done
222  } else if (ms45xx_trans.status == I2CTransFailed) {
223  // Just retry if failed
225  }
226 }
unsigned short uint16_t
Definition: types.h:16
status
Definition: anemotaxis.c:10
static float update_butterworth_2_low_pass(Butterworth2LowPass *filter, float value)
Update second order Butterworth low pass filter state with a new value.
arch independent UART (Universal Asynchronous Receiver/Transmitter) API
static void init_butterworth_2_low_pass(Butterworth2LowPass *filter, float tau, float sample_time, float value)
Init a second order Butterworth filter.
#define MS45XX_I2C_ADDR
Sensor I2C slave address (defaults 0x50, 0x6C and 0x8C)
volatile uint8_t buf[I2C_BUF_LEN]
Transaction buffer With I2C_BUF_LEN number of bytes.
Definition: i2c.h:122
transaction successfully finished by I2C driver
Definition: i2c.h:57
int16_t temperature
temperature in 0.1 deg Celcius
Periodic telemetry system header (includes downlink utility and generated code).
Simple first order low pass filter with bilinear transform.
void ms45xx_i2c_init(void)
Main include for ABI (AirBorneInterface).
struct AirspeedMs45xx ms45xx
float diff_pressure
differential pressure in Pascal
#define MS45XX_PRESSURE_OFFSET
bool sync_send
flag to enable sending every new measurement via telemetry
void ms45xx_i2c_event(void)
float airspeed
Airspeed in m/s estimated from differential pressure.
transaction set to done by user level
Definition: i2c.h:59
#define MS45XX_AIRSPEED_SCALE
Quadratic scale factor for airspeed.
static Butterworth2LowPass ms45xx_filter
float pressure_scale
scaling factor from raw measurement to Pascal
unsigned long uint32_t
Definition: types.h:18
float airspeed_scale
quadratic scale factor to convert differential pressure to airspeed
PRINT_CONFIG_MSG("USE_INS_NAV_INIT defaulting to TRUE")
#define MS45XX_SYNC_SEND
Send a AIRSPEED_MS45XX message with every new measurement.
#define DefaultPeriodic
Set default periodic telemetry.
Definition: telemetry.h:66
transaction failed
Definition: i2c.h:58
float pressure_offset
offset in Pascal
#define Max(x, y)
Definition: main_fbw.c:53
I2C transaction structure.
Definition: i2c.h:93
enum I2CTransactionStatus status
Transaction status.
Definition: i2c.h:126
static const struct usb_device_descriptor dev
Definition: usb_ser_hw.c:73
#define MS45XX_SENDER_ID
unsigned char uint8_t
Definition: types.h:14
API to get/set the generic vehicle states.
static struct i2c_transaction ms45xx_trans
Airspeed driver for the MS45xx via I2C.
static void stateSetAirspeed_f(float airspeed)
Set airspeed (float).
Definition: state.h:1309
bool i2c_receive(struct i2c_periph *p, struct i2c_transaction *t, uint8_t s_addr, uint16_t len)
Submit a read only transaction.
Definition: i2c.c:268
Second order low pass filter structure.
#define MS45XX_I2C_DEV
Default I2C device.
void ms45xx_i2c_periodic(void)
#define MS45XX_LOWPASS_TAU
Time constant for second order Butterworth low pass filter Default of 0.15 should give cut-off freq o...
#define MS45XX_PRESSURE_SCALE
int8_t register_periodic_telemetry(struct periodic_telemetry *_pt, uint8_t _id, telemetry_cb _cb)
Register a telemetry callback function.
Definition: telemetry.c:46
static void ms45xx_downlink(struct transport_tx *trans, struct link_device *dev)
Architecture independent I2C (Inter-Integrated Circuit Bus) API.