Skip to content

Commit

Permalink
add cali_encoder_en support
Browse files Browse the repository at this point in the history
  • Loading branch information
dukelec committed Jul 24, 2024
1 parent 7578911 commit c09828f
Show file tree
Hide file tree
Showing 2 changed files with 167 additions and 11 deletions.
45 changes: 34 additions & 11 deletions mdrv_fw/usr/app_motor.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,28 +312,32 @@ static inline void speed_loop_compute(void)
#define HIST_LEN 2
static uint16_t hist[HIST_LEN] = { 0 };
static int8_t hist_err = -2;
static uint16_t sen_encoder_bk = 0;

void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
{
gpio_set_value(&dbg_out1, 1);
gpio_set_value(&s_cs, 1);

uint16_t tbl_idx = 0;
uint16_t tbl_idx_next = 0;
float tbl_percent = 0;
float voltage_ratio = csa.bus_voltage / csa.nominal_voltage;

float sin_tmp_angle_elec, cos_tmp_angle_elec; // reduce the amount of calculations
int16_t out_pwm_u = 0, out_pwm_v = 0, out_pwm_w = 0;
bool dbg_str = csa.dbg_str_msk && (csa.loop_cnt % csa.dbg_str_skip) == 0;

uint16_t noc_encoder_bk = csa.noc_encoder;
csa.ori_encoder = encoder_read();
csa.noc_encoder = csa.ori_encoder - csa.bias_encoder;
int16_t delta_enc = csa.noc_encoder - noc_encoder_bk;

//gpio_set_value(&dbg_out2, 1);

// filter out disturbed error position values
#if 1
if (hist_err < 0 || abs(hist[1] - hist[0]) > 500) {
csa.sen_encoder = csa.noc_encoder;
csa.delta_encoder = delta_enc;
if (hist_err < 0)
hist_err++;
} else {
Expand All @@ -357,12 +361,10 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
uint32_t estimate = hist_raised[1] + hist_delta;
if (abs(sen_raised - estimate) > 500) {
csa.sen_encoder = estimate >= 0x10000 ? (estimate - 0x10000) : estimate;
csa.delta_encoder = hist_delta;
if(++hist_err > 2)
hist_err = -2;
} else {
csa.sen_encoder = csa.noc_encoder;
csa.delta_encoder = delta_enc;
hist_err = 0;
}
}
Expand All @@ -371,12 +373,26 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
hist[1] = csa.sen_encoder;
#else
csa.sen_encoder = csa.noc_encoder;
csa.delta_encoder = delta_enc;
#endif

if (csa.sen_encoder != csa.noc_encoder)
encoder_err++;

if (csa.cali_encoder_en) {
tbl_idx = csa.sen_encoder >> 4;
tbl_idx_next = (tbl_idx == 4095) ? 0 : (tbl_idx + 1);
tbl_percent = (float)(csa.sen_encoder & 0xf) / 0x10;
uint16_t idx_val = *(uint16_t *)(CALI_ENCODER_TBL + tbl_idx * 2);
uint32_t idx_next_val = *(uint16_t *)(CALI_ENCODER_TBL + tbl_idx_next * 2);
if (tbl_idx == 4095)
idx_next_val += 0x10000;
csa.sen_encoder = lroundf(idx_val + (idx_next_val - idx_val) * tbl_percent);
}

int16_t delta_enc = csa.sen_encoder - sen_encoder_bk;
csa.delta_encoder = delta_enc;
sen_encoder_bk = csa.sen_encoder;

// 9us lag steps = step/sec * 0.000009 sec
csa.sen_encoder += delta_enc * ((float)CURRENT_LOOP_FREQ * 0.000019f); // 0.000009f

Expand Down Expand Up @@ -455,8 +471,13 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
csa.sen_i_sd = i_alpha * cos_tmp_angle_elec + i_beta * sin_tmp_angle_elec;

if (csa.anticogging_en) {
int8_t *p = (int8_t *)ANTICOGGING_TBL + (csa.sen_encoder >> 4) * 2;
csa.sen_i_sq -= csa.anticogging_max_val[0] * (*p) / 100.0f;
tbl_idx = csa.sen_encoder >> 4;
tbl_idx_next = (tbl_idx == 4095) ? 0 : (tbl_idx + 1);
tbl_percent = (float)(csa.sen_encoder & 0xf) / 0x10;
int8_t idx_val = *(int8_t *)(ANTICOGGING_TBL + tbl_idx * 2);
int8_t idx_next_val = *(int8_t *)(CALI_ENCODER_TBL + tbl_idx_next * 2);
float val = idx_val + (idx_next_val - idx_val) * tbl_percent;
csa.sen_i_sq -= csa.anticogging_max_val[0] * val / 100.0f;
}
float err_i_sq = csa.sen_i_sq - csa.sen_i_sq_avg;
csa.sen_i_sq_avg += err_i_sq * 0.001f;
Expand Down Expand Up @@ -486,12 +507,14 @@ void HAL_ADCEx_InjectedConvCpltCallback(ADC_HandleTypeDef* hadc)
#else
pid_f_set_target(&csa.pid_i_sq, target_current);
#endif
csa.cal_v_sq = pid_f_compute_no_d(&csa.pid_i_sq, csa.sen_i_sq);
csa.cal_v_sd = pid_f_compute_no_d(&csa.pid_i_sd, csa.sen_i_sd); // target default 0
csa.cal_v_sq = pid_f_compute_no_d(&csa.pid_i_sq, csa.sen_i_sq) / voltage_ratio;
csa.cal_v_sd = pid_f_compute_no_d(&csa.pid_i_sd, csa.sen_i_sd) / voltage_ratio; // target default 0

if (csa.anticogging_en) {
int8_t *p = (int8_t *)ANTICOGGING_TBL + (csa.sen_encoder >> 4) * 2;
csa.cal_v_sq += csa.anticogging_max_val[1] * (*(p+1)) / 100.0f;
int8_t idx_val = *(int8_t *)(ANTICOGGING_TBL + tbl_idx * 2 + 1);
int8_t idx_next_val = *(int8_t *)(CALI_ENCODER_TBL + tbl_idx_next * 2 + 1);
float val = idx_val + (idx_next_val - idx_val) * tbl_percent;
csa.cal_v_sq += (csa.anticogging_max_val[1] * val / 100.0f) / voltage_ratio;
}
float err_v_sq = csa.cal_v_sq - csa.cal_v_sq_avg;
csa.cal_v_sq_avg += err_v_sq * 0.001f;
Expand Down
133 changes: 133 additions & 0 deletions tools/cali_encoder.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
#!/usr/bin/env python3

import sys
import time
import math
import struct
import umsgpack
import _thread
#import numpy as np
import matplotlib.pyplot as plt

if len(sys.argv) <= 1:
print(f'usage: {sys.argv[0]} mpk_dat_file')
exit(-1)

print('open data file: %s' % sys.argv[1])


with open(sys.argv[1], 'rb') as f:
in_file = f.read()
in_data = umsgpack.unpackb(in_file)

dat_x = in_data['plot'][0][0]
dat_encoder = in_data['plot'][0][6]

if dat_x[-1] - dat_x[0] + 1 != len(dat_x):
print('dat_x not continued, exit')
exit(-1)


def find_edge(i_start, is_first=True):
if i_start + 1 >= len(dat_encoder):
return None
val_max = dat_encoder[i_start]
val_cur = val_max
i_cur = i_start
while True:
i_cur += 1
if i_cur >= len(dat_encoder):
return None
val_cur = dat_encoder[i_cur]
if val_cur > val_max:
val_max = val_cur
elif val_max - val_cur > 60000:
if is_first:
return i_cur
else:
if i_cur - i_start >= 20:
return i_cur
else:
val_max = 0

i_s = find_edge(0)
i_e = find_edge(i_s, False)
i_len = i_e - i_s
print(f'start at: {i_s}, end at: {i_e}, len: {i_len}')

plt.figure()
plt.subplot(211)

t = list(range(0, len(dat_encoder)))
plt.setp(plt.plot(t, dat_encoder, 'g.-'), alpha=0.2) # green


def get_avg(idx, is_low=True):
vlist = [
dat_encoder[idx-1],
dat_encoder[idx],
dat_encoder[idx+1],
]
if is_low:
for i in range(len(vlist)):
if vlist[i] > 0x10000*(3/4):
vlist[i] -= 0x10000
else:
for i in range(len(vlist)):
if vlist[i] < 0x10000*(1/4):
vlist[i] += 0x10000
avg = (vlist[0] + vlist[1] + vlist[2]) / 3
return avg


dat_filtered = []
for i in range(i_len):
is_low = i < (i_len / 2)
dat_filtered.append(get_avg(i_s + i, is_low))


plt.setp(plt.plot(t[i_s:i_e], dat_filtered, 'b.-'), alpha=0.2)
plt.setp(plt.plot([i_s, i_e-1], [dat_encoder[i_s], dat_encoder[i_e-1]], 'r.-'), alpha=0.6) # red


plt.tight_layout()
plt.grid()

cali_t = []
cali_table = []
next_val = 0

def find_val(y_val):
for i in range(len(dat_filtered)):
if dat_filtered[i] >= y_val:
return round(i / len(dat_filtered) * 65535)
return 65535

for i in range(4096):
cali_t.append(i)
cali_table.append(find_val(i * 16))

print(f'cali len: {len(cali_table)}')

flash_val = b''
for i in range(4096):
flash_val += struct.pack("<H", cali_table[i])

print(f'write cali_encoder data to file: cali_encoder_data.bin, data len: {len(flash_val)} ...')
with open('cali_encoder_data.bin', 'wb') as f:
f.write(flash_val)


plt.subplot(212)
plt.setp(plt.plot(cali_t, cali_table, 'b.-'), alpha=0.2)

plt.setp(plt.plot([0, 4095], [0, 65535], 'r.-'), alpha=0.6) # red

plt.tight_layout()
plt.grid()

plt.show()

# cdbus_gui/tools:
# ./cdg_iap.py --cfg ../configs/cdfoc-xxx.json --in-file cali_encoder_data.bin --addr=0x0801b800

0 comments on commit c09828f

Please sign in to comment.