PX4 Firmware
PX4 Autopilot Software http://px4.io
qmc5883.cpp
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 /**
35  * @file qmc5883.cpp
36  *
37  * Driver for the QMC5883 magnetometer connected via I2C or SPI.
38  */
39 
40 #include <px4_platform_common/px4_config.h>
41 #include <px4_platform_common/defines.h>
42 
43 #include <drivers/device/i2c.h>
44 
45 #include <sys/types.h>
46 #include <stdint.h>
47 #include <stdlib.h>
48 #include <stdbool.h>
49 #include <semaphore.h>
50 #include <string.h>
51 #include <fcntl.h>
52 #include <poll.h>
53 #include <errno.h>
54 #include <stdio.h>
55 #include <math.h>
56 #include <unistd.h>
57 
58 #include <nuttx/arch.h>
59 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
60 #include <nuttx/clock.h>
61 
62 #include <board_config.h>
63 
64 #include <perf/perf_counter.h>
65 #include <systemlib/err.h>
66 
67 #include <drivers/drv_mag.h>
68 #include <drivers/drv_hrt.h>
70 #include <drivers/drv_device.h>
71 
72 #include <uORB/uORB.h>
73 
74 #include <float.h>
75 #include <getopt.h>
77 
78 #include "qmc5883.h"
79 
80 /*
81  * QMC5883 internal constants and data structures.
82  */
83 
84 /* Max measurement rate is 200Hz */
85 #define QMC5883_CONVERSION_INTERVAL (1000000 / 150) /* microseconds */
86 #define QMC5883_MAX_COUNT 32767
87 
88 #define QMC5883_ADDR_DATA_OUT_X_LSB 0x00
89 #define QMC5883_ADDR_DATA_OUT_X_MSB 0x01
90 #define QMC5883_ADDR_DATA_OUT_Y_LSB 0x02
91 #define QMC5883_ADDR_DATA_OUT_Y_MSB 0x03
92 #define QMC5883_ADDR_DATA_OUT_Z_LSB 0x04
93 #define QMC5883_ADDR_DATA_OUT_Z_MSB 0x05
94 #define QMC5883_ADDR_STATUS 0x06
95 #define QMC5883_ADDR_TEMP_OUT_LSB 0x07
96 #define QMC5883_ADDR_TEMP_OUT_MSB 0x08
97 #define QMC5883_ADDR_CONTROL_1 0x09
98 #define QMC5883_ADDR_CONTROL_2 0x0A
99 #define QMC5883_ADDR_SET_RESET 0x0B
100 
101 
102 #define QMC5883_STATUS_REG_DRDY (1 << 0) /* Data Ready: "0": no new data, "1": new data is ready */
103 #define QMC5883_STATUS_REG_OVL (1 << 1) /* Overflow Flag: "0": normal, "1": data overflow */
104 #define QMC5883_STATUS_REG_DOR (1 << 2) /* Data Skip: "0": normal, "1": data skipped for reading */
105 
106 /* Control Register 1 */
107 #define QMC5883_MODE_REG_STANDBY (0 << 0)
108 #define QMC5883_MODE_REG_CONTINOUS_MODE (1 << 0)
109 #define QMC5883_OUTPUT_DATA_RATE_10 (0 << 2) /* Hz */
110 #define QMC5883_OUTPUT_DATA_RATE_50 (1 << 2)
111 #define QMC5883_OUTPUT_DATA_RATE_100 (2 << 2)
112 #define QMC5883_OUTPUT_DATA_RATE_200 (3 << 2)
113 #define QMC5883_OUTPUT_RANGE_2G (0 << 4) /* +/- 2 gauss */
114 #define QMC5883_OUTPUT_RANGE_8G (1 << 4) /* +/- 8 gauss */
115 #define QMC5883_OVERSAMPLE_512 (0 << 6) /* controls digital filter bw - larger OSR -> smaller bw */
116 #define QMC5883_OVERSAMPLE_256 (1 << 6)
117 #define QMC5883_OVERSAMPLE_128 (2 << 6)
118 #define QMC5883_OVERSAMPLE_64 (3 << 6)
119 
120 /* Control Register 2 */
121 #define QMC5883_INT_ENB (1 << 0)
122 #define QMC5883_ROL_PNT (1 << 6)
123 #define QMC5883_SOFT_RESET (1 << 7)
124 
125 /* Set Register */
126 #define QMC5883_SET_DEFAULT (1 << 0)
127 
128 #define QMC5883_TEMP_OFFSET 50 /* deg celsius */
129 
135 };
136 
137 class QMC5883 : public device::CDev, public px4::ScheduledWorkItem
138 {
139 public:
140  QMC5883(device::Device *interface, const char *path, enum Rotation rotation);
141  virtual ~QMC5883();
142 
143  virtual int init();
144 
145  virtual ssize_t read(struct file *filp, char *buffer, size_t buflen);
146  virtual int ioctl(struct file *filp, int cmd, unsigned long arg);
147 
148  /**
149  * Stop the automatic measurement state machine.
150  */
151  void stop();
152 
153  /**
154  * Diagnostics - print some basic information about the driver.
155  */
156  void print_info();
157 
158 protected:
160 
161 private:
162  unsigned _measure_interval{0};
163 
164  ringbuffer::RingBuffer *_reports;
167  float _range_ga;
171 
173 
178 
179  /* status reporting */
180  bool _sensor_ok; /**< sensor was found and reports ok */
181 
183 
184  struct mag_report _last_report {}; /**< used for info() */
185 
186  uint8_t _range_bits;
187  uint8_t _conf_reg;
190 
191  /**
192  * Initialise the automatic measurement state machine and start it.
193  *
194  * @note This function is called at open and error time. It might make sense
195  * to make it more aggressive about resetting the bus in case of errors.
196  */
197  void start();
198 
199  /**
200  * Reset the device
201  */
202  int reset();
203 
204  /**
205  * check the sensor configuration.
206  *
207  * checks that the config of the sensor is correctly set, to
208  * cope with communication errors causing the configuration to
209  * change
210  */
211  void check_conf(void);
212 
213  /**
214  * Perform a poll cycle; collect from the previous measurement
215  * and start a new one.
216  *
217  * This is the heart of the measurement state machine. This function
218  * alternately starts a measurement, or collects the data from the
219  * previous measurement.
220  *
221  * When the interval between measurements is greater than the minimum
222  * measurement interval, a gap is inserted between collection
223  * and measurement to provide the most recent measurement possible
224  * at the next interval.
225  */
226  void Run() override;
227 
228  /**
229  * Write a register.
230  *
231  * @param reg The register to write.
232  * @param val The value to write.
233  * @return OK on write success.
234  */
235  int write_reg(uint8_t reg, uint8_t val);
236 
237  /**
238  * Read a register.
239  *
240  * @param reg The register to read.
241  * @param val The value read.
242  * @return OK on read success.
243  */
244  int read_reg(uint8_t reg, uint8_t &val);
245 
246  /**
247  * Collect the result of the most recent measurement.
248  */
249  int collect();
250 
251  /* this class has pointer data members, do not allow copying it */
252  QMC5883(const QMC5883 &);
253  QMC5883 operator=(const QMC5883 &);
254 };
255 
256 /*
257  * Driver 'main' command.
258  */
259 extern "C" __EXPORT int qmc5883_main(int argc, char *argv[]);
260 
261 
262 QMC5883::QMC5883(device::Device *interface, const char *path, enum Rotation rotation) :
263  CDev("QMC5883", path),
264  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
265  _interface(interface),
266  _reports(nullptr),
267  _scale{},
268  _range_scale(1.0f / 12000.0f),
269  _range_ga(2.0f),
270  _collect_phase(false),
271  _class_instance(-1),
273  _mag_topic(nullptr),
274  _sample_perf(perf_alloc(PC_ELAPSED, "qmc5883_read")),
275  _comms_errors(perf_alloc(PC_COUNT, "qmc5883_com_err")),
276  _range_errors(perf_alloc(PC_COUNT, "qmc5883_rng_err")),
277  _conf_errors(perf_alloc(PC_COUNT, "qmc5883_conf_err")),
278  _sensor_ok(false),
279  _rotation(rotation),
280  _range_bits(0),
281  _conf_reg(0),
284 {
285  // set the device type from the interface
286  _device_id.devid_s.bus_type = _interface->get_device_bus_type();
287  _device_id.devid_s.bus = _interface->get_device_bus();
288  _device_id.devid_s.address = _interface->get_device_address();
289  _device_id.devid_s.devtype = DRV_MAG_DEVTYPE_QMC5883;
290 
291  // default scaling
292  _scale.x_offset = 0;
293  _scale.x_scale = 1.0f;
294  _scale.y_offset = 0;
295  _scale.y_scale = 1.0f;
296  _scale.z_offset = 0;
297  _scale.z_scale = 1.0f;
298 }
299 
301 {
302  /* make sure we are truly inactive */
303  stop();
304 
305  if (_reports != nullptr) {
306  delete _reports;
307  }
308 
309  if (_class_instance != -1) {
311  }
312 
313  // free perf counters
318 }
319 
320 int
322 {
323  int ret = PX4_ERROR;
324 
325  ret = CDev::init();
326 
327  if (ret != OK) {
328  DEVICE_DEBUG("CDev init failed");
329  goto out;
330  }
331 
332  /* allocate basic report buffers */
333  _reports = new ringbuffer::RingBuffer(2, sizeof(mag_report));
334 
335  if (_reports == nullptr) {
336  goto out;
337  }
338 
339  /* reset the device configuration */
340  reset();
341 
343 
344  ret = OK;
345  /* sensor is ok */
346  _sensor_ok = true;
347 out:
348  return ret;
349 }
350 
351 /**
352  check that the configuration register has the right value. This is
353  done periodically to cope with I2C bus noise causing the
354  configuration of the compass to change.
355  */
357 {
358  int ret;
359 
360  uint8_t conf_reg_in = 0;
361  ret = read_reg(QMC5883_ADDR_CONTROL_1, conf_reg_in);
362 
363  if (OK != ret) {
365  return;
366  }
367 
368  if (conf_reg_in != _conf_reg) {
371 
372  if (OK != ret) {
374  }
375  }
376 }
377 
378 ssize_t
379 QMC5883::read(struct file *filp, char *buffer, size_t buflen)
380 {
381  unsigned count = buflen / sizeof(struct mag_report);
382  struct mag_report *mag_buf = reinterpret_cast<struct mag_report *>(buffer);
383  int ret = 0;
384 
385  /* buffer must be large enough */
386  if (count < 1) {
387  return -ENOSPC;
388  }
389 
390  /* if automatic measurement is enabled */
391  if (_measure_interval > 0) {
392  /*
393  * While there is space in the caller's buffer, and reports, copy them.
394  * Note that we may be pre-empted by the workq thread while we are doing this;
395  * we are careful to avoid racing with them.
396  */
397  while (count--) {
398  if (_reports->get(mag_buf)) {
399  ret += sizeof(struct mag_report);
400  mag_buf++;
401  }
402  }
403 
404  /* if there was no data, warn the caller */
405  return ret ? ret : -EAGAIN;
406  }
407 
408  /* manual measurement - run one conversion */
409  /* XXX really it'd be nice to lock against other readers here */
410  do {
411  _reports->flush();
412 
413  /* wait for it to complete */
415 
416  /* run the collection phase */
417  if (OK != collect()) {
418  ret = -EIO;
419  break;
420  }
421 
422  if (_reports->get(mag_buf)) {
423  ret = sizeof(struct mag_report);
424  }
425  } while (0);
426 
427  return ret;
428 }
429 
430 int
431 QMC5883::ioctl(struct file *filp, int cmd, unsigned long arg)
432 {
433  unsigned dummy = arg;
434 
435  switch (cmd) {
436  case SENSORIOCSPOLLRATE: {
437  switch (arg) {
438 
439  /* zero would be bad */
440  case 0:
441  return -EINVAL;
442 
443  /* set default polling rate */
445  /* do we need to start internal polling? */
446  bool want_start = (_measure_interval == 0);
447 
448  /* set interval for next measurement to minimum legal value */
450 
451  /* if we need to start the poll state machine, do it */
452  if (want_start) {
453  start();
454  }
455 
456  return OK;
457  }
458 
459  /* adjust to a legal polling interval in Hz */
460  default: {
461  /* do we need to start internal polling? */
462  bool want_start = (_measure_interval == 0);
463 
464  /* convert hz to tick interval via microseconds */
465  unsigned interval = (1000000 / arg);
466 
467  /* check against maximum rate */
468  if (interval < QMC5883_CONVERSION_INTERVAL) {
469  return -EINVAL;
470  }
471 
472  /* update interval for next measurement */
473  _measure_interval = interval;
474 
475  /* if we need to start the poll state machine, do it */
476  if (want_start) {
477  start();
478  }
479 
480  return OK;
481  }
482  }
483  }
484 
485  case SENSORIOCRESET:
486  return reset();
487 
488  case MAGIOCSRANGE:
489  return OK;
490 
491  case MAGIOCSSCALE:
492  /* set new scale factors */
493  memcpy(&_scale, (struct mag_calibration_s *)arg, sizeof(_scale));
494  return 0;
495 
496  case MAGIOCGSCALE:
497  /* copy out scale factors */
498  memcpy((struct mag_calibration_s *)arg, &_scale, sizeof(_scale));
499  return 0;
500 
501  case MAGIOCGEXTERNAL:
502  DEVICE_DEBUG("MAGIOCGEXTERNAL in main driver");
503  return _interface->ioctl(cmd, dummy);
504 
505  default:
506  /* give it to the superclass */
507  return CDev::ioctl(filp, cmd, arg);
508  }
509 }
510 
511 void
513 {
514  /* reset the report ring and state machine */
515  _collect_phase = false;
516  _reports->flush();
517 
518  /* schedule a cycle to start things */
519  ScheduleNow();
520 }
521 
522 void
524 {
525  if (_measure_interval > 0) {
526  /* ensure no new items are queued while we cancel this one */
527  _measure_interval = 0;
528  ScheduleClear();
529  }
530 }
531 
532 int
534 {
535  /* read 0x00 once */
536  uint8_t data_bits_in = 0;
537  read_reg(QMC5883_ADDR_DATA_OUT_X_LSB, data_bits_in);
538 
539  /* software reset */
541 
542  /* set reset period to 0x01 */
544 
545  //use fixed range of 2G
546  _range_scale = 1.0f / 12000.0f; // 12000 LSB/Gauss at +/- 2G range
547  _range_ga = 2.00f;
548  _range_bits = 0x00;
549 
550  /* set control register */
556 
557  return OK;
558 }
559 
560 void
562 {
563  if (_measure_interval == 0) {
564  return;
565  }
566 
567  /* collection phase? */
568  if (_collect_phase) {
569 
570  /* perform collection */
571  if (OK != collect()) {
572  DEVICE_DEBUG("collection error");
573  /* restart the measurement state machine */
574  start();
575  return;
576  }
577 
578  /* next phase is measurement */
579  _collect_phase = false;
580 
581  /*
582  * Is there a collect->measure gap?
583  */
585  /* schedule a fresh cycle call when we are ready to measure again */
587 
588  return;
589  }
590  }
591 
592  /* next phase is collection */
593  _collect_phase = true;
594 
595  if (_measure_interval > 0) {
596  /* schedule a fresh cycle call when the measurement is done */
597  ScheduleDelayed(QMC5883_CONVERSION_INTERVAL);
598  }
599 }
600 
601 
602 int
604 {
605 #pragma pack(push, 1)
606  struct { /* status register and data as read back from the device */
607  uint8_t x[2];
608  uint8_t y[2];
609  uint8_t z[2];
610  } qmc_report;
611 #pragma pack(pop)
612  struct {
613  int16_t x, y, z;
614  } report;
615 
616  int ret;
617  uint8_t check_counter;
618 
620  struct mag_report new_report;
621  bool sensor_is_onboard = false;
622 
623  float xraw_f;
624  float yraw_f;
625  float zraw_f;
626 
627  /* this should be fairly close to the end of the measurement, so the best approximation of the time */
628  new_report.timestamp = hrt_absolute_time();
629  new_report.error_count = perf_event_count(_comms_errors);
630  new_report.scaling = _range_scale;
631  new_report.device_id = _device_id.devid;
632 
633  /*
634  * @note We could read the status register here, which could tell us that
635  * we were too early and that the output registers are still being
636  * written. In the common case that would just slow us down, and
637  * we're better off just never being early.
638  */
639 
640  /* get measurements from the device */
641  ret = _interface->read(QMC5883_ADDR_DATA_OUT_X_LSB, (uint8_t *)&qmc_report, sizeof(qmc_report));
642 
643  if (ret != OK) {
645  DEVICE_DEBUG("data/status read error");
646  goto out;
647  }
648 
649  /* map data we just received LSB, MSB */
650  report.x = (((int16_t)qmc_report.x[1]) << 8) + qmc_report.x[0];
651  report.y = (((int16_t)qmc_report.y[1]) << 8) + qmc_report.y[0];
652  report.z = (((int16_t)qmc_report.z[1]) << 8) + qmc_report.z[0];
653 
654  /*
655  * If any of the values are -4096, there was an internal math error in the sensor.
656  * Generalise this to a simple range check that will also catch some bit errors.
657  */
658  if ((abs(report.x) > QMC5883_MAX_COUNT) ||
659  (abs(report.y) > QMC5883_MAX_COUNT) ||
660  (abs(report.z) > QMC5883_MAX_COUNT)) {
662  goto out;
663  }
664 
665  /* get temperature measurements from the device */
666  new_report.temperature = 0;
667 
668  if (_temperature_counter++ == 100) {
669  uint8_t raw_temperature[2];
670 
672 
674  raw_temperature, sizeof(raw_temperature));
675 
676  if (ret == OK) {
677  int16_t temp16 = (((int16_t)raw_temperature[1]) << 8) +
678  raw_temperature[0];
679  new_report.temperature = QMC5883_TEMP_OFFSET + temp16 * 1.0f / 100.0f;
680  }
681 
682  } else {
683  new_report.temperature = _last_report.temperature;
684  }
685 
686 
687  /*
688  * RAW outputs
689  *
690  * to align the sensor axes with the board, x and y need to be flipped
691  * and y needs to be negated
692  */
693  new_report.x_raw = -report.y;
694  new_report.y_raw = report.x;
695  /* z remains z */
696  new_report.z_raw = report.z;
697 
698  /* scale values for output */
699 
700  // XXX revisit for SPI part, might require a bus type IOCTL
701  unsigned dummy;
702  sensor_is_onboard = !_interface->ioctl(MAGIOCGEXTERNAL, dummy);
703  new_report.is_external = !sensor_is_onboard;
704 
705  if (sensor_is_onboard) {
706  // convert onboard so it matches offboard for the
707  // scaling below
708  report.y = -report.y;
709  report.x = -report.x;
710  }
711 
712  /* the standard external mag by 3DR has x pointing to the
713  * right, y pointing backwards, and z down, therefore switch x
714  * and y and invert y */
715  //TODO: sort out axes mapping
716  xraw_f = -report.y;
717  yraw_f = report.x;
718  zraw_f = report.z;
719 
720  // apply user specified rotation
721  rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);
722 
723  new_report.x = ((xraw_f * _range_scale) - _scale.x_offset) * _scale.x_scale;
724  /* flip axes and negate value for y */
725  new_report.y = ((yraw_f * _range_scale) - _scale.y_offset) * _scale.y_scale;
726  /* z remains z */
727  new_report.z = ((zraw_f * _range_scale) - _scale.z_offset) * _scale.z_scale;
728 
729  if (!(_pub_blocked)) {
730 
731  if (_mag_topic != nullptr) {
732  /* publish it */
733  orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);
734 
735  } else {
736  _mag_topic = orb_advertise_multi(ORB_ID(sensor_mag), &new_report,
737  &_orb_class_instance, (sensor_is_onboard) ? ORB_PRIO_HIGH : ORB_PRIO_MAX);
738 
739  if (_mag_topic == nullptr) {
740  DEVICE_DEBUG("ADVERT FAIL");
741  }
742  }
743  }
744 
745  _last_report = new_report;
746 
747  /* post a report to the ring */
748  _reports->force(&new_report);
749 
750  /* notify anyone waiting for data */
751  poll_notify(POLLIN);
752 
753  /*
754  periodically check the configuration
755  registers. With a bad I2C cable it is possible for the
756  registers to become corrupt, leading to bad readings. It
757  doesn't happen often, but given the poor cables some
758  vehicles have it is worth checking for.
759  */
760  check_counter = perf_event_count(_sample_perf) % 256;
761 
762 
763  if (check_counter == 0) {
764  check_conf();
765  }
766 
767  ret = OK;
768 
769 out:
771  return ret;
772 }
773 
774 int
775 QMC5883::write_reg(uint8_t reg, uint8_t val)
776 {
777  uint8_t buf = val;
778  return _interface->write(reg, &buf, 1);
779 }
780 
781 int
782 QMC5883::read_reg(uint8_t reg, uint8_t &val)
783 {
784  uint8_t buf = val;
785  int ret = _interface->read(reg, &buf, 1);
786  val = buf;
787  return ret;
788 }
789 
790 void
792 {
795  printf("poll interval: %u us\n", _measure_interval);
796  print_message(_last_report);
797  _reports->print_info("report queue");
798 }
799 
800 /**
801  * Local functions in support of the shell command.
802  */
803 namespace qmc5883
804 {
805 
806 /*
807  list of supported bus configurations
808  */
810  enum QMC5883_BUS busid;
811  const char *devpath;
813  uint8_t busnum;
815 } bus_options[] = {
816  { QMC5883_BUS_I2C_EXTERNAL, "/dev/qmc5883_ext", &QMC5883_I2C_interface, PX4_I2C_BUS_EXPANSION, NULL },
817 #ifdef PX4_I2C_BUS_EXPANSION1
818  { QMC5883_BUS_I2C_EXTERNAL, "/dev/qmc5883_ext1", &QMC5883_I2C_interface, PX4_I2C_BUS_EXPANSION1, NULL },
819 #endif
820 #ifdef PX4_I2C_BUS_EXPANSION2
821  { QMC5883_BUS_I2C_EXTERNAL, "/dev/qmc5883_ext2", &QMC5883_I2C_interface, PX4_I2C_BUS_EXPANSION2, NULL },
822 #endif
823 #ifdef PX4_I2C_BUS_ONBOARD
824  { QMC5883_BUS_I2C_INTERNAL, "/dev/qmc5883_int", &QMC5883_I2C_interface, PX4_I2C_BUS_ONBOARD, NULL },
825 #endif
826 #ifdef PX4_SPIDEV_HMC
827  { QMC5883_BUS_SPI, "/dev/qmc5883_spi", &QMC5883_SPI_interface, PX4_SPI_BUS_SENSORS, NULL },
828 #endif
829 };
830 #define NUM_BUS_OPTIONS (sizeof(bus_options)/sizeof(bus_options[0]))
831 
832 void start(enum QMC5883_BUS busid, enum Rotation rotation);
833 int stop();
834 bool start_bus(struct qmc5883_bus_option &bus, enum Rotation rotation);
835 struct qmc5883_bus_option &find_bus(enum QMC5883_BUS busid);
836 void test(enum QMC5883_BUS busid);
837 void reset(enum QMC5883_BUS busid);
838 int info(enum QMC5883_BUS busid);
839 int temp_enable(QMC5883_BUS busid, bool enable);
840 void usage();
841 
842 /**
843  * start driver for a specific bus option
844  */
845 bool
846 start_bus(struct qmc5883_bus_option &bus, enum Rotation rotation)
847 {
848  if (bus.dev != nullptr) {
849  errx(1, "bus option already started");
850  }
851 
852  device::Device *interface = bus.interface_constructor(bus.busnum);
853 
854  if (interface->init() != OK) {
855  delete interface;
856  warnx("no device on bus %u (type: %u)", (unsigned)bus.busnum, (unsigned)bus.busid);
857  return false;
858  }
859 
860  bus.dev = new QMC5883(interface, bus.devpath, rotation);
861 
862  if (bus.dev != nullptr && OK != bus.dev->init()) {
863  delete bus.dev;
864  bus.dev = NULL;
865  return false;
866  }
867 
868  int fd = open(bus.devpath, O_RDONLY);
869 
870  if (fd < 0) {
871  return false;
872  }
873 
875  close(fd);
876  errx(1, "Failed to setup poll rate");
877  }
878 
879  close(fd);
880 
881  return true;
882 }
883 
884 /**
885  * Start the driver.
886  *
887  * This function call only returns once the driver
888  * is either successfully up and running or failed to start.
889  */
890 void
891 start(enum QMC5883_BUS busid, enum Rotation rotation)
892 {
893  bool started = false;
894 
895  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
896  if (busid == QMC5883_BUS_ALL && bus_options[i].dev != NULL) {
897  // this device is already started
898  continue;
899  }
900 
901  if (busid != QMC5883_BUS_ALL && bus_options[i].busid != busid) {
902  // not the one that is asked for
903  continue;
904  }
905 
906  started |= start_bus(bus_options[i], rotation);
907  }
908 
909  if (!started) {
910  exit(1);
911  }
912 }
913 
914 int
916 {
917  bool stopped = false;
918 
919  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
920  if (bus_options[i].dev != nullptr) {
921  bus_options[i].dev->stop();
922  delete bus_options[i].dev;
923  bus_options[i].dev = nullptr;
924  stopped = true;
925  }
926  }
927 
928  return !stopped;
929 }
930 
931 /**
932  * find a bus structure for a busid
933  */
935 {
936  for (unsigned i = 0; i < NUM_BUS_OPTIONS; i++) {
937  if ((busid == QMC5883_BUS_ALL ||
938  busid == bus_options[i].busid) && bus_options[i].dev != NULL) {
939  return bus_options[i];
940  }
941  }
942 
943  errx(1, "bus %u not started", (unsigned)busid);
944 }
945 
946 
947 /**
948  * Perform some basic functional tests on the driver;
949  * make sure we can collect data from the sensor in polled
950  * and automatic modes.
951  */
952 void
953 test(enum QMC5883_BUS busid)
954 {
955  struct qmc5883_bus_option &bus = find_bus(busid);
956  struct mag_report report;
957  ssize_t sz;
958  int ret;
959  const char *path = bus.devpath;
960 
961  int fd = open(path, O_RDONLY);
962 
963  if (fd < 0) {
964  err(1, "%s open failed (try 'qmc5883 start')", path);
965  }
966 
967  /* do a simple demand read */
968  sz = read(fd, &report, sizeof(report));
969 
970  if (sz != sizeof(report)) {
971  err(1, "immediate read failed");
972  }
973 
974  print_message(report);
975 
976  /* check if mag is onboard or external */
977  if ((ret = ioctl(fd, MAGIOCGEXTERNAL, 0)) < 0) {
978  errx(1, "failed to get if mag is onboard or external");
979  }
980 
981  warnx("device active: %s", ret ? "external" : "onboard");
982 
983  /* read the sensor 5x and report each value */
984  for (unsigned i = 0; i < 5; i++) {
985  struct pollfd fds;
986 
987  /* wait for data to be ready */
988  fds.fd = fd;
989  fds.events = POLLIN;
990  ret = poll(&fds, 1, 2000);
991 
992  if (ret != 1) {
993  errx(1, "timed out waiting for sensor data");
994  }
995 
996  /* now go get it */
997  sz = read(fd, &report, sizeof(report));
998 
999  if (sz != sizeof(report)) {
1000  err(1, "periodic read failed");
1001  }
1002 
1003  print_message(report);
1004  }
1005 
1006  PX4_INFO("PASS");
1007  exit(0);
1008 }
1009 
1010 /**
1011  * Reset the driver.
1012  */
1013 void
1014 reset(enum QMC5883_BUS busid)
1015 {
1016  struct qmc5883_bus_option &bus = find_bus(busid);
1017  const char *path = bus.devpath;
1018 
1019  int fd = open(path, O_RDONLY);
1020 
1021  if (fd < 0) {
1022  err(1, "failed ");
1023  }
1024 
1025  if (ioctl(fd, SENSORIOCRESET, 0) < 0) {
1026  err(1, "driver reset failed");
1027  }
1028 
1030  err(1, "driver poll restart failed");
1031  }
1032 
1033  exit(0);
1034 }
1035 
1036 
1037 /**
1038  * Print a little info about the driver.
1039  */
1040 int
1041 info(enum QMC5883_BUS busid)
1042 {
1043  struct qmc5883_bus_option &bus = find_bus(busid);
1044 
1045  warnx("running on bus: %u (%s)\n", (unsigned)bus.busid, bus.devpath);
1046  bus.dev->print_info();
1047  exit(0);
1048 }
1049 
1050 void
1052 {
1053  warnx("missing command: try 'start', 'info', 'test', 'reset', 'info'");
1054  warnx("options:");
1055  warnx(" -R rotation");
1056  warnx(" -X only external bus");
1057 #if (PX4_I2C_BUS_ONBOARD || PX4_SPIDEV_HMC)
1058  warnx(" -I only internal bus");
1059 #endif
1060 }
1061 
1062 } // namespace
1063 
1064 int
1065 qmc5883_main(int argc, char *argv[])
1066 {
1067  int ch;
1068  enum QMC5883_BUS busid = QMC5883_BUS_ALL;
1069  enum Rotation rotation = ROTATION_NONE;
1070 
1071  if (argc < 2) {
1072  qmc5883::usage();
1073  exit(0);
1074  }
1075 
1076  while ((ch = getopt(argc, argv, "XISR:CT")) != EOF) {
1077  switch (ch) {
1078  case 'R':
1079  rotation = (enum Rotation)atoi(optarg);
1080  break;
1081 #if (PX4_I2C_BUS_ONBOARD || PX4_SPIDEV_HMC)
1082 
1083  case 'I':
1084  busid = QMC5883_BUS_I2C_INTERNAL;
1085  break;
1086 #endif
1087 
1088  case 'X':
1089  busid = QMC5883_BUS_I2C_EXTERNAL;
1090  break;
1091 
1092  case 'S':
1093  busid = QMC5883_BUS_SPI;
1094  break;
1095 
1096  default:
1097  qmc5883::usage();
1098  exit(0);
1099  }
1100  }
1101 
1102  const char *verb = argv[optind];
1103 
1104  /*
1105  * Start/load the driver.
1106  */
1107  if (!strcmp(verb, "start")) {
1108  qmc5883::start(busid, rotation);
1109 
1110  exit(0);
1111  }
1112 
1113  /*
1114  * Stop the driver
1115  */
1116  if (!strcmp(verb, "stop")) {
1117  return qmc5883::stop();
1118  }
1119 
1120  /*
1121  * Test the driver/device.
1122  */
1123  if (!strcmp(verb, "test")) {
1124  qmc5883::test(busid);
1125  }
1126 
1127  /*
1128  * Reset the driver.
1129  */
1130  if (!strcmp(verb, "reset")) {
1131  qmc5883::reset(busid);
1132  }
1133 
1134 
1135  /*
1136  * Print driver information.
1137  */
1138  if (!strcmp(verb, "info") || !strcmp(verb, "status")) {
1139  qmc5883::info(busid);
1140  }
1141 
1142  errx(1, "unrecognized command, try 'start', 'test', 'reset', or 'info'");
1143 }
virtual ~QMC5883()
Definition: qmc5883.cpp:300
#define QMC5883_ADDR_TEMP_OUT_LSB
Definition: qmc5883.cpp:95
#define MAGIOCGSCALE
copy the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:76
#define MAGIOCGEXTERNAL
determine if mag is external or onboard
Definition: drv_mag.h:88
int _orb_class_instance
Definition: qmc5883.cpp:170
Local functions in support of the shell command.
Definition: qmc5883.cpp:803
orb_advert_t _mag_topic
Definition: qmc5883.cpp:172
virtual int open(file_t *filep)
Handle an open of the device.
Definition: CDev.cpp:141
void start(enum QMC5883_BUS busid, enum Rotation rotation)
Start the driver.
Definition: qmc5883.cpp:891
measure the time elapsed performing an event
Definition: perf_counter.h:56
uint8_t _temperature_counter
Definition: qmc5883.cpp:188
API for the uORB lightweight object broker.
enum QMC5883_BUS busid
Definition: qmc5883.cpp:810
QMC5883_BUS
Definition: qmc5883.cpp:130
__EXPORT int qmc5883_main(int argc, char *argv[])
Definition: qmc5883.cpp:1065
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 SENSOR_POLLRATE_DEFAULT
poll at driver normal rate
Definition: drv_sensor.h:136
__EXPORT void rotate_3f(enum Rotation rot, float &x, float &y, float &z)
rotate a 3 element float vector in-place
Definition: rotation.cpp:63
void usage(const char *reason)
Print the correct usage.
Definition: Commander.cpp:4238
device::Device * QMC5883_SPI_interface(int bus)
uint8_t _conf_reg
Definition: qmc5883.cpp:187
#define QMC5883_CONVERSION_INTERVAL
Definition: qmc5883.cpp:85
float _range_ga
Definition: qmc5883.cpp:167
Definition: I2C.hpp:51
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
struct qmc5883_bus_option & find_bus(enum QMC5883_BUS busid)
find a bus structure for a busid
Definition: qmc5883.cpp:934
Device(const Device &)=delete
struct mag_calibration_s _scale
Definition: qmc5883.cpp:165
QMC5883(device::Device *interface, const char *path, enum Rotation rotation)
Definition: qmc5883.cpp:262
count the number of times an event occurs
Definition: perf_counter.h:55
perf_counter_t _range_errors
Definition: qmc5883.cpp:176
#define QMC5883_MODE_REG_CONTINOUS_MODE
Definition: qmc5883.cpp:108
Shared defines for the qmc5883 driver.
Vector rotation library.
#define QMC5883_SOFT_RESET
Definition: qmc5883.cpp:123
perf_counter_t _conf_errors
Definition: qmc5883.cpp:177
High-resolution timer with callouts and timekeeping.
#define QMC5883_ADDR_CONTROL_2
Definition: qmc5883.cpp:98
int _class_instance
Definition: qmc5883.cpp:169
#define QMC5883_TEMP_OFFSET
Definition: qmc5883.cpp:128
virtual int close(file_t *filep)
Handle a close of the device.
Definition: CDev.cpp:166
Abstract class for any character device.
Definition: CDev.hpp:60
virtual void poll_notify(pollevent_t events)
Report new poll events.
Definition: CDev.cpp:330
#define MAGIOCSRANGE
set the measurement range to handle (at least) arg Gauss
Definition: drv_mag.h:79
QMC5883_constructor interface_constructor
Definition: qmc5883.cpp:812
float x_offset
Definition: drv_mag.h:57
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
int read_reg(uint8_t reg, uint8_t &val)
Read a register.
Definition: qmc5883.cpp:782
void Run() override
Perform a poll cycle; collect from the previous measurement and start a new one.
Definition: qmc5883.cpp:561
Generic device / sensor interface.
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
#define QMC5883_ADDR_SET_RESET
Definition: qmc5883.cpp:99
enum Rotation _rotation
Definition: qmc5883.cpp:182
device identifier information
Definition: Device.hpp:240
void perf_count(perf_counter_t handle)
Count a performance event.
void usage()
Prints info about the driver argument usage.
Definition: qmc5883.cpp:1051
bool start_bus(struct qmc5883_bus_option &bus, enum Rotation rotation)
start driver for a specific bus option
Definition: qmc5883.cpp:846
#define MAGIOCSSCALE
set the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:73
Header common to all counters.
void print_info()
Diagnostics - print some basic information about the driver.
Definition: qmc5883.cpp:791
device::Device *(* QMC5883_constructor)(int)
Definition: qmc5883.h:52
void perf_free(perf_counter_t handle)
Free a counter.
#define MAG_BASE_DEVICE_PATH
Definition: drv_mag.h:47
#define QMC5883_MAX_COUNT
Definition: qmc5883.cpp:86
void init()
Activates/configures the hardware registers.
perf_counter_t _sample_perf
Definition: qmc5883.cpp:174
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 perf_alloc(a, b)
Definition: px4io.h:59
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
#define NUM_BUS_OPTIONS
Definition: qmc5883.cpp:830
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
Device * _interface
Definition: qmc5883.cpp:159
float y_offset
Definition: drv_mag.h:59
#define warnx(...)
Definition: err.h:95
#define QMC5883_OUTPUT_DATA_RATE_200
Definition: qmc5883.cpp:112
Simple error/warning functions, heavily inspired by the BSD functions of the same names...
virtual int ioctl(struct file *filp, int cmd, unsigned long arg)
Definition: qmc5883.cpp:431
bool _collect_phase
Definition: qmc5883.cpp:168
void perf_end(perf_counter_t handle)
End a performance event.
uint8_t _range_bits
Definition: qmc5883.cpp:186
void start()
Initialise the automatic measurement state machine and start it.
Definition: qmc5883.cpp:512
int write_reg(uint8_t reg, uint8_t val)
Write a register.
Definition: qmc5883.cpp:775
int info(enum QMC5883_BUS busid)
Print a little info about the driver.
Definition: qmc5883.cpp:1041
void test(enum QMC5883_BUS busid)
Perform some basic functional tests on the driver; make sure we can collect data from the sensor in p...
Definition: qmc5883.cpp:953
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
void reset(enum QMC5883_BUS busid)
Reset the driver.
Definition: qmc5883.cpp:1014
int fd
Definition: dataman.cpp:146
void stop()
Stop the automatic measurement state machine.
Definition: qmc5883.cpp:523
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
#define err(eval,...)
Definition: err.h:83
float z_offset
Definition: drv_mag.h:61
uint8_t _temperature_error_count
Definition: qmc5883.cpp:189
QMC5883 operator=(const QMC5883 &)
void check_conf(void)
check the sensor configuration.
Definition: qmc5883.cpp:356
#define DRV_MAG_DEVTYPE_QMC5883
Definition: drv_sensor.h:62
unsigned _measure_interval
Definition: qmc5883.cpp:162
virtual ssize_t read(struct file *filp, char *buffer, size_t buflen)
Definition: qmc5883.cpp:379
used for info()
Definition: qmc5883.cpp:184
#define QMC5883_SET_DEFAULT
Definition: qmc5883.cpp:126
#define QMC5883_ADDR_DATA_OUT_X_LSB
Definition: qmc5883.cpp:88
struct @83::@85::@87 file
#define QMC5883_OVERSAMPLE_512
Definition: qmc5883.cpp:115
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
#define errx(eval,...)
Definition: err.h:89
Definition: bst.cpp:62
float _range_scale
Definition: qmc5883.cpp:166
CDev(const char *name, const char *devname)
Constructor.
Definition: CDev.cpp:50
#define QMC5883_ADDR_CONTROL_1
Definition: qmc5883.cpp:97
#define OK
Definition: uavcan_main.cpp:71
int temp_enable(QMC5883_BUS busid, bool enable)
bool _sensor_ok
sensor was found and reports ok
Definition: qmc5883.cpp:180
perf_counter_t _comms_errors
Definition: qmc5883.cpp:175
#define QMC5883_OUTPUT_RANGE_2G
Definition: qmc5883.cpp:113
int reset()
Reset the device.
Definition: qmc5883.cpp:533
bool _pub_blocked
true if publishing should be blocked
Definition: CDev.hpp:91
Dual< Scalar, N > abs(const Dual< Scalar, N > &a)
Definition: Dual.hpp:196
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
device::Device * QMC5883_I2C_interface(int bus)
Definition: qmc5883_i2c.cpp:83
void perf_begin(perf_counter_t handle)
Begin a performance event.
struct qmc5883::qmc5883_bus_option bus_options[]
virtual int init()
Definition: qmc5883.cpp:321
#define DEVICE_DEBUG(FMT,...)
Definition: Device.hpp:52
ringbuffer::RingBuffer * _reports
Definition: qmc5883.cpp:164
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
int collect()
Collect the result of the most recent measurement.
Definition: qmc5883.cpp:603
int stop()
Stop the driver.
Definition: qmc5883.cpp:915
virtual int poll(file_t *filep, px4_pollfd_struct_t *fds, bool setup)
Perform a poll setup/teardown operation.
Definition: CDev.cpp:213
Performance measuring tools.
Base class for devices connected via I2C.
#define mag_report
Definition: drv_mag.h:53