auto_pilot.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523
  1. #include "auto_pilot.h"
  2. #include "common.h"
  3. #include "control_rate.h"
  4. #include "control_throttle.h"
  5. #include "data_save.h"
  6. #include "flight_mode.h"
  7. #include "my_math.h"
  8. #include "params.h"
  9. #include "pilot_navigation.h"
  10. #include "soft_flash.h"
  11. #include "soft_gs.h"
  12. #include "soft_imu.h"
  13. #include "soft_motor_output.h"
  14. #include "soft_port_uart4.h"
  15. #include "soft_rc_input.h"
  16. #include "soft_sdcard.h"
  17. #include "soft_time.h"
  18. #include "soft_timer.h"
  19. #include "soft_voltage.h"
  20. #include "soft_warn.h"
  21. #include "ver_config.h"
  22. #include "helpler_funtions.h"
  23. #include <math.h>
  24. #include <stdlib.h>
  25. char pilot_mode = PILOT_NORMAL;
  26. char warn_reason = WARN_NO;
  27. uint8_t home_pos_isrecord = HOME_POS_NOT_SET;
  28. uint8_t takeoff_pos_isrecord = 0;
  29. // 本次上电飞行时间
  30. static float have_fly_time = 0.0f;
  31. // 本架次飞行时间
  32. static float have_fly_time_this_sort = 0.0f;
  33. // @brief 5hz计算解锁飞行的时间
  34. static void calculate_have_fly_time_5hz(void)
  35. {
  36. static unsigned int record_fly_time = 0;
  37. if (thr_lock_status == LOCKED)
  38. {
  39. record_fly_time = micros();
  40. have_fly_time_this_sort = 0.0f;
  41. }
  42. else if (thr_lock_status == UNLOCKED)
  43. {
  44. float dt = (float)(micros() - record_fly_time) / 1000000.0f;
  45. if (dt < 0.0f)
  46. {
  47. dt = 0.2f;
  48. }
  49. have_fly_time += dt;
  50. have_fly_time_this_sort += dt;
  51. record_fly_time = micros();
  52. }
  53. }
  54. // @brief 获取总飞行时间 s
  55. float Get_HaveFlyTime(void) { return have_fly_time; }
  56. // @brief 获取本架次飞行时间 s
  57. float Get_HaveFlyTimeThisSort(void) { return have_fly_time_this_sort; }
  58. static float have_fly_miles_this_sort = 0;
  59. static float have_fly_miles = 0;
  60. // 已飞航线里程
  61. static float have_fly_wp_miles;
  62. // @brief 判断是否使用遥控器进入磁校准
  63. void judge_mag_calibrateion(void)
  64. {
  65. static short preinput_ch5_mag = 1000;
  66. static uint8_t magcal_change_counts = 0;
  67. static uint32_t magcal_time = 0;
  68. if ((rc_in[RC_CH5] >= MAX_S && rc_in[RC_CH5] <= MAX_E) &&
  69. (preinput_ch5_mag >= MIN_S && preinput_ch5_mag <= MIN_E))
  70. {
  71. magcal_change_counts++;
  72. preinput_ch5_mag = rc_in[RC_CH5];
  73. magcal_time = micros();
  74. }
  75. else if ((rc_in[RC_CH5] >= MIN_S && rc_in[RC_CH5] <= MIN_E) &&
  76. (preinput_ch5_mag >= MAX_S && preinput_ch5_mag <= MAX_E))
  77. {
  78. magcal_change_counts++;
  79. preinput_ch5_mag = rc_in[RC_CH5];
  80. magcal_time = micros();
  81. }
  82. // 5通道连续切换8次,且两次之间间隔小于1.5s,则识别为需要磁校准
  83. // 实际能识别7次就可以了。
  84. if (magcal_change_counts >= 8)
  85. {
  86. // 上锁状态并且未进入磁校准下才能执行,防止连续点击多次发送
  87. if (thr_lock_status == LOCKED && mag_cal_status == MAG_CAL_NO &&
  88. pilot_mode == PILOT_NORMAL)
  89. {
  90. ci_jiao_zhun = true;
  91. magcal_change_counts = 0;
  92. }
  93. }
  94. // 如果1.5s之内没有切换,则清零计数
  95. if (micros() - magcal_time >= 1500000)
  96. {
  97. magcal_change_counts = 0;
  98. magcal_time = micros();
  99. }
  100. }
  101. // @brief 判断是否使用遥控器进入遥控器校准
  102. void judge_rc_calibration(void)
  103. {
  104. static short preinput_CH7_rc = 1000;
  105. static unsigned char rccal_change_counts = 0;
  106. static unsigned int rccal_time = 0;
  107. // 解锁时不允许校准遥控器
  108. if (thr_lock_status == UNLOCKED)
  109. return;
  110. if (((raw_rc_in[RC_CH7] >= MAX_S && raw_rc_in[RC_CH7] <= MAX_E) &&
  111. (preinput_CH7_rc >= MIN_S && preinput_CH7_rc <= MIN_E)) ||
  112. ((raw_rc_in[RC_CH7] >= MIN_S && raw_rc_in[RC_CH7] <= MIN_E) &&
  113. (preinput_CH7_rc >= MAX_S && preinput_CH7_rc <= MAX_E)))
  114. {
  115. rccal_change_counts++;
  116. preinput_CH7_rc = raw_rc_in[RC_CH7];
  117. rccal_time = micros();
  118. }
  119. // 6通道切换输出8次
  120. if (rccal_change_counts >= 8)
  121. {
  122. rccal_change_counts = 0;
  123. if (rc_cal_flag == RC_CALIB_NO)
  124. {
  125. // 赋值进入遥控器校准模式
  126. pilot_mode = PILOT_RC_CLB;
  127. rc_cal_flag = RC_CALIB_START;
  128. rc_offset_capture_flag = true;
  129. // 点击遥控器校准后需要延时一段时间,,不然会记录一个原先的值。填充滤波新数据额需要时间,,,
  130. rc_cal_time = micros();
  131. }
  132. else if (rc_cal_flag == RC_CALIB_START)
  133. {
  134. rc_cal_flag = RC_CALIB_NO;
  135. write_rcfactor_flag = true;
  136. }
  137. }
  138. if (micros() - rccal_time >= 1500000)
  139. {
  140. rccal_change_counts = 0;
  141. rccal_time = micros();
  142. }
  143. }
  144. //===================================================================
  145. //
  146. //================获取警告信息=====================================
  147. //
  148. //=====================================================================
  149. void get_warn_info(void)
  150. {
  151. int rcunlock_allow_flag = judge_pilot_rcunlock_allow();
  152. if (imu_link_status != COMP_NORMAL)
  153. {
  154. set_warn_flag_bit(WARN_NO_IMU);
  155. }
  156. else
  157. {
  158. reset_warn_flag_bit(WARN_NO_IMU);
  159. }
  160. if (ins.temprature > 80)
  161. {
  162. set_warn_flag_bit(WARN_HIGH_TEMPERATURE);
  163. }
  164. else
  165. {
  166. reset_warn_flag_bit(WARN_HIGH_TEMPERATURE);
  167. }
  168. if (gs_get_link_status(&gcs_link) == COMP_LOST)
  169. {
  170. set_warn_flag_bit(WARN_LINK_LOST);
  171. }
  172. else
  173. {
  174. reset_warn_flag_bit(WARN_LINK_LOST);
  175. }
  176. if (imu_link_status != COMP_NORMAL)
  177. {
  178. warn_reason = WARN_NOIMU;
  179. }
  180. else if (dma_iserror == true)
  181. {
  182. warn_reason = WARN_DMA;
  183. }
  184. else if (ins.temprature > 80)
  185. {
  186. warn_reason = WARN_OVER_TEMPRATURE;
  187. }
  188. else if (battary_volt_islow == true)
  189. {
  190. warn_reason = WARN_VOLT;
  191. }
  192. else if (COMP_LOST == gs_get_link_status(&gcs_link))
  193. {
  194. warn_reason = WARN_GS;
  195. }
  196. else if (rcunlock_allow_flag == UNLOCK_RCERR)
  197. {
  198. warn_reason = WARN_RC;
  199. }
  200. else if (ins.insgps_ok == F_AHRS)
  201. {
  202. warn_reason = WARN_AHRS;
  203. }
  204. else if (unlock_fail == true)
  205. {
  206. warn_reason = WARN_ULOCK_FAIL;
  207. }
  208. else if (sdcard_initok() != 1)
  209. {
  210. warn_reason = WARN_SD_ERROR;
  211. }
  212. else
  213. {
  214. warn_reason = WARN_NO;
  215. }
  216. }
  217. /**************************实现函数********************************************
  218. *函数原型: void rate_control(void)
  219. *功  能: 底层的陀螺角速度控制 调用频率400hz,一次运行时间11us
  220. *******************************************************************************/
  221. void rate_control(void)
  222. {
  223. static unsigned int pid_time = 0;
  224. float pid_dt = 0.0f;
  225. pid_dt = time_interval(micros(), &pid_time) / 1000000.0f;
  226. pid_time = micros();
  227. pid_roll = rate_pid_ctl_rp(&pid_m_roll, &pid_v_roll, pid_dt); // delta_t 是时间间隔,单位是秒
  228. pid_pitch = -rate_pid_ctl_rp(&pid_m_pitch, &pid_v_pitch, pid_dt);
  229. pid_yaw = rate_pid_ctl_yaw(&pid_m_yaw, &pid_v_yaw, pid_dt);
  230. rate_pid_acctothrottle_alt(pid_dt);
  231. pid_thr = rate_pid_ctl_thr();
  232. }
  233. /*
  234. 1hz 低频率计算一些数据
  235. */
  236. void loop_1_hz(void)
  237. {
  238. if (hz_1_flag == true)
  239. {
  240. hz_1_flag = false;
  241. // 检测 imu 连接状态
  242. get_ins_status();
  243. // 获取警告信息
  244. get_warn_info();
  245. }
  246. }
  247. void loop_2_hz(void)
  248. {
  249. if (hz_2_flag == true)
  250. {
  251. hz_2_flag = false;
  252. }
  253. }
  254. /*
  255. 正常控制模式的5hz循环
  256. */
  257. void normal_loop_5_hz(void)
  258. {
  259. if (hz_5_flag == true)
  260. {
  261. hz_5_flag = false;
  262. // 计算已飞时间
  263. calculate_have_fly_time_5hz();
  264. // get_fly_data_type_data_5hz();
  265. // 更新存储数据的buff
  266. // 只有在解锁的情况下才来记录数据,不解锁就记录会有问题:
  267. // 1,资源浪费.2,数据量怎多时同时200ms内FLASH无法写完会造成无法结束写入。
  268. #ifdef REC_DATA_POS
  269. // if (thr_lock_status == UNLOCKED)
  270. #endif
  271. }
  272. }
  273. /*
  274. 正常控制模式的20hz循环
  275. */
  276. void normal_loop_10_hz(void)
  277. {
  278. if (hz_10_flag == true)
  279. {
  280. hz_10_flag = false;
  281. // 检测SBUS接收机连接状态。
  282. check_sbus_link_status(0.1f);
  283. // 判断是否进入磁校准程序
  284. judge_mag_calibrateion();
  285. // 判断是否进入遥控器校准程序
  286. judge_rc_calibration();
  287. // 解锁识别
  288. pilot_unlock_decide();
  289. // 起飞识别
  290. pilot_takeoff_decide();
  291. // 上锁识别
  292. pilot_lock_decide();
  293. get_fly_data_type_data_5hz();
  294. }
  295. }
  296. /*
  297. 正常控制模式的50hz循环
  298. */
  299. void normal_loop_50_hz(void)
  300. {
  301. if (hz_50_flag == true)
  302. {
  303. hz_50_flag = false;
  304. const float dt = 1 / 50.0f;
  305. // 更新电压采集
  306. Voltage_Update();
  307. // 获取遥控器的值及当前状态
  308. get_rc_value();
  309. // 飞行模式判断
  310. flight_mode_switch();
  311. // 在锁定情况下如果是要检测电机,在输出电机值
  312. locked_motor_output();
  313. // 2 biaozhi 1ge chuan dimianzhan 1ge chuan yaokongqi flight
  314. // mode flag == 条件 (1、地面站模式 flag1 2、遥控器模式 flag2)
  315. }
  316. }
  317. /*
  318. 正常控制模式的200hz循环
  319. */
  320. unsigned int fast_loop_time = 0;
  321. const float fast_loop_dt = 1.f / 200.f;
  322. void normal_loop_200_hz(void)
  323. {
  324. // 200hZ调用,设置飞机的工作模式
  325. if (hz_200_flag == true)
  326. {
  327. hz_200_flag = false;
  328. // 更新并执行飞行模式,模式识别在50hz循环中
  329. if (thr_lock_status == UNLOCKED || flight_mode == GCS_VEHICLE_LAUNCH)
  330. {
  331. update_flight_mode();
  332. }
  333. }
  334. }
  335. /**
  336. * 标准模式 400hz
  337. */
  338. void loop_400_hz(void)
  339. {
  340. if (hz_400_flag)
  341. {
  342. hz_400_flag = false;
  343. }
  344. }
  345. /*
  346. 磁校准模式 50hz的loop
  347. */
  348. void compasscal_loop_50_hz(void)
  349. {
  350. if (hz_50_flag == true)
  351. {
  352. hz_50_flag = false;
  353. if (mag_cal_status == MAG_CAL_NO)
  354. {
  355. // 经常出现无法进入磁校准的状况,所以,进不去后,可以重传
  356. ci_jiao_zhun = true;
  357. }
  358. /* 如果磁校准通过则退出磁校准模式进入普通模式 */
  359. if (mag_cal_status == MAG_CAL_OK)
  360. {
  361. /*V8M 在此退出磁校准, V7Pro 退出磁校准模式在它的电灯循环中进行 */
  362. if (ver_par.hardware_id == HW_V8M_YY)
  363. {
  364. pilot_mode = PILOT_NORMAL;
  365. mag_cal_status = MAG_CAL_NO;
  366. ci_jiao_zhun = false;
  367. }
  368. }
  369. }
  370. }
  371. /*
  372. 遥控器校准模式50hz的loop
  373. */
  374. void rccal_loop_50_hz(void)
  375. {
  376. if (hz_10_flag == true)
  377. {
  378. hz_10_flag = false;
  379. judge_rc_calibration();
  380. }
  381. if (hz_50_flag == true)
  382. {
  383. hz_50_flag = false;
  384. // 点击遥控器校准后需要延时一段时间,,不然会记录一个原先的值。填充滤波新数据额需要时间,,
  385. if ((rc_cal_flag == RC_CALIB_START) &&
  386. (micros() - rc_cal_time > 100000))
  387. {
  388. rc_input_calibration();
  389. }
  390. // 遥控器校准时需要校准的四个通道输出原始遥控器值,便于地面站观察
  391. for (uint8_t i = 0; i < RC_CALIB_CH_NUM; i++)
  392. {
  393. // 赋值给tmp_rc_in来在地面站显示。
  394. tmp_rc_in[i] = raw_rc_in[i];
  395. }
  396. }
  397. }
  398. /*
  399. 电调校准模式50hz的loop
  400. */
  401. void esccal_loop_50_hz(void)
  402. {
  403. char i = 0;
  404. if (hz_50_flag == true)
  405. {
  406. hz_50_flag = false;
  407. // 获取遥控器的值
  408. get_rc_value();
  409. // 根据机型,全部输出CH3油门量。
  410. for (i = 1; i <= conf_par.jixing / 10; i++)
  411. {
  412. set_motor_pwm(i, rc_in[RC_CH3]);
  413. }
  414. }
  415. }
  416. /*
  417. 飞行器的主要控制循环函数
  418. */
  419. void pilot_main_loop(void)
  420. {
  421. loop_1_hz();
  422. loop_2_hz();
  423. loop_400_hz();
  424. // 正常控制模式
  425. if (pilot_mode == PILOT_NORMAL)
  426. {
  427. normal_loop_5_hz();
  428. normal_loop_10_hz();
  429. normal_loop_50_hz();
  430. normal_loop_200_hz();
  431. }
  432. // 磁校准模式
  433. else if (pilot_mode == PILOT_MAG_CLB)
  434. {
  435. compasscal_loop_50_hz();
  436. }
  437. // 遥控器校准模式
  438. else if (pilot_mode == PILOT_RC_CLB)
  439. {
  440. rccal_loop_50_hz();
  441. }
  442. // 电调校准模式
  443. else if (pilot_mode == PILOT_ESC_CLB)
  444. {
  445. esccal_loop_50_hz();
  446. }
  447. }