找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3814|回复: 1
收起左侧

dsPIC3EP256MC506的AN1160用择多函数实现饭电动势滤波的无传感器BLDC控制

[复制链接]
ID:284710 发表于 2018-12-29 15:24 | 显示全部楼层 |阅读模式
本应用笔记介绍一种采用 dsPIC ® 数字信号控制器
(Digital Signal Controller, DSC)或 PIC24 单片机来实现无刷直流 (Brushless Direct Current, BLDC)电机无传感器控制的算法。该算法利用对反电动势(Back-Electromotive Force,BEMF)进行数字滤波的择多函数来实现。通过对电机的每一相进行滤波来确定电机驱动电压换相的时刻。这一控制技术省却了分立的低通滤波硬件和片外比较器。需指出,这里论述的所有内容及应用软件,都是假定使用三相电机。该电机控制算法包括四个主要部分:
• 利用 DSC 或单片机的模数转换器(Analog-to-Digital Converter,ADC)来采样梯形波 BEMF 信号
• PWM 导通侧 ADC 采样,以降低噪声并解决低电感问题
• 将梯形波BEMF信号与V BUS /2进行比较,以检测过零点
• 用择多函数滤波器对比较结果信号进行滤波
• 以三种不同模式对电机驱动电压进行换相:
- 传统开环控制器
- 传统闭环控制器
- 比例 - 积分(Proportional-Integral,PI)闭环
控制器
0.png

单片机源程序如下:
  1. /************************************************************************************************************************
  2. * ?2011 Microchip Technology Inc.
  3. *
  4. * MICROCHIP SOFTWARE NOTICE AND DISCLAIMER:
  5. *
  6. * You may use this software, and any derivatives
  7. * created by any person or entity by or on your behalf, exclusively with Microchip抯 products.
  8. * Microchip and its licensors retain all ownership and intellectual property rights in the
  9. * accompanying software and in all derivatives hereto.  
  10. *
  11. * This software and any accompanying information is for suggestion only.
  12. * It does not modify Microchip抯 standard warranty for its products.  You agree that you are
  13. * solely responsible for testing the software and determining its suitability.
  14. * Microchip has no obligation to modify, test, certify, or support the software.
  15. *
  16. * THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED OR STATUTORY,
  17. * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY, AND FITNESS FOR
  18. * A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE, ITS INTERACTION WITH MICROCHIP扴 PRODUCTS, COMBINATION WITH
  19. * ANY OTHER PRODUCTS, OR USE IN ANY APPLICATION.
  20. *
  21. * IN NO EVENT, WILL MICROCHIP BE LIABLE, WHETHER IN CONTRACT, WARRANTY, TORT (INCLUDING NEGLIGENCE OR BREACH
  22. * OF STATUTORY DUTY), STRICT LIABILITY, INDEMNITY, CONTRIBUTION, OR OTHERWISE, FOR ANY INDIRECT, SPECIAL, PUNITIVE,
  23. * EXEMPLARY, INCIDENTAL OR CONSEQUENTIAL LOSS, DAMAGE, FOR COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE SOFTWARE,
  24. * HOWSOEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST
  25. * EXTENT ALLOWABLE BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY RELATED TO THIS SOFTWARE WILL NOT EXCEED
  26. * THE AMOUNT OF FEES, IF ANY, THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.

  27. * MICROCHIP PROVIDES THIS SOFTWARE CONDITIONALLY UPON YOUR ACCEPTANCE OF THESE TERMS.
  28. ***********************************************************************************************************************/
  29. #include "defs.h"                //defines, function headers, pi, etc

  30. #ifdef RTDM_DEMO
  31.         #include "debug.h"                //RTDM/DMCI functionality
  32. #endif

  33. int main(void)
  34. {
  35.         Init_Ports();        // Clock ( Fcy 70MHz ) , port configuration, etc

  36.         #ifdef RTDM_DEMO
  37.                 DBG_Init();                // RTDM ( Debugger ) Initialization
  38.         #endif

  39.         //defaults: CLKW rotation, motor stopped
  40.         Flags.RunMotor = 0;
  41.         Flags.Startup = 0;
  42.         Flags.CLKW = 1;
  43.         Flags.newCLKW = 1;
  44.         Flags.DMCI_Control_SW = 0;                //default potentiometer read

  45.         Timer2Average = TMR2_MAX;
  46.         trigger_count = 1;
  47.         Flags.nb_delay_on = 0;

  48.         #ifdef OPEN_LOOP_CONTROL
  49.         DesiredDuty = MIN_DUTY_CYCLE;
  50.         #else
  51.         DesiredRPM = STARTUP_RPM;
  52.         #endif

  53.         Flags.current_state = STATE_STOPPED;
  54.         while(1) {
  55.                
  56.                 if(S2) { //CLKW/CCLKW switch
  57.                         while(S2) //debounce
  58.                                 Delay_100uSec(DEBOUNCE_DELAY*10);
  59.                         Flags.newCLKW = !Flags.CLKW;
  60.                 }

  61.                 if(S3) { //start/stop switch
  62.                         while(S3) //debounce
  63.                                 Delay_100uSec(DEBOUNCE_DELAY*10);

  64.                         if(Flags.current_state == STATE_STOPPED)
  65.                                 Flags.current_state = STATE_STARTING;
  66.                         else
  67.                                    Flags.current_state = STATE_STOPPING;
  68.                 }


  69.                 switch(Flags.current_state) {
  70.                         case STATE_STOPPING:
  71.                                 Stop_Motor();
  72.                                 Flags.current_state = STATE_STOPPED;
  73.                         break;

  74.                         case STATE_STARTING:
  75.                                 //startup done on MCPWM ISR
  76.                         break;

  77.                         case STATE_FAULT:
  78.                                 Stop_Motor();
  79.                                 Flags.current_state = STATE_STOPPED;
  80.                         break;

  81.                         case STATE_STARTED:
  82.                                 if(Flags.newCLKW != Flags.CLKW) {
  83.                                         Stop_Motor();
  84.                                         Flags.CLKW = Flags.newCLKW;
  85.                                         Delay_100uSec(5000);        //delay 500 ms for motor to actually stop
  86.                                         Flags.current_state = STATE_STARTING;
  87.                                 }
  88.                         break;

  89.                         case STATE_STOPPED:
  90.                                 if(Flags.newCLKW != Flags.CLKW)
  91.                                         Flags.CLKW = Flags.newCLKW;
  92.                         break;
  93.                 }

  94.                 #ifdef RTDM_DEMO
  95.                         DBG_SyncComm();        //assure RTDM communication
  96.                 #endif
  97.         }

  98.         return 0;
  99. }

  100. /*******************************************************************
  101. Init_Motor()
  102.         Procedure used to initialize all params for the motor and
  103. for the AN1160 algorithm.
  104.         Also rotor alignment is done here.
  105. *******************************************************************/
  106. void Init_Motor()
  107. {
  108.         int i;        //auxiliary counter

  109.         if(Flags.nb_delay_on == 0) {
  110.                 T1CONbits.TON = 0;
  111.                 T2CONbits.TON = 0;
  112.                 TMR1 = 0;
  113.                 TMR2 = 0;

  114.                 Flags.TrainPI = 0;
  115.        
  116.             //setting direction CLKW or CCLKW
  117.                 if(Flags.CLKW == 1) {

  118.                         for(i=0;i<6;i++) {
  119.                                 PWM_STATE1[i] = PWM_STATE1_CLKW[i];
  120.                                 PWM_STATE2[i] = PWM_STATE2_CLKW[i];
  121.                                 PWM_STATE3[i] = PWM_STATE3_CLKW[i];
  122.                                 MotorPhaseAState[i] = MotorPhaseAState_CLKW[i];
  123.                                 MotorPhaseBState[i] = MotorPhaseBState_CLKW[i];
  124.                                 MotorPhaseCState[i] = MotorPhaseCState_CLKW[i];
  125.                                 ADC_CHANNEL[i] = ADC_CHANNEL_CLKW[i];

  126.                                 ADC_MASK[i] = ADC_MASK_CLKW[i];
  127.                                 ADC_XOR[i] = ADC_XOR_CLKW[5-i];
  128.                         }
  129.                         for(i=0;i<64;i++)
  130.                                 ADC_BEMF_FILTER[i] = ADC_BEMF_FILTER_CLKW[63-i];

  131.                 } else {
  132.                         for(i=0;i<6;i++) {
  133.                                 PWM_STATE1[i] = PWM_STATE1_CLKW[5-i];
  134.                                 PWM_STATE2[i] = PWM_STATE2_CLKW[5-i];
  135.                                 PWM_STATE3[i] = PWM_STATE3_CLKW[5-i];
  136.                                 MotorPhaseAState[i] = MotorPhaseAState_CLKW[5-i];
  137.                                 MotorPhaseBState[i] = MotorPhaseBState_CLKW[5-i];
  138.                                 MotorPhaseCState[i] = MotorPhaseCState_CLKW[5-i];
  139.                                 ADC_CHANNEL[i] = ADC_CHANNEL_CLKW[5-i];

  140.                                 ADC_MASK[i] = ADC_MASK_CLKW[5-i];
  141.                                 ADC_XOR[i] = ADC_XOR_CLKW[5-i];
  142.                         }
  143.                         for(i=0;i<64;i++)
  144.                                 ADC_BEMF_FILTER[i] = ADC_BEMF_FILTER_CLKW[63-i];
  145.                 }
  146.        
  147.             stallCount = 0;

  148.                 PIDStructure.qInMeas = STARTUP_RPM;
  149.                 PIDStructure.qInRef = STARTUP_RPM;
  150.             InitPI(&PIDStructure,SpeedControl_P,SpeedControl_I,PI_ANTI_WINDUP,MAX_DUTY_CYCLE,MIN_DUTY_CYCLE,0);

  151.                 TMR2 = TMR2_MAX; //initialize TMR2 and TMR2 average with the value corresponding to the minimum motor speed
  152.                 Timer2Value = TMR2;
  153.                 Timer2Average = TMR2;
  154.                 Timer1Value = 0;

  155.                 Flags.RunMotor = 1;                     // turn the motor ON
  156.                 Flags.Startup = 1;                                                // motor initialized, go to starting sequence
  157.    
  158.                 ADCCommState = 5;        //always start with sector 6 forced

  159.                 //set pwm overdrive to the according PWM channel
  160.                 IOCON1 = PWM_STATE1[ADCCommState];
  161.                 IOCON2 = PWM_STATE2[ADCCommState];
  162.                 IOCON3 = PWM_STATE3[ADCCommState];
  163.             CurrentDuty = STARTUP_DUTY;   //Init PWM duty cycle value to minimum duty allowed
  164.             PDC1 = CurrentDuty;
  165.                 PDC2 = CurrentDuty;
  166.                 PDC3 = CurrentDuty;

  167.                 nb_delay = ROTOR_ALIGN_T*PWM_100us_FACTOR*10;
  168.                 delay_counter = 0;
  169.                 Flags.nb_delay_on = 1;               

  170.                 t_current = STARTUP_START_T*10;        //in ms
  171.                 t_sector = 0;
  172.         }
  173. }

  174. /**********************************************************************
  175. Start_Motor()
  176.         Procedure for starting the motor according to the implemented
  177. startup ramp. After the ramp, PI loop training will begin.
  178. **********************************************************************/
  179. void Start_Motor()
  180. {
  181.         if(Flags.nb_delay_on == 0) {        //this is just to test if we're not in a non-blocking delay actually

  182.             if(++ADCCommState>5)        // Change The Six-Step Commutation Sector
  183.                      ADCCommState = 0;

  184.                 AD1CHS0 = ADC_CHANNEL[ADCCommState];        //Change ADC Channel AN Selection

  185.                 if(t_current < (unsigned long int)STARTUP_T_RAMP*10) {
  186.                          t_sector = STARTUP_SEC_C/t_current;        //calculates T for 1 sector, in 100s of uS.
  187.                         if(t_sector <= 0) t_sector = 1;
  188.                 } else
  189.                 if (t_current < ((unsigned int)STARTUP_T_RAMP*10 + STARTUP_T_SUST*10)) {

  190.                         Flags.TrainPI = 1;
  191.                         AD1CON1bits.SSRC = 3;
  192.                 }       
  193.                 else
  194.                         Flags.TrainPI = 0;

  195.                 //overdrive and output next motor sector
  196.                 IOCON1 = PWM_STATE1[ADCCommState];
  197.                 IOCON2 = PWM_STATE2[ADCCommState];
  198.                 IOCON3 = PWM_STATE3[ADCCommState];

  199.                 //here we want a non-blocking delay for the startup to execute
  200.                 nb_delay = t_sector * PWM_100us_FACTOR;
  201.                 delay_counter = 0;
  202.                 Flags.nb_delay_on = 1;               

  203.                 t_current += t_sector;       

  204.             adcBackEMFFilter = 0;    //clear the BEMF filter
  205.         }
  206. }


  207. ……………………

  208. …………限于本文篇幅 余下代码请从51黑下载附件…………
复制代码

所有资料51hei提供下载:
dsPICDEM MCLV-2开发板用户指南.pdf (1.18 MB, 下载次数: 47)

评分

参与人数 1黑币 +50 收起 理由
admin + 50 共享资料的黑币奖励!

查看全部评分

回复

使用道具 举报

ID:324611 发表于 2019-9-18 14:37 | 显示全部楼层
好东西,学习了。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表