soft_rc_input.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398
  1. #include "soft_rc_input.h"
  2. #include "auto_pilot.h"
  3. #include "common.h"
  4. #include "control_throttle.h"
  5. #include "hard_rc_sbus.h"
  6. #include "soft_flash.h"
  7. #include "soft_time.h"
  8. #include "ver_config.h"
  9. /* sbus 信号状态 */
  10. typedef enum
  11. {
  12. SBUS_SIGNAL_OK = 0x00,
  13. SBUS_SIGNAL_LOST = 0x01,
  14. SBUS_SIGNAL_FAILSAFE = 0x03,
  15. } RCSbus_SignalStatus;
  16. //******************************************
  17. //摇杆输入
  18. short rock_in[4] = {1500, 1500, 1500, 1500};
  19. //摇杆按键
  20. char rock_key = KEY_UP;
  21. //******************************************
  22. // PWM输入的值 单位 us //不上电时是默认值
  23. short rc_in[RC_INPUT_CH_NUM] = {1500, 1500, 1500, 1500, 1200, 1800, 1800};
  24. // pwm输入的原始值 //不上电时是默认值
  25. short raw_rc_in[RC_INPUT_CH_NUM] = {1500, 1500, 1500, 1500, 1200, 1800, 1800};
  26. /**************************实现函数********************************************
  27. *函数原型: void rc_input_initial(void)
  28. *功  能: 输入初始化
  29. *******************************************************************************/
  30. void rc_input_initial(void) { rc_sbus_init(SBUS_BPS); }
  31. /**************************实现函数********************************************
  32. *函数原型: void get_rc_value(void)
  33. *功  能: 获取get_rc的输入值
  34. *返 回 值: 1 正常
  35. 0 异常
  36. *******************************************************************************/
  37. unsigned char subs_failsafe_status;
  38. //遥控器是否有效
  39. comp_status comp_rc_status = COMP_NOEXIST;
  40. // sbus 失联记时
  41. static uint32_t sbus_data_link_lost_time_us = 0;
  42. //遥控器健康标志位
  43. RcSignalHealthType rc_signal_health = RC_SIGNAL_HEALTH;
  44. //遥控器输入中间量
  45. short tmp_rc_in[RC_INPUT_CH_NUM] = {0};
  46. void get_rc_value(void)
  47. {
  48. uint8_t i = 0;
  49. static short health_counts = 0;
  50. static short fail_counts = 0;
  51. static short bad_counts = 0;
  52. //如果遥控器有效
  53. if (comp_rc_status == COMP_NORMAL)
  54. {
  55. for (i = 0; i < RC_CALIB_CH_NUM; i++)
  56. {
  57. if (raw_rc_in[i] >= rc_cal_offset[i])
  58. {
  59. tmp_rc_in[i] = (raw_rc_in[i] - rc_cal_offset[i]) *
  60. rc_cal_factor_up[i] / 1000 +
  61. 1500;
  62. }
  63. else if (raw_rc_in[i] < rc_cal_offset[i])
  64. {
  65. tmp_rc_in[i] = (raw_rc_in[i] - rc_cal_offset[i]) *
  66. rc_cal_factor_down[i] / 1000 +
  67. 1500;
  68. }
  69. }
  70. for (uint8_t i = RC_CH5; i < RC_INPUT_CH_NUM; ++i)
  71. {
  72. tmp_rc_in[i] = raw_rc_in[i];
  73. }
  74. //所有通道都在最大最小值得范围内,所有数据正常
  75. if ((tmp_rc_in[RC_CH1] >= RC_IN_MIN &&
  76. tmp_rc_in[RC_CH1] <= RC_IN_MAX) &&
  77. (tmp_rc_in[RC_CH2] >= RC_IN_MIN &&
  78. tmp_rc_in[RC_CH2] <= RC_IN_MAX) &&
  79. (tmp_rc_in[RC_CH3] >= RC_IN_MIN &&
  80. tmp_rc_in[RC_CH3] <= RC_IN_MAX) &&
  81. (tmp_rc_in[RC_CH4] >= RC_IN_MIN &&
  82. tmp_rc_in[RC_CH4] <= RC_IN_MAX) &&
  83. (tmp_rc_in[RC_CH5] >= RC_IN_MIN &&
  84. tmp_rc_in[RC_CH5] <= RC_IN_MAX) &&
  85. (tmp_rc_in[RC_CH6] >= RC_IN_MIN &&
  86. tmp_rc_in[RC_CH6] <= RC_IN_MAX) &&
  87. (tmp_rc_in[RC_CH7] >= RC_IN_MIN &&
  88. tmp_rc_in[RC_CH7] <= RC_IN_MAX) &&
  89. (subs_failsafe_status == SBUS_SIGNAL_OK))
  90. {
  91. //正常数据,赋值给rc_in
  92. for (i = 0; i < RC_INPUT_CH_NUM; i++)
  93. {
  94. rc_in[i] = tmp_rc_in[i];
  95. }
  96. //出错或失控后如果400ms都正常,就恢复遥控器的值
  97. if ((health_counts++) >= 25)
  98. {
  99. rc_signal_health = RC_SIGNAL_HEALTH;
  100. health_counts = 25;
  101. }
  102. fail_counts = 0;
  103. bad_counts = 0;
  104. }
  105. //失控保护,futaba的遥控器的拨码开关不是直接跳变,会有中间值出现,所以要加缓冲
  106. else if ((tmp_rc_in[RC_CH1] >= RC_IN_MIN &&
  107. tmp_rc_in[RC_CH1] <= RC_IN_MAX) &&
  108. (tmp_rc_in[RC_CH2] >= RC_IN_MIN &&
  109. tmp_rc_in[RC_CH2] <= RC_IN_MAX) &&
  110. (tmp_rc_in[RC_CH3] >= RC_IN_MIN &&
  111. tmp_rc_in[RC_CH3] <= RC_IN_MAX) &&
  112. (tmp_rc_in[RC_CH4] >= RC_IN_MIN &&
  113. tmp_rc_in[RC_CH4] <= RC_IN_MAX) &&
  114. (tmp_rc_in[RC_CH5] >= RC_IN_MIN &&
  115. tmp_rc_in[RC_CH5] <= RC_IN_MAX) &&
  116. (tmp_rc_in[RC_CH6] >= RC_IN_MIN &&
  117. tmp_rc_in[RC_CH6] <= RC_IN_MAX) &&
  118. ((tmp_rc_in[RC_CH7] >= RC_FS_MIN &&
  119. tmp_rc_in[RC_CH7] <= RC_FS_MAX) ||
  120. (subs_failsafe_status != SBUS_SIGNAL_OK)))
  121. {
  122. //失控保护数据,赋值给rc_in
  123. for (i = 0; i < RC_INPUT_CH_NUM; i++)
  124. {
  125. rc_in[i] = tmp_rc_in[i];
  126. }
  127. if ((fail_counts++) >= 50)
  128. {
  129. rc_signal_health = RC_SIGNAL_FAIL;
  130. fail_counts = 50;
  131. }
  132. health_counts = 0;
  133. bad_counts = 0;
  134. }
  135. //跳出最大最小值的范围就认为遥控器出错,遥控器出错不更新rc_in的值,持续出错执行错误保护
  136. else
  137. { //数据错误后都赋值为默认值,赋值给rc_in
  138. for (i = 0; i < 4; i++)
  139. {
  140. rc_in[i] = 1500;
  141. }
  142. // GPS模式
  143. rc_in[RC_CH5] = 1200;
  144. //机头锁定
  145. rc_in[RC_CH6] = 1800;
  146. //待命
  147. rc_in[RC_CH7] = 1800;
  148. if ((bad_counts++) >= 25)
  149. {
  150. rc_signal_health = RC_SIGNAL_BAD;
  151. bad_counts = 25;
  152. }
  153. health_counts = 0;
  154. fail_counts = 0;
  155. }
  156. }
  157. }
  158. /**
  159. * @brief sbus 信号转 pwm
  160. */
  161. void sbus2pwm(int16_t *pwm, int16_t *sbus_ch)
  162. {
  163. uint8_t i = 0;
  164. for (i = 0; i < RC_INPUT_CH_NUM; i++)
  165. {
  166. pwm[i] = (sbus_ch[i] - 1024) * 420 / 672 + 1500;
  167. }
  168. }
  169. /**
  170. * @brief sbus 信号解析
  171. */
  172. void sbus_channel_anslysis(uint8_t *sbus_data)
  173. {
  174. static int16_t channels[SBUS_CH] = {1023, 1023, 1023, 1023, 1023, 1023,
  175. 1023, 1023, 1023, 1023, 1023, 1023,
  176. 1023, 1023, 1023, 1023, 0, 0};
  177. // buf1的8位作为ch1的低8位,buf2的低3位作为ch1的高3位,组成ch1的11位。
  178. channels[0] = ((sbus_data[1] | sbus_data[2] << 8) & 0x07FF);
  179. // buf2的高5位作为ch2的低5位,buf3的低6位作为ch2的高6位,组成ch2的11位。
  180. channels[1] = ((sbus_data[2] >> 3 | sbus_data[3] << 5) & 0x07FF);
  181. //以此类推,每个通道占11位
  182. channels[2] =
  183. ((sbus_data[3] >> 6 | sbus_data[4] << 2 | sbus_data[5] << 10) & 0x07FF);
  184. channels[3] = ((sbus_data[5] >> 1 | sbus_data[6] << 7) & 0x07FF);
  185. channels[4] = ((sbus_data[6] >> 4 | sbus_data[7] << 4) & 0x07FF);
  186. channels[5] =
  187. ((sbus_data[7] >> 7 | sbus_data[8] << 1 | sbus_data[9] << 9) & 0x07FF);
  188. channels[6] = ((sbus_data[9] >> 2 | sbus_data[10] << 6) & 0x07FF);
  189. channels[7] = ((sbus_data[10] >> 5 | sbus_data[11] << 3) & 0x07FF);
  190. #ifdef ALL_CHANNELS
  191. // & the other 8 + 2 channels if you need them
  192. channels[8] = ((sbus_data[12] | sbus_data[13] << 8) & 0x07FF);
  193. channels[9] = ((sbus_data[13] >> 3 | sbus_data[14] << 5) & 0x07FF);
  194. channels[10] =
  195. ((sbus_data[14] >> 6 | sbus_data[15] << 2 | sbus_data[16] << 10) &
  196. 0x07FF);
  197. channels[11] = ((sbus_data[16] >> 1 | sbus_data[17] << 7) & 0x07FF);
  198. channels[12] = ((sbus_data[17] >> 4 | sbus_data[18] << 4) & 0x07FF);
  199. channels[13] =
  200. ((sbus_data[18] >> 7 | sbus_data[19] << 1 | sbus_data[20] << 9) &
  201. 0x07FF);
  202. channels[14] = ((sbus_data[20] >> 2 | sbus_data[21] << 6) & 0x07FF);
  203. channels[15] = ((sbus_data[21] >> 5 | sbus_data[22] << 3) & 0x07FF);
  204. // DigiChannel 1
  205. if (sbus_data[23] & (1 << 0))
  206. {
  207. channels[16] = 1;
  208. }
  209. else
  210. {
  211. channels[16] = 0;
  212. }
  213. // DigiChannel 2
  214. if (sbus_data[23] & (1 << 1))
  215. {
  216. channels[17] = 1;
  217. }
  218. else
  219. {
  220. channels[17] = 0;
  221. }
  222. #endif
  223. // Failsafe
  224. subs_failsafe_status = SBUS_SIGNAL_OK;
  225. //信号丢失
  226. if (sbus_data[23] & (1 << 2))
  227. {
  228. subs_failsafe_status = SBUS_SIGNAL_LOST;
  229. }
  230. //失控保护激活
  231. if (sbus_data[23] & (1 << 3))
  232. {
  233. subs_failsafe_status = SBUS_SIGNAL_FAILSAFE;
  234. }
  235. sbus2pwm(raw_rc_in, channels);
  236. }
  237. /**
  238. * @brief 串口接收到sbus信号的钩子函数
  239. */
  240. void recv_rcsbus_data_hookfunction(unsigned int len)
  241. {
  242. //中断处理函数
  243. if (len == 25 && uart2_dma_rx_buf[0] == 0x0f &&
  244. (uart2_dma_rx_buf[24] == 0x00 || uart2_dma_rx_buf[24] == 0x04 ||
  245. uart2_dma_rx_buf[24] == 0x14 || uart2_dma_rx_buf[24] == 0x24 ||
  246. uart2_dma_rx_buf[24] == 0x34))
  247. {
  248. comp_rc_status = COMP_NORMAL;
  249. sbus_data_link_lost_time_us = 0;
  250. sbus_channel_anslysis(uart2_dma_rx_buf);
  251. }
  252. }
  253. /**
  254. * @brief sbus 输入信号失联判断
  255. * @param dt_s 运行间隔 s
  256. */
  257. void check_sbus_link_status(float dt_s)
  258. {
  259. if (COMP_NORMAL == comp_rc_status)
  260. {
  261. sbus_data_link_lost_time_us += dt_s * 1000000;
  262. if (sbus_data_link_lost_time_us > 500 * 1000)
  263. {
  264. comp_rc_status = COMP_LOST;
  265. }
  266. }
  267. }
  268. unsigned int rc_cal_time = 0;
  269. //用来记录遥控器输入的最大最小值,全部初始化为1500.。。。
  270. int rc_cal_max[RC_CALIB_CH_NUM] = {1500, 1500, 1500, 1500},
  271. rc_cal_min[RC_CALIB_CH_NUM] = {1500, 1500, 1500, 1500};
  272. //开始遥控器校准的参数
  273. RCCalibStatusType rc_cal_flag = RC_CALIB_NO;
  274. bool rc_offset_capture_flag = false;
  275. // 遥控器各通道的中立位
  276. short rc_cal_offset[RC_CALIB_CH_NUM] = {1500, 1500, 1500, 1500};
  277. void rc_input_calib_start(void)
  278. {
  279. if (rc_cal_flag == RC_CALIB_NO)
  280. {
  281. //赋值进入遥控器校准模式
  282. pilot_mode = PILOT_RC_CLB;
  283. rc_cal_flag = RC_CALIB_START;
  284. rc_offset_capture_flag = true;
  285. //点击遥控器校准后需要延时一段时间,,不然会记录一个原先的值。填充滤波新数据额需要时间,,,
  286. rc_cal_time = micros();
  287. }
  288. }
  289. void rc_input_calib_end(void)
  290. {
  291. //开始校准并且上锁状态下
  292. if ((rc_cal_flag == RC_CALIB_START) && (thr_lock_status == LOCKED))
  293. {
  294. rc_cal_flag = RC_CALIB_NO;
  295. write_rcfactor_flag = true;
  296. //点击校准结束后,绿灯灭,只剩红灯
  297. }
  298. }
  299. void rc_input_calibration(void)
  300. {
  301. uint8_t i = 0;
  302. //捕获中立位同时清除以前记录的最大最小值
  303. if (rc_offset_capture_flag == true)
  304. {
  305. for (i = 0; i < RC_CALIB_CH_NUM; i++)
  306. {
  307. //记录中立位
  308. rc_cal_offset[i] = raw_rc_in[i];
  309. //初始化最大最小值
  310. rc_cal_min[i] = 1500;
  311. rc_cal_max[i] = 1500;
  312. }
  313. //如果校准时油门没放在中间,就不记录油门的中立位
  314. if (rc_cal_offset[RC_CH3] < 1350 || rc_cal_offset[RC_CH3] > 1650)
  315. {
  316. rc_cal_offset[RC_CH3] = 1500;
  317. }
  318. rc_offset_capture_flag = false;
  319. }
  320. for (i = 0; i < RC_CALIB_CH_NUM; i++)
  321. {
  322. //记录CH的最大最小值
  323. if (rc_cal_max[i] < raw_rc_in[i])
  324. {
  325. rc_cal_max[i] = raw_rc_in[i];
  326. }
  327. if (rc_cal_min[i] > raw_rc_in[i])
  328. {
  329. rc_cal_min[i] = raw_rc_in[i];
  330. }
  331. }
  332. }
  333. //比例系数,,实际的比例系数放大1000倍后的值,便于flash存储
  334. short rc_cal_factor_up[RC_CALIB_CH_NUM] = {1000, 1000, 1000, 1000};
  335. short rc_cal_factor_down[RC_CALIB_CH_NUM] = {1000, 1000, 1000, 1000};
  336. /**
  337. * @brief 计算遥控器校准系数
  338. */
  339. void calc_rcfactor_calibration(void)
  340. {
  341. unsigned char i = 0;
  342. for (i = 0; i < RC_CALIB_CH_NUM; i++)
  343. {
  344. rc_cal_factor_up[i] =
  345. (short)((1000 * 500) / (rc_cal_max[i] - rc_cal_offset[i]));
  346. rc_cal_factor_down[i] =
  347. (short)((1000 * 500) / (rc_cal_offset[i] - rc_cal_min[i]));
  348. }
  349. }