|
|
@@ -6,25 +6,12 @@
|
|
|
#include "libs/logger.h"
|
|
|
#include "app/nv_storage.h"
|
|
|
#include "math/fast_math.h"
|
|
|
-
|
|
|
#include "encoder_off.h"
|
|
|
|
|
|
-#define ANGLE_OFFSET (-50.0f)//133.0f
|
|
|
/* 磁编码器使用一对极的磁铁,所以编码器获取的角度和机械角度相同需要转为电角度*/
|
|
|
-#define DIR_ADJUGE_MAX_CNT 10
|
|
|
-#define PLL_BANDWIDTH 200
|
|
|
-encoder_t g_encoder;
|
|
|
|
|
|
-u8 encoder_off_count[1024] = {0};
|
|
|
-s16 encoder_off_map[1024] = {0};
|
|
|
-s16 encoder_off_r_map[1024] = {0};
|
|
|
-u8 encoder_off_r_count[1024] = {0};
|
|
|
+encoder_t g_encoder;
|
|
|
|
|
|
-bool encoder_off_finished = false;
|
|
|
-s16 encoder_off_comp = 940.0f;
|
|
|
-float encoder_off_mul = 1.0f;
|
|
|
-int encoder_off_cn_add = 542;
|
|
|
-float encoder_off_angle_add = 0.0f;
|
|
|
static __INLINE void encoder_pll_update_gain(void) {
|
|
|
if (g_encoder.pll_bandwidth_shadow != g_encoder.pll_bandwidth) {
|
|
|
g_encoder.pll_bandwidth = g_encoder.pll_bandwidth_shadow;
|
|
|
@@ -44,18 +31,12 @@ static void _init_pll(void) {
|
|
|
|
|
|
|
|
|
void encoder_init(void) {
|
|
|
- for (int i = i; i < 1024; i++) {
|
|
|
- encoder_off_count[i] = 0;
|
|
|
- encoder_off_map[i] = 0;
|
|
|
- encoder_off_r_map[i] = 0;
|
|
|
- encoder_off_r_count[i] = 0;
|
|
|
- }
|
|
|
encoder_init_clear(POSITIVE);
|
|
|
enc_intf_init(ENC_MAX_RES);
|
|
|
}
|
|
|
|
|
|
void encoder_set_direction(s8 direction) {
|
|
|
- encoder_init_clear(direction);
|
|
|
+ g_encoder.direction = direction;
|
|
|
}
|
|
|
|
|
|
void encoder_set_bandwidth(float bandwidth) {
|
|
|
@@ -65,7 +46,7 @@ void encoder_set_bandwidth(float bandwidth) {
|
|
|
void encoder_init_clear(s8 diretcion) {
|
|
|
_init_pll();
|
|
|
g_encoder.cpr = ENC_MAX_RES;
|
|
|
- g_encoder.enc_offset = nv_get_motor_params()->encoder_offset;
|
|
|
+ g_encoder.enc_offset = nv_get_motor_params()->offset;
|
|
|
g_encoder.motor_poles = nv_get_motor_params()->poles;
|
|
|
g_encoder.b_index_found = false;
|
|
|
g_encoder.direction = diretcion;
|
|
|
@@ -98,7 +79,7 @@ static __INLINE float _pll_over_comp(void) {
|
|
|
return (float)g_encoder.cpr;
|
|
|
}
|
|
|
|
|
|
-static __INLINE void encoder_run_pll(float cnt) {
|
|
|
+static __INLINE bool encoder_run_pll(float cnt) {
|
|
|
float pll_comp = 0.0f;
|
|
|
if (g_encoder.b_timer_ov) {
|
|
|
pll_comp = _pll_over_comp();
|
|
|
@@ -107,6 +88,12 @@ static __INLINE void encoder_run_pll(float cnt) {
|
|
|
encoder_pll_update_gain();
|
|
|
g_encoder.est_vel_counts = PLL_run(&g_encoder.est_pll, cnt, pll_comp);
|
|
|
g_encoder.est_angle_counts = g_encoder.est_pll.observer;
|
|
|
+ bool snap_to_zero_vel = false;
|
|
|
+ if (ABS(g_encoder.est_pll.out) < 0.5f * g_encoder.est_pll.DT * g_encoder.est_pll.ki) {
|
|
|
+ g_encoder.est_vel_counts = g_encoder.est_pll.out = 0.0f; // align delta-sigma on zero to prevent jitter
|
|
|
+ snap_to_zero_vel = true;
|
|
|
+ }
|
|
|
+ return snap_to_zero_vel;
|
|
|
}
|
|
|
|
|
|
static __INLINE u32 _abi_count(void) {
|
|
|
@@ -117,6 +104,19 @@ static __INLINE u32 _abi_count(void) {
|
|
|
#endif
|
|
|
}
|
|
|
|
|
|
+/* 偏心补偿 */
|
|
|
+static __INLINE float _eccentricity_compensation(int cnt) {
|
|
|
+#ifdef FIR_PHASE_SHIFT
|
|
|
+ int cnt_off = (cnt + FIR_PHASE_SHIFT) % g_encoder.cpr;
|
|
|
+ if (g_encoder.encoder_off_map != NULL) { //do offset calibrate, can not do encentricity compensation
|
|
|
+ return 0.0f;
|
|
|
+ }
|
|
|
+ return -((_encoder_off_map[cnt_off])/100.0f);
|
|
|
+#else
|
|
|
+ return 0.0f;
|
|
|
+#endif
|
|
|
+}
|
|
|
+
|
|
|
float encoder_get_theta(void) {
|
|
|
if (!g_encoder.b_index_found) {
|
|
|
return g_encoder.pwm_angle;
|
|
|
@@ -128,12 +128,9 @@ float encoder_get_theta(void) {
|
|
|
g_encoder.b_timer_ov = true;
|
|
|
ENC_ClearUpFlags();
|
|
|
}
|
|
|
- encoder_run_pll((float)(cnt));
|
|
|
- bool snap_to_zero_vel = false;
|
|
|
- if (ABS(g_encoder.est_pll.out) < 0.5f * g_encoder.est_pll.DT * g_encoder.est_pll.ki) {
|
|
|
- g_encoder.est_vel_counts = g_encoder.est_pll.out = 0.0f; // align delta-sigma on zero to prevent jitter
|
|
|
- snap_to_zero_vel = true;
|
|
|
- }
|
|
|
+
|
|
|
+ bool snap_to_zero_vel = encoder_run_pll((float)(cnt));
|
|
|
+
|
|
|
if (snap_to_zero_vel) {
|
|
|
g_encoder.interpolation = 0.5f;
|
|
|
}else {
|
|
|
@@ -149,13 +146,9 @@ float encoder_get_theta(void) {
|
|
|
}
|
|
|
}
|
|
|
g_encoder.abi_angle = ENC_Pluse_Nr_2_angle((float)cnt + g_encoder.interpolation) * g_encoder.motor_poles + g_encoder.enc_offset;
|
|
|
- if (encoder_off_finished) {
|
|
|
- int cnt_off = (cnt + FIR_PHASE_SHIFT) % g_encoder.cpr;
|
|
|
- g_encoder.abi_angle -= ((_encoder_off_map[cnt_off])/100.0f);
|
|
|
- }
|
|
|
+ g_encoder.abi_angle += _eccentricity_compensation(cnt);
|
|
|
rand_angle(g_encoder.abi_angle);
|
|
|
|
|
|
-
|
|
|
g_encoder.last_cnt = cnt;
|
|
|
g_encoder.last_us = timer_count32_get();
|
|
|
return g_encoder.abi_angle;
|
|
|
@@ -166,8 +159,30 @@ float encoder_get_speed(void) {
|
|
|
}
|
|
|
|
|
|
|
|
|
-extern int jtag_plot;
|
|
|
-void encoder_detect_offset(float angle, bool r){
|
|
|
+void _encoder_caliberate_init(void) {
|
|
|
+ if (g_encoder.encoder_off_map != NULL) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ g_encoder.encoder_off_map = (s16 *)os_alloc(g_encoder.cpr * sizeof(s16));
|
|
|
+ g_encoder.encoder_off_count = (u8 *)os_alloc(g_encoder.cpr);
|
|
|
+
|
|
|
+ for (int i = 0; i < g_encoder.cpr; i++) {
|
|
|
+ g_encoder.encoder_off_map[i] = 0;
|
|
|
+ g_encoder.encoder_off_count[i] = 0;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+void _encoder_caliberate_deinit(void) {
|
|
|
+ if (g_encoder.encoder_off_map != NULL) {
|
|
|
+ os_free(g_encoder.encoder_off_map);
|
|
|
+ os_free(g_encoder.encoder_off_count);
|
|
|
+ }
|
|
|
+ g_encoder.encoder_off_map = NULL;
|
|
|
+ g_encoder.encoder_off_count = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+void encoder_detect_offset(float angle){
|
|
|
+ _encoder_caliberate_init();
|
|
|
float delta = (g_encoder.abi_angle - angle);
|
|
|
if (delta > 200) {
|
|
|
delta = delta - 360;
|
|
|
@@ -175,57 +190,53 @@ void encoder_detect_offset(float angle, bool r){
|
|
|
if (delta < -200) {
|
|
|
delta = delta + 360;
|
|
|
}
|
|
|
- int last_cn = (g_encoder.last_cnt + 0) % 1024;
|
|
|
- if (!r) {
|
|
|
- encoder_off_map[last_cn] = (s16)(delta*100.0f);
|
|
|
- encoder_off_count[last_cn] ++;
|
|
|
+ if (g_encoder.direction == POSITIVE) {
|
|
|
+ if ((g_encoder.encoder_off_count[g_encoder.last_cnt] & 0xF) <= 2) {
|
|
|
+ g_encoder.encoder_off_map[g_encoder.last_cnt] += (s16)(delta*100.0f);
|
|
|
+ g_encoder.encoder_off_count[g_encoder.last_cnt] += 0x01;
|
|
|
+ }
|
|
|
}else {
|
|
|
- encoder_off_r_map[last_cn] = (s16)(delta*100.0f);
|
|
|
- encoder_off_r_count[last_cn] ++;
|
|
|
- }
|
|
|
- if (jtag_plot==1) {
|
|
|
- plot_1data16((s16)(delta*100.0f));
|
|
|
+ if (((g_encoder.encoder_off_count[g_encoder.last_cnt] >> 4) & 0xF) <= 2) {
|
|
|
+ g_encoder.encoder_off_map[g_encoder.last_cnt] += (s16)(delta*100.0f);
|
|
|
+ g_encoder.encoder_off_count[g_encoder.last_cnt] += 0x10;
|
|
|
+ }
|
|
|
}
|
|
|
- encoder_off_finished = false;
|
|
|
}
|
|
|
-
|
|
|
-
|
|
|
-float encoder_detect_finish(bool r) {
|
|
|
+static void _detect_off_finished(void);
|
|
|
+bool encoder_detect_finish(void) {
|
|
|
+ u8 off_count = 0;
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
|
- if (!r) {
|
|
|
- if (encoder_off_count[i] <= 2) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ if (g_encoder.direction == POSITIVE) {
|
|
|
+ off_count = g_encoder.encoder_off_count[i] & 0xF;
|
|
|
}else {
|
|
|
- if (encoder_off_r_count[i] <= 2) {
|
|
|
- return false;
|
|
|
- }
|
|
|
+ off_count = (g_encoder.encoder_off_count[i] >> 4)& 0xF;
|
|
|
+ }
|
|
|
+ if (off_count <= 2) {
|
|
|
+ return false;
|
|
|
}
|
|
|
}
|
|
|
- encoder_off_finished = true;
|
|
|
- return encoder_off_finished;
|
|
|
+ if (g_encoder.direction == NEGATIVE) {
|
|
|
+ _detect_off_finished();//output data to PC tools, and use Matlab do FIR filter
|
|
|
+ _encoder_caliberate_deinit();
|
|
|
+ }
|
|
|
+ return true;
|
|
|
}
|
|
|
|
|
|
|
|
|
-void encoder_detect_off_finished(void) {
|
|
|
- for (int i = 0; i < 100; i++) {
|
|
|
- plot_3data16(0,0,1000);
|
|
|
- delay_ms(2);
|
|
|
- }
|
|
|
+static void _detect_off_finished(void) {
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
|
- float angle_off = (encoder_off_map[i] + encoder_off_r_map[i]) / 2;
|
|
|
- plot_3data16(0, 0 , angle_off);
|
|
|
+ float angle_off = g_encoder.encoder_off_map[i] / (((g_encoder.encoder_off_count[i] >> 4)&0xF) + (g_encoder.encoder_off_count[i]&0xF));
|
|
|
+ plot_1data16((s16)angle_off);
|
|
|
delay_ms(2);
|
|
|
}
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
|
- float angle_off = (encoder_off_map[i] + encoder_off_r_map[i]) / 2;
|
|
|
- plot_3data16(0, 0 , angle_off);
|
|
|
+ float angle_off = g_encoder.encoder_off_map[i] / (((g_encoder.encoder_off_count[i] >> 4)&0xF) + (g_encoder.encoder_off_count[i]&0xF));
|
|
|
+ plot_1data16((s16)angle_off);
|
|
|
delay_ms(2);
|
|
|
-
|
|
|
}
|
|
|
for (int i = 0; i < 1024; i++) {
|
|
|
- float angle_off = (encoder_off_map[i] + encoder_off_r_map[i]) / 2;
|
|
|
- plot_3data16(0, 0 , angle_off);
|
|
|
+ float angle_off = g_encoder.encoder_off_map[i] / (((g_encoder.encoder_off_count[i] >> 4)&0xF) + (g_encoder.encoder_off_count[i]&0xF));
|
|
|
+ plot_1data16((s16)angle_off);
|
|
|
delay_ms(2);
|
|
|
}
|
|
|
}
|
|
|
@@ -234,6 +245,22 @@ float encoder_get_vel_count(void) {
|
|
|
return g_encoder.est_vel_counts;
|
|
|
}
|
|
|
|
|
|
+float encoder_zero_phase_detect(void) {
|
|
|
+ float phase = g_encoder.pwm_angle;
|
|
|
+ float total_ph = phase;
|
|
|
+ int count = 0;
|
|
|
+ for(; count < 10; count++) {
|
|
|
+ delay_ms(ENC_PWM_Min_P * 1000 + 2); //wait time for pwm
|
|
|
+ if ABS(phase - g_encoder.pwm_angle > 2.0f) {
|
|
|
+ return INVALID_ANGLE;
|
|
|
+ }
|
|
|
+ phase = g_encoder.pwm_angle;
|
|
|
+ total_ph += phase;
|
|
|
+ }
|
|
|
+ return (total_ph/(float)count);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
static void encoder_sync_pwm_abs(void) {
|
|
|
ENC_COUNT = g_encoder.pwm_count;
|
|
|
g_encoder.last_cnt = g_encoder.pwm_count;
|