hall.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284
  1. #include <string.h>
  2. #include "bsp/bsp_driver.h"
  3. #include "os/os_task.h"
  4. #include "libs/utils.h"
  5. #include "libs/logger.h"
  6. #include "math/fast_math.h"
  7. #include "foc/motor/hall.h"
  8. #include "foc/mc_config.h"
  9. #include "libs/time_measure.h"
  10. #include "app/nv_storage.h"
  11. #include "libs/logger.h"
  12. //#define USE_DETECTED_ANGLE 1
  13. #define HALL_READ_TIMES 9
  14. #define SMOOTH_COUNT 0
  15. /*
  16. 1,5,4,6,2,3
  17. 0,1,2,3,4,5
  18. //////
  19. 2,6,4,5,1,3
  20. 0,1,2,3,4,5
  21. ////
  22. 2,3,1,5,4,6
  23. 0,1,2,3,4,5
  24. */
  25. static s8 hall_2_pos[] = {7,2,0,1,4,3,5,7};
  26. static hall_t g_hall;
  27. measure_time_t g_meas_hall = {.exec_max_time = 6,};
  28. #define us_2_s(tick) ((float)tick / 1000000.0f) //s32q14
  29. u32 stop_cnt = 0;
  30. static u8 __INLINE hall_read_state(void) {
  31. u8 hall_a = 0, hall_b = 0, hall_c = 0;
  32. for (int i = 0; i < HALL_READ_TIMES; i++) {
  33. hall_a += gpio_hall_a_value();
  34. hall_b += gpio_hall_b_value();
  35. hall_c += gpio_hall_c_value();
  36. }
  37. u8 state = 0;
  38. if (hall_a > (HALL_READ_TIMES/2 + 1)) {
  39. state = 1;
  40. }
  41. if (hall_b > (HALL_READ_TIMES/2 + 1)) {
  42. state = state | (1<<1);
  43. }
  44. if (hall_c > (HALL_READ_TIMES/2 + 1)) {
  45. state = state | (1 << 2);
  46. }
  47. return state;
  48. }
  49. static void hall_init_low_pos(void) {
  50. u8 state = hall_read_state();
  51. s16 pos = hall_2_pos[state];
  52. if (pos == 7) {
  53. g_hall.sig_errors ++;
  54. return;
  55. }
  56. g_hall.state = state;
  57. g_hall.prev_dir = g_hall.dir = POSITIVE;
  58. g_hall.low_res_pos = pos + 0.5f;
  59. }
  60. static void __INLINE hall_put_sample(u32 ticks, float angle) {
  61. hsample_t *s = &g_hall.samples;
  62. g_hall.last_delta_ticks = ticks;
  63. s->ticks_sum -= s->ticks[s->index];
  64. s->angles_sum -= s->angles[s->index];
  65. s->ticks[s->index] = ticks;
  66. s->angles[s->index] = angle;
  67. s->ticks_sum += s->ticks[s->index];
  68. s->angles_sum += s->angles[s->index];
  69. s->index += 1;
  70. if (s->index >= SAMPLE_MAX_COUNT) {
  71. s->full = true;
  72. s->index = 0;
  73. }
  74. }
  75. static float __INLINE hall_elec_angle_vel(void){
  76. hsample_t *s = &g_hall.samples;
  77. if (s->ticks_sum == 0) {
  78. return 0.0f;
  79. }
  80. return s->angles_sum / us_2_s(s->ticks_sum);
  81. }
  82. void hall_debug_log(void) {
  83. sys_debug("angle dir %d, stat %d, lowres %f, err %d,%d, sp %d\n", g_hall.dir, g_hall.state, g_hall.low_res_pos, g_hall.sig_errors, g_hall.noise_errors, stop_cnt);
  84. }
  85. void hall_init(void) {
  86. g_hall.phase_offset = mc_conf()->m.encoder_offset;
  87. g_hall.mot_poles = mc_conf()->m.poles;
  88. g_hall.b_trns_det = false;
  89. g_hall.angle_smooth_cnt = SMOOTH_COUNT + 1;
  90. g_hall.angle_smooth_step = 0;
  91. g_hall.samples.ticks_sum = 0;
  92. g_hall.samples.angles_sum = 0;
  93. g_hall.position = 0;
  94. g_hall.samples.full = false;
  95. g_hall.samples.index = 0;
  96. g_hall.elec_angle_vel = 0;
  97. for (int i = 0; i < SAMPLE_MAX_COUNT; i++) {
  98. g_hall.samples.ticks[i] = 0;
  99. g_hall.samples.angles[i] = 0;
  100. }
  101. if (!g_hall.inited) {
  102. g_hall.inited = true;
  103. gpio_hall_init();
  104. }
  105. hall_init_low_pos();
  106. stop_cnt = 0;
  107. }
  108. #if SMOOTH_COUNT > 0
  109. static float get_angle_diff(float a1, float a2) {
  110. float diff = a1 - a2;
  111. float abs_diff = ABS(diff);
  112. if (abs_diff >= PHASE_180_DEGREE) {
  113. return (PHASE_360_DEGREE - abs_diff);
  114. }else {
  115. return diff;
  116. }
  117. }
  118. #endif
  119. static bool hall_update_low_pos(void) {
  120. u8 state = hall_read_state();
  121. s16 pos = hall_2_pos[state];
  122. if (pos == 7) {
  123. g_hall.sig_errors ++;
  124. return false;
  125. }
  126. s16 pos_prev = hall_2_pos[g_hall.state];
  127. g_hall.state = state;
  128. s16 delta_pos = pos - pos_prev;
  129. g_hall.low_res_pos = pos;
  130. if (delta_pos != 0) {
  131. s8 prev_dir = g_hall.dir;
  132. if (delta_pos == 1 || delta_pos == -5) {
  133. g_hall.dir = POSITIVE;
  134. g_hall.prev_dir = prev_dir;
  135. }else if (delta_pos == -1 || delta_pos == 5){
  136. g_hall.dir = NEGATIVE;
  137. g_hall.prev_dir = prev_dir;
  138. }else {
  139. //keep prev dir value
  140. }
  141. g_hall.edge_ticks = task_ticks_abs();
  142. }else {
  143. g_hall.sig_errors ++;
  144. }
  145. return true;
  146. }
  147. hall_t *hall_get(void) {
  148. return &g_hall;
  149. }
  150. float hall_get_elec_angle(void) {
  151. float angle = g_hall.elec_angle + g_hall.phase_offset;
  152. norm_angle_deg(angle);
  153. return angle;
  154. }
  155. float hall_update_elec_angle(void) {
  156. float delta_ticks = (float)time_delta_us(g_hall.edge_ticks, NULL);//上次hall变换到目前的时间
  157. float low_res = g_hall.low_res_pos;
  158. float delta_pos = g_hall.elec_angle_vel / PHASE_60_DEGREE * us_2_s(delta_ticks) * g_hall.dir;//上次hall变换到目前走过的角度(对60度的比值,小于1),通过速度插值
  159. if (delta_pos > 1.0f) {
  160. delta_pos = 1.0f;
  161. }else if (delta_pos < -1.0f) {
  162. delta_pos = -1.0f;
  163. }
  164. float high_res_pos = delta_pos + low_res;
  165. float elec_angle = high_res_pos * PHASE_60_DEGREE;
  166. float elec_smooth_angle;
  167. #if SMOOTH_COUNT>0
  168. float delta_angle = delta_pos * PHASE_60_DEGREE;
  169. if (g_hall.angle_smooth_cnt < (SMOOTH_COUNT + 1)) {
  170. elec_smooth_angle = g_hall.elec_angle_edge + g_hall.angle_smooth_step * g_hall.angle_smooth_cnt + delta_angle;
  171. g_hall.angle_smooth_cnt++;
  172. if (g_hall.angle_smooth_step >= 0) {
  173. elec_smooth_angle = min(elec_smooth_angle, elec_angle);
  174. }else {
  175. elec_smooth_angle = MAX(elec_smooth_angle, elec_angle);
  176. }
  177. }else {
  178. elec_smooth_angle = elec_angle;
  179. }
  180. #else
  181. elec_smooth_angle = elec_angle;
  182. #endif
  183. norm_angle_deg(elec_smooth_angle);
  184. g_hall.elec_angle = elec_smooth_angle;
  185. g_hall.position += g_hall.elec_angle_vel * FOC_CTRL_US / g_hall.mot_poles;
  186. if (g_hall.samples.full && (delta_ticks / g_hall.last_delta_ticks >= 1.3f)) {
  187. stop_cnt ++;
  188. g_hall.elec_angle_vel = g_hall.elec_angle_vel * 0.99f;
  189. if (g_hall.elec_angle_vel < 10) {
  190. g_hall.elec_angle_vel = 0;
  191. }
  192. float velocity_raw = g_hall.elec_angle_vel/PHASE_360_DEGREE/g_hall.mot_poles * 60.0f * g_hall.dir;
  193. g_hall.velocity_raw = velocity_raw;
  194. LowPass_Filter(g_hall.velocity_filted, velocity_raw, 1.0f);
  195. }
  196. return hall_get_elec_angle();
  197. }
  198. float hall_get_velocity(void) {
  199. return g_hall.velocity_filted;
  200. }
  201. float hall_get_position(void) {
  202. return g_hall.position;
  203. }
  204. static void hall_calc_mot_velocity(u32 prev_ticks) {
  205. u32 delta_cnt = time_delta_us(prev_ticks, NULL);
  206. if (!g_hall.samples.full && g_hall.samples.index == 0) {
  207. if (delta_cnt <= 1000) {
  208. delta_cnt = 1000;
  209. }
  210. }
  211. hall_put_sample(delta_cnt, PHASE_60_DEGREE);
  212. float elec_vel;
  213. if (g_hall.b_trns_det) {
  214. elec_vel = PHASE_60_DEGREE/(us_2_s(delta_cnt));
  215. LowPass_Filter(g_hall.elec_angle_vel, elec_vel, 0.5f);
  216. }else {
  217. g_hall.elec_angle_vel = hall_elec_angle_vel();
  218. }
  219. float velocity_raw = g_hall.elec_angle_vel/PHASE_360_DEGREE/g_hall.mot_poles * 60.0f * g_hall.dir;
  220. float del_abs = ABS(velocity_raw - g_hall.velocity_raw);
  221. if (del_abs > 140) {
  222. g_hall.b_trns_det = true;
  223. }else if (del_abs < 100) {
  224. g_hall.b_trns_det = false;
  225. }
  226. g_hall.velocity_raw = velocity_raw;
  227. LowPass_Filter(g_hall.velocity_filted, velocity_raw, 1.0f);
  228. }
  229. float hall_offset_detect(float *off) {
  230. return 0.0f;
  231. }
  232. void HALL_IRQHandler(void) {
  233. u32 mask = cpu_enter_critical();
  234. u32 prev_ticks = g_hall.edge_ticks;
  235. if (!hall_update_low_pos()) {
  236. goto hall_end;
  237. }
  238. if (time_delta_us(prev_ticks, NULL) == 0) {
  239. g_hall.noise_errors++;
  240. goto hall_end;
  241. }
  242. g_hall.elec_angle_edge = g_hall.elec_angle;
  243. #if SMOOTH_COUNT>0
  244. g_hall.delta_angle_edge = get_angle_diff(g_hall.low_res_pos * PHASE_60_DEGREE, g_hall.elec_angle_edge);
  245. if (ABS(g_hall.delta_angle_edge) >= 2.0f) {
  246. g_hall.angle_smooth_step = 0;//g_hall.delta_angle_edge/SMOOTH_COUNT;
  247. g_hall.angle_smooth_cnt = SMOOTH_COUNT + 1;
  248. }else {
  249. g_hall.angle_smooth_step = 0;
  250. g_hall.angle_smooth_cnt = SMOOTH_COUNT + 1;
  251. }
  252. #endif
  253. hall_calc_mot_velocity(prev_ticks);
  254. hall_end:
  255. cpu_exit_critical(mask);
  256. return;
  257. }