mirror of https://github.com/rusefi/bldc.git
Add support for calibrating current sensors
Hw_conf can define CURRENT_CAL1,2,3 to set individual calibrations for each current sensor. By default no calibration is used. (x1.0) For example this is used on the A50S by looping a calibrated current using a power supply through each phase. Then the correction is saved in external eeprom to persist across firmware updates. Tested on FOC, DC and BLDC modes.
This commit is contained in:
parent
c5b8bb7feb
commit
af65f521de
|
@ -120,6 +120,9 @@
|
|||
|
||||
// Current ADC to amperes factor
|
||||
#define FAC_CURRENT ((V_REG / 4095.0) / (CURRENT_SHUNT_RES * CURRENT_AMP_GAIN))
|
||||
#define FAC_CURRENT1 ((V_REG / 4095.0) / (CURRENT_SHUNT_RES * CURRENT_AMP_GAIN )) * CURRENT_CAL1
|
||||
#define FAC_CURRENT2 ((V_REG / 4095.0) / (CURRENT_SHUNT_RES * CURRENT_AMP_GAIN )) * CURRENT_CAL2
|
||||
#define FAC_CURRENT3 ((V_REG / 4095.0) / (CURRENT_SHUNT_RES * CURRENT_AMP_GAIN )) * CURRENT_CAL3
|
||||
|
||||
#define VOLTAGE_TO_ADC_FACTOR ( VIN_R2 / (VIN_R2 + VIN_R1) ) * ( 4096.0 / V_REG )
|
||||
|
||||
|
|
10
hwconf/hw.h
10
hwconf/hw.h
|
@ -383,6 +383,16 @@
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef CURRENT_CAL1
|
||||
#define CURRENT_CAL1 1.0
|
||||
#endif
|
||||
#ifndef CURRENT_CAL2
|
||||
#define CURRENT_CAL2 1.0
|
||||
#endif
|
||||
#ifndef CURRENT_CAL3
|
||||
#define CURRENT_CAL3 1.0
|
||||
#endif
|
||||
|
||||
#ifndef HW_MAX_CURRENT_OFFSET
|
||||
#define HW_MAX_CURRENT_OFFSET 620
|
||||
#endif
|
||||
|
|
|
@ -2442,17 +2442,18 @@ static lbm_value ext_raw_adc_current(lbm_value *args, lbm_uint argn) {
|
|||
mcpwm_foc_get_current_offsets(&ofs1, &ofs2, &ofs3, motor == 2);
|
||||
float ph1, ph2, ph3;
|
||||
mcpwm_foc_get_currents_adc(&ph1, &ph2, &ph3, motor == 2);
|
||||
float scale = FAC_CURRENT;
|
||||
float scale1, scale2, scale3;
|
||||
scale1 = FAC_CURRENT1; scale2 = FAC_CURRENT2; scale3 = FAC_CURRENT3;
|
||||
|
||||
if (argn == 3 && lbm_dec_as_i32(args[2]) != 0) {
|
||||
scale = 1.0;
|
||||
scale1 = 1.0; scale2 = 1.0; scale3 = 1.0;
|
||||
ofs1 = 0.0; ofs2 = 0.0; ofs3 = 0.0;
|
||||
}
|
||||
|
||||
switch(phase) {
|
||||
case 1: return lbm_enc_float((ph1 - ofs1) * scale);
|
||||
case 2: return lbm_enc_float((ph2 - ofs2) * scale);
|
||||
case 3: return lbm_enc_float((ph3 - ofs3) * scale);
|
||||
case 1: return lbm_enc_float((ph1 - ofs1) * scale1);
|
||||
case 2: return lbm_enc_float((ph2 - ofs2) * scale2);
|
||||
case 3: return lbm_enc_float((ph3 - ofs3) * scale3);
|
||||
default: return ENC_SYM_EERROR;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2881,9 +2881,9 @@ static THD_FUNCTION(sample_send_thread, arg) {
|
|||
buffer_append_float32_auto(buffer, (float)m_vzero_samples[ind_samp], &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr_fir_samples[ind_samp], &index);
|
||||
} else {
|
||||
buffer_append_float32_auto(buffer, (float)m_curr0_samples[ind_samp] * FAC_CURRENT, &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr1_samples[ind_samp] * FAC_CURRENT, &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr2_samples[ind_samp] * FAC_CURRENT, &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr0_samples[ind_samp] * FAC_CURRENT1, &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr1_samples[ind_samp] * FAC_CURRENT2, &index);
|
||||
buffer_append_float32_auto(buffer, (float)m_curr2_samples[ind_samp] * FAC_CURRENT3, &index);
|
||||
buffer_append_float32_auto(buffer, ((float)m_ph1_samples[ind_samp] / 4096.0 * V_REG) * ((VIN_R1 + VIN_R2) / VIN_R2) * ADC_VOLTS_PH_FACTOR, &index);
|
||||
buffer_append_float32_auto(buffer, ((float)m_ph2_samples[ind_samp] / 4096.0 * V_REG) * ((VIN_R1 + VIN_R2) / VIN_R2) * ADC_VOLTS_PH_FACTOR, &index);
|
||||
buffer_append_float32_auto(buffer, ((float)m_ph3_samples[ind_samp] / 4096.0 * V_REG) * ((VIN_R1 + VIN_R2) / VIN_R2) * ADC_VOLTS_PH_FACTOR, &index);
|
||||
|
|
|
@ -1562,12 +1562,12 @@ void mcpwm_adc_inj_int_handler(void) {
|
|||
if (conf->motor_type == MOTOR_TYPE_DC) {
|
||||
if (direction) {
|
||||
#ifdef HW_HAS_3_SHUNTS
|
||||
curr_tot_sample = -(GET_CURRENT3() - curr2_offset);
|
||||
curr_tot_sample = -(GET_CURRENT3() - curr2_offset) * FAC_CURRENT3;;
|
||||
#else
|
||||
curr_tot_sample = -(GET_CURRENT2() - curr1_offset);
|
||||
curr_tot_sample = -(GET_CURRENT2() - curr1_offset) * FAC_CURRENT2;;
|
||||
#endif
|
||||
} else {
|
||||
curr_tot_sample = -(GET_CURRENT1() - curr0_offset);
|
||||
curr_tot_sample = -(GET_CURRENT1() - curr0_offset) * FAC_CURRENT1;;
|
||||
}
|
||||
} else {
|
||||
static int detect_now = 0;
|
||||
|
@ -1593,52 +1593,52 @@ void mcpwm_adc_inj_int_handler(void) {
|
|||
*/
|
||||
|
||||
if (state == MC_STATE_FULL_BRAKE) {
|
||||
float c0 = (float)ADC_curr_norm_value[0];
|
||||
float c1 = (float)ADC_curr_norm_value[1];
|
||||
float c2 = (float)ADC_curr_norm_value[2];
|
||||
float c0 = (float)ADC_curr_norm_value[0] * FAC_CURRENT1;
|
||||
float c1 = (float)ADC_curr_norm_value[1] * FAC_CURRENT2;
|
||||
float c2 = (float)ADC_curr_norm_value[2] * FAC_CURRENT3;
|
||||
curr_tot_sample = sqrtf((c0*c0 + c1*c1 + c2*c2) / 1.5);
|
||||
} else {
|
||||
#ifdef HW_HAS_3_SHUNTS
|
||||
if (direction) {
|
||||
switch (comm_step) {
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[2]; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[2]; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[2] * FAC_CURRENT3; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[2] * FAC_CURRENT3; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
switch (comm_step) {
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[2]; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[2]; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[2] * FAC_CURRENT3; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[2] * FAC_CURRENT3; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
#else
|
||||
if (direction) {
|
||||
switch (comm_step) {
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 3: curr_tot_sample = (float)ADC_curr_norm_value[0]; break;
|
||||
case 4: curr_tot_sample = (float)ADC_curr_norm_value[1]; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 1: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 2: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 3: curr_tot_sample = (float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 4: curr_tot_sample = (float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
default: break;
|
||||
}
|
||||
} else {
|
||||
switch (comm_step) {
|
||||
case 1: curr_tot_sample = (float)ADC_curr_norm_value[1]; break;
|
||||
case 2: curr_tot_sample = (float)ADC_curr_norm_value[0]; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[1]; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0]; break;
|
||||
case 1: curr_tot_sample = (float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 2: curr_tot_sample = (float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 3: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 4: curr_tot_sample = -(float)ADC_curr_norm_value[1] * FAC_CURRENT2; break;
|
||||
case 5: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
case 6: curr_tot_sample = -(float)ADC_curr_norm_value[0] * FAC_CURRENT1; break;
|
||||
default: break;
|
||||
}
|
||||
}
|
||||
|
@ -1722,7 +1722,7 @@ void mcpwm_adc_inj_int_handler(void) {
|
|||
}
|
||||
}
|
||||
|
||||
last_current_sample = curr_tot_sample * FAC_CURRENT;
|
||||
last_current_sample = curr_tot_sample;
|
||||
|
||||
// Filter out outliers
|
||||
if (fabsf(last_current_sample) > (conf->l_abs_current_max * 1.2)) {
|
||||
|
|
|
@ -2830,8 +2830,8 @@ void mcpwm_foc_adc_int_handler(void *p, uint32_t flags) {
|
|||
float curr1;
|
||||
|
||||
if (is_second_motor) {
|
||||
curr0 = (GET_CURRENT1() - conf_other->foc_offsets_current[0]) * FAC_CURRENT;
|
||||
curr1 = (GET_CURRENT2() - conf_other->foc_offsets_current[1]) * FAC_CURRENT;
|
||||
curr0 = (GET_CURRENT1() - conf_other->foc_offsets_current[0]) * FAC_CURRENT1;
|
||||
curr1 = (GET_CURRENT2() - conf_other->foc_offsets_current[1]) * FAC_CURRENT2;
|
||||
TIMER_UPDATE_DUTY_M1(motor_other->m_duty1_next, motor_other->m_duty2_next, motor_other->m_duty3_next);
|
||||
} else {
|
||||
curr0 = (GET_CURRENT1_M2() - conf_other->foc_offsets_current[0]) * FAC_CURRENT;
|
||||
|
@ -2839,8 +2839,8 @@ void mcpwm_foc_adc_int_handler(void *p, uint32_t flags) {
|
|||
TIMER_UPDATE_DUTY_M2(motor_other->m_duty1_next, motor_other->m_duty2_next, motor_other->m_duty3_next);
|
||||
}
|
||||
#else
|
||||
float curr0 = (GET_CURRENT1() - conf_other->foc_offsets_current[0]) * FAC_CURRENT;
|
||||
float curr1 = (GET_CURRENT2() - conf_other->foc_offsets_current[1]) * FAC_CURRENT;
|
||||
float curr0 = (GET_CURRENT1() - conf_other->foc_offsets_current[0]) * FAC_CURRENT1;
|
||||
float curr1 = (GET_CURRENT2() - conf_other->foc_offsets_current[1]) * FAC_CURRENT2;
|
||||
|
||||
TIMER_UPDATE_DUTY_M1(motor_other->m_duty1_next, motor_other->m_duty2_next, motor_other->m_duty3_next);
|
||||
#ifdef HW_HAS_DUAL_PARALLEL
|
||||
|
@ -3042,9 +3042,9 @@ void mcpwm_foc_adc_int_handler(void *p, uint32_t flags) {
|
|||
}
|
||||
#endif
|
||||
|
||||
float ia = ADC_curr_norm_value[0 + norm_curr_ofs] * FAC_CURRENT;
|
||||
float ib = ADC_curr_norm_value[1 + norm_curr_ofs] * FAC_CURRENT;
|
||||
float ic = ADC_curr_norm_value[2 + norm_curr_ofs] * FAC_CURRENT;
|
||||
float ia = ADC_curr_norm_value[0 + norm_curr_ofs] * FAC_CURRENT1;
|
||||
float ib = ADC_curr_norm_value[1 + norm_curr_ofs] * FAC_CURRENT2;
|
||||
float ic = ADC_curr_norm_value[2 + norm_curr_ofs] * FAC_CURRENT3;
|
||||
|
||||
// This has to be done for the skip function to have any chance at working with the
|
||||
// observer and control loops.
|
||||
|
|
Loading…
Reference in New Issue