PX4 Firmware
PX4 Autopilot Software http://px4.io
HMC5883.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2012-2015 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 #include "HMC5883.hpp"
35 
36 HMC5883::HMC5883(device::Device *interface, const char *path, enum Rotation rotation) :
37  CDev("HMC5883", path),
38  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(interface->get_device_id())),
39  _interface(interface),
40  _reports(nullptr),
41  _scale{},
42  _range_scale(0), /* default range scale from counts to gauss */
43  _range_ga(1.9f),
44  _collect_phase(false),
45  _class_instance(-1),
47  _mag_topic(nullptr),
48  _sample_perf(perf_alloc(PC_ELAPSED, MODULE_NAME": read")),
49  _comms_errors(perf_alloc(PC_COUNT, MODULE_NAME": com_err")),
50  _range_errors(perf_alloc(PC_COUNT, MODULE_NAME": rng_err")),
51  _conf_errors(perf_alloc(PC_COUNT, MODULE_NAME": conf_err")),
52  _sensor_ok(false),
53  _rotation(rotation),
54  _range_bits(0),
55  _conf_reg(0),
58 {
59  // set the device type from the interface
60  _device_id.devid_s.bus_type = _interface->get_device_bus_type();
61  _device_id.devid_s.bus = _interface->get_device_bus();
62  _device_id.devid_s.address = _interface->get_device_address();
63  _device_id.devid_s.devtype = DRV_MAG_DEVTYPE_HMC5883;
64 
65  // default scaling
66  _scale.x_offset = 0;
67  _scale.x_scale = 1.0f;
68  _scale.y_offset = 0;
69  _scale.y_scale = 1.0f;
70  _scale.z_offset = 0;
71  _scale.z_scale = 1.0f;
72 }
73 
75 {
76  /* make sure we are truly inactive */
77  stop();
78 
79  if (_reports != nullptr) {
80  delete _reports;
81  }
82 
83  if (_class_instance != -1) {
85  }
86 
87  // free perf counters
92 }
93 
94 int
96 {
97  int ret = PX4_ERROR;
98 
99  ret = CDev::init();
100 
101  if (ret != OK) {
102  DEVICE_DEBUG("CDev init failed");
103  goto out;
104  }
105 
106  /* allocate basic report buffers */
107  _reports = new ringbuffer::RingBuffer(2, sizeof(mag_report));
108 
109  if (_reports == nullptr) {
110  goto out;
111  }
112 
113  /* reset the device configuration */
114  reset();
115 
117 
118  ret = OK;
119  /* sensor is ok, but not calibrated */
120  _sensor_ok = true;
121 out:
122  return ret;
123 }
124 
125 int HMC5883::set_range(unsigned range)
126 {
127  if (range < 0.88f) {
128  _range_bits = 0x00;
129  _range_scale = 1.0f / 1370.0f;
130  _range_ga = 0.88f;
131 
132  } else if (range <= 1.3f) {
133  _range_bits = 0x01;
134  _range_scale = 1.0f / 1090.0f;
135  _range_ga = 1.3f;
136 
137  } else if (range <= 2) {
138  _range_bits = 0x02;
139  _range_scale = 1.0f / 820.0f;
140  _range_ga = 1.9f;
141 
142  } else if (range <= 3) {
143  _range_bits = 0x03;
144  _range_scale = 1.0f / 660.0f;
145  _range_ga = 2.5f;
146 
147  } else if (range <= 4) {
148  _range_bits = 0x04;
149  _range_scale = 1.0f / 440.0f;
150  _range_ga = 4.0f;
151 
152  } else if (range <= 4.7f) {
153  _range_bits = 0x05;
154  _range_scale = 1.0f / 390.0f;
155  _range_ga = 4.7f;
156 
157  } else if (range <= 5.6f) {
158  _range_bits = 0x06;
159  _range_scale = 1.0f / 330.0f;
160  _range_ga = 5.6f;
161 
162  } else {
163  _range_bits = 0x07;
164  _range_scale = 1.0f / 230.0f;
165  _range_ga = 8.1f;
166  }
167 
168  int ret;
169 
170  /*
171  * Send the command to set the range
172  */
173  ret = write_reg(ADDR_CONF_B, (_range_bits << 5));
174 
175  if (OK != ret) {
177  }
178 
179  uint8_t range_bits_in = 0;
180  ret = read_reg(ADDR_CONF_B, range_bits_in);
181 
182  if (OK != ret) {
184  }
185 
186  return !(range_bits_in == (_range_bits << 5));
187 }
188 
189 /**
190  check that the range register has the right value. This is done
191  periodically to cope with I2C bus noise causing the range of the
192  compass changing.
193  */
195 {
196  int ret;
197 
198  uint8_t range_bits_in = 0;
199  ret = read_reg(ADDR_CONF_B, range_bits_in);
200 
201  if (OK != ret) {
203  return;
204  }
205 
206  if (range_bits_in != (_range_bits << 5)) {
208  ret = write_reg(ADDR_CONF_B, (_range_bits << 5));
209 
210  if (OK != ret) {
212  }
213  }
214 }
215 
216 /**
217  check that the configuration register has the right value. This is
218  done periodically to cope with I2C bus noise causing the
219  configuration of the compass to change.
220  */
222 {
223  int ret;
224 
225  uint8_t conf_reg_in = 0;
226  ret = read_reg(ADDR_CONF_A, conf_reg_in);
227 
228  if (OK != ret) {
230  return;
231  }
232 
233  if (conf_reg_in != _conf_reg) {
236 
237  if (OK != ret) {
239  }
240  }
241 }
242 
243 ssize_t
244 HMC5883::read(cdev::file_t *filp, char *buffer, size_t buflen)
245 {
246  unsigned count = buflen / sizeof(struct mag_report);
247  struct mag_report *mag_buf = reinterpret_cast<struct mag_report *>(buffer);
248  int ret = 0;
249 
250  /* buffer must be large enough */
251  if (count < 1) {
252  return -ENOSPC;
253  }
254 
255  /* if automatic measurement is enabled */
256  if (_measure_interval > 0) {
257  /*
258  * While there is space in the caller's buffer, and reports, copy them.
259  * Note that we may be pre-empted by the workq thread while we are doing this;
260  * we are careful to avoid racing with them.
261  */
262  while (count--) {
263  if (_reports->get(mag_buf)) {
264  ret += sizeof(struct mag_report);
265  mag_buf++;
266  }
267  }
268 
269  /* if there was no data, warn the caller */
270  return ret ? ret : -EAGAIN;
271  }
272 
273  /* manual measurement - run one conversion */
274  /* XXX really it'd be nice to lock against other readers here */
275  do {
276  _reports->flush();
277 
278  /* trigger a measurement */
279  if (OK != measure()) {
280  ret = -EIO;
281  break;
282  }
283 
284  /* wait for it to complete */
285  px4_usleep(HMC5883_CONVERSION_INTERVAL);
286 
287  /* run the collection phase */
288  if (OK != collect()) {
289  ret = -EIO;
290  break;
291  }
292 
293  if (_reports->get(mag_buf)) {
294  ret = sizeof(struct mag_report);
295  }
296  } while (0);
297 
298  return ret;
299 }
300 
301 int
302 HMC5883::ioctl(cdev::file_t *filp, int cmd, unsigned long arg)
303 {
304  unsigned dummy = arg;
305 
306  switch (cmd) {
307  case SENSORIOCSPOLLRATE: {
308  switch (arg) {
309 
310  /* zero would be bad */
311  case 0:
312  return -EINVAL;
313 
314  /* set default polling rate */
316  /* do we need to start internal polling? */
317  bool want_start = (_measure_interval == 0);
318 
319  /* set interval for next measurement to minimum legal value */
321 
322  /* if we need to start the poll state machine, do it */
323  if (want_start) {
324  start();
325  }
326 
327  return OK;
328  }
329 
330  /* adjust to a legal polling interval in Hz */
331  default: {
332  /* do we need to start internal polling? */
333  bool want_start = (_measure_interval == 0);
334 
335  /* convert hz to interval in microseconds */
336  unsigned interval = (1000000 / arg);
337 
338  /* check against maximum rate */
339  if (interval < HMC5883_CONVERSION_INTERVAL) {
340  return -EINVAL;
341  }
342 
343  /* update interval for next measurement */
344  _measure_interval = interval;
345 
346  /* if we need to start the poll state machine, do it */
347  if (want_start) {
348  start();
349  }
350 
351  return OK;
352  }
353  }
354  }
355 
356  case SENSORIOCRESET:
357  return reset();
358 
359  case MAGIOCSRANGE:
360  return set_range(arg);
361 
362  case MAGIOCSSCALE:
363  /* set new scale factors */
364  memcpy(&_scale, (struct mag_calibration_s *)arg, sizeof(_scale));
365  return 0;
366 
367  case MAGIOCGSCALE:
368  /* copy out scale factors */
369  memcpy((struct mag_calibration_s *)arg, &_scale, sizeof(_scale));
370  return 0;
371 
372  case MAGIOCCALIBRATE:
373  return calibrate(filp, arg);
374 
375  case MAGIOCEXSTRAP:
376  return set_excitement(arg);
377 
378  case MAGIOCGEXTERNAL:
379  DEVICE_DEBUG("MAGIOCGEXTERNAL in main driver");
380  return _interface->ioctl(cmd, dummy);
381 
382  case MAGIOCSTEMPCOMP:
383  return set_temperature_compensation(arg);
384 
385  default:
386  /* give it to the superclass */
387  return CDev::ioctl(filp, cmd, arg);
388  }
389 }
390 
391 void
393 {
394  /* reset the report ring and state machine */
395  _collect_phase = false;
396  _reports->flush();
397 
398  /* schedule a cycle to start things */
399  ScheduleNow();
400 }
401 
402 void
404 {
405  if (_measure_interval > 0) {
406  /* ensure no new items are queued while we cancel this one */
407  _measure_interval = 0;
408  ScheduleClear();
409  }
410 }
411 
412 int
414 {
415  /* set range, ceil floating point number */
416  return set_range(_range_ga + 0.5f);
417 }
418 
419 void
421 {
422  if (_measure_interval == 0) {
423  return;
424  }
425 
426  /* collection phase? */
427  if (_collect_phase) {
428 
429  /* perform collection */
430  if (OK != collect()) {
431  DEVICE_DEBUG("collection error");
432  /* restart the measurement state machine */
433  start();
434  return;
435  }
436 
437  /* next phase is measurement */
438  _collect_phase = false;
439 
440  /*
441  * Is there a collect->measure gap?
442  */
444 
445  /* schedule a fresh cycle call when we are ready to measure again */
447 
448  return;
449  }
450  }
451 
452  /* measurement phase */
453  if (OK != measure()) {
454  DEVICE_DEBUG("measure error");
455  }
456 
457  /* next phase is collection */
458  _collect_phase = true;
459 
460  if (_measure_interval > 0) {
461  /* schedule a fresh cycle call when the measurement is done */
462  ScheduleDelayed(HMC5883_CONVERSION_INTERVAL);
463  }
464 }
465 
466 int
468 {
469  int ret;
470 
471  /*
472  * Send the command to begin a measurement.
473  */
475 
476  if (OK != ret) {
478  }
479 
480  return ret;
481 }
482 
483 int
485 {
486 #pragma pack(push, 1)
487  struct { /* status register and data as read back from the device */
488  uint8_t x[2];
489  uint8_t z[2];
490  uint8_t y[2];
491  } hmc_report;
492 #pragma pack(pop)
493  struct {
494  int16_t x, y, z;
495  } report;
496 
497  int ret;
498  uint8_t check_counter;
499 
501  struct mag_report new_report;
502  bool sensor_is_onboard = false;
503 
504  float xraw_f;
505  float yraw_f;
506  float zraw_f;
507 
508  /* this should be fairly close to the end of the measurement, so the best approximation of the time */
509  new_report.timestamp = hrt_absolute_time();
510  new_report.error_count = perf_event_count(_comms_errors);
511  new_report.scaling = _range_scale;
512  new_report.device_id = _device_id.devid;
513 
514  /*
515  * @note We could read the status register here, which could tell us that
516  * we were too early and that the output registers are still being
517  * written. In the common case that would just slow us down, and
518  * we're better off just never being early.
519  */
520 
521  /* get measurements from the device */
522  ret = _interface->read(ADDR_DATA_OUT_X_MSB, (uint8_t *)&hmc_report, sizeof(hmc_report));
523 
524  if (ret != OK) {
526  DEVICE_DEBUG("data/status read error");
527  goto out;
528  }
529 
530  /* swap the data we just received */
531  report.x = (((int16_t)hmc_report.x[0]) << 8) + hmc_report.x[1];
532  report.y = (((int16_t)hmc_report.y[0]) << 8) + hmc_report.y[1];
533  report.z = (((int16_t)hmc_report.z[0]) << 8) + hmc_report.z[1];
534 
535  /*
536  * If any of the values are -4096, there was an internal math error in the sensor.
537  * Generalise this to a simple range check that will also catch some bit errors.
538  */
539  if ((abs(report.x) > 2048) ||
540  (abs(report.y) > 2048) ||
541  (abs(report.z) > 2048)) {
543  goto out;
544  }
545 
546  /* get measurements from the device */
547  new_report.temperature = 0;
548 
550  /*
551  if temperature compensation is enabled read the
552  temperature too.
553 
554  We read the temperature every 10 samples to avoid
555  excessive I2C traffic
556  */
557  if (_temperature_counter++ == 10) {
558  uint8_t raw_temperature[2];
559 
561 
562  ret = _interface->read(ADDR_TEMP_OUT_MSB,
563  raw_temperature, sizeof(raw_temperature));
564 
565  if (ret == OK) {
566  int16_t temp16 = (((int16_t)raw_temperature[0]) << 8) +
567  raw_temperature[1];
568  new_report.temperature = 25 + (temp16 / (16 * 8.0f));
570 
571  } else {
573 
574  if (_temperature_error_count == 10) {
575  /*
576  it probably really is an old HMC5883,
577  and can't do temperature. Disable it
578  */
580  DEVICE_DEBUG("disabling temperature compensation");
582  }
583  }
584 
585  } else {
586  new_report.temperature = _last_report.temperature;
587  }
588  }
589 
590  /*
591  * RAW outputs
592  *
593  * to align the sensor axes with the board, x and y need to be flipped
594  * and y needs to be negated
595  */
596  new_report.x_raw = -report.y;
597  new_report.y_raw = report.x;
598  /* z remains z */
599  new_report.z_raw = report.z;
600 
601  /* scale values for output */
602 
603  // XXX revisit for SPI part, might require a bus type IOCTL
604  unsigned dummy;
605  sensor_is_onboard = !_interface->ioctl(MAGIOCGEXTERNAL, dummy);
606  new_report.is_external = !sensor_is_onboard;
607 
608  if (sensor_is_onboard) {
609  // convert onboard so it matches offboard for the
610  // scaling below
611  report.y = -report.y;
612  report.x = -report.x;
613  }
614 
615  /* the standard external mag by 3DR has x pointing to the
616  * right, y pointing backwards, and z down, therefore switch x
617  * and y and invert y */
618  xraw_f = -report.y;
619  yraw_f = report.x;
620  zraw_f = report.z;
621 
622  // apply user specified rotation
623  rotate_3f(_rotation, xraw_f, yraw_f, zraw_f);
624 
625  new_report.x = ((xraw_f * _range_scale) - _scale.x_offset) * _scale.x_scale;
626  /* flip axes and negate value for y */
627  new_report.y = ((yraw_f * _range_scale) - _scale.y_offset) * _scale.y_scale;
628  /* z remains z */
629  new_report.z = ((zraw_f * _range_scale) - _scale.z_offset) * _scale.z_scale;
630 
631  if (!(_pub_blocked)) {
632 
633  if (_mag_topic != nullptr) {
634  /* publish it */
635  orb_publish(ORB_ID(sensor_mag), _mag_topic, &new_report);
636 
637  } else {
638  _mag_topic = orb_advertise_multi(ORB_ID(sensor_mag), &new_report,
639  &_orb_class_instance, (sensor_is_onboard) ? ORB_PRIO_HIGH : ORB_PRIO_MAX);
640 
641  if (_mag_topic == nullptr) {
642  DEVICE_DEBUG("ADVERT FAIL");
643  }
644  }
645  }
646 
647  _last_report = new_report;
648 
649  /* post a report to the ring */
650  _reports->force(&new_report);
651 
652  /* notify anyone waiting for data */
653  poll_notify(POLLIN);
654 
655  /*
656  periodically check the range register and configuration
657  registers. With a bad I2C cable it is possible for the
658  registers to become corrupt, leading to bad readings. It
659  doesn't happen often, but given the poor cables some
660  vehicles have it is worth checking for.
661  */
662  check_counter = perf_event_count(_sample_perf) % 256;
663 
664  if (check_counter == 0) {
665  check_range();
666  }
667 
668  if (check_counter == 128) {
669  check_conf();
670  }
671 
672  ret = OK;
673 
674 out:
676  return ret;
677 }
678 
679 int HMC5883::calibrate(cdev::file_t *filp, unsigned enable)
680 {
681  sensor_mag_s report{};
682  ssize_t sz;
683  int ret = 1;
684  uint8_t good_count = 0;
685 
686  // XXX do something smarter here
687  int fd = (int)enable;
688 
689  struct mag_calibration_s mscale_previous;
690  mscale_previous.x_offset = 0.0f;
691  mscale_previous.x_scale = 1.0f;
692  mscale_previous.y_offset = 0.0f;
693  mscale_previous.y_scale = 1.0f;
694  mscale_previous.z_offset = 0.0f;
695  mscale_previous.z_scale = 1.0f;
696 
697  struct mag_calibration_s mscale_null;
698  mscale_null.x_offset = 0.0f;
699  mscale_null.x_scale = 1.0f;
700  mscale_null.y_offset = 0.0f;
701  mscale_null.y_scale = 1.0f;
702  mscale_null.z_offset = 0.0f;
703  mscale_null.z_scale = 1.0f;
704 
705  float sum_excited[3] = {0.0f, 0.0f, 0.0f};
706 
707  /* expected axis scaling. The datasheet says that 766 will
708  * be places in the X and Y axes and 713 in the Z
709  * axis. Experiments show that in fact 766 is placed in X,
710  * and 713 in Y and Z. This is relative to a base of 660
711  * LSM/Ga, giving 1.16 and 1.08 */
712  float expected_cal[3] = { 1.16f, 1.08f, 1.08f };
713 
714  /* start the sensor polling at 50 Hz */
715  if (OK != ioctl(filp, SENSORIOCSPOLLRATE, 50)) {
716  warn("FAILED: SENSORIOCSPOLLRATE 50Hz");
717  ret = 1;
718  goto out;
719  }
720 
721  /* Set to 2.5 Gauss. We ask for 3 to get the right part of
722  * the chained if statement above. */
723  if (OK != ioctl(filp, MAGIOCSRANGE, 3)) {
724  warnx("FAILED: MAGIOCSRANGE 2.5 Ga");
725  ret = 1;
726  goto out;
727  }
728 
729  if (OK != ioctl(filp, MAGIOCEXSTRAP, 1)) {
730  warnx("FAILED: MAGIOCEXSTRAP 1");
731  ret = 1;
732  goto out;
733  }
734 
735  if (OK != ioctl(filp, MAGIOCGSCALE, (long unsigned int)&mscale_previous)) {
736  warn("FAILED: MAGIOCGSCALE 1");
737  ret = 1;
738  goto out;
739  }
740 
741  if (OK != ioctl(filp, MAGIOCSSCALE, (long unsigned int)&mscale_null)) {
742  warn("FAILED: MAGIOCSSCALE 1");
743  ret = 1;
744  goto out;
745  }
746 
747  // discard 10 samples to let the sensor settle
748  for (uint8_t i = 0; i < 10; i++) {
749  px4_pollfd_struct_t fds{};
750 
751  /* wait for data to be ready */
752  fds.fd = fd;
753  fds.events = POLLIN;
754  ret = px4_poll(&fds, 1, 2000);
755 
756  if (ret != 1) {
757  warn("ERROR: TIMEOUT 1");
758  goto out;
759  }
760 
761  /* now go get it */
762  sz = px4_read(fd, &report, sizeof(report));
763 
764  if (sz != sizeof(report)) {
765  warn("ERROR: READ 1");
766  ret = -EIO;
767  goto out;
768  }
769  }
770 
771  /* read the sensor up to 150x, stopping when we have 50 good values */
772  for (uint8_t i = 0; i < 150 && good_count < 50; i++) {
773  px4_pollfd_struct_t fds{};
774 
775  /* wait for data to be ready */
776  fds.fd = fd;
777  fds.events = POLLIN;
778  ret = px4_poll(&fds, 1, 2000);
779 
780  if (ret != 1) {
781  warn("ERROR: TIMEOUT 2");
782  goto out;
783  }
784 
785  /* now go get it */
786  sz = px4_read(fd, &report, sizeof(report));
787 
788  if (sz != sizeof(report)) {
789  warn("ERROR: READ 2");
790  ret = -EIO;
791  goto out;
792  }
793 
794  float cal[3] = {fabsf(expected_cal[0] / report.x),
795  fabsf(expected_cal[1] / report.y),
796  fabsf(expected_cal[2] / report.z)
797  };
798 
799  if (cal[0] > 0.3f && cal[0] < 1.7f &&
800  cal[1] > 0.3f && cal[1] < 1.7f &&
801  cal[2] > 0.3f && cal[2] < 1.7f) {
802  good_count++;
803  sum_excited[0] += cal[0];
804  sum_excited[1] += cal[1];
805  sum_excited[2] += cal[2];
806  }
807  }
808 
809  if (good_count < 5) {
810  ret = -EIO;
811  goto out;
812  }
813 
814  float scaling[3];
815 
816  scaling[0] = sum_excited[0] / good_count;
817  scaling[1] = sum_excited[1] / good_count;
818  scaling[2] = sum_excited[2] / good_count;
819 
820  /* set scaling in device */
821  mscale_previous.x_scale = 1.0f / scaling[0];
822  mscale_previous.y_scale = 1.0f / scaling[1];
823  mscale_previous.z_scale = 1.0f / scaling[2];
824 
825  ret = OK;
826 
827 out:
828 
829  if (OK != ioctl(filp, MAGIOCSSCALE, (long unsigned int)&mscale_previous)) {
830  warn("FAILED: MAGIOCSSCALE 2");
831  }
832 
833  /* set back to normal mode */
834  /* Set to 1.9 Gauss */
835  if (OK != px4_ioctl(fd, MAGIOCSRANGE, 2)) {
836  warnx("FAILED: MAGIOCSRANGE 1.9 Ga");
837  }
838 
839  if (OK != px4_ioctl(fd, MAGIOCEXSTRAP, 0)) {
840  warnx("FAILED: MAGIOCEXSTRAP 0");
841  }
842 
843  if (ret == OK) {
844  if (check_scale()) {
845  /* failed */
846  warnx("FAILED: SCALE");
847  ret = PX4_ERROR;
848  }
849 
850  }
851 
852  return ret;
853 }
854 
856 {
857  bool scale_valid;
858 
859  if ((-FLT_EPSILON + 1.0f < _scale.x_scale && _scale.x_scale < FLT_EPSILON + 1.0f) &&
860  (-FLT_EPSILON + 1.0f < _scale.y_scale && _scale.y_scale < FLT_EPSILON + 1.0f) &&
861  (-FLT_EPSILON + 1.0f < _scale.z_scale && _scale.z_scale < FLT_EPSILON + 1.0f)) {
862  /* scale is one */
863  scale_valid = false;
864 
865  } else {
866  scale_valid = true;
867  }
868 
869  /* return 0 if calibrated, 1 else */
870  return !scale_valid;
871 }
872 
874 {
875  bool offset_valid;
876 
877  if ((-2.0f * FLT_EPSILON < _scale.x_offset && _scale.x_offset < 2.0f * FLT_EPSILON) &&
878  (-2.0f * FLT_EPSILON < _scale.y_offset && _scale.y_offset < 2.0f * FLT_EPSILON) &&
879  (-2.0f * FLT_EPSILON < _scale.z_offset && _scale.z_offset < 2.0f * FLT_EPSILON)) {
880  /* offset is zero */
881  offset_valid = false;
882 
883  } else {
884  offset_valid = true;
885  }
886 
887  /* return 0 if calibrated, 1 else */
888  return !offset_valid;
889 }
890 
891 int HMC5883::set_excitement(unsigned enable)
892 {
893  int ret;
894  /* arm the excitement strap */
896 
897  if (OK != ret) {
899  }
900 
901  _conf_reg &= ~0x03; // reset previous excitement mode
902 
903  if (((int)enable) < 0) {
904  _conf_reg |= 0x01;
905 
906  } else if (enable > 0) {
907  _conf_reg |= 0x02;
908 
909  }
910 
911  // ::printf("set_excitement enable=%d regA=0x%x\n", (int)enable, (unsigned)_conf_reg);
912 
914 
915  if (OK != ret) {
917  }
918 
919  uint8_t conf_reg_ret = 0;
920  read_reg(ADDR_CONF_A, conf_reg_ret);
921 
922  //print_info();
923 
924  return !(_conf_reg == conf_reg_ret);
925 }
926 
927 
928 /*
929  enable/disable temperature compensation on the HMC5983
930 
931  Unfortunately we don't yet know of a way to auto-detect the
932  difference between the HMC5883 and HMC5983. Both of them do
933  temperature sensing, but only the 5983 does temperature
934  compensation. We have noy yet found a behaviour that can be reliably
935  distinguished by reading registers to know which type a particular
936  sensor is
937 
938  update: Current best guess is that many sensors marked HMC5883L on
939  the package are actually 5983 but without temperature compensation
940  tables. Reading the temperature works, but the mag field is not
941  automatically adjusted for temperature. We suspect that there may be
942  some early 5883L parts that don't have the temperature sensor at
943  all, although we haven't found one yet. The code that reads the
944  temperature looks for 10 failed transfers in a row and disables the
945  temperature sensor if that happens. It is hoped that this copes with
946  the genuine 5883L parts.
947  */
949 {
950  int ret;
951  /* get current config */
953 
954  if (OK != ret) {
956  return -EIO;
957  }
958 
959  if (enable != 0) {
961 
962  } else {
964  }
965 
967 
968  if (OK != ret) {
970  return -EIO;
971  }
972 
973  uint8_t conf_reg_ret = 0;
974 
975  if (read_reg(ADDR_CONF_A, conf_reg_ret) != OK) {
977  return -EIO;
978  }
979 
980  return conf_reg_ret == _conf_reg;
981 }
982 
983 int
984 HMC5883::write_reg(uint8_t reg, uint8_t val)
985 {
986  uint8_t buf = val;
987  return _interface->write(reg, &buf, 1);
988 }
989 
990 int
991 HMC5883::read_reg(uint8_t reg, uint8_t &val)
992 {
993  uint8_t buf = val;
994  int ret = _interface->read(reg, &buf, 1);
995  val = buf;
996  return ret;
997 }
998 
999 float
1001 {
1002  union {
1003  uint8_t b[2];
1004  int16_t w;
1005  } u;
1006 
1007  u.b[0] = in[1];
1008  u.b[1] = in[0];
1009 
1010  return (float) u.w;
1011 }
1012 
1013 void
1015 {
1018  printf("interval: %u us\n", _measure_interval);
1019  print_message(_last_report);
1020  _reports->print_info("report queue");
1021 }
void print_info()
Diagnostics - print some basic information about the driver.
Definition: HMC5883.cpp:1014
#define MAGIOCGSCALE
copy the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:76
int measure()
Issue a measurement command.
Definition: HMC5883.cpp:467
#define MAGIOCGEXTERNAL
determine if mag is external or onboard
Definition: drv_mag.h:88
unsigned _measure_interval
Definition: HMC5883.hpp:139
measure the time elapsed performing an event
Definition: perf_counter.h:56
float _range_ga
Definition: HMC5883.hpp:144
#define MAGIOCEXSTRAP
excite strap
Definition: drv_mag.h:85
bool _collect_phase
Definition: HMC5883.hpp:145
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
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
#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
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
int px4_poll(px4_pollfd_struct_t *fds, nfds_t nfds, int timeout)
mag scaling factors; Vout = (Vin * Vscale) + Voffset
Definition: drv_mag.h:56
#define HMC5883_CONVERSION_INTERVAL
Definition: HMC5883.hpp:78
Device * _interface
Definition: HMC5883.hpp:135
#define DRV_MAG_DEVTYPE_HMC5883
Sensor type definitions.
Definition: drv_sensor.h:55
int set_range(unsigned range)
Set the sensor range.
Definition: HMC5883.cpp:125
count the number of times an event occurs
Definition: perf_counter.h:55
perf_counter_t _comms_errors
Definition: HMC5883.hpp:152
uint8_t _temperature_error_count
Definition: HMC5883.hpp:166
#define FLT_EPSILON
#define ADDR_CONF_A
Definition: HMC5883.hpp:80
bool _sensor_ok
sensor was found and reports ok
Definition: HMC5883.hpp:157
perf_counter_t _sample_perf
Definition: HMC5883.hpp:151
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
float x_offset
Definition: drv_mag.h:57
#define SENSORIOCSPOLLRATE
Set the driver polling rate to (arg) Hz, or one of the SENSOR_POLLRATE constants. ...
Definition: drv_sensor.h:134
ringbuffer::RingBuffer * _reports
Definition: HMC5883.hpp:141
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
#define MODE_REG_SINGLE_MODE
Definition: HMC5883.hpp:106
device identifier information
Definition: Device.hpp:240
void perf_count(perf_counter_t handle)
Count a performance event.
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
#define MAGIOCSSCALE
set the mag scaling constants to the structure pointed to by (arg)
Definition: drv_mag.h:73
struct mag_calibration_s _scale
Definition: HMC5883.hpp:142
ssize_t px4_read(int fd, void *buffer, size_t buflen)
void perf_free(perf_counter_t handle)
Free a counter.
#define MAG_BASE_DEVICE_PATH
Definition: drv_mag.h:47
void init()
Activates/configures the hardware registers.
#define MAGIOCCALIBRATE
perform self-calibration, update scale factors to canonical units
Definition: drv_mag.h:82
int read_reg(uint8_t reg, uint8_t &val)
Read a register.
Definition: HMC5883.cpp:991
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
int _orb_class_instance
Definition: HMC5883.hpp:147
#define perf_alloc(a, b)
Definition: px4io.h:59
#define ADDR_TEMP_OUT_MSB
Definition: HMC5883.hpp:92
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
int check_scale()
Check the current scale calibration.
Definition: HMC5883.cpp:855
#define ADDR_MODE
Definition: HMC5883.hpp:82
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
float y_offset
Definition: drv_mag.h:59
#define warnx(...)
Definition: err.h:95
void perf_end(perf_counter_t handle)
End a performance event.
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
#define HMC5983_TEMP_SENSOR_ENABLE
Definition: HMC5883.hpp:111
int fd
Definition: dataman.cpp:146
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
float z_offset
Definition: drv_mag.h:61
void check_conf(void)
check the sensor configuration.
Definition: HMC5883.cpp:221
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
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.
#define MAGIOCSTEMPCOMP
enable/disable temperature compensation
Definition: drv_mag.h:91
Fundamental base class for all physical drivers (I2C, SPI).
Definition: Device.hpp:65
Definition: bst.cpp:62
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
#define ADDR_CONF_B
Definition: HMC5883.hpp:81
#define OK
Definition: uavcan_main.cpp:71
int _class_instance
Definition: HMC5883.hpp:146
#define ADDR_DATA_OUT_X_MSB
Definition: HMC5883.hpp:83
bool _pub_blocked
true if publishing should be blocked
Definition: CDev.hpp:91
perf_counter_t _range_errors
Definition: HMC5883.hpp:153
Dual< Scalar, N > abs(const Dual< Scalar, N > &a)
Definition: Dual.hpp:196
orb_advert_t _mag_topic
Definition: HMC5883.hpp:149
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
#define warn(...)
Definition: err.h:94
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
void perf_begin(perf_counter_t handle)
Begin a performance event.
#define DEVICE_DEBUG(FMT,...)
Definition: Device.hpp:52
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
#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
int px4_ioctl(int fd, int cmd, unsigned long arg)