throttle.c 9.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347
  1. #include "foc/foc_config.h"
  2. #include "foc/core/controller.h"
  3. #include "foc/samples.h"
  4. #include "math/fast_math.h"
  5. #include "bsp/bsp_driver.h"
  6. #include "libs/logger.h"
  7. #include "foc/mc_config.h"
  8. #include "foc/motor/throttle.h"
  9. #include "foc/motor/motor.h"
  10. #include "foc/mc_error.h"
  11. static u8 err_mask;
  12. static float _start_v, _end_v;
  13. static bool _auto_detect_sv = true;
  14. static int _auto_detect_sv_cnt = 0;
  15. static float _auto_detect_sv_totle = 0;
  16. static int _detect_release_cnt = 0;
  17. #define CONFIG_SAFE_INV_V 0.06f
  18. static throttle_torque_t _throttle;
  19. void throttle_torque_reset(void) {
  20. _throttle.accl = false;
  21. _throttle.thro_filted = 0.0f;
  22. _throttle.thro_ration = _throttle.thro_ration_last = 0.0f;
  23. _throttle.torque_req = _throttle.torque_real = _throttle.torque_acc_ = 0.0f;
  24. _throttle.gear = mc_get_internal_gear();
  25. }
  26. void throttle_init(void) {
  27. _start_v = mc_conf()->c.thro_start_vol;
  28. _end_v = mc_conf()->c.thro_end_vol;
  29. throttle_torque_reset();
  30. _throttle.vel_filted = 0;
  31. }
  32. bool throttle1_is_error(void) {
  33. if (err_mask & (THRO1_5V_ERR_BIT | THRO1_SIG_ERR_BIT)) {
  34. return true;
  35. }
  36. return false;
  37. }
  38. bool throttle2_is_error(void) {
  39. if (err_mask & (THRO2_5V_ERR_BIT | THRO2_SIG_ERR_BIT)) {
  40. return true;
  41. }
  42. return false;
  43. }
  44. u8 throttle_get_errors(void) {
  45. return err_mask;
  46. }
  47. bool throttle_is_all_error(void) {
  48. #if CONFIG_DAUL_THROTTLE==1
  49. return throttle1_is_error() && throttle2_is_error();
  50. #else
  51. return throttle1_is_error();
  52. #endif
  53. }
  54. float throttle_start_vol(void) {
  55. return _start_v;
  56. }
  57. float throttle_end_vol(void) {
  58. return _end_v;
  59. }
  60. float throttle_vol_range(void) {
  61. return (_end_v - _start_v);
  62. }
  63. float throttle_get_signal(void) {
  64. #if CONFIG_DAUL_THROTTLE==1
  65. if (throttle1_is_error() && throttle2_is_error()) {
  66. return 0.0f;
  67. }else if (throttle1_is_error() && !throttle2_is_error()) {
  68. float thr = get_thro2_5v_float() - get_throttle2_float();
  69. return fclamp(thr, _start_v, _end_v);
  70. }else if (!throttle1_is_error() && throttle2_is_error()) {
  71. return get_throttle_float();
  72. }else {
  73. float thr1 = get_throttle_float();
  74. float thr2 = get_thro2_5v_float() - get_throttle2_float();
  75. return (thr1+thr2)/2.0f;
  76. }
  77. #else
  78. return get_throttle_float();
  79. #endif
  80. }
  81. bool throttle_is_released(void) {
  82. #if CONFIG_DAUL_THROTTLE==1
  83. float signal = 0;
  84. if (throttle1_is_error() && !throttle2_is_error()) {
  85. float thr = get_thro2_5v_float() - get_throttle2_float();
  86. signal = fclamp(thr, _start_v, _end_v);
  87. }else if (!throttle1_is_error() && throttle2_is_error()) {
  88. signal = get_throttle_float();
  89. }else {
  90. float thr1 = get_throttle_float();
  91. float thr2 = get_thro2_5v_float() - get_throttle2_float();
  92. signal = (thr1+thr2)/2.0f;
  93. }
  94. return signal <= _start_v;
  95. #else
  96. return get_throttle_float() <= _start_v;
  97. #endif
  98. }
  99. bool throttle_not_released_err(void)
  100. {
  101. return ((err_mask & THRO_NOT_RELEASED) != 0);
  102. }
  103. void throttle_force_detect(void) {
  104. u32 mask = cpu_enter_critical();
  105. throttle_init();
  106. _auto_detect_sv = true;
  107. _auto_detect_sv_cnt = 0;
  108. _auto_detect_sv_totle = 0;
  109. _detect_release_cnt = 0;
  110. err_mask = 0; //clear err mask
  111. cpu_exit_critical(mask);
  112. }
  113. /* 获取转把电压对应的油门开度 */
  114. float throttle_vol_to_open_ration(int thro_val) {
  115. if (thro_val <= throttle_start_vol()) {
  116. return 0;
  117. }
  118. float delta = thro_val - throttle_start_vol();
  119. int ration = (delta * 100.0f) / throttle_vol_range();
  120. return ((float)ration)/100.0f;
  121. }
  122. /* 获取油门开度 */
  123. float throttle_get_open_ration(void) {
  124. float thro_val = throttle_get_signal();
  125. return throttle_vol_to_open_ration(thro_val);
  126. }
  127. /* 获取油门开度对应的转把电压 */
  128. float throttle_open_ration_to_vol(float r) {
  129. if (r == 0) {
  130. return 0;
  131. }
  132. float vol = throttle_start_vol() + r * throttle_vol_range();
  133. return fclamp(vol, 0, throttle_end_vol());
  134. }
  135. void throttle_detect(bool ready) {
  136. float thr_5v, thr_sig;
  137. sample_throttle();
  138. thr_5v = get_thro_5v_float();
  139. thr_sig = get_throttle_float();
  140. if (thr_sig <= mc_conf()->c.thro_min_vol || thr_sig >= mc_conf()->c.thro_max_vol) {
  141. err_mask |= THRO1_SIG_ERR_BIT;
  142. }
  143. if (thr_5v <= 4.5f || thr_5v >= 5.5f) {
  144. err_mask |= THRO1_5V_ERR_BIT;
  145. }
  146. #if CONFIG_DAUL_THROTTLE==1
  147. thr_5v = get_thro2_5v_float();
  148. if (thr_5v <= 4.5f || thr_5v >= 5.5f) {
  149. err_mask |= THRO2_5V_ERR_BIT;
  150. }else {
  151. float thr2_sig = get_thro2_5v_float() - get_throttle2_float();
  152. if (thr2_sig <= mc_conf()->c.thro_min_vol || thr2_sig >= mc_conf()->c.thro_max_vol) {
  153. err_mask |= THRO2_SIG_ERR_BIT;
  154. }else {
  155. if (ABS(thr2_sig - thr_sig) > 0.5f) {
  156. err_mask |= THRO2_SIG_ERR_BIT;
  157. err_mask |= THRO1_SIG_ERR_BIT;
  158. }
  159. }
  160. }
  161. #endif
  162. if (!ready && throttle_get_signal() > _start_v) {
  163. if (_detect_release_cnt < 500) {
  164. _detect_release_cnt ++;
  165. }else {
  166. err_mask |= THRO_NOT_RELEASED;
  167. }
  168. }
  169. if (ready) {
  170. _auto_detect_sv = false;
  171. }else if (!throttle_is_all_error() && !throttle_not_released_err() && !ready && _auto_detect_sv) {
  172. float v = throttle_get_signal();
  173. if (v < _start_v) {
  174. _auto_detect_sv_totle += v;
  175. _auto_detect_sv_cnt ++;
  176. if (_auto_detect_sv_cnt == 200) {
  177. _start_v = _auto_detect_sv_totle / (float)_auto_detect_sv_cnt + CONFIG_SAFE_INV_V;
  178. _auto_detect_sv = false;
  179. mc_crit_err_add_s16(FOC_EV_THRO_START_V, (s16)(_start_v * 100.0f));
  180. }
  181. }
  182. }
  183. }
  184. static float _throttle_torque_for_accelerate(float ration) {
  185. float max_torque = mc_get_max_torque_with_gear_vel((s16)_throttle.vel_filted, _throttle.gear);
  186. float thro_torque = max_torque * ration;
  187. float acc_r = 1.0f;
  188. if (_throttle.thro_ration_last < 1.0f) {
  189. acc_r = (ration - _throttle.thro_ration_last)/ (1.0f - _throttle.thro_ration_last);
  190. }
  191. acc_r = fclamp(acc_r, 0, 1.0f);
  192. float acc_torque = _throttle.torque_real + acc_r * (max_torque - _throttle.torque_real);
  193. if (acc_torque < 0) {
  194. acc_torque = 0;
  195. }
  196. /*
  197. 直接获取油门开度对应的加速扭矩thro_torque 不小于间接计算得到的 acc_torque
  198. */
  199. float torque_acc_ = thro_torque - acc_torque;
  200. float step = 0.0f;
  201. if (torque_acc_ > 0) {
  202. float acc_t = mc_gear_conf()->accl_time;
  203. step = torque_acc_ / (acc_t + 0.00001f);
  204. }else {
  205. torque_acc_ = 0;
  206. }
  207. step_towards(&_throttle.torque_acc_, torque_acc_, step);
  208. return (acc_torque + _throttle.torque_acc_);
  209. }
  210. static float throttle_torque_for_accelerate(void) {
  211. return _throttle_torque_for_accelerate(_throttle.thro_ration);
  212. }
  213. static float throttle_torque_for_decelerate(void) {
  214. if (_throttle.thro_ration_last == 0.0f) {
  215. return 0;
  216. }
  217. float dec_r = _throttle.thro_ration / _throttle.thro_ration_last;
  218. dec_r = fclamp(dec_r, 0.0f, 1.0f);
  219. return dec_r * _throttle.torque_real;
  220. }
  221. float throttle_get_open_ration_filted(void) {
  222. return _throttle.thro_ration;
  223. }
  224. #define THRO_RPM_LP_CEOF 0.01f
  225. float throttle_get_torque(mot_contrl_t * ctrl, float vol) {
  226. float thro_r = throttle_vol_to_open_ration(vol);
  227. _throttle.gear = mc_get_internal_gear();
  228. LowPass_Filter(_throttle.vel_filted, mot_contrl_get_speed(ctrl), THRO_RPM_LP_CEOF);
  229. if (thro_r > _throttle.thro_ration) {
  230. if (!_throttle.accl) {
  231. _throttle.thro_ration_last = _throttle.thro_ration;
  232. _throttle.torque_real = _throttle.torque_req;
  233. if (_throttle.torque_real < 0) { //电子刹车的时候,扭矩可能为负
  234. _throttle.torque_real = 0;
  235. }
  236. _throttle.torque_acc_ = 0;
  237. }
  238. _throttle.accl = true;
  239. }else if (thro_r < _throttle.thro_ration) {
  240. if (_throttle.accl) {
  241. _throttle.thro_ration_last = _throttle.thro_ration;
  242. _throttle.torque_real = ctrl->target_torque_raw;
  243. /* 如果扭矩给定的ramp没有结束,使用原始扭矩请求作为减扭矩的起始点 */
  244. if (_throttle.torque_req - line_ramp_get_interp(&ctrl->input_torque) >= 10.0f ) {
  245. _throttle.torque_real = _throttle.torque_req;
  246. }
  247. if (_throttle.torque_real < 0) { //电子刹车的时候,扭矩可能为负
  248. _throttle.torque_real = 0;
  249. }
  250. }
  251. _throttle.accl = false;
  252. }
  253. _throttle.thro_ration = thro_r;
  254. if (_throttle.accl) {
  255. return throttle_torque_for_accelerate();
  256. }else {
  257. return throttle_torque_for_decelerate();
  258. }
  259. }
  260. void throttle_set_torque(mot_contrl_t * ctrl, float torque) {
  261. float curr_vel = mot_contrl_get_speed(ctrl);
  262. float ref_torque = torque;
  263. if (_throttle.accl) { //加速需求
  264. float hold_torque = ctrl->autohold_torque;
  265. if (hold_torque < 0) { //下坡驻车,最小给0扭矩
  266. hold_torque = 0;
  267. }
  268. ref_torque = MAX(hold_torque, ref_torque);
  269. if (curr_vel <= CONFIG_ZERO_SPEED_RPM) {//从静止开始加速
  270. if (_throttle.torque_req < hold_torque) {
  271. _throttle.torque_req = hold_torque;
  272. line_ramp_reset(&ctrl->input_torque, hold_torque);
  273. }
  274. }else {
  275. ctrl->autohold_torque = 0;
  276. }
  277. /* 处理加速ramp时间的变化,需要缓慢变小,变大可以立即处理,
  278. * 加速时间缓慢变小可以防止突然大扭矩加速
  279. */
  280. u16 now_ramp_time = mot_contrl_get_torque_acc_time(ctrl);
  281. u16 next_ramp_time = mc_gear_conf()->accl_time;
  282. if (curr_vel < CONFIG_ZERO_SPEED_RAMP_RMP) {
  283. next_ramp_time = mc_gear_conf()->zero_accl;
  284. }
  285. if (now_ramp_time != next_ramp_time) {
  286. if (next_ramp_time > now_ramp_time) {
  287. mot_contrl_set_torque_acc_time(ctrl, next_ramp_time);
  288. }else {
  289. float f_now = (float)now_ramp_time;
  290. float f_next = (float)next_ramp_time;
  291. step_towards(&f_now, f_next, 0.5f);
  292. mot_contrl_set_torque_acc_time(ctrl ,(u16)f_now);
  293. }
  294. }
  295. _throttle.torque_req = ref_torque;
  296. }else {
  297. float ref_torque = throttle_torque_for_decelerate();
  298. /* autohold 启动的情况下,转把在0位置附近小幅抖动 */
  299. if (curr_vel <= CONFIG_ZERO_SPEED_RPM) {
  300. float hold_torque = ctrl->autohold_torque;
  301. ref_torque = MAX(hold_torque, ref_torque);
  302. }
  303. _throttle.torque_req = ref_torque;
  304. }
  305. mot_contrl_set_torque(ctrl, _throttle.torque_req);
  306. }
  307. /* 定速巡航需要判断是否需要加速 */
  308. float get_user_request_torque(void) {
  309. if (_throttle.accl) {
  310. return throttle_torque_for_accelerate();
  311. }
  312. return throttle_torque_for_decelerate();
  313. }