hall.c 8.1 KB

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