PX4 Firmware
PX4 Autopilot Software http://px4.io
rc_receiver_main.cpp
Go to the documentation of this file.
1 /****************************************************************************
2  *
3  * Copyright (C) 2015 Mark Charlebois. 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 <px4_platform_common/getopt.h>
35 #include <px4_platform_common/tasks.h>
36 #include <px4_platform_common/log.h>
37 #include <string.h>
38 #include <drivers/drv_hrt.h>
39 #include <uORB/topics/input_rc.h>
41 #include <drivers/drv_rc_input.h>
42 
43 #ifdef __cplusplus
44 extern "C" {
45 #endif
46 #include <semaphore.h>
47 #include "rc_receiver_api.h"
48 #ifdef __cplusplus
49 }
50 #endif
51 
52 /** driver 'main' command */
53 extern "C" { __EXPORT int rc_receiver_main(int argc, char *argv[]); }
54 
55 #define MAX_LEN_DEV_PATH 32
56 
57 namespace rc_receiver
58 {
59 
60 /** Threshold value to detect rc receiver signal lost in millisecond */
61 #define SIGNAL_LOST_THRESHOLD_MS 500
62 
63 /** serial device path that rc receiver is connected to */
65 
66 /** flag indicating if rc_receiver module is running */
67 static bool _is_running = false;
68 
69 /** flag indicating if task thread should exit */
70 static bool _task_should_exit = false;
71 
72 /** handle to the task main thread */
73 static px4_task_t _task_handle = -1;
74 
75 /** RC receiver type */
76 static enum RC_RECEIVER_TYPES _rc_receiver_type;
77 
78 /** RC input channel value array accomondating up to RC_INPUT_MAX_CHANNELS */
79 static uint16_t rc_inputs[input_rc_s::RC_INPUT_MAX_CHANNELS];
80 
81 /** rc_input uorb topic publication handle */
82 static orb_advert_t _input_rc_pub = nullptr;
83 
84 /** rc_input uorb topic data */
85 static struct input_rc_s _rc_in;
86 
87 /**< parameter update subscription */
88 static int _params_sub;
89 
90 struct {
92 } _params_handles; /**< parameter handles */
93 
94 /** Print out the usage information */
95 static void usage();
96 
97 /** mpu9x50 start measurement */
98 static void start();
99 
100 /** mpu9x50 stop measurement */
101 static void stop();
102 
103 /** task main trampoline function */
104 static void task_main_trampoline(int argc, char *argv[]);
105 
106 /** mpu9x50 measurement thread primary entry point */
107 static void task_main(int argc, char *argv[]);
108 
109 /** update all parameters */
110 static void parameters_update();
111 
112 /** poll parameter update */
113 static void parameter_update_poll();
114 
116 {
117  PX4_DEBUG("rc_receiver_parameters_update");
118  float v;
119 
120  // accel params
121  if (param_get(_params_handles.rc_receiver_type, &v) == 0) {
122  _rc_receiver_type = (enum RC_RECEIVER_TYPES)v;
123  PX4_DEBUG("rc_receiver_parameters_update rc_receiver_type %f", v);
124  }
125 }
126 
128 {
129  _params_handles.rc_receiver_type = param_find("RC_RECEIVER_TYPE");
130 
132 }
133 
135 {
136  bool updated;
137 
138  /* Check if parameters have changed */
139  orb_check(_params_sub, &updated);
140 
141  if (updated) {
142  struct parameter_update_s param_update;
143  orb_copy(ORB_ID(parameter_update), _params_sub, &param_update);
145  }
146 }
147 
148 void start()
149 {
150  ASSERT(_task_handle == -1);
151 
152  /* start the task */
153  _task_handle = px4_task_spawn_cmd("rc_receiver_main",
154  SCHED_DEFAULT,
155  SCHED_PRIORITY_MAX,
156  1500,
157  (px4_main_t)&task_main_trampoline,
158  nullptr);
159 
160  if (_task_handle < 0) {
161  warn("task start failed");
162  return;
163  }
164 
165  _is_running = true;
166 }
167 
168 void stop()
169 {
170  // TODO - set thread exit signal to terminate the task main thread
171 
172  _is_running = false;
173  _task_handle = -1;
174 }
175 
176 void task_main_trampoline(int argc, char *argv[])
177 {
178  PX4_WARN("task_main_trampoline");
179  task_main(argc, argv);
180 }
181 
182 void task_main(int argc, char *argv[])
183 {
184  PX4_WARN("enter rc_receiver task_main");
185  uint32_t fd;
186 
187  // clear the rc_input report for topic advertise
188  memset(&_rc_in, 0, sizeof(struct input_rc_s));
189 
190  _input_rc_pub = orb_advertise(ORB_ID(input_rc), &_rc_in);
191 
192  if (_input_rc_pub == nullptr) {
193  PX4_WARN("failed to advertise input_rc uorb topic. Quit!");
194  return ;
195  }
196 
197  // subscribe to parameter_update topic
198  _params_sub = orb_subscribe(ORB_ID(parameter_update));
199 
200  // Open the RC receiver device on the specified serial port
201  fd = rc_receiver_open(_rc_receiver_type, _device);
202 
203  if (fd <= 0) {
204  PX4_WARN("failed to open rc receiver type %d dev %s. Quit!",
205  _rc_receiver_type, _device);
206  return ;
207  }
208 
209  // Continuously receive RC packet from serial device, until task is signaled
210  // to exit
211  uint32_t num_channels;
212  uint64_t ts = hrt_absolute_time();
213  int ret;
214  int counter = 0;
215 
217 
218  while (!_task_should_exit) {
219  // poll parameter update
221 
222  // read RC packet from serial device in blocking mode.
223  num_channels = input_rc_s::RC_INPUT_MAX_CHANNELS;
224 
225  ret = rc_receiver_get_packet(fd, rc_inputs, &num_channels);
226  ts = hrt_absolute_time();
227 
228  _rc_in.input_source = input_rc_s::RC_INPUT_SOURCE_QURT;
229 
230  if (ret < 0) {
231  // enum RC_RECEIVER_ERRORS error_code = rc_receiver_get_last_error(fd);
232  // PX4_WARN("RC packet receiving timed out. error code %d", error_code);
233 
234  uint64_t time_diff_us = ts - _rc_in.timestamp_last_signal;
235 
236  if (time_diff_us > SIGNAL_LOST_THRESHOLD_MS * 1000) {
237  _rc_in.rc_lost = true;
238 
239  if (++counter == 500) {
240  PX4_WARN("RC signal lost for %u ms", time_diff_us / 1000);
241  counter = 0;
242  }
243 
244  } else {
245  continue;
246  }
247  }
248 
249  // populate the input_rc_s structure
250  if (ret == 0) {
251  _rc_in.timestamp = ts;
253  _rc_in.channel_count = num_channels;
254 
255  // TODO - need to add support for RSSI, failsafe mode
257  _rc_in.rc_failsafe = false;
258  _rc_in.rc_lost = false;
261  }
262 
263  for (uint32_t i = 0; i < num_channels; i++) {
264  // Scale the Spektrum DSM value to ppm encoding. This is for the
265  // consistency with PX4 which internally translates DSM to PPM.
266  // See modules/px4iofirmware/dsm.c for details
267  // NOTE: rc_receiver spektrum driver outputs the data in 10bit DSM
268  // format, so we need to double the channel value before the scaling
269  _rc_in.values[i] = ((((int)(rc_inputs[i] * 2) - 1024) * 1000) / 1700) + 1500;
270  }
271 
272  orb_publish(ORB_ID(input_rc), _input_rc_pub, &_rc_in);
273  }
274 
275  rc_receiver_close(fd);
276 }
277 
278 void usage()
279 {
280  PX4_WARN("missing command: try 'start', 'stop', 'status'");
281  PX4_WARN("options:");
282  PX4_WARN(" -D device");
283 }
284 
285 } // namespace rc_receiver
286 
287 int rc_receiver_main(int argc, char *argv[])
288 {
289  const char *device = NULL;
290  int ch;
291  int myoptind = 1;
292  const char *myoptarg = NULL;
293 
294  /* jump over start/off/etc and look at options first */
295  while ((ch = px4_getopt(argc, argv, "D:", &myoptind, &myoptarg)) != EOF) {
296  switch (ch) {
297  case 'D':
298  device = myoptarg;
299  break;
300 
301  default:
303  return 1;
304  }
305  }
306 
307  // Check on required arguments
308  if (device == NULL || strlen(device) == 0) {
310  return 1;
311  }
312 
314  strncpy(rc_receiver::_device, device, strlen(device));
315 
316  const char *verb = argv[myoptind];
317 
318  /*
319  * Start/load the driver.
320  */
321  if (!strcmp(verb, "start")) {
323  PX4_WARN("rc_receiver already running");
324  return 1;
325  }
326 
328 
329  } else if (!strcmp(verb, "stop")) {
331  PX4_WARN("rc_receiver is not running");
332  return 1;
333  }
334 
336 
337  } else if (!strcmp(verb, "status")) {
338  PX4_WARN("rc_receiver is %s", rc_receiver::_is_running ? "running" : "stopped");
339  return 0;
340 
341  } else {
343  return 1;
344  }
345 
346  return 0;
347 }
int orb_copy(const struct orb_metadata *meta, int handle, void *buffer)
Definition: uORB.cpp:90
R/C input interface.
int32_t rssi
Definition: input_rc.h:72
#define SIGNAL_LOST_THRESHOLD_MS
Threshold value to detect rc receiver signal lost in millisecond.
bool rc_failsafe
Definition: input_rc.h:77
__EXPORT int param_get(param_t param, void *val)
Copy the value of a parameter.
Definition: parameters.cpp:589
static bool _is_running
flag indicating if rc_receiver module is running
Definition: I2C.hpp:51
__EXPORT int rc_receiver_main(int argc, char *argv[])
driver &#39;main&#39; command
uint8_t input_source
Definition: input_rc.h:79
orb_advert_t orb_advertise(const struct orb_metadata *meta, const void *data)
Definition: uORB.cpp:43
static void task_main(int argc, char *argv[])
mpu9x50 measurement thread primary entry point
struct rc_receiver::@17 _params_handles
parameter handles
uint64_t timestamp
Definition: input_rc.h:69
Namespace encapsulating all device framework classes, functions and data.
Definition: CDev.cpp:47
static void task_main_trampoline(int argc, char *argv[])
task main trampoline function
High-resolution timer with callouts and timekeeping.
static int _params_sub
uint16_t rc_lost_frame_count
Definition: input_rc.h:73
int orb_subscribe(const struct orb_metadata *meta)
Definition: uORB.cpp:75
static char _device[MAX_LEN_DEV_PATH]
serial device path that rc receiver is connected to
#define ORB_ID(_name)
Generates a pointer to the uORB metadata structure for a given topic.
Definition: uORB.h:87
static struct input_rc_s _rc_in
rc_input uorb topic data
static enum RC_RECEIVER_TYPES _rc_receiver_type
RC receiver type.
uint16_t values[18]
Definition: input_rc.h:76
static uint16_t rc_inputs[input_rc_s::RC_INPUT_MAX_CHANNELS]
RC input channel value array accomondating up to RC_INPUT_MAX_CHANNELS.
static bool _task_should_exit
flag indicating if task thread should exit
uint32_t channel_count
Definition: input_rc.h:71
static px4_task_t _task_handle
handle to the task main thread
static void stop()
mpu9x50 stop measurement
static unsigned counter
Definition: safety.c:56
__BEGIN_DECLS typedef void * orb_advert_t
ORB topic advertiser handle.
Definition: uORB.h:134
static orb_advert_t _input_rc_pub
rc_input uorb topic publication handle
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
#define RC_INPUT_RSSI_MAX
Maximum RSSI value.
Definition: drv_rc_input.h:64
__EXPORT param_t param_find(const char *name)
Look up a parameter by name.
Definition: parameters.cpp:370
uint16_t rc_total_frame_count
Definition: input_rc.h:74
bool rc_lost
Definition: input_rc.h:78
int orb_check(int handle, bool *updated)
Definition: uORB.cpp:95
param_t rc_receiver_type
static void start()
mpu9x50 start measurement
#define MAX_LEN_DEV_PATH
static void parameters_update()
update all parameters
static void parameter_update_poll()
poll parameter update
#define warn(...)
Definition: err.h:94
static void usage()
Print out the usage information.
uint64_t timestamp_last_signal
Definition: input_rc.h:70
__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