本杰明电调源代码重要变量追踪图

10 篇文章 35 订阅

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*)&amp_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  为 

 

 

 

 

 

/* This file is part of AutoQuad ESC32. AutoQuad ESC32 is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. AutoQuad ESC32 is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with AutoQuad ESC32. If not, see . Copyright © 2011, 2012 Bill Nesbitt */ /* * pwm.c文件.此文件有2个功能,2个功能分别使用,不能同时使用 * 1、pwm in输入模式,pwm输入中断里,调用runNewInput函数 * 2、one wire通讯协议,pwm输入中断里,调用owEdgeDetect函数,来输入新的数据,调用owReset函数来复位1wire通讯 * */ #include "pwm.h" #include "timer.h" #include "run.h" #include "main.h" #include "ow.h" #include "stm32f10x_gpio.h" #include "stm32f10x_tim.h" #include "misc.h" static int16_t pwmMinPeriod; //timer1 ch1 pwm 输入最小周期 static int16_t pwmMaxPeriod; //timer1 ch1 pwm 输入最大周期 int16_t pwmMinValue; //timer1 ch2 pwm 输入最小周期 static int16_t pwmMaxValue; //timer1 ch2 pwm 输入最大周期 int16_t pwmLoValue; int16_t pwmHiValue; int16_t pwmMinStart; volatile uint32_t pwmValidMicros; //关闭输入捕获比较中断 1和2 void pwmIsrAllOff(void) { PWM_TIM->DIER &= (uint16_t)~(TIM_IT_CC1 | TIM_IT_CC2);//关闭中断 } //开启输入捕获比较中断 1和2 void pwmIsrAllOn(void) { PWM_TIM->CCR1; PWM_TIM->CCR2; PWM_TIM->DIER |= (TIM_IT_CC1 | TIM_IT_CC2);//允许捕获比较 1 2中断 } //开启捕获比较2中断 void pwmIsrRunOn(void) { uint16_t dier = PWM_TIM->DIER; dier &= (uint16_t)~(TIM_IT_CC1 | TIM_IT_CC2); dier |= TIM_IT_CC2;//允许捕获/比较2中断 PWM_TIM->CCR1; PWM_TIM->CCR2; PWM_TIM->DIER = dier; } //timer 1 void pwmInit(void) { GPIO_InitTypeDef GPIO_InitStructure; NVIC_InitTypeDef NVIC_InitStructure; TIM_ICInitTypeDef TIM_ICInitStructure; TIM_TimeBaseInitTypeDef TIM_TimeBaseStructure; pwmSetConstants(); // TIM1 channel 1 pin (PA.08) configuration GPIO_InitStructure.GPIO_Pin = PWM_PIN; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_Init(PWM_PORT, &GPIO;_InitStructure); // Enable the TIM1 global Interrupt NVIC_InitStructure.NVIC_IRQChannel = PWM_IRQ; NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2; NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1; NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; NVIC_Init(&NVIC;_InitStructure); TIM_TimeBaseStructInit(&TIM;_TimeBaseStructure); TIM_TimeBaseStructure.TIM_Prescaler = (PWM_CLK_DIVISOR-1); TIM_TimeBaseStructure.TIM_Period = 0xffff; TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up; TIM_TimeBaseInit(PWM_TIM, &TIM;_TimeBaseStructure); TIM_ICInitStructure.TIM_Channel = PWM_CHANNEL; TIM_ICInitStructure.TIM_ICPolarity = TIM_ICPolarity_Rising; TIM_ICInitStructure.TIM_ICSelection = TIM_ICSelection_DirectTI; TIM_ICInitStructure.TIM_ICPrescaler = TIM_ICPSC_DIV1; TIM_ICInitStructure.TIM_ICFilter = 0x0; TIM_PWMIConfig(PWM_TIM, &TIM;_ICInitStructure); // Select the TIM Input Trigger: TI1FP1 // 滤波后的定时器输入1(TI1FP1) TIM_SelectInputTrigger(PWM_TIM, TIM_TS_TI1FP1); // Select the slave Mode: Reset Mode TIM_SelectSlaveMode(PWM_TIM, TIM_SlaveMode_Reset);//复位模式 // Enable the Master/Slave Mode TIM_SelectMasterSlaveMode(PWM_TIM, TIM_MasterSlaveMode_Enable); // TIM enable counter TIM_Cmd(PWM_TIM, ENABLE); pwmIsrAllOn(); } //timer1 TIM1_CC_IRQHandler中断 void PWM_IRQ_HANDLER(void) { uint16_t pwmValue; uint16_t periodValue; uint8_t edge; edge = !(PWM_TIM->SR & TIM_IT_CC2); periodValue = PWM_TIM->CCR1; //IO 输入PA8 周期 pwmValue = PWM_TIM->CCR2; //IO 输入(但是没有看到配置了使用哪个IO做为输入了) 脉宽长度 // look for good RC PWM input if (inputMode == ESC_INPUT_PWM && //PWM输入模式 periodValue >= pwmMinPeriod && periodValue = pwmMinValue && pwmValue <= pwmMaxValue //脉宽长度 ) { if (edge == 0) { pwmValidMicros = timerMicros; runNewInput(pwmValue); //PWM正确.输入 } } } void pwmSetConstants(void) { float rpmScale = p[PWM_RPM_SCALE]; pwmMinPeriod = p[PWM_MIN_PERIOD] = (int)p[PWM_MIN_PERIOD];//PWM最小周期 timer1 ch1 pwmMaxPeriod = p[PWM_MAX_PERIOD] = (int)p[PWM_MAX_PERIOD];//PWM最大周期 timer1 ch1 pwmMinValue = p[PWM_MIN_VALUE] = (int)p[PWM_MIN_VALUE]; //PWM最小周期 timer1 ch2 pwmMaxValue = p[PWM_MAX_VALUE] = (int)p[PWM_MAX_VALUE]; //PWM最大周期 timer1 ch2 pwmLoValue = p[PWM_LO_VALUE] = (int)p[PWM_LO_VALUE]; pwmHiValue = p[PWM_HI_VALUE] = (int)p[PWM_HI_VALUE]; pwmMinStart = p[PWM_MIN_START] = (int)p[PWM_MIN_START]; if (rpmScale PWM_RPM_SCALE_MAX) rpmScale = PWM_RPM_SCALE_MAX; p[PWM_RPM_SCALE] = rpmScale; } ESC32开源电调 源码与原理,此源码采用RTT操作系统,CAN PWM操作方式 ,本人已用PWM方式成功驱动起来,CAN 暂且还没做测试。 此资料是 啊嘉 开源出来的,好资料不敢独享,稍加整理放到这与大家共享。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大饼酱人

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值