PX4 Firmware
PX4 Autopilot Software http://px4.io
LPS22HB.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2018 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 lps22hb.cpp
36  *
37  * Driver for the LPS22HB barometer connected via I2C or SPI.
38  */
39 
40 #include "LPS22HB.hpp"
41 
42 /* Max measurement rate is 25Hz */
43 #define LPS22HB_CONVERSION_INTERVAL (1000000 / 25) /* microseconds */
44 
45 LPS22HB::LPS22HB(device::Device *interface, const char *path) :
46  CDev(path),
47  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
48  _interface(interface),
49  _sample_perf(perf_alloc(PC_ELAPSED, "lps22hb_read")),
50  _comms_errors(perf_alloc(PC_COUNT, "lps22hb_comms_errors"))
51 {
52  // set the interface device type
54 }
55 
57 {
58  /* make sure we are truly inactive */
59  stop();
60 
61  if (_class_instance != -1) {
63  }
64 
65  // free perf counters
68 
69  delete _interface;
70 }
71 
72 int
74 {
75  int ret = CDev::init();
76 
77  if (ret != OK) {
78  PX4_DEBUG("CDev init failed");
79  goto out;
80  }
81 
82  if (reset() != OK) {
83  goto out;
84  }
85 
86  /* register alternate interfaces if we have to */
88 
89  ret = OK;
90 
91  PX4_INFO("starting");
93  start();
94 
95 out:
96  return ret;
97 }
98 
99 int
100 LPS22HB::ioctl(struct file *filp, int cmd, unsigned long arg)
101 {
102  unsigned dummy = arg;
103 
104  switch (cmd) {
105  case SENSORIOCSPOLLRATE: {
106  switch (arg) {
107 
108  /* zero would be bad */
109  case 0:
110  return -EINVAL;
111 
112  /* set default polling rate */
114  /* do we need to start internal polling? */
115  bool want_start = (_measure_interval == 0);
116 
117  /* set interval for next measurement to minimum legal value */
119 
120  /* if we need to start the poll state machine, do it */
121  if (want_start) {
123  start();
124  }
125 
126  return OK;
127  }
128 
129  /* adjust to a legal polling interval in Hz */
130  default: {
131  /* do we need to start internal polling? */
132  bool want_start = (_measure_interval == 0);
133 
134  /* convert hz to tick interval via microseconds */
135  unsigned interval = (1000000 / arg);
136 
137  /* check against maximum rate */
138  if (interval < (LPS22HB_CONVERSION_INTERVAL)) {
139  return -EINVAL;
140  }
141 
142  /* update interval for next measurement */
143  _measure_interval = interval;
144 
145  /* if we need to start the poll state machine, do it */
146  if (want_start) {
147  start();
148  }
149 
150  return OK;
151  }
152  }
153  }
154 
155  case SENSORIOCRESET:
156  return reset();
157 
158  case DEVIOCGDEVICEID:
159  return _interface->ioctl(cmd, dummy);
160 
161  default:
162  /* give it to the superclass */
163  return CDev::ioctl(filp, cmd, arg);
164  }
165 }
166 
167 void
169 {
170  /* reset the report ring and state machine */
171  _collect_phase = false;
172 
173  /* schedule a cycle to start things */
174  ScheduleNow();
175 }
176 
177 void
179 {
180  ScheduleClear();
181 }
182 
183 int
185 {
186  int ret = PX4_ERROR;
187 
188  ret = write_reg(CTRL_REG2, BOOT | SWRESET);
189 
190  return ret;
191 }
192 
193 void
195 {
196  /* collection phase? */
197  if (_collect_phase) {
198 
199  /* perform collection */
200  if (OK != collect()) {
201  PX4_DEBUG("collection error");
202  /* restart the measurement state machine */
203  start();
204  return;
205  }
206 
207  /* next phase is measurement */
208  _collect_phase = false;
209 
210  /*
211  * Is there a collect->measure gap?
212  */
214 
215  /* schedule a fresh cycle call when we are ready to measure again */
217 
218  return;
219  }
220  }
221 
222  /* measurement phase */
223  if (OK != measure()) {
224  PX4_DEBUG("measure error");
225  }
226 
227  /* next phase is collection */
228  _collect_phase = true;
229 
230  /* schedule a fresh cycle call when the measurement is done */
231  ScheduleDelayed(LPS22HB_CONVERSION_INTERVAL);
232 }
233 
234 int
236 {
237  // Send the command to begin a 16-bit measurement.
238  int ret = write_reg(CTRL_REG2, IF_ADD_INC | ONE_SHOT);
239 
240  if (OK != ret) {
242  }
243 
244  return ret;
245 }
246 
247 int
249 {
251  sensor_baro_s new_report;
252 
253  /* get measurements from the device : MSB enables register address auto-increment */
254 #pragma pack(push, 1)
255  struct {
256  uint8_t STATUS;
257  uint8_t PRESS_OUT_XL;
258  uint8_t PRESS_OUT_L;
259  uint8_t PRESS_OUT_H;
260  uint8_t TEMP_OUT_L;
261  uint8_t TEMP_OUT_H;
262  } report;
263 #pragma pack(pop)
264 
265  /* this should be fairly close to the end of the measurement, so the best approximation of the time */
266  new_report.timestamp = hrt_absolute_time();
267  int ret = _interface->read(STATUS, (uint8_t *)&report, sizeof(report));
268 
269  if (ret != OK) {
272  return ret;
273  }
274 
275  // To obtain the pressure in hPa, take the two’s complement of the complete word and then divide by 4096 LSB/hPa.
276  uint32_t P = report.PRESS_OUT_XL + (report.PRESS_OUT_L << 8) + (report.PRESS_OUT_H << 16);
277 
278  uint32_t TEMP_OUT = report.TEMP_OUT_L + (report.TEMP_OUT_H << 8);
279 
280  /* Pressure and MSL in mBar */
281  new_report.pressure = P / 4096.0f;
282  new_report.temperature = 42.5f + (TEMP_OUT / 480.0f);
283 
284  /* get device ID */
285  new_report.device_id = _interface->get_device_id();
287 
288  if (_baro_topic != nullptr) {
289  /* publish it */
290  orb_publish(ORB_ID(sensor_baro), _baro_topic, &new_report);
291 
292  } else {
293  bool sensor_is_onboard = !_interface->external();
294  _baro_topic = orb_advertise_multi(ORB_ID(sensor_baro), &new_report, &_orb_class_instance,
295  (sensor_is_onboard) ? ORB_PRIO_HIGH : ORB_PRIO_MAX);
296 
297  if (_baro_topic == nullptr) {
298  PX4_ERR("advertise failed");
299  }
300  }
301 
302  _last_report = new_report;
303 
304  ret = OK;
305 
307  return ret;
308 }
309 
310 int
311 LPS22HB::write_reg(uint8_t reg, uint8_t val)
312 {
313  uint8_t buf = val;
314  return _interface->write(reg, &buf, 1);
315 }
316 
317 int
318 LPS22HB::read_reg(uint8_t reg, uint8_t &val)
319 {
320  uint8_t buf = val;
321  int ret = _interface->read(reg, &buf, 1);
322  val = buf;
323  return ret;
324 }
325 
326 void
328 {
331 
332  PX4_INFO("poll interval: %u", _measure_interval);
333 
334  print_message(_last_report);
335 }
int reset()
Reset the device.
Definition: LPS22HB.cpp:184
bool _collect_phase
Definition: LPS22HB.hpp:105
#define BARO_BASE_DEVICE_PATH
Definition: drv_baro.h:50
measure the time elapsed performing an event
Definition: perf_counter.h:56
int measure()
Issue a measurement command.
Definition: LPS22HB.cpp:235
static constexpr uint8_t PRESS_OUT_XL
Definition: LPS22HB.hpp:72
virtual int register_class_devname(const char *class_devname)
Register a class device name, automatically adding device class instance suffix if need be...
Definition: CDev.cpp:78
#define DRV_BARO_DEVTYPE_LPS22HB
Definition: drv_sensor.h:109
#define SENSOR_POLLRATE_DEFAULT
poll at driver normal rate
Definition: drv_sensor.h:136
static constexpr uint8_t TEMP_OUT_H
Definition: LPS22HB.hpp:77
unsigned _measure_interval
Definition: LPS22HB.hpp:103
uint64_t error_count
Definition: sensor_baro.h:54
device::Device * _interface
Definition: LPS22HB.hpp:100
static constexpr uint8_t PRESS_OUT_L
Definition: LPS22HB.hpp:73
uint32_t device_id
Definition: sensor_baro.h:55
count the number of times an event occurs
Definition: perf_counter.h:55
void start()
Initialise the automatic measurement state machine and start it.
Definition: LPS22HB.cpp:168
sensor_baro_s _last_report
used for info()
Definition: LPS22HB.hpp:115
static constexpr uint8_t CTRL_REG2
Definition: LPS22HB.hpp:54
void Run() override
Perform a poll cycle; collect from the previous measurement and start a new one.
Definition: LPS22HB.cpp:194
perf_counter_t _sample_perf
Definition: LPS22HB.hpp:112
virtual ~LPS22HB()
Definition: LPS22HB.cpp:56
#define BOOT
Definition: LPS22HB.hpp:57
#define SWRESET
Definition: LPS22HB.hpp:62
static constexpr uint8_t STATUS
Definition: LPS22HB.hpp:65
uint32_t get_device_id() const
Definition: Device.hpp:161
#define SENSORIOCSPOLLRATE
Set the driver polling rate to (arg) Hz, or one of the SENSOR_POLLRATE constants. ...
Definition: drv_sensor.h:134
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
virtual int ioctl(struct file *filp, int cmd, unsigned long arg)
Definition: LPS22HB.cpp:100
orb_advert_t _baro_topic
Definition: LPS22HB.hpp:107
void perf_count(perf_counter_t handle)
Count a performance event.
float pressure
Definition: sensor_baro.h:56
void perf_free(perf_counter_t handle)
Free a counter.
void init()
Activates/configures the hardware registers.
virtual int unregister_class_devname(const char *class_devname, unsigned class_instance)
Register a class device name, automatically adding device class instance suffix if need be...
Definition: CDev.cpp:109
#define LPS22HB_CONVERSION_INTERVAL
Definition: LPS22HB.cpp:43
#define perf_alloc(a, b)
Definition: px4io.h:59
static constexpr uint8_t TEMP_OUT_L
Definition: LPS22HB.hpp:76
perf_counter_t _comms_errors
Definition: LPS22HB.hpp:113
void perf_end(perf_counter_t handle)
End a performance event.
void print_info()
Diagnostics - print some basic information about the driver.
Definition: LPS22HB.cpp:327
virtual int write(unsigned address, void *data, unsigned count)
Write directly to the device.
Definition: Device.hpp:115
int collect()
Collect the result of the most recent measurement.
Definition: LPS22HB.cpp:248
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
virtual int ioctl(unsigned operation, unsigned &arg)
Perform a device-specific operation.
Definition: Device.hpp:124
void set_device_type(uint8_t devtype)
Definition: Device.hpp:214
virtual bool external() const
Definition: Device.hpp:237
static constexpr uint8_t PRESS_OUT_H
Definition: LPS22HB.hpp:74
LPS22HB(device::Device *interface, const char *path)
Definition: LPS22HB.cpp:45
struct @83::@85::@87 file
int write_reg(uint8_t reg, uint8_t val)
Write a register.
Definition: LPS22HB.cpp:311
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
#define SENSORIOCRESET
Reset the sensor to its default configuration.
Definition: drv_sensor.h:141
uint64_t perf_event_count(perf_counter_t handle)
Return current event_count.
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
Definition: bst.cpp:62
void stop()
Stop the automatic measurement state machine.
Definition: LPS22HB.cpp:178
#define ONE_SHOT
Definition: LPS22HB.hpp:63
int _class_instance
Definition: LPS22HB.hpp:110
virtual int init()
Definition: LPS22HB.cpp:73
#define OK
Definition: uavcan_main.cpp:71
uint64_t timestamp
Definition: sensor_baro.h:53
P[0][0]
Definition: quatCovMat.c:44
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
#define IF_ADD_INC
Definition: LPS22HB.hpp:60
void perf_begin(perf_counter_t handle)
Begin a performance event.
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
virtual int read(unsigned address, void *data, unsigned count)
Read directly from the device.
Definition: Device.hpp:103
int _orb_class_instance
Definition: LPS22HB.hpp:109
int read_reg(uint8_t reg, uint8_t &val)
Read a register.
Definition: LPS22HB.cpp:318