hall.c 8.7 KB

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