hall.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  1. #include <string.h>
  2. #include "bsp/bsp.h"
  3. #include "bsp/mc_hall_gpio.h"
  4. #include "os/os_task.h"
  5. #include "libs/utils.h"
  6. #include "libs/logger.h"
  7. #include "math/fast_math.h"
  8. #include "foc/motor/hall.h"
  9. #include "app/nv_storage.h"
  10. #include "bsp/timer_count32.h"
  11. #include "libs/time_measure.h"
  12. //#define USE_DETECTED_ANGLE 1
  13. #define HALL_READ_TIMES 3
  14. static u32 _hall_detect_task(void *args);
  15. static void _hall_init_el_angle(void);
  16. #define HALL_PLACE_OFFSET (315 << 19) //(345) //315
  17. /*
  18. 4,5,1,3,2,6,4
  19. */
  20. static hall_sensor_t _sensor_hander;
  21. measure_time_t g_meas_hall = {.exec_max_time = 6,};
  22. //#define read_hall(h,t) {h = get_hall_stat(HALL_READ_TIMES); t = _hall_table[h];}
  23. #define us_2_s(tick) S32Q14((float)tick / 1000000.0f) //s32q14
  24. #define rand_angle(a) {if (a >= PHASE_360_DEGREE) a-=PHASE_360_DEGREE;else if (a < 0) a +=PHASE_360_DEGREE;};
  25. static void __inline _hall_put_sample(u32 ticks, s32q19_t angle) {
  26. hall_sample_t *s = &_sensor_hander.samples;
  27. s->ticks_sum -= s->ticks[s->index];
  28. s->angles_sum -= s->angles[s->index];
  29. s->ticks[s->index] = ticks;
  30. s->angles[s->index] = angle;
  31. s->ticks_sum += s->ticks[s->index];
  32. s->angles_sum += s->angles[s->index];
  33. s->index += 1;
  34. if (s->index >= SAMPLE_MAX_COUNT) {
  35. s->full = true;
  36. s->index = 0;
  37. }
  38. }
  39. static s32q5_t __inline _hall_angle_speed(void){
  40. hall_sample_t *s = &_sensor_hander.samples;
  41. if (s->ticks_sum == 0) {
  42. return 0.0f;
  43. }
  44. if (!s->full) {
  45. return s->angles[s->index - 1] / us_2_s(s->ticks[s->index-1]);
  46. }else {
  47. return s->angles_sum / us_2_s(s->ticks_sum);
  48. }
  49. }
  50. void hall_debug_log(void) {
  51. sys_debug("angle dir %d\n", _sensor_hander.direction);
  52. }
  53. /*
  54. static bool __inline _hall_data_empty(void) {
  55. hall_sample_t *s = &_sensor_hander.samples;
  56. if ((!s->full) && (s->index == 0)){
  57. return true;
  58. }
  59. return false;
  60. }
  61. */
  62. static void hall_sensor_default(void) {
  63. memset(&_sensor_hander, 0, sizeof(_sensor_hander));
  64. _sensor_hander.phase_offset = HALL_PLACE_OFFSET;//mc_config_get()->hall_offset;
  65. memcpy((char *)_sensor_hander.angle_table, (char *)mc_config_get()->hall_table, sizeof(_sensor_hander.angle_table));
  66. _hall_init_el_angle();
  67. hall_debug_log();
  68. }
  69. void hall_sensor_init(void) {
  70. mc_hall_init();
  71. hall_sensor_default();
  72. shark_task_create(_hall_detect_task, NULL);
  73. }
  74. void hall_sensor_clear(void) {
  75. hall_sensor_default();
  76. }
  77. static u32 _hall_detect_task(void *args) {
  78. if (_sensor_hander.el_speed != 0) {
  79. u32 ticks_now = timer_count32_get();
  80. u32 delta_us = timer_count32_delta(ticks_now, _sensor_hander.hall_ticks);
  81. if (delta_us >= (1200*1000)) {
  82. hall_sensor_clear();
  83. }
  84. }
  85. return 0;
  86. }
  87. s16q5_t hall_sensor_get_theta(void){
  88. u32 us_now = timer_count32_get();
  89. u32 us_delta = timer_count32_delta(us_now, _sensor_hander.estimate_time_ticks);
  90. _sensor_hander.estimate_time_ticks = us_now;
  91. s32q19_t angle_step = _sensor_hander.estimate_el_speed * us_2_s(us_delta);
  92. _sensor_hander.estimate_delta_angle += angle_step;
  93. if (_sensor_hander.direction == POSITIVE) {
  94. _sensor_hander.estimate_el_angle += angle_step;
  95. }else {
  96. _sensor_hander.estimate_el_angle -= angle_step;
  97. }
  98. rand_angle(_sensor_hander.estimate_el_angle);
  99. return (_sensor_hander.estimate_el_angle >> 14);
  100. }
  101. s32q5_t hall_sensor_get_speed(void) {
  102. return _sensor_hander.rpm;
  103. }
  104. int hall_offset_increase(int inc) {
  105. inc = inc << 19;
  106. if (_sensor_hander.phase_offset + inc >= PHASE_360_DEGREE) {
  107. _sensor_hander.phase_offset = _sensor_hander.phase_offset + inc - PHASE_360_DEGREE;
  108. }else {
  109. _sensor_hander.phase_offset += inc;
  110. }
  111. return _sensor_hander.phase_offset;
  112. }
  113. s32 *hall_get_table(void) {
  114. return _sensor_hander.angle_table;
  115. }
  116. static void _hall_init_el_angle(void) {
  117. _sensor_hander.hall_stat = get_hall_stat(HALL_READ_TIMES);
  118. #ifdef USE_DETECTED_ANGLE
  119. if (_sensor_hander.hall_stat == 0 || _sensor_hander.hall_stat == 7) {
  120. _sensor_hander.sensor_error ++;
  121. return;
  122. }
  123. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + _sensor_hander.angle_table[_sensor_hander.hall_stat];
  124. #else
  125. s32 sector_center = PHASE_60_DEGREE/2;
  126. switch ( _sensor_hander.hall_stat )
  127. {
  128. case STATE_5:
  129. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + sector_center;
  130. break;
  131. case STATE_1:
  132. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + PHASE_60_DEGREE + sector_center;
  133. break;
  134. case STATE_3:
  135. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + PHASE_120_DEGREE + sector_center;
  136. break;
  137. case STATE_2:
  138. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + PHASE_180_DEGREE + sector_center;
  139. break;
  140. case STATE_6:
  141. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + PHASE_240_DEGREE + sector_center;
  142. break;
  143. case STATE_4:
  144. _sensor_hander.measured_el_angle = _sensor_hander.phase_offset + PHASE_300_DEGREE + sector_center;
  145. break;
  146. default:
  147. /* Bad hall sensor configutarion so update the speed reliability */
  148. _sensor_hander.sensor_error ++;
  149. return;
  150. }
  151. #endif
  152. _sensor_hander.sensor_error = 0;
  153. /* Initialize the measured angle */
  154. rand_angle(_sensor_hander.measured_el_angle);
  155. _sensor_hander.estimate_el_angle = _sensor_hander.measured_el_angle;
  156. _sensor_hander.hall_ticks = timer_count32_get();
  157. _sensor_hander.estimate_time_ticks = timer_count32_get();
  158. }
  159. static __inline__ s32 _get_angle(u8 state, s32 added) {
  160. #ifdef USE_DETECTED_ANGLE
  161. return _sensor_hander.phase_offset + _sensor_hander.angle_table[state];
  162. #else
  163. return _sensor_hander.phase_offset + added;
  164. #endif
  165. }
  166. /* 4,5,1,3,2,6,4 */
  167. static s32 _hall_position(u8 state_now, u8 state_prev) {
  168. s32 theta_now = 0xFFFFFFFF;
  169. switch (state_now) {
  170. case STATE_1:
  171. if (state_prev == STATE_5) {
  172. _sensor_hander.direction = POSITIVE;
  173. theta_now = _get_angle(state_now, PHASE_60_DEGREE);//_sensor_hander.phase_offset + PHASE_60_DEGREE;
  174. }else if (state_prev == STATE_3) {
  175. _sensor_hander.direction = NEGATIVE;
  176. theta_now = _get_angle(state_now, PHASE_120_DEGREE);//_sensor_hander.phase_offset + PHASE_120_DEGREE;
  177. }
  178. break;
  179. case STATE_2:
  180. if (state_prev == STATE_3) {
  181. _sensor_hander.direction = POSITIVE;
  182. theta_now = _get_angle(state_now, PHASE_180_DEGREE);//_sensor_hander.phase_offset + PHASE_180_DEGREE;
  183. }else if (state_prev == STATE_6) {
  184. _sensor_hander.direction = NEGATIVE;
  185. theta_now = _get_angle(state_now, PHASE_240_DEGREE);//_sensor_hander.phase_offset + PHASE_240_DEGREE;
  186. }
  187. break;
  188. case STATE_3:
  189. if (state_prev == STATE_1) {
  190. _sensor_hander.direction = POSITIVE;
  191. theta_now = _get_angle(state_now, PHASE_120_DEGREE);//_sensor_hander.phase_offset + PHASE_120_DEGREE;
  192. }else if (state_prev == STATE_2) {
  193. _sensor_hander.direction = NEGATIVE;
  194. theta_now = _get_angle(state_now, PHASE_180_DEGREE);//_sensor_hander.phase_offset + PHASE_180_DEGREE;
  195. }
  196. break;
  197. case STATE_4:
  198. if (state_prev == STATE_6) {
  199. _sensor_hander.direction = POSITIVE;
  200. theta_now = _get_angle(state_now, PHASE_300_DEGREE);//_sensor_hander.phase_offset + PHASE_300_DEGREE;
  201. }else if (state_prev == STATE_5) {
  202. _sensor_hander.direction = NEGATIVE;
  203. theta_now = _get_angle(state_now, PHASE_0_DEGREE);//_sensor_hander.phase_offset + PHASE_0_DEGREE;
  204. }
  205. break;
  206. case STATE_5:
  207. if (state_prev == STATE_4) {
  208. _sensor_hander.direction = POSITIVE;
  209. theta_now = _get_angle(state_now, PHASE_0_DEGREE);//_sensor_hander.phase_offset + PHASE_0_DEGREE;
  210. }else if (state_prev == STATE_1) {
  211. _sensor_hander.direction = NEGATIVE;
  212. theta_now = _get_angle(state_now, PHASE_60_DEGREE);//_sensor_hander.phase_offset + PHASE_60_DEGREE;
  213. }
  214. break;
  215. case STATE_6:
  216. if (state_prev == STATE_2) {
  217. _sensor_hander.direction = POSITIVE;
  218. theta_now = _get_angle(state_now, PHASE_240_DEGREE);//_sensor_hander.phase_offset + PHASE_240_DEGREE;
  219. }else if (state_prev == STATE_4) {
  220. _sensor_hander.direction = NEGATIVE;
  221. theta_now = _get_angle(state_now, PHASE_300_DEGREE);//_sensor_hander.phase_offset + PHASE_300_DEGREE;
  222. }
  223. break;
  224. default:
  225. _sensor_hander.sensor_error ++;
  226. return 0xFFFFFFFF;
  227. }
  228. rand_angle(theta_now);
  229. return theta_now;
  230. }
  231. #ifdef USE_DETECTED_ANGLE
  232. static __inline u8 _next_hall(u8 hall_now) {
  233. switch (hall_now) {
  234. case STATE_1:
  235. if (_sensor_hander.direction == POSITIVE) {
  236. return STATE_3;
  237. }else {
  238. return STATE_5;
  239. }
  240. case STATE_2:
  241. if (_sensor_hander.direction == POSITIVE) {
  242. return STATE_6;
  243. }else {
  244. return STATE_3;
  245. }
  246. case STATE_3:
  247. if (_sensor_hander.direction == POSITIVE) {
  248. return STATE_2;
  249. }else {
  250. return STATE_1;
  251. }
  252. case STATE_4:
  253. if (_sensor_hander.direction == POSITIVE) {
  254. return STATE_5;
  255. }else {
  256. return STATE_6;
  257. }
  258. case STATE_5:
  259. if (_sensor_hander.direction == POSITIVE) {
  260. return STATE_1;
  261. }else {
  262. return STATE_4;
  263. }
  264. case STATE_6:
  265. if (_sensor_hander.direction == POSITIVE) {
  266. return STATE_4;
  267. }else {
  268. return STATE_2;
  269. }
  270. default: //not reached here
  271. return STATE_1;
  272. }
  273. }
  274. static __inline__ s32 _get_delta_angle(u8 now, u8 next) {
  275. s32 delta_angle = _sensor_hander.angle_table[next] - _sensor_hander.angle_table[now];
  276. if (_sensor_hander.direction == POSITIVE) {
  277. if (delta_angle < 0) { //process cross 360 degree
  278. delta_angle += PHASE_360_DEGREE;
  279. }
  280. }else if (_sensor_hander.direction == NEGATIVE) {
  281. if (delta_angle > 0) { //process cross 360 degree
  282. delta_angle -= PHASE_360_DEGREE;
  283. }
  284. delta_angle = -delta_angle;
  285. }
  286. return delta_angle;
  287. }
  288. #endif
  289. void HALL_IRQHandler(void) {
  290. time_measure_start(&g_meas_hall);
  291. u8 hall_stat_now = get_hall_stat(HALL_READ_TIMES);
  292. u8 hall_stat_prev = _sensor_hander.hall_stat;
  293. u32 hall_ticks_now = timer_count32_get();
  294. /*获取当前转子角度*/
  295. s32 theta_now = _hall_position(hall_stat_now, hall_stat_prev);
  296. if (theta_now == 0xFFFFFFFF) {
  297. return;
  298. }
  299. //获取两次中断的时间间隔,估计速度
  300. u32 delta_us = timer_count32_delta(hall_ticks_now, _sensor_hander.hall_ticks);
  301. if (delta_us == 0) {
  302. return;
  303. }
  304. //获取两次中断之间转子转过的角度,获取预期的下次hall状态变换转过的角度
  305. #ifdef USE_DETECTED_ANGLE
  306. s32 delta_angle = _get_delta_angle(hall_stat_prev, hall_stat_now);
  307. s32 next_delta_angle = _get_delta_angle(hall_stat_now, _next_hall(hall_stat_now));
  308. #else
  309. s32 delta_angle = PHASE_60_DEGREE;
  310. s32 next_delta_angle = delta_angle;
  311. #endif
  312. s32 delta_time = us_2_s(delta_us);
  313. s32 prev_imme_el_speed = _sensor_hander.immediately_el_speed;
  314. _sensor_hander.immediately_el_speed = delta_angle/delta_time; //s32q5
  315. s32 delta_el_speed = abs(_sensor_hander.immediately_el_speed - prev_imme_el_speed);
  316. if (delta_el_speed*100/prev_imme_el_speed >= 20) { //即时速度增加10%,认为不稳定,需要使用即时速度估计转子位置
  317. _sensor_hander.trns_detect = true;
  318. }else {
  319. _sensor_hander.trns_detect = false;
  320. }
  321. _hall_put_sample(delta_us, delta_angle);
  322. os_disable_irq();
  323. _sensor_hander.el_speed = _hall_angle_speed(); //s32q5
  324. _sensor_hander.estimate_delta_angle = _sensor_hander.estimate_delta_angle - delta_angle;
  325. /*通过上次预估的转子位置,对当前的预估速度进行补偿*/
  326. s32q14_t est_el_speed = ((next_delta_angle - _sensor_hander.estimate_delta_angle)<<9)/delta_angle * _sensor_hander.el_speed;
  327. if (_sensor_hander.trns_detect) { //s32q14
  328. est_el_speed = ((next_delta_angle - _sensor_hander.estimate_delta_angle)<<9)/delta_angle * _sensor_hander.immediately_el_speed;
  329. }
  330. //s32q5
  331. _sensor_hander.estimate_el_speed = est_el_speed >> 9;
  332. _sensor_hander.next_delta_angle = next_delta_angle;
  333. //_sensor_hander.measured_el_angle = theta_now;
  334. os_enable_irq();
  335. _sensor_hander.hall_stat = hall_stat_now;
  336. _sensor_hander.hall_ticks = hall_ticks_now;
  337. _sensor_hander.rpm = _sensor_hander.el_speed / 360 * 60; //s32q5
  338. time_measure_end(&g_meas_hall);
  339. }