| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- #include <string.h>
- #include "bsp/bsp_driver.h"
- #include "os/os_task.h"
- #include "libs/utils.h"
- #include "libs/logger.h"
- #include "math/fast_math.h"
- #include "foc/motor/hall.h"
- #include "foc/mc_config.h"
- #include "app/nv_storage.h"
- #include "libs/logger.h"
- #define HALL_READ_TIMES 5
- #define SMOOTH_COUNT 0
- #define HALL_DETECT_OFFSET 0
- /*
- 1,5,4,6,2,3
- 0,1,2,3,4,5
- //////
- 2,6,4,5,1,3
- 0,1,2,3,4,5
- ////
- 2,3,1,5,4,6
- 0,1,2,3,4,5
- */
- static s8 hall_2_pos[] = {7,2,0,1,4,3,5,7};
- static hall_t g_hall;
- #define us_2_s(tick) ((float)tick / 1000000.0f) //s32q14
- #define HALL_MAX_TIME 1000000UL
- static u32 g_delta_cnt = 0;
- static u32 g_trns_cnt = 0;
- static u32 g_min_delta;
- #define COUNT_2_US(c) (c/(SYSTEM_CLOCK/1000000))
- #if HALL_DETECT_OFFSET > 0
- static float hall_off[6];
- static u32 hall_off_cnt[6];
- static void hall_offset_dec_init(void) {
- for (int i = 0; i < 6; i++) {
- hall_off[i] = 0;
- hall_off_cnt[i] = 0;
- }
- }
- float mc_get_mot_angle(void);
- static __INLINE void hall_offset_update(void) {
- int pos_int = (int)g_hall.low_res_pos;
- float hall_pos = g_hall.low_res_pos * PHASE_60_DEGREE;
- float delta_pos = hall_pos - (mc_get_mot_angle() + 90.0f);
- norm_angle_deg(delta_pos);
- hall_off[pos_int] = delta_pos;
- hall_off_cnt[pos_int] += 1;
- }
- static void hall_offset_log(void) {
- if (hall_off_cnt[0] < 20) {
- return;
- }
- s16 value[6];
- u32 mask = cpu_enter_critical();
- for (int i = 0; i < 6; i++) {
- value[i] = (s16)(hall_off[i]/(float)hall_off_cnt[i]);
- hall_off_cnt[i] = 0;
- }
- cpu_exit_critical(mask);
- sys_debug("off:%d,%d,%d,%d,%d,%d\n", value[0], value[1], value[2], value[3], value[4], value[5]);
- }
- #else
- static void hall_offset_dec_init(void) {
- }
- static __INLINE void hall_offset_update(void) {
- }
- static void hall_offset_log(void) {
- }
- #endif
- static __INLINE u32 hall_delta_us(u32 count) {
- u32 now = task_ticks_abs();
- u32 delta = now - count;
- if (now < count) { //wrap
- delta = 0xFFFFFFFF - count + now + 1;
- }
- return COUNT_2_US(delta);
- }
- static u8 __INLINE hall_read_state(void) {
- u8 hall_a = 0, hall_b = 0, hall_c = 0;
- for (int i = 0; i < HALL_READ_TIMES; i++) {
- hall_a += gpio_hall_a_value();
- hall_b += gpio_hall_b_value();
- hall_c += gpio_hall_c_value();
- }
- u8 state = 0;
- if (hall_a > (HALL_READ_TIMES/2 + 1)) {
- state = 1;
- }
- if (hall_b > (HALL_READ_TIMES/2 + 1)) {
- state = state | (1<<1);
- }
- if (hall_c > (HALL_READ_TIMES/2 + 1)) {
- state = state | (1 << 2);
- }
- return state;
- }
- static void hall_init_low_pos(void) {
- u8 state = hall_read_state();
- s16 pos = hall_2_pos[state];
- if (pos == 7) {
- g_hall.sig_errors ++;
- return;
- }
- g_hall.state = state;
- if (g_hall.dir == POSITIVE) {
- g_hall.low_res_pos = pos + 0.5f;
- }else {
- g_hall.low_res_pos = pos - 0.5f;
- }
- }
- static void __INLINE hall_put_sample(u32 ticks) {
- hsample_t *s = &g_hall.samples;
- g_hall.last_delta_ticks = ticks;
- s->ticks_sum -= s->ticks[s->index];
- s->ticks[s->index] = ticks;
- s->ticks_sum += s->ticks[s->index];
- s->index += 1;
- if (s->index >= SAMPLE_MAX_COUNT) {
- s->index = 0;
- }
- if (s->filled < SAMPLE_MAX_COUNT) {
- s->filled++;
- }
- }
- static float __INLINE hall_elec_angle_vel(void){
- hsample_t *s = &g_hall.samples;
- if (s->filled < SAMPLE_MAX_COUNT) {
- return (PHASE_60_DEGREE) / us_2_s(g_hall.last_delta_ticks);
- }
- if (s->ticks_sum == 0) {
- return 0.0f;
- }
- return (PHASE_60_DEGREE * SAMPLE_MAX_COUNT) / us_2_s(s->ticks_sum);
- }
- void hall_debug_log(void) {
- 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);
- sys_debug("D: %d,%d,%d\n", g_delta_cnt, g_trns_cnt, g_min_delta);
- sys_debug("RPM: %f\n", hall_get_velocity());
- hall_offset_log();
- }
- void hall_init(void) {
- g_hall.phase_offset = mc_conf()->m.encoder_offset;
- g_hall.mot_poles = mc_conf()->m.poles;
- g_hall.b_trns_det = false;
- g_hall.angle_smooth_cnt = SMOOTH_COUNT + 1;
- g_hall.angle_smooth_step = 0;
- g_hall.samples.ticks_sum = 0;
- g_hall.position = 0;
- g_hall.samples.index = 0;
- g_hall.samples.filled = 0;
- g_hall.elec_angle_vel = 0;
- g_hall.edge_ticks = 0;
- g_hall.dir_set = g_hall.prev_dir = g_hall.dir = POSITIVE;
- g_min_delta = 1000000 * 100;
- for (int i = 0; i < SAMPLE_MAX_COUNT; i++) {
- g_hall.samples.ticks[i] = HALL_MAX_TIME;
- }
- g_hall.samples.ticks_sum = HALL_MAX_TIME * SAMPLE_MAX_COUNT;
- if (!g_hall.inited) {
- g_hall.inited = true;
- #ifdef HALL_TIMER
- hall_tmr_init();
- #else
- gpio_hall_init();
- #endif
- }
- hall_offset_dec_init();
- hall_init_low_pos();
- }
- void hall_set_direction(s8 dir) {
- if (dir == g_hall.dir_set) {
- return;
- }
- g_hall.dir_set = g_hall.dir = g_hall.prev_dir = dir;
- hall_init_low_pos();
- }
- #if SMOOTH_COUNT > 0
- static float get_angle_diff(float a1, float a2) {
- float diff = a1 - a2;
- float abs_diff = ABS(diff);
- if (abs_diff >= PHASE_180_DEGREE) {
- return (PHASE_360_DEGREE - abs_diff);
- }else {
- return diff;
- }
- }
- #endif
- static __INLINE bool hall_update_low_pos(void) {
- u8 state = hall_read_state();
- s16 pos = hall_2_pos[state];
- if (pos == 7) {
- g_hall.sig_errors ++;
- return false;
- }
- s16 pos_prev = hall_2_pos[g_hall.state];
- s16 delta_pos = pos - pos_prev;
- if (delta_pos != 0) {
- s8 prev_dir = g_hall.dir;
- if (delta_pos == 1 || delta_pos == -5) {
- g_hall.dir = POSITIVE;
- g_hall.prev_dir = prev_dir;
- }else if (delta_pos == -1 || delta_pos == 5){
- g_hall.dir = NEGATIVE;
- g_hall.prev_dir = prev_dir;
- }else {
- if (g_hall.samples.filled > 0) {
- g_hall.sig_errors ++;
- return false;
- }
- }
- g_hall.edge_ticks = task_ticks_abs();
- }else {
- g_hall.sig_errors ++;
- return false;
- }
- g_hall.state = state;
-
- g_hall.low_res_pos = pos;
- return true;
- }
- hall_t *hall_get(void) {
- return &g_hall;
- }
- float hall_get_elec_angle(void) {
- float phase_offset = g_hall.phase_offset;
- if (g_hall.dir == NEGATIVE) {
- phase_offset = PHASE_60_DEGREE + phase_offset;
- }
- float angle = g_hall.elec_angle + phase_offset;
- norm_angle_deg(angle);
- return angle;
- }
- float hall_update_elec_angle(void) {
- float delta_ticks = (float)hall_delta_us(g_hall.edge_ticks);//上次hall变换到目前的时间
- float low_res = g_hall.low_res_pos;
- float delta_pos = g_hall.elec_angle_vel / PHASE_60_DEGREE * us_2_s(delta_ticks) * g_hall.dir;//上次hall变换到目前走过的角度(对60度的比值,小于1),通过速度插值
- if (delta_pos > 1.0f) {
- delta_pos = 1.0f;
- }else if (delta_pos < -1.0f) {
- delta_pos = -1.0f;
- }
- float high_res_pos = delta_pos + low_res;
- float elec_angle = high_res_pos * PHASE_60_DEGREE;
- float elec_smooth_angle;
- #if SMOOTH_COUNT>0
- float delta_angle = delta_pos * PHASE_60_DEGREE;
- if (g_hall.angle_smooth_cnt < (SMOOTH_COUNT + 1)) {
- elec_smooth_angle = g_hall.elec_angle_edge + g_hall.angle_smooth_step * g_hall.angle_smooth_cnt + delta_angle;
- g_hall.angle_smooth_cnt++;
- if (g_hall.angle_smooth_step >= 0) {
- elec_smooth_angle = min(elec_smooth_angle, elec_angle);
- }else {
- elec_smooth_angle = MAX(elec_smooth_angle, elec_angle);
- }
- }else {
- elec_smooth_angle = elec_angle;
- }
- #else
- elec_smooth_angle = elec_angle;
- #endif
- norm_angle_deg(elec_smooth_angle);
- g_hall.elec_angle = elec_smooth_angle;
- g_hall.position += g_hall.elec_angle_vel * FOC_CTRL_US / g_hall.mot_poles;
- if ((g_hall.elec_angle_vel > 0.000001f) && (delta_ticks >= HALL_MAX_TIME)) {
- g_hall.elec_angle_vel = 0;
- g_hall.samples.filled = 0;
- g_hall.samples.index = 0;
- g_hall.velocity_filted = 0;
- g_hall.dir = g_hall.prev_dir = g_hall.dir_set;
- hall_init_low_pos();
- }
- return hall_get_elec_angle();
- }
- float hall_get_vel_counts(void) {
- return g_hall.elec_angle_vel/PHASE_60_DEGREE * g_hall.dir;
- }
- float hall_get_velocity(void) {
- return g_hall.velocity_filted;
- }
- float hall_get_position(void) {
- return g_hall.position;
- }
- static __INLINE void hall_calc_mot_velocity(u32 delta_cnt) {
- if (g_hall.samples.filled == 0) {
- hall_put_sample(HALL_MAX_TIME/10);
- return;
- }
- if (delta_cnt < g_min_delta) {
- g_min_delta = delta_cnt;
- }
- hall_put_sample(delta_cnt);
- g_hall.elec_angle_vel = hall_elec_angle_vel();
- float velocity_raw = g_hall.elec_angle_vel/PHASE_360_DEGREE/g_hall.mot_poles * 60.0f * g_hall.dir;
- LowPass_Filter(g_hall.velocity_filted, velocity_raw, 0.5F);
- }
- float hall_offset_detect(float *off) {
- return 0.0f;
- }
- void HALL_IRQHandler(void) {
- g_delta_cnt++;
- u32 mask = cpu_enter_critical();
- u32 delta_cnt = hall_delta_us(g_hall.edge_ticks);
- if (delta_cnt < 200) { //1200rpm, 30 poles
- g_hall.noise_errors++;
- goto hall_end;
- }
- if (!hall_update_low_pos()) {
- goto hall_end;
- }
- hall_offset_update();
- g_hall.elec_angle_edge = g_hall.elec_angle;
- #if SMOOTH_COUNT>0
- g_hall.delta_angle_edge = get_angle_diff(g_hall.low_res_pos * PHASE_60_DEGREE, g_hall.elec_angle_edge);
- if (ABS(g_hall.delta_angle_edge) >= 2.0f) {
- g_hall.angle_smooth_step = g_hall.delta_angle_edge/SMOOTH_COUNT;
- g_hall.angle_smooth_cnt = 1;
- }else {
- g_hall.angle_smooth_step = 0;
- g_hall.angle_smooth_cnt = SMOOTH_COUNT + 1;
- }
- #endif
- hall_calc_mot_velocity(delta_cnt);
- hall_end:
- cpu_exit_critical(mask);
- return;
- }
|