ADC_V_L1 // 相电压 第一分支
->mcpwm_detect_voltages[detect_step] = ADC_V_L1 - vzero // 相电压和零点(电源电压一半)的差值
-> m_ph1_samples[m_sample_now] = (int16_t)mcpwm_detect_voltages[0] //m_sample_now电压采样点数最多2000
->buffer[index++] = m_ph1_samples[i] >> 8 //右移
->commands_send_samples(buffer, index); ->commands_send_packet(buffer, index); //发送数据包
ADC_V_L1 //相电压 第二分支
->mcpwm_vzero = (ADC_V_L1 + ADC_V_L2 + ADC_V_L3) / 3; // 三相电压平均值·
->mcpwm_vzero = ADC_V_ZERO; //电池电压的一半
--m_ph1_samples[m_sample_now] = ADC_V_L1 - mcpwm_vzero; //采集相电压 要发送
--m_vzero_samples[m_sample_now] = mcpwm_vzero;//要发送
--ph1 = ADC_V_L1 - mcpwm_vzero; //相电压差 运转起来mcpwm_vzero是电池电压的一半
-> amp = sqrtf((float)(ph1*ph1 + ph2*ph2 + ph3*ph3)) * sqrtf(2.0);//三相差压运算
-> filter_add_sample((float*)amp_fir_samples, amp,AMP_FIR_TAPS_BITS, (uint32_t*)&_fir_index);//滤波运算
--void filter_add_sample(float *buffer, float sample, int bits, uint32_t *offset) {
uint32_t cnt_mask = 0xFFFFFFFF >> (32 - bits);
buffer[*offset] = sample;
*offset += 1;
*offset &= cnt_mask;
} //float *buffer 存采样值缓存区 float sample采样值 bits 缓存区长度 uint32_t *offset 缓存区索引值
--amp = filter_run_fir_iteration((float*)amp_fir_samples, (float*)amp_fir_coeffs, AMP_FIR_TAPS_BITS, amp_fir_index);//重要的是amp_fir_coeffs滤波系数 amp_fir_samples采样值 AMP_FIR_TAPS_BITS采样数 amp_fir_index索引值
--filter_create_fir_lowpass((float*)amp_fir_coeffs, AMP_FIR_FCUT, AMP_FIR_TAPS_BITS, 1);//创建fir低通滤波器 AMP_FIR_FCUT是0.02 AMP_FIR_TAPS_BITS是7
--void filter_create_fir_lowpass(float *filter_vector, float f_break, int bits, int use_hamming) {
int taps = 1 << bits;
float imag[taps];
for(int i = 0;i < taps;i++) {
if (i < (int)((float)taps * f_break)) {
filter_vector[i] = 1;
} else {
filter_vector[i] = 0;
}
imag[i] = 0;
}
// Make filter symmetric
for (int i = 0;i < taps / 2;i++) {
filter_vector[taps - i - 1] = filter_vector[i];
}
filter_fft(1, bits, filter_vector, imag);
filter_fftshift(filter_vector, taps);
if (use_hamming) { //使用汉明窗
filter_hamming(filter_vector, taps);
}
}
--受限于理论知识欠缺, filter_fft filter_fftshift已经看不懂了,想了解的看
--float filter_run_fir_iteration(float *vector, float *filter, int bits, uint32_t offset) {
float result = 0;
int size = 1 << bits;
uint32_t cnt_mask = 0xFFFFFFFF >> (32 - bits);
for (int i = 0;i < size;i++) {
result += filter[i] * vector[offset];
offset++;
offset &= cnt_mask;
}
return result;
}
->v_diff = ph1; //分支二一
--hall_detect_table[read_hall()][comm_step]++;//霍尔传感器的程序
--for (int j = 1;j < 7;j++) {
if (hall_detect_table[i][j] > samples) {
samples = hall_detect_table[i][j];
if (samples > 15) {
res = j;
}
}
table[i] = res;
->ph1_raw = ADC_V_L1; ph_now_raw = ph1_raw; //分支二二
->f (pwm_cycles_sum > (last_pwm_cycles_sum / 2.0) ||
!has_commutated || (ph_now_raw > min && ph_now_raw < (ADC_Value[ADC_IND_VIN_SENS] - min))) {
cycle_integrator += (float)v_diff / switching_frequency_now; //pwm开关频率,最大是40k,目前用10k
//大于电源电压1/4且小于电源电压3/4才下一步 注意:这是上桥pwm情况下,如下图是本杰明的波形图
//pwm_cycles_sum 每次AD采集完会加4 换相时清零,起到类似记录换相时间的作用
//pwm_cycles 每次AD采集完会加1 当大于2时才采样,滤掉前两个ad时间
--if (has_commutated) {
limit = rpm_dep.cycle_int_limit_running * (0.0005 * VDIV_CORR);//VDIV_CORR 是电阻校正系数 大概是1
} else {
limit = rpm_dep.cycle_int_limit * (0.0005 * VDIV_CORR);
}
--if (cycle_integrator >= (rpm_dep.cycle_int_limit_max * (0.0005 * VDIV_CORR)) ||
cycle_integrator >= limit) {
commutate(1);
cycle_integrator = 0.0;
} //
-> cycle_integrator += (float)v_diff / switching_frequency_now; //密勒计数器,控制进行换相的关键变量
每次换相完cycle_integrator = 0
--// Update the cycle integrator limit 除了傅里叶变换(可能foc用)这应该是第二核心,即对六步换相的积分进行限制
rpm_dep.cycle_int_limit = conf->sl_cycle_int_limit;
//sl_cycle_int_limit可以被上位机设置,默认80 应该是滤波用,即积分必须大于这个数才能开始起作用
rpm_dep.cycle_int_limit_running = rpm_dep.cycle_int_limit + (float)ADC_Value[ADC_IND_VIN_SENS] *
conf->sl_bemf_coupling_k / (rpm_abs > conf->sl_min_erpm ? rpm_abs : conf->sl_min_erpm);
//conf->sl_bemf_coupling_k默认600 是输入电压到反电动势的耦合常数 再除以当前转速 ;即当前转速越高rpm_dep.cycle_int_limit_running 越小,cycle_integrator就越容易达到阈值,换相越快
rpm_dep.cycle_int_limit_running = utils_map(rpm_abs, 0,
conf->sl_cycle_int_rpm_br, rpm_dep.cycle_int_limit_running,
rpm_dep.cycle_int_limit_running * conf->sl_phase_advance_at_br);
//utils_map函数:float utils_map(float x, float in_min, float in_max, float out_min, float out_max) {
return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
} //这个公式大概就是把min 映射到另一条曲线(函数)max上 类似放大器或缩小器
//rpm_abs是当前转速 rpm_now = (comms * MCPWM_RPM_TIMER_FREQ * 60.0) / (time_at_comm * 6.0);//comms是每换一相就加一 MCPWM_RPM_TIMER_FREQ是转速器计数频率1M time_at_comm是累加的时间
rpm_dep.cycle_int_limit_max = rpm_dep.cycle_int_limit + (float)ADC_Value[ADC_IND_VIN_SENS] *
conf->sl_bemf_coupling_k / conf->sl_min_erpm_cycle_int_limit; //conf->sl_min_erpm_cycle_int_limit //最小转速
通过上位机可以看出来,六步换相本杰明没有用30度进角延时(当然也可以选择),用的是积分,积的是相电压和电源电压一半的差值,至于哪一相由当前步决定
如果是下桥pwm,波形如下,进入积分判断条件就要改 大于电源电压1/4且小于电源电压3/4 为