PX4 Firmware
PX4 Autopilot Software http://px4.io
TFMINI.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (c) 2017-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 #include "TFMINI.hpp"
35 
36 TFMINI::TFMINI(const char *port, uint8_t rotation) :
37  ScheduledWorkItem(MODULE_NAME, px4::serial_port_to_wq(port)),
38  _px4_rangefinder(0 /* TODO: device id */, ORB_PRIO_DEFAULT, rotation)
39 {
40  // store port name
41  strncpy(_port, port, sizeof(_port) - 1);
42 
43  // enforce null termination
44  _port[sizeof(_port) - 1] = '\0';
45 }
46 
48 {
49  // make sure we are truly inactive
50  stop();
51 
54 }
55 
56 int
58 {
59  int32_t hw_model = 1; // only one model so far...
60 
61  switch (hw_model) {
62  case 1: // TFMINI (12m, 100 Hz)
66 
67  break;
68 
69  default:
70  PX4_ERR("invalid HW model %d.", hw_model);
71  return -1;
72  }
73 
74  // status
75  int ret = 0;
76 
77  do { // create a scope to handle exit conditions using break
78 
79  // open fd
80  _fd = ::open(_port, O_RDWR | O_NOCTTY);
81 
82  if (_fd < 0) {
83  PX4_ERR("Error opening fd");
84  return -1;
85  }
86 
87  // baudrate 115200, 8 bits, no parity, 1 stop bit
88  unsigned speed = B115200;
89  termios uart_config{};
90  int termios_state{};
91 
92  tcgetattr(_fd, &uart_config);
93 
94  // clear ONLCR flag (which appends a CR for every LF)
95  uart_config.c_oflag &= ~ONLCR;
96 
97  // set baud rate
98  if ((termios_state = cfsetispeed(&uart_config, speed)) < 0) {
99  PX4_ERR("CFG: %d ISPD", termios_state);
100  ret = -1;
101  break;
102  }
103 
104  if ((termios_state = cfsetospeed(&uart_config, speed)) < 0) {
105  PX4_ERR("CFG: %d OSPD\n", termios_state);
106  ret = -1;
107  break;
108  }
109 
110  if ((termios_state = tcsetattr(_fd, TCSANOW, &uart_config)) < 0) {
111  PX4_ERR("baud %d ATTR", termios_state);
112  ret = -1;
113  break;
114  }
115 
116  uart_config.c_cflag |= (CLOCAL | CREAD); // ignore modem controls
117  uart_config.c_cflag &= ~CSIZE;
118  uart_config.c_cflag |= CS8; // 8-bit characters
119  uart_config.c_cflag &= ~PARENB; // no parity bit
120  uart_config.c_cflag &= ~CSTOPB; // only need 1 stop bit
121  uart_config.c_cflag &= ~CRTSCTS; // no hardware flowcontrol
122 
123  // setup for non-canonical mode
124  uart_config.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
125  uart_config.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
126  uart_config.c_oflag &= ~OPOST;
127 
128  // fetch bytes as they become available
129  uart_config.c_cc[VMIN] = 1;
130  uart_config.c_cc[VTIME] = 1;
131 
132  if (_fd < 0) {
133  PX4_ERR("FAIL: laser fd");
134  ret = -1;
135  break;
136  }
137  } while (0);
138 
139  // close the fd
140  ::close(_fd);
141  _fd = -1;
142 
143  if (ret == PX4_OK) {
144  start();
145  }
146 
147  return ret;
148 }
149 
150 int
152 {
154 
155  // clear buffer if last read was too long ago
156  int64_t read_elapsed = hrt_elapsed_time(&_last_read);
157 
158  // the buffer for read chars is buflen minus null termination
159  char readbuf[sizeof(_linebuf)] {};
160  unsigned readlen = sizeof(readbuf) - 1;
161 
162  int ret = 0;
163  float distance_m = -1.0f;
164 
165  // Check the number of bytes available in the buffer
166  int bytes_available = 0;
167  ::ioctl(_fd, FIONREAD, (unsigned long)&bytes_available);
168 
169  if (!bytes_available) {
171  return -EAGAIN;
172  }
173 
174  // parse entire buffer
175  const hrt_abstime timestamp_sample = hrt_absolute_time();
176 
177  do {
178  // read from the sensor (uart buffer)
179  ret = ::read(_fd, &readbuf[0], readlen);
180 
181  if (ret < 0) {
182  PX4_ERR("read err: %d", ret);
185 
186  // only throw an error if we time out
187  if (read_elapsed > (kCONVERSIONINTERVAL * 2)) {
188  /* flush anything in RX buffer */
189  tcflush(_fd, TCIFLUSH);
190  return ret;
191 
192  } else {
193  return -EAGAIN;
194  }
195  }
196 
198 
199  // parse buffer
200  for (int i = 0; i < ret; i++) {
201  tfmini_parse(readbuf[i], _linebuf, &_linebuf_index, &_parse_state, &distance_m);
202  }
203 
204  // bytes left to parse
205  bytes_available -= ret;
206 
207  } while (bytes_available > 0);
208 
209  // no valid measurement after parsing buffer
210  if (distance_m < 0.0f) {
212  return -EAGAIN;
213  }
214 
215  // publish most recent valid measurement from buffer
216  _px4_rangefinder.update(timestamp_sample, distance_m);
217 
219 
220  return PX4_OK;
221 }
222 
223 void
225 {
226  // schedule a cycle to start things
227  ScheduleOnInterval(100_us);
228 }
229 
230 void
232 {
233  ScheduleClear();
234 }
235 
236 void
238 {
239  // fds initialized?
240  if (_fd < 0) {
241  // open fd
242  _fd = ::open(_port, O_RDWR | O_NOCTTY);
243  }
244 
245  // perform collection
246  if (collect() == -EAGAIN) {
247  // reschedule to grab the missing bits, time to transmit 9 bytes @ 115200 bps
248  ScheduleClear();
249  ScheduleOnInterval(100_us, 87 * 9);
250  return;
251  }
252 }
253 
254 void
256 {
257  printf("Using port '%s'\n", _port);
260 
262 }
void set_max_distance(const float distance)
void set_fov(const float fov)
TFMINI_PARSE_STATE _parse_state
Definition: TFMINI.hpp:84
int tfmini_parse(char c, char *parserbuf, unsigned *parserbuf_index, TFMINI_PARSE_STATE *state, float *dist)
int init()
Definition: TFMINI.cpp:57
unsigned int _linebuf_index
Definition: TFMINI.hpp:93
void Run() override
Definition: TFMINI.cpp:237
static void read(bootloader_app_shared_t *pshared)
void update(const hrt_abstime timestamp, const float distance, const int8_t quality=-1)
void perf_count(perf_counter_t handle)
Count a performance event.
hrt_abstime _last_read
Definition: TFMINI.hpp:95
void perf_free(perf_counter_t handle)
Free a counter.
void start()
Definition: TFMINI.cpp:224
constexpr T radians(T degrees)
Definition: Limits.hpp:85
Vector< float, 6 > f(float t, const Matrix< float, 6, 1 > &, const Matrix< float, 3, 1 > &)
Definition: integration.cpp:8
void set_min_distance(const float distance)
TFMINI(const char *port, uint8_t rotation=distance_sensor_s::ROTATION_DOWNWARD_FACING)
Definition: TFMINI.cpp:36
static hrt_abstime hrt_elapsed_time(const hrt_abstime *then)
Compute the delta between a timestamp taken in the past and now.
Definition: drv_hrt.h:102
PX4Rangefinder _px4_rangefinder
Definition: TFMINI.hpp:82
void perf_end(perf_counter_t handle)
End a performance event.
perf_counter_t _sample_perf
Definition: TFMINI.hpp:98
__BEGIN_DECLS typedef uint64_t hrt_abstime
Absolute time, in microsecond units.
Definition: drv_hrt.h:58
virtual ~TFMINI()
Definition: TFMINI.cpp:47
int _fd
Definition: TFMINI.hpp:91
static constexpr int kCONVERSIONINTERVAL
Definition: TFMINI.hpp:89
void perf_print_counter(perf_counter_t handle)
Print one performance counter to stdout.
int collect()
Definition: TFMINI.cpp:151
Definition: bst.cpp:62
void stop()
Definition: TFMINI.cpp:231
char _port[20]
Definition: TFMINI.hpp:87
void perf_begin(perf_counter_t handle)
Begin a performance event.
perf_counter_t _comms_errors
Definition: TFMINI.hpp:97
__EXPORT hrt_abstime hrt_absolute_time(void)
Get absolute time in [us] (does not wrap).
char _linebuf[10]
Definition: TFMINI.hpp:86
void print_info()
Definition: TFMINI.cpp:255