hall.c 8.0 KB

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