PX4 Firmware
PX4 Autopilot Software http://px4.io
HMC5883.hpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2019 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 #pragma once
35 
36 #include <px4_platform_common/px4_config.h>
37 #include <px4_platform_common/defines.h>
38 #include <px4_platform_common/time.h>
39 
40 #include <drivers/device/i2c.h>
41 
42 #include <sys/types.h>
43 #include <stdint.h>
44 #include <stdlib.h>
45 #include <stdbool.h>
46 #include <semaphore.h>
47 #include <string.h>
48 #include <fcntl.h>
49 #include <poll.h>
50 #include <errno.h>
51 #include <stdio.h>
52 #include <math.h>
53 #include <unistd.h>
54 
55 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
56 
57 #include <lib/perf/perf_counter.h>
58 #include <systemlib/err.h>
59 
60 #include <drivers/drv_mag.h>
61 #include <drivers/drv_hrt.h>
63 #include <drivers/drv_device.h>
64 
65 #include <uORB/uORB.h>
66 
67 #include <float.h>
68 #include <px4_platform_common/getopt.h>
70 
71 #include "hmc5883.h"
72 
73 /*
74  * HMC5883 internal constants and data structures.
75  */
76 
77 /* Max measurement rate is 160Hz, however with 160 it will be set to 166 Hz, therefore workaround using 150 */
78 #define HMC5883_CONVERSION_INTERVAL (1000000 / 150) /* microseconds */
79 
80 #define ADDR_CONF_A 0x00
81 #define ADDR_CONF_B 0x01
82 #define ADDR_MODE 0x02
83 #define ADDR_DATA_OUT_X_MSB 0x03
84 #define ADDR_DATA_OUT_X_LSB 0x04
85 #define ADDR_DATA_OUT_Z_MSB 0x05
86 #define ADDR_DATA_OUT_Z_LSB 0x06
87 #define ADDR_DATA_OUT_Y_MSB 0x07
88 #define ADDR_DATA_OUT_Y_LSB 0x08
89 #define ADDR_STATUS 0x09
90 
91 /* temperature on hmc5983 only */
92 #define ADDR_TEMP_OUT_MSB 0x31
93 #define ADDR_TEMP_OUT_LSB 0x32
94 
95 /* modes not changeable outside of driver */
96 #define HMC5883L_MODE_NORMAL (0 << 0) /* default */
97 #define HMC5883L_MODE_POSITIVE_BIAS (1 << 0) /* positive bias */
98 #define HMC5883L_MODE_NEGATIVE_BIAS (1 << 1) /* negative bias */
99 
100 #define HMC5883L_AVERAGING_1 (0 << 5) /* conf a register */
101 #define HMC5883L_AVERAGING_2 (1 << 5)
102 #define HMC5883L_AVERAGING_4 (2 << 5)
103 #define HMC5883L_AVERAGING_8 (3 << 5)
104 
105 #define MODE_REG_CONTINOUS_MODE (0 << 0)
106 #define MODE_REG_SINGLE_MODE (1 << 0) /* default */
107 
108 #define STATUS_REG_DATA_OUT_LOCK (1 << 1) /* page 16: set if data is only partially read, read device to reset */
109 #define STATUS_REG_DATA_READY (1 << 0) /* page 16: set if all axes have valid measurements */
110 
111 #define HMC5983_TEMP_SENSOR_ENABLE (1 << 7)
112 
113 class HMC5883 : public device::CDev, public px4::ScheduledWorkItem
114 {
115 public:
116  HMC5883(device::Device *interface, const char *path, enum Rotation rotation);
117  virtual ~HMC5883();
118 
119  virtual int init();
120 
121  virtual ssize_t read(cdev::file_t *filp, char *buffer, size_t buflen);
122  virtual int ioctl(cdev::file_t *filp, int cmd, unsigned long arg);
123 
124  /**
125  * Stop the automatic measurement state machine.
126  */
127  void stop();
128 
129  /**
130  * Diagnostics - print some basic information about the driver.
131  */
132  void print_info();
133 
134 protected:
136 
137 private:
138 
139  unsigned _measure_interval{0};
140 
141  ringbuffer::RingBuffer *_reports;
144  float _range_ga;
148 
150 
155 
156  /* status reporting */
157  bool _sensor_ok; /**< sensor was found and reports ok */
158 
160 
161  struct mag_report _last_report {}; /**< used for info() */
162 
163  uint8_t _range_bits;
164  uint8_t _conf_reg;
167 
168  /**
169  * Initialise the automatic measurement state machine and start it.
170  *
171  * @note This function is called at open and error time. It might make sense
172  * to make it more aggressive about resetting the bus in case of errors.
173  */
174  void start();
175 
176  /**
177  * Reset the device
178  */
179  int reset();
180 
181  /**
182  * Perform the on-sensor scale calibration routine.
183  *
184  * @note The sensor will continue to provide measurements, these
185  * will however reflect the uncalibrated sensor state until
186  * the calibration routine has been completed.
187  *
188  * @param enable set to 1 to enable self-test strap, 0 to disable
189  */
190  int calibrate(cdev::file_t *filp, unsigned enable);
191 
192  /**
193  * Perform the on-sensor scale calibration routine.
194  *
195  * @note The sensor will continue to provide measurements, these
196  * will however reflect the uncalibrated sensor state until
197  * the calibration routine has been completed.
198  *
199  * @param enable set to 1 to enable self-test positive strap, -1 to enable
200  * negative strap, 0 to set to normal mode
201  */
202  int set_excitement(unsigned enable);
203 
204  /**
205  * enable hmc5983 temperature compensation
206  */
207  int set_temperature_compensation(unsigned enable);
208 
209  /**
210  * Set the sensor range.
211  *
212  * Sets the internal range to handle at least the argument in Gauss.
213  */
214  int set_range(unsigned range);
215 
216  /**
217  * check the sensor range.
218  *
219  * checks that the range of the sensor is correctly set, to
220  * cope with communication errors causing the range to change
221  */
222  void check_range(void);
223 
224  /**
225  * check the sensor configuration.
226  *
227  * checks that the config of the sensor is correctly set, to
228  * cope with communication errors causing the configuration to
229  * change
230  */
231  void check_conf(void);
232 
233  /**
234  * Perform a poll cycle; collect from the previous measurement
235  * and start a new one.
236  *
237  * This is the heart of the measurement state machine. This function
238  * alternately starts a measurement, or collects the data from the
239  * previous measurement.
240  *
241  * When the interval between measurements is greater than the minimum
242  * measurement interval, a gap is inserted between collection
243  * and measurement to provide the most recent measurement possible
244  * at the next interval.
245  */
246  void Run() override;
247 
248  /**
249  * Write a register.
250  *
251  * @param reg The register to write.
252  * @param val The value to write.
253  * @return OK on write success.
254  */
255  int write_reg(uint8_t reg, uint8_t val);
256 
257  /**
258  * Read a register.
259  *
260  * @param reg The register to read.
261  * @param val The value read.
262  * @return OK on read success.
263  */
264  int read_reg(uint8_t reg, uint8_t &val);
265 
266  /**
267  * Issue a measurement command.
268  *
269  * @return OK if the measurement command was successful.
270  */
271  int measure();
272 
273  /**
274  * Collect the result of the most recent measurement.
275  */
276  int collect();
277 
278  /**
279  * Convert a big-endian signed 16-bit value to a float.
280  *
281  * @param in A signed 16-bit big-endian value.
282  * @return The floating-point representation of the value.
283  */
284  float meas_to_float(uint8_t in[2]);
285 
286  /**
287  * Check the current scale calibration
288  *
289  * @return 0 if scale calibration is ok, 1 else
290  */
291  int check_scale();
292 
293  /**
294  * Check the current offset calibration
295  *
296  * @return 0 if offset calibration is ok, 1 else
297  */
298  int check_offset();
299 };
void print_info()
Diagnostics - print some basic information about the driver.
Definition: HMC5883.cpp:1014
int measure()
Issue a measurement command.
Definition: HMC5883.cpp:467
unsigned _measure_interval
Definition: HMC5883.hpp:139
API for the uORB lightweight object broker.
float _range_ga
Definition: HMC5883.hpp:144
bool _collect_phase
Definition: HMC5883.hpp:145
uint8_t _conf_reg
Definition: HMC5883.hpp:164
void Run() override
Perform a poll cycle; collect from the previous measurement and start a new one.
Definition: HMC5883.cpp:420
int write_reg(uint8_t reg, uint8_t val)
Write a register.
Definition: HMC5883.cpp:984
perf_counter_t _conf_errors
Definition: HMC5883.hpp:154
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
Device(const Device &)=delete
Device * _interface
Definition: HMC5883.hpp:135
int set_range(unsigned range)
Set the sensor range.
Definition: HMC5883.cpp:125
perf_counter_t _comms_errors
Definition: HMC5883.hpp:152
uint8_t _temperature_error_count
Definition: HMC5883.hpp:166
Vector rotation library.
High-resolution timer with callouts and timekeeping.
bool _sensor_ok
sensor was found and reports ok
Definition: HMC5883.hpp:157
perf_counter_t _sample_perf
Definition: HMC5883.hpp:151
Abstract class for any character device.
Definition: CDev.hpp:60
ringbuffer::RingBuffer * _reports
Definition: HMC5883.hpp:141
Generic device / sensor interface.
HMC5883(device::Device *interface, const char *path, enum Rotation rotation)
Definition: HMC5883.cpp:36
int set_temperature_compensation(unsigned enable)
enable hmc5983 temperature compensation
Definition: HMC5883.cpp:948
struct mag_calibration_s _scale
Definition: HMC5883.hpp:142
Header common to all counters.
int read_reg(uint8_t reg, uint8_t &val)
Read a register.
Definition: HMC5883.cpp:991
int _orb_class_instance
Definition: HMC5883.hpp:147
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
int check_scale()
Check the current scale calibration.
Definition: HMC5883.cpp:855
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
uint8_t _temperature_counter
Definition: HMC5883.hpp:165
virtual ssize_t read(cdev::file_t *filp, char *buffer, size_t buflen)
Perform a read from the device.
Definition: HMC5883.cpp:244
int collect()
Collect the result of the most recent measurement.
Definition: HMC5883.cpp:484
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
void check_conf(void)
check the sensor configuration.
Definition: HMC5883.cpp:221
Shared defines for the hmc5883 driver.
int reset()
Reset the device.
Definition: HMC5883.cpp:413
virtual int init()
Definition: HMC5883.cpp:95
used for info()
Definition: HMC5883.hpp:161
virtual ~HMC5883()
Definition: HMC5883.cpp:74
float _range_scale
Definition: HMC5883.hpp:143
int check_offset()
Check the current offset calibration.
Definition: HMC5883.cpp:873
virtual int ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
Perform an ioctl operation on the device.
Definition: HMC5883.cpp:302
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
void check_range(void)
check the sensor range.
Definition: HMC5883.cpp:194
uint8_t _range_bits
Definition: HMC5883.hpp:163
void start()
Initialise the automatic measurement state machine and start it.
Definition: HMC5883.cpp:392
enum Rotation _rotation
Definition: HMC5883.hpp:159
int _class_instance
Definition: HMC5883.hpp:146
perf_counter_t _range_errors
Definition: HMC5883.hpp:153
orb_advert_t _mag_topic
Definition: HMC5883.hpp:149
void stop()
Stop the automatic measurement state machine.
Definition: HMC5883.cpp:403
int calibrate(cdev::file_t *filp, unsigned enable)
Perform the on-sensor scale calibration routine.
Definition: HMC5883.cpp:679
Performance measuring tools.
Base class for devices connected via I2C.
#define mag_report
Definition: drv_mag.h:53
int set_excitement(unsigned enable)
Perform the on-sensor scale calibration routine.
Definition: HMC5883.cpp:891
float meas_to_float(uint8_t in[2])
Convert a big-endian signed 16-bit value to a float.
Definition: HMC5883.cpp:1000