rc_sbus.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include "rc_sbus.h"
  2. #define SBUS_HEAD 0x0F
  3. #define SBUS_TAIL0 0x00
  4. #define SBUS_TAIL1 0x04
  5. #define SBUS_TAIL2 0x14
  6. #define SBUS_TAIL3 0x24
  7. #define SBUS_TAIL4 0x34
  8. /** sbus 协议接收解析阶段 */
  9. enum
  10. {
  11. SBUS_PARSE_HEAD = 0,
  12. SBUS_PARSE_DATA,
  13. SBUS_PARSE_TAIL
  14. };
  15. void RcSbus_StructInit(RC_SBUS_Data *prc_sbus)
  16. {
  17. prc_sbus->rc.signal_health = RC_SIGNAL_HEALTH;
  18. prc_sbus->rc.link_status = COMP_NOEXIST;
  19. for (uint8_t ch = 0; ch < RC_INPUT_CH_NUM; ch++)
  20. {
  21. prc_sbus->rc.ch_value[ch] = 1500;
  22. prc_sbus->rc.raw_ch_value[ch] = 1500;
  23. prc_sbus->rc.calib_offset[ch] = 1500;
  24. prc_sbus->rc.calib_factor_up[ch] = 1000;
  25. prc_sbus->rc.calib_factor_down[ch] = 1000;
  26. }
  27. prc_sbus->_bad_count_s = 0;
  28. prc_sbus->_fail_count_s = 0;
  29. prc_sbus->_health_count_s = 0;
  30. prc_sbus->_link_lost_time_us = 0;
  31. prc_sbus->_sbus_signal_status = SBUS_PARSE_HEAD;
  32. }
  33. /**
  34. * @brief sbus 协议接收
  35. *
  36. * @param rc_sbus
  37. * @param data
  38. * @return true
  39. * @return false
  40. */
  41. bool rc_sbus_protocal_parse_char(RC_SBUS_Data *rc_sbus, uint8_t data)
  42. {
  43. bool ret_val = false;
  44. switch (rc_sbus->_raw_sbus_parse_stage)
  45. {
  46. /* sbus 帧头 */
  47. case SBUS_PARSE_HEAD:
  48. if (SBUS_HEAD == data)
  49. {
  50. rc_sbus->_raw_sbus_head = data;
  51. rc_sbus->_raw_sbus_parse_stage = SBUS_PARSE_DATA;
  52. rc_sbus->_raw_sbus_data_rx_index = 0;
  53. }
  54. break;
  55. /* sbus 数据 */
  56. case SBUS_PARSE_DATA:
  57. rc_sbus->_raw_sbus_data[rc_sbus->_raw_sbus_data_rx_index++] = data;
  58. if (rc_sbus->_raw_sbus_data_rx_index >= _SBUS_DATA_NUM)
  59. {
  60. rc_sbus->_raw_sbus_data_rx_index = 0;
  61. rc_sbus->_raw_sbus_parse_stage = SBUS_PARSE_TAIL;
  62. }
  63. break;
  64. /* sbus 帧尾 */
  65. case SBUS_PARSE_TAIL:
  66. switch (data)
  67. {
  68. case SBUS_TAIL0:
  69. case SBUS_TAIL1:
  70. case SBUS_TAIL2:
  71. case SBUS_TAIL3:
  72. case SBUS_TAIL4:
  73. ret_val = true;
  74. break;
  75. default:
  76. break;
  77. }
  78. rc_sbus->_raw_sbus_tail = data;
  79. rc_sbus->_raw_sbus_parse_stage = SBUS_PARSE_HEAD;
  80. break;
  81. default:
  82. rc_sbus->_raw_sbus_parse_stage = SBUS_PARSE_HEAD;
  83. break;
  84. }
  85. return ret_val;
  86. }
  87. /**
  88. * @brief sbus 信号转 pwm
  89. */
  90. static void sbus2pwm(uint16_t *pwm, uint16_t *sbus_ch)
  91. {
  92. uint8_t i = 0;
  93. for (i = 0; i < 14; i++)
  94. {
  95. pwm[i] = (sbus_ch[i] - 1024) * 420 / 672 + 1500;
  96. }
  97. }
  98. /**
  99. * @brief sbus 协议解析
  100. *
  101. * @param rc_sbus
  102. */
  103. void rc_sbus_protocal_decode(RC_SBUS_Data *rc_sbus)
  104. {
  105. uint16_t channels[18] = {1023, 1023, 1023, 1023, 1023, 1023,
  106. 1023, 1023, 1023, 1023, 1023, 1023,
  107. 1023, 1023, 1023, 1023, 0, 0};
  108. const uint8_t *sbus_data = rc_sbus->_raw_sbus_data;
  109. channels[0] = ((sbus_data[0] | sbus_data[1] << 8) & 0x07FF);
  110. channels[1] = ((sbus_data[1] >> 3 | sbus_data[2] << 5) & 0x07FF);
  111. channels[2] =
  112. ((sbus_data[2] >> 6 | sbus_data[3] << 2 | sbus_data[4] << 10) & 0x07FF);
  113. channels[3] = ((sbus_data[4] >> 1 | sbus_data[5] << 7) & 0x07FF);
  114. channels[4] = ((sbus_data[5] >> 4 | sbus_data[6] << 4) & 0x07FF);
  115. channels[5] =
  116. ((sbus_data[6] >> 7 | sbus_data[7] << 1 | sbus_data[8] << 9) & 0x07FF);
  117. channels[6] = ((sbus_data[8] >> 2 | sbus_data[9] << 6) & 0x07FF);
  118. channels[7] = ((sbus_data[9] >> 5 | sbus_data[10] << 3) & 0x07FF);
  119. // & the other 8 + 2 channels if you need them
  120. channels[8] = ((sbus_data[11] | sbus_data[12] << 8) & 0x07FF);
  121. channels[9] = ((sbus_data[12] >> 3 | sbus_data[13] << 5) & 0x07FF);
  122. channels[10] =
  123. ((sbus_data[13] >> 6 | sbus_data[14] << 2 | sbus_data[15] << 10) &
  124. 0x07FF);
  125. channels[11] = ((sbus_data[15] >> 1 | sbus_data[16] << 7) & 0x07FF);
  126. channels[12] = ((sbus_data[16] >> 4 | sbus_data[17] << 4) & 0x07FF);
  127. channels[13] =
  128. ((sbus_data[17] >> 7 | sbus_data[18] << 1 | sbus_data[19] << 9) &
  129. 0x07FF);
  130. channels[14] = ((sbus_data[19] >> 2 | sbus_data[20] << 6) & 0x07FF);
  131. channels[15] = ((sbus_data[20] >> 5 | sbus_data[21] << 3) & 0x07FF);
  132. // DigiChannel 1
  133. if (sbus_data[22] & (1 << 0))
  134. {
  135. channels[16] = 1;
  136. }
  137. else
  138. {
  139. channels[16] = 0;
  140. }
  141. // DigiChannel 2
  142. if (sbus_data[22] & (1 << 1))
  143. {
  144. channels[17] = 1;
  145. }
  146. else
  147. {
  148. channels[17] = 0;
  149. }
  150. /* 信号失控异常标志位判断 */
  151. rc_sbus->_sbus_signal_status = SBUS_SIGNAL_OK;
  152. /* 信号丢失 */
  153. if (sbus_data[22] & (1 << 2))
  154. {
  155. rc_sbus->_sbus_signal_status = SBUS_SIGNAL_LOST;
  156. }
  157. /* 失控保护激活 */
  158. if (sbus_data[22] & (1 << 3))
  159. {
  160. rc_sbus->_sbus_signal_status = SBUS_SIGNAL_FAILSAFE;
  161. }
  162. sbus2pwm(rc_sbus->rc.raw_ch_value, channels);
  163. }
  164. /**
  165. * @brief 计算遥控器校准后的值
  166. *
  167. * @param rc_sbus
  168. */
  169. void rc_sbus_calib_value(RC_SBUS_Data *rc_sbus)
  170. {
  171. if (COMP_NORMAL == rc_sbus->rc.link_status)
  172. {
  173. /* 校准前 4 个通道到 1000~2000 范围 */
  174. for (uint8_t ch = 0; ch < _SBUS_CALIB_CH_NUM; ch++)
  175. {
  176. float cal_factor = 1.0f;
  177. if (rc_sbus->rc.raw_ch_value[ch] >= rc_sbus->rc.calib_offset[ch])
  178. {
  179. cal_factor = rc_sbus->rc.calib_factor_up[ch] / 1000.0f;
  180. }
  181. else
  182. {
  183. cal_factor = rc_sbus->rc.calib_factor_down[ch] / 1000.0f;
  184. }
  185. rc_sbus->rc.ch_value[ch] = 1500 + (rc_sbus->rc.raw_ch_value[ch] -
  186. rc_sbus->rc.calib_offset[ch]) *
  187. cal_factor;
  188. }
  189. /* 后面的通道则用原始值 */
  190. for (uint8_t ch = _SBUS_CALIB_CH_NUM; ch < 14; ch++)
  191. {
  192. rc_sbus->rc.ch_value[ch] = rc_sbus->rc.raw_ch_value[ch];
  193. }
  194. }
  195. }
  196. /**
  197. * @brief 检查 rc_sbus 信号质量
  198. *
  199. * @param rc_sbus
  200. * @param dt_s
  201. */
  202. void rc_sbus_signal_health_check(RC_SBUS_Data *rc_sbus, float dt_s)
  203. {
  204. /* 检查信号质量 */
  205. bool rc_value_range_is_legal = true;
  206. /* 规定前 7 个通道必须在 920 ~ 2080 的范围内, 否则视为超范围 */
  207. for (uint8_t ch = 0; ch < 7; ch++)
  208. {
  209. if (rc_sbus->rc.raw_ch_value[ch] <= 920 &&
  210. rc_sbus->rc.raw_ch_value[ch] >= 2080)
  211. {
  212. rc_value_range_is_legal = false;
  213. break;
  214. }
  215. }
  216. if (rc_value_range_is_legal)
  217. {
  218. switch (rc_sbus->_sbus_signal_status)
  219. {
  220. case SBUS_SIGNAL_OK:
  221. rc_sbus->_health_count_s += dt_s;
  222. if (rc_sbus->_health_count_s > 0.5f)
  223. {
  224. rc_sbus->_health_count_s = 0.5f;
  225. rc_sbus->rc.signal_health = RC_SIGNAL_HEALTH;
  226. }
  227. rc_sbus->_fail_count_s = 0.0f;
  228. rc_sbus->_bad_count_s = 0.0f;
  229. break;
  230. case SBUS_SIGNAL_FAILSAFE:
  231. case SBUS_SIGNAL_LOST:
  232. rc_sbus->_fail_count_s += dt_s;
  233. if (rc_sbus->_fail_count_s > 0.5f)
  234. {
  235. rc_sbus->_fail_count_s = 0.5f;
  236. rc_sbus->rc.signal_health = RC_SIGNAL_FAIL;
  237. }
  238. rc_sbus->_health_count_s = 0.0f;
  239. rc_sbus->_bad_count_s = 0.0f;
  240. break;
  241. default:
  242. break;
  243. }
  244. }
  245. else
  246. {
  247. rc_sbus->_bad_count_s += dt_s;
  248. if (rc_sbus->_bad_count_s > 0.5f)
  249. {
  250. rc_sbus->_bad_count_s = 0.5f;
  251. rc_sbus->rc.signal_health = RC_SIGNAL_BAD;
  252. }
  253. rc_sbus->_health_count_s = 0;
  254. rc_sbus->_fail_count_s = 0;
  255. }
  256. }