PX4 Firmware
PX4 Autopilot Software http://px4.io
px4flow.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2013-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 px4flow.cpp
36  * @author Dominik Honegger
37  * @author Ban Siesta <bansiesta@gmail.com>
38  *
39  * Driver for the PX4FLOW module connected via I2C.
40  */
41 
42 #include <drivers/device/i2c.h>
44 #include <drivers/drv_hrt.h>
47 #include <lib/parameters/param.h>
48 #include <lib/perf/perf_counter.h>
49 #include <px4_platform_common/px4_config.h>
50 #include <px4_platform_common/defines.h>
51 #include <px4_platform_common/getopt.h>
52 #include <px4_platform_common/px4_work_queue/ScheduledWorkItem.hpp>
55 
56 #define PX4FLOW0_DEVICE_PATH "/dev/px4flow0"
57 
58 /* Configuration Constants */
59 #define I2C_FLOW_ADDRESS_DEFAULT 0x42 ///< 7-bit address. 8-bit address is 0x84, range 0x42 - 0x49
60 #define I2C_FLOW_ADDRESS_MIN 0x42 ///< 7-bit address.
61 #define I2C_FLOW_ADDRESS_MAX 0x49 ///< 7-bit address.
62 
63 /* PX4FLOW Registers addresses */
64 #define PX4FLOW_REG 0x16 ///< Measure Register 22
65 
66 #define PX4FLOW_CONVERSION_INTERVAL_DEFAULT 100000 ///< in microseconds! = 10Hz
67 #define PX4FLOW_CONVERSION_INTERVAL_MIN 10000 ///< in microseconds! = 100 Hz
68 #define PX4FLOW_CONVERSION_INTERVAL_MAX 1000000 ///< in microseconds! = 1 Hz
69 
70 #define PX4FLOW_I2C_MAX_BUS_SPEED 400000 ///< 400 KHz maximum speed
71 
72 #define PX4FLOW_MAX_DISTANCE 5.0f
73 #define PX4FLOW_MIN_DISTANCE 0.3f
74 
75 #include "i2c_frame.h"
76 
77 class PX4FLOW: public device::I2C, public px4::ScheduledWorkItem
78 {
79 public:
80  PX4FLOW(int bus, int address = I2C_FLOW_ADDRESS_DEFAULT, enum Rotation rotation = (enum Rotation)0,
81  int conversion_interval = PX4FLOW_CONVERSION_INTERVAL_DEFAULT,
82  uint8_t sonar_rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING);
83  virtual ~PX4FLOW();
84 
85  virtual int init();
86 
87  /**
88  * Diagnostics - print some basic information about the driver.
89  */
90  void print_info();
91 
92 protected:
93  virtual int probe();
94 
95 private:
96 
97  uint8_t _sonar_rotation;
98  bool _sensor_ok{false};
99  bool _collect_phase{false};
104 
107 
109  float _sensor_min_range{0.0f};
110  float _sensor_max_range{0.0f};
112 
115 
116  /**
117  * Test whether the device supported by the driver is present at a
118  * specific address.
119  *
120  * @param address The I2C bus address to probe.
121  * @return True if the device is present.
122  */
123  int probe_address(uint8_t address);
124 
125  /**
126  * Initialise the automatic measurement state machine and start it.
127  *
128  * @note This function is called at open and error time. It might make sense
129  * to make it more aggressive about resetting the bus in case of errors.
130  */
131  void start();
132 
133  /**
134  * Stop the automatic measurement state machine.
135  */
136  void stop();
137 
138  /**
139  * Perform a poll cycle; collect from the previous measurement
140  * and start a new one.
141  */
142  void Run() override;
143 
144  int measure();
145  int collect();
146 
147 };
148 
149 /*
150  * Driver 'main' command.
151  */
152 extern "C" __EXPORT int px4flow_main(int argc, char *argv[]);
153 
154 PX4FLOW::PX4FLOW(int bus, int address, enum Rotation rotation, int conversion_interval, uint8_t sonar_rotation) :
155  I2C("PX4FLOW", PX4FLOW0_DEVICE_PATH, bus, address, PX4FLOW_I2C_MAX_BUS_SPEED), /* 100-400 KHz */
156  ScheduledWorkItem(MODULE_NAME, px4::device_bus_to_wq(get_device_id())),
157  _sonar_rotation(sonar_rotation),
158  _sample_perf(perf_alloc(PC_ELAPSED, "px4f_read")),
159  _comms_errors(perf_alloc(PC_COUNT, "px4f_com_err")),
160  _sensor_rotation(rotation)
161 {
162 }
163 
165 {
166  /* make sure we are truly inactive */
167  stop();
168 
171 }
172 
173 int
175 {
176  int ret = PX4_ERROR;
177 
178  /* do I2C init (and probe) first */
179  if (I2C::init() != OK) {
180  return ret;
181  }
182 
183  _class_instance = register_class_devname(RANGE_FINDER_BASE_DEVICE_PATH);
184 
185  /* get a publish handle on the range finder topic */
186  struct distance_sensor_s ds_report = {};
187 
189  _distance_sensor_topic = orb_advertise_multi(ORB_ID(distance_sensor), &ds_report,
191 
192  if (_distance_sensor_topic == nullptr) {
193  PX4_ERR("failed to create distance_sensor object");
194  }
195 
196  } else {
197  DEVICE_LOG("not primary range device, not advertising");
198  }
199 
200  ret = OK;
201  /* sensor is ok, but we don't really know if it is within range */
202  _sensor_ok = true;
203 
204  /* get yaw rotation from sensor frame to body frame */
205  param_t rot = param_find("SENS_FLOW_ROT");
206 
207  if (rot != PARAM_INVALID) {
208  int32_t val = 6; // the recommended installation for the flow sensor is with the Y sensor axis forward
209  param_get(rot, &val);
210 
211  _sensor_rotation = (enum Rotation)val;
212  }
213 
214  /* get operational limits of the sensor */
215  param_t hmin = param_find("SENS_FLOW_MINHGT");
216 
217  if (hmin != PARAM_INVALID) {
218  float val = 0.7;
219  param_get(hmin, &val);
220 
221  _sensor_min_range = val;
222  }
223 
224  param_t hmax = param_find("SENS_FLOW_MAXHGT");
225 
226  if (hmax != PARAM_INVALID) {
227  float val = 3.0;
228  param_get(hmax, &val);
229 
230  _sensor_max_range = val;
231  }
232 
233  param_t ratemax = param_find("SENS_FLOW_MAXR");
234 
235  if (ratemax != PARAM_INVALID) {
236  float val = 2.5;
237  param_get(ratemax, &val);
238 
239  _sensor_max_flow_rate = val;
240  }
241 
242  start();
243 
244  return ret;
245 }
246 
247 int
249 {
250  uint8_t val[I2C_FRAME_SIZE] {};
251 
252  // to be sure this is not a ll40ls Lidar (which can also be on
253  // 0x42) we check if a I2C_FRAME_SIZE byte transfer works from address
254  // 0. The ll40ls gives an error for that, whereas the flow
255  // happily returns some data
256  if (transfer(nullptr, 0, &val[0], 22) != OK) {
257  return -EIO;
258  }
259 
260  // that worked, so start a measurement cycle
261  return measure();
262 }
263 
264 int
266 {
267  /*
268  * Send the command to begin a measurement.
269  */
270  uint8_t cmd = PX4FLOW_REG;
271  int ret = transfer(&cmd, 1, nullptr, 0);
272 
273  if (OK != ret) {
275  DEVICE_DEBUG("i2c::transfer returned %d", ret);
276  return ret;
277  }
278 
279  return PX4_OK;
280 }
281 
282 int
284 {
285  int ret = -EIO;
286 
287  /* read from the sensor */
288  uint8_t val[I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE] = { };
289 
291 
292  if (PX4FLOW_REG == 0x00) {
293  ret = transfer(nullptr, 0, &val[0], I2C_FRAME_SIZE + I2C_INTEGRAL_FRAME_SIZE);
294  }
295 
296  if (PX4FLOW_REG == 0x16) {
297  ret = transfer(nullptr, 0, &val[0], I2C_INTEGRAL_FRAME_SIZE);
298  }
299 
300  if (ret < 0) {
301  DEVICE_DEBUG("error reading from sensor: %d", ret);
304  return ret;
305  }
306 
307  if (PX4FLOW_REG == 0) {
308  memcpy(&_frame, val, I2C_FRAME_SIZE);
310  }
311 
312  if (PX4FLOW_REG == 0x16) {
314  }
315 
316 
317  optical_flow_s report{};
318 
319  report.timestamp = hrt_absolute_time();
320  report.pixel_flow_x_integral = static_cast<float>(_frame_integral.pixel_flow_x_integral) / 10000.0f;//convert to radians
321  report.pixel_flow_y_integral = static_cast<float>(_frame_integral.pixel_flow_y_integral) / 10000.0f;//convert to radians
322  report.frame_count_since_last_readout = _frame_integral.frame_count_since_last_readout;
323  report.ground_distance_m = static_cast<float>(_frame_integral.ground_distance) / 1000.0f;//convert to meters
324  report.quality = _frame_integral.qual; //0:bad ; 255 max quality
325  report.gyro_x_rate_integral = static_cast<float>(_frame_integral.gyro_x_rate_integral) / 10000.0f; //convert to radians
326  report.gyro_y_rate_integral = static_cast<float>(_frame_integral.gyro_y_rate_integral) / 10000.0f; //convert to radians
327  report.gyro_z_rate_integral = static_cast<float>(_frame_integral.gyro_z_rate_integral) / 10000.0f; //convert to radians
328  report.integration_timespan = _frame_integral.integration_timespan; //microseconds
329  report.time_since_last_sonar_update = _frame_integral.sonar_timestamp;//microseconds
330  report.gyro_temperature = _frame_integral.gyro_temperature;//Temperature * 100 in centi-degrees Celsius
331  report.sensor_id = 0;
332  report.max_flow_rate = _sensor_max_flow_rate;
333  report.min_ground_distance = _sensor_min_range;
334  report.max_ground_distance = _sensor_max_range;
335 
336  /* rotate measurements in yaw from sensor frame to body frame according to parameter SENS_FLOW_ROT */
337  float zeroval = 0.0f;
338 
339  rotate_3f(_sensor_rotation, report.pixel_flow_x_integral, report.pixel_flow_y_integral, zeroval);
340  rotate_3f(_sensor_rotation, report.gyro_x_rate_integral, report.gyro_y_rate_integral, report.gyro_z_rate_integral);
341 
342  if (_px4flow_topic == nullptr) {
343  _px4flow_topic = orb_advertise(ORB_ID(optical_flow), &report);
344 
345  } else {
346  /* publish it */
347  orb_publish(ORB_ID(optical_flow), _px4flow_topic, &report);
348  }
349 
350  /* publish to the distance_sensor topic as well */
351  distance_sensor_s distance_report{};
352  distance_report.timestamp = report.timestamp;
353  distance_report.min_distance = PX4FLOW_MIN_DISTANCE;
354  distance_report.max_distance = PX4FLOW_MAX_DISTANCE;
355  distance_report.current_distance = report.ground_distance_m;
356  distance_report.variance = 0.0f;
357  distance_report.signal_quality = -1;
358  distance_report.type = distance_sensor_s::MAV_DISTANCE_SENSOR_ULTRASOUND;
359  /* TODO: the ID needs to be properly set */
360  distance_report.id = 0;
361  distance_report.orientation = _sonar_rotation;
362 
363  orb_publish(ORB_ID(distance_sensor), _distance_sensor_topic, &distance_report);
364 
366 
367  return PX4_OK;
368 }
369 
370 void
372 {
373  /* reset the report ring and state machine */
374  _collect_phase = false;
375 
376  /* schedule a cycle to start things */
377  ScheduleNow();
378 }
379 
380 void
382 {
383  ScheduleClear();
384 }
385 
386 void
388 {
389  if (OK != measure()) {
390  DEVICE_DEBUG("measure error");
391  }
392 
393  /* perform collection */
394  if (OK != collect()) {
395  DEVICE_DEBUG("collection error");
396  /* restart the measurement state machine */
397  start();
398  return;
399  }
400 
401  ScheduleDelayed(PX4FLOW_CONVERSION_INTERVAL_DEFAULT);
402 }
403 
404 void
406 {
409 }
410 
411 /**
412  * Local functions in support of the shell command.
413  */
414 namespace px4flow
415 {
416 
417 PX4FLOW *g_dev = nullptr;
418 bool start_in_progress = false;
419 
420 const int START_RETRY_COUNT = 5;
421 const int START_RETRY_TIMEOUT = 1000;
422 
423 int start(int argc, char *argv[]);
424 int stop();
425 int info();
426 void usage();
427 
428 /**
429  * Start the driver.
430  */
431 int
432 start(int argc, char *argv[])
433 {
434  /* entry check: */
435  if (start_in_progress) {
436  PX4_WARN("start already in progress");
437  return 1;
438  }
439 
440  if (g_dev != nullptr) {
441  start_in_progress = false;
442  PX4_WARN("already started");
443  return 1;
444  }
445 
446  /* parse command line options */
447  int address = I2C_FLOW_ADDRESS_DEFAULT;
448  int conversion_interval = PX4FLOW_CONVERSION_INTERVAL_DEFAULT;
449 
450  /* don't exit from getopt loop to leave getopt global variables in consistent state,
451  * set error flag instead */
452  bool err_flag = false;
453  int ch;
454  int myoptind = 1;
455  const char *myoptarg = nullptr;
456  uint8_t sonar_rotation = distance_sensor_s::ROTATION_DOWNWARD_FACING;
457 
458  while ((ch = px4_getopt(argc, argv, "a:i:R:", &myoptind, &myoptarg)) != EOF) {
459  switch (ch) {
460  case 'a':
461  address = strtoul(myoptarg, nullptr, 16);
462 
463  if (address < I2C_FLOW_ADDRESS_MIN || address > I2C_FLOW_ADDRESS_MAX) {
464  PX4_WARN("invalid i2c address '%s'", myoptarg);
465  err_flag = true;
466 
467  }
468 
469  break;
470 
471  case 'i':
472  conversion_interval = strtoul(myoptarg, nullptr, 10);
473 
474  if (conversion_interval < PX4FLOW_CONVERSION_INTERVAL_MIN || conversion_interval > PX4FLOW_CONVERSION_INTERVAL_MAX) {
475  PX4_WARN("invalid conversion interval '%s'", myoptarg);
476  err_flag = true;
477  }
478 
479  break;
480 
481  case 'R':
482  sonar_rotation = (uint8_t)atoi(myoptarg);
483  PX4_INFO("Setting sonar orientation to %d", (int)sonar_rotation);
484 
485  break;
486 
487  default:
488  err_flag = true;
489  break;
490  }
491  }
492 
493  if (err_flag) {
494  usage();
495  return PX4_ERROR;
496  }
497 
498  /* starting */
499  start_in_progress = true;
500  PX4_INFO("scanning I2C buses for device..");
501 
502  int retry_nr = 0;
503 
504  while (1) {
505  const int busses_to_try[] = {
506  PX4_I2C_BUS_EXPANSION,
507 #ifdef PX4_I2C_BUS_ESC
508  PX4_I2C_BUS_ESC,
509 #endif
510 #ifdef PX4_I2C_BUS_ONBOARD
511  PX4_I2C_BUS_ONBOARD,
512 #endif
513 #ifdef PX4_I2C_BUS_EXPANSION1
514  PX4_I2C_BUS_EXPANSION1,
515 #endif
516 #ifdef PX4_I2C_BUS_EXPANSION2
517  PX4_I2C_BUS_EXPANSION2,
518 #endif
519 
520  -1
521  };
522 
523  const int *cur_bus = busses_to_try;
524 
525  while (*cur_bus != -1) {
526  /* create the driver */
527  /* PX4_WARN("trying bus %d", *cur_bus); */
528  g_dev = new PX4FLOW(*cur_bus, address, (enum Rotation)0, conversion_interval, sonar_rotation);
529 
530  if (g_dev == nullptr) {
531  /* this is a fatal error */
532  break;
533  }
534 
535  /* init the driver: */
536  if (OK == g_dev->init()) {
537  /* success! */
538  break;
539  }
540 
541  /* destroy it again because it failed. */
542  delete g_dev;
543  g_dev = nullptr;
544 
545  /* try next! */
546  cur_bus++;
547  }
548 
549  /* check whether we found it: */
550  if (*cur_bus != -1) {
551 
552  /* check for failure: */
553  if (g_dev == nullptr) {
554  break;
555  }
556 
557  /* success! */
558  start_in_progress = false;
559  return 0;
560  }
561 
562  if (retry_nr < START_RETRY_COUNT) {
563  /* lets not be too verbose */
564  // PX4_WARN("PX4FLOW not found on I2C busses. Retrying in %d ms. Giving up in %d retries.", START_RETRY_TIMEOUT, START_RETRY_COUNT - retry_nr);
565  px4_usleep(START_RETRY_TIMEOUT * 1000);
566  retry_nr++;
567 
568  } else {
569  break;
570  }
571  }
572 
573  if (g_dev != nullptr) {
574  delete g_dev;
575  g_dev = nullptr;
576  }
577 
578  start_in_progress = false;
579 
580  return PX4_OK;
581 }
582 
583 /**
584  * Stop the driver
585  */
586 int
588 {
589  start_in_progress = false;
590 
591  if (g_dev != nullptr) {
592  delete g_dev;
593  g_dev = nullptr;
594 
595  return PX4_OK;
596 
597  } else {
598  PX4_WARN("driver not running");
599  }
600 
601  return PX4_ERROR;
602 }
603 
604 /**
605  * Print a little info about the driver.
606  */
607 int
609 {
610  if (g_dev == nullptr) {
611  PX4_WARN("driver not running");
612  return PX4_ERROR;
613  }
614 
615  g_dev->print_info();
616 
617  return PX4_OK;
618 }
619 
620 void usage()
621 {
622  PX4_INFO("usage: px4flow {start|info'}");
623  PX4_INFO(" [-a i2c_address]");
624  PX4_INFO(" [-i i2c_interval]");
625 }
626 
627 } // namespace
628 
629 int
630 px4flow_main(int argc, char *argv[])
631 {
632  if (argc < 2) {
633  px4flow::usage();
634  return 1;
635  }
636 
637  /*
638  * Start/load the driver.
639  */
640  if (!strcmp(argv[1], "start")) {
641  return px4flow::start(argc, argv);
642  }
643 
644  /*
645  * Stop the driver
646  */
647  if (!strcmp(argv[1], "stop")) {
648  return px4flow::stop();
649  }
650 
651  /*
652  * Print driver information.
653  */
654  if (!strcmp(argv[1], "info") || !strcmp(argv[1], "status")) {
655  return px4flow::info();
656  }
657 
658  px4flow::usage();
659 
660  return PX4_OK;
661 }
#define PARAM_INVALID
Handle returned when a parameter cannot be found.
Definition: param.h:103
float _sensor_min_range
Definition: px4flow.cpp:109
int measure()
Definition: px4flow.cpp:265
#define PX4FLOW_MAX_DISTANCE
Definition: px4flow.cpp:72
void stop()
Stop the automatic measurement state machine.
Definition: px4flow.cpp:381
#define RANGE_FINDER_BASE_DEVICE_PATH
orb_advert_t _px4flow_topic
Definition: px4flow.cpp:102
measure the time elapsed performing an event
Definition: perf_counter.h:56
int info()
Print a little info about the driver.
Definition: px4flow.cpp:608
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
uint64_t timestamp
Definition: optical_flow.h:53
#define PX4FLOW0_DEVICE_PATH
Definition: px4flow.cpp:56
virtual ~PX4FLOW()
Definition: px4flow.cpp:164
PX4FLOW(int bus, int address=I2C_FLOW_ADDRESS_DEFAULT, enum Rotation rotation=(enum Rotation) 0, int conversion_interval=PX4FLOW_CONVERSION_INTERVAL_DEFAULT, uint8_t sonar_rotation=distance_sensor_s::ROTATION_DOWNWARD_FACING)
Definition: px4flow.cpp:154
int16_t pixel_flow_x_integral
accumulated flow in radians*10000 around x axis since last I2C readout [rad*10000] ...
Definition: i2c_frame.h:68
void start()
Initialise the automatic measurement state machine and start it.
Definition: px4flow.cpp:371
int start(int argc, char *argv[])
Start the driver.
Definition: px4flow.cpp:432
bool start_in_progress
Definition: px4flow.cpp:418
orb_advert_t _distance_sensor_topic
Definition: px4flow.cpp:103
__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
const int START_RETRY_COUNT
Definition: px4flow.cpp:420
void usage(const char *reason)
Print the correct usage.
Definition: Commander.cpp:4238
int stop()
Stop the driver.
Definition: px4flow.cpp:587
Definition: I2C.hpp:51
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
Definition: uORB.cpp:43
void Run() override
Perform a poll cycle; collect from the previous measurement and start a new one.
Definition: px4flow.cpp:387
virtual int probe()
Definition: px4flow.cpp:248
count the number of times an event occurs
Definition: perf_counter.h:55
Vector rotation library.
High-resolution timer with callouts and timekeeping.
float _sensor_max_range
Definition: px4flow.cpp:110
uint8_t _sonar_rotation
Definition: px4flow.cpp:97
int16_t gyro_temperature
Temperature * 100 in centi-degrees Celsius [degcelsius*100].
Definition: i2c_frame.h:76
uint16_t frame_count_since_last_readout
number of flow measurements since last I2C readout [#frames]
Definition: i2c_frame.h:67
Global flash based parameter store.
uint32_t sonar_timestamp
time since last sonar update [microseconds]
Definition: i2c_frame.h:74
#define I2C_FLOW_ADDRESS_MAX
7-bit address.
Definition: px4flow.cpp:61
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
void perf_count(perf_counter_t handle)
Count a performance event.
#define PX4FLOW_MIN_DISTANCE
Definition: px4flow.cpp:73
Header common to all counters.
void perf_free(perf_counter_t handle)
Free a counter.
void init()
Activates/configures the hardware registers.
Definition of i2c frames.
PX4FLOW * g_dev
Definition: px4flow.cpp:417
bool _sensor_ok
Definition: px4flow.cpp:98
uint32_t integration_timespan
accumulation timespan in microseconds since last I2C readout [microseconds]
Definition: i2c_frame.h:73
#define DEVICE_LOG(FMT,...)
Definition: Device.hpp:51
#define perf_alloc(a, b)
Definition: px4io.h:59
Rotation
Enum for board and external compass rotations.
Definition: rotation.h:51
__EXPORT int px4flow_main(int argc, char *argv[])
Definition: px4flow.cpp:630
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
uint16_t ground_distance
Ground distance in meters*1000 [meters*1000].
Definition: i2c_frame.h:75
int collect()
Definition: px4flow.cpp:283
void perf_end(perf_counter_t handle)
End a performance event.
int probe_address(uint8_t address)
Test whether the device supported by the driver is present at a specific address. ...
#define PX4FLOW_REG
Measure Register 22.
Definition: px4flow.cpp:64
perf_counter_t _sample_perf
Definition: px4flow.cpp:105
int16_t pixel_flow_y_integral
accumulated flow in radians*10000 around y axis since last I2C readout [rad*10000] ...
Definition: i2c_frame.h:69
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
int orb_publish(const struct orb_metadata *meta, orb_advert_t handle, const void *data)
Definition: uORB.cpp:70
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
const int START_RETRY_TIMEOUT
Definition: px4flow.cpp:421
enum Rotation _sensor_rotation
Definition: px4flow.cpp:108
#define PX4FLOW_CONVERSION_INTERVAL_DEFAULT
in microseconds! = 10Hz
Definition: px4flow.cpp:66
i2c_integral_frame _frame_integral
Definition: px4flow.cpp:114
bool _collect_phase
Definition: px4flow.cpp:99
int16_t gyro_x_rate_integral
accumulated gyro x rates in radians*10000 since last I2C readout [rad*10000]
Definition: i2c_frame.h:70
float _sensor_max_flow_rate
Definition: px4flow.cpp:111
#define PX4FLOW_CONVERSION_INTERVAL_MAX
in microseconds! = 1 Hz
Definition: px4flow.cpp:68
int16_t gyro_z_rate_integral
accumulated gyro z rates in radians*10000 since last I2C readout [rad*10000]
Definition: i2c_frame.h:72
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
int _class_instance
Definition: px4flow.cpp:100
perf_counter_t _comms_errors
Definition: px4flow.cpp:106
int16_t gyro_y_rate_integral
accumulated gyro y rates in radians*10000 since last I2C readout [rad*10000]
Definition: i2c_frame.h:71
Definition: bst.cpp:62
#define I2C_FLOW_ADDRESS_DEFAULT
7-bit address. 8-bit address is 0x84, range 0x42 - 0x49
Definition: px4flow.cpp:59
void usage()
Prints info about the driver argument usage.
Definition: px4flow.cpp:620
#define OK
Definition: uavcan_main.cpp:71
#define I2C_FRAME_SIZE
Definition: i2c_frame.h:63
uint8_t qual
averaged quality of accumulated flow values [0:bad quality;255: max quality]
Definition: i2c_frame.h:77
virtual int init()
Definition: px4flow.cpp:174
orb_advert_t orb_advertise_multi(const struct orb_metadata *meta, const void *data, int *instance, int priority)
Definition: uORB.cpp:53
Local functions in support of the shell command.
Definition: px4flow.cpp:414
i2c_frame _frame
Definition: px4flow.cpp:113
void print_info()
Diagnostics - print some basic information about the driver.
Definition: px4flow.cpp:405
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).
uint32_t param_t
Parameter handle.
Definition: param.h:98
#define I2C_INTEGRAL_FRAME_SIZE
Definition: i2c_frame.h:80
#define PX4FLOW_I2C_MAX_BUS_SPEED
400 KHz maximum speed
Definition: px4flow.cpp:70
Performance measuring tools.
int _orb_class_instance
Definition: px4flow.cpp:101
Base class for devices connected via I2C.