找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 8162|回复: 12
打印 上一主题 下一主题
收起左侧

无刷无感电机过零检测单片机源程序

  [复制链接]
跳转到指定楼层
楼主
ID:299262 发表于 2018-3-30 09:18 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
附件中的源文件是无感三相电机零速定位,开环加速以前闭环控制(含过零检测的程序)

单片机源程序如下:

  1. #include "hardware.h"
  2. #include "bldc.h"

  3. u16 Temp = 0;

  4. volatile State_TypeDef State = Idle;

  5. Task_TypeDef Task;

  6. Flag_TypeDef Flag;

  7. vu16        ADC_VALUE[ADC_NUMBER*ADC_BUFFER]={0};
  8. u16          SysTime = 0;                                                                                                                                                                                /* 系统时间 */
  9. u8                 Phase = 0;                                                                                                                                                                                        /* 通电绕组 */
  10. u16         PwmDuty = 0;                                                                                                                                                                                /* PWM占空比 */
  11. u8                 AlignRotorCount = 0;                                                                                                                                                /* 电机启动时锁定转子的次数 */
  12. u8                 BlankingCount = 0;                                                                                                                                                        /* 消隐时长 */
  13. //u8         ZeroBeforeCount = 0;                                                                                                                                                /* 过零点之前的检测次数 */
  14. u8                 ZeroCrossCount = 0;                                                                                                                                                        /* 到达过零点的检测次数 */
  15. u8                 ZeroAcquireCount = 0;                                                                                                                                                /* 进入到同步运行状态前的过零点次数 */
  16. u16         CommutateTime = 0;                                                                                                                                                        /* 过零检测到到换向的时间 */
  17. u16         AccelerateCommutateTime = 0;                                                                                                                /* 电机加速的换向的时间 */
  18. u16         AdcPotentiometer = 0;                                                                                                                                                /* 电位器ADC转换结果 */
  19. u16         AdcBEMF = 0;                                                                                                                                                                                /* BEMF电压ADC转换结果 */
  20. u16         AdcCurrent = 0;                                                                                                                                                                        /* 电流放大器ADC转换结果 */
  21. u16         AdcVbus = 0;                                                                                                                                                                                /* 电源电压ADC转换结果 */
  22. u16         ZeroVref = 0;                                                                                                                                                                                /* 过零检测基准电压,等于电源电压的一半 */
  23. u8                 SpeedErrorCount = 0;                                                                                                                                                /* 电机速度异常次数 */
  24. u16         ZeroPeriod = 1000;                                                                                                                                                        /* 过零周期即60度换向时间 */
  25. u16         MotorRpm = 0;                                                                                                                                                                                /* 电机转速,单位RPM */
  26. u16                AccelerateTime = 0;                                                                                                                                                        /* 电机加速运转的时间 */
  27. //u16 PhaseAdvance = 0;                                                                                                                                                                /* 超前相位 */
  28. u16         Current = 0;                                                                                                                                                                                /* 电流值 */
  29. u16         Iref = 0;                                                                                                                                                                                                /* 电流放大器输出偏置 */

  30. #define MaxIX                                                                999                                                                                                                         //最大记录条数
  31. vu16        BEMF_REC[MaxIX+1]={0};                                                                                                                                        // 反电动势记录
  32. u16   ix = 0;                                                                                                                                                                                                        // 记录下标
  33. /********************************************************************************************
  34. * Function Name  : void Scan_Key(void)
  35. * Description    : 按键扫描程序,用于启动或者停止电机运转
  36. * Input          : 无
  37. * Return         : 无
  38. *********************************************************************************************/
  39. void Scan_Key(void)
  40. {
  41.     if(Key_Status() == PRESS)
  42.     {
  43.         if(State == Idle)
  44.         {
  45.             while(Key_Status() != RELEASE);
  46.             State = Start;
  47.         }
  48.         else
  49.         {
  50.             while(Key_Status() != RELEASE);
  51.             State = Stop;
  52.         }
  53.     }
  54. }


  55. void Start_Motor(void)
  56. {
  57.     Close_LED7();
  58.     Close_LED8();
  59.     Close_LED9();

  60.     Flag.AcquireZero         = 0;
  61.     Flag.ZeroCross                 = 0;
  62.     SpeedErrorCount                = 0;
  63.     AccelerateTime                 = 0;
  64.     AlignRotorCount         = 3;                                                                                                                                                                                                                                /* 初始化电机转子定位次数 */

  65.     Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
  66.     Phase                                                 = 0;
  67.     Commutate();
  68.     TIM_CtrlPWMOutputs(TIM1, ENABLE);
  69.     State                                                 = AlignRotor;
  70.     SysTime                                         = 0;
  71.     Task.AlignRotor         = 0;
  72.     printf("Start AlignRotor !!!\n\r");
  73. }

  74. /********************************************************************************************
  75. * Function Name  : void AlignMotorRotor(void)
  76. * Description    : 转子定位程序
  77. * Input          : 无
  78. * Return         : 无
  79. *********************************************************************************************/
  80. void Align_MotorRotor(void)
  81. {
  82.     if(AlignRotorCount > 0)
  83.     {
  84.                                 Phase                                                 = 0;
  85.         Commutate();
  86.         Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
  87.         AlignRotorCount --;
  88.         if (AlignRotorCount == 0)
  89.         {
  90.             Update_PwmDuty((u32)PWM_ACCELERATE_START*FULL_DUTY/100);                                                                                //更新初始加速占空比
  91.             AccelerateCommutateTime = TIM2_FREQ*20/START_RPM/MOTOR_POLES;                                                                //设计初始加速时间参数

  92.             /* 启动TIM2,进入到加速状态 */
  93.             TIM2_Counter = 0;
  94.             Clear_TIM2_Update_IF();
  95.             Enable_TIM2_Update_IT();

  96.             Clear_TIM1_CC4_IF();
  97.             Enable_TIM1_CC4_IT();

  98.             State = Accelerate;
  99.             //State = Stop;
  100.         }
  101.     }
  102. }

  103. void Commutate(void)
  104. {
  105.     Disable_AH();
  106.     Disable_AL();
  107.     Disable_BH();
  108.     Disable_BL();
  109.     Disable_CH();
  110.     Disable_CL();

  111.     switch(Phase)
  112.     {
  113.         case 0:                                                                                                                                                                                                                                                                                                /* AB相 */
  114.         {
  115.             //Disable_CH();
  116.             Enable_AH();
  117.             Enable_BL();
  118.             #if (DIRECTION == COUNTER_CLOCKWISE)
  119.                 Flag.BemfEdge = FALLING;
  120.                 Phase = 1;
  121.             #else
  122.                 Flag.BemfEdge = RISING;
  123.                 Phase = 5;
  124.             #endif
  125.         }
  126.         break;

  127.         case 1:                                                                                                                                                                                                                                                                                                /* AC相 */
  128.         {
  129.             Enable_AH();
  130.             //Disable_BL();
  131.             Enable_CL();
  132.             #if (DIRECTION == COUNTER_CLOCKWISE)
  133.                 Flag.BemfEdge = RISING;
  134.                 Phase = 2;
  135.             #else
  136.                 Flag.BemfEdge = FALLING;
  137.                 Phase = 0;
  138.             #endif
  139.         }
  140.         break;

  141.         case 2:                                                                                                                                                                                                                                                                                                /* BC相 */
  142.         {
  143.             //Disable_AH();
  144.             Enable_BH();
  145.             Enable_CL();
  146.             #if (DIRECTION == COUNTER_CLOCKWISE)
  147.                 Flag.BemfEdge = FALLING;
  148.                 Phase = 3;
  149.             #else
  150.                 Flag.BemfEdge = RISING;
  151.                 Phase = 1;
  152.             #endif
  153.         }
  154.         break;
  155.                                
  156.         case 3:                                                                                                                                                                                                                                                                                                /* BA相 */
  157.         {
  158.             Enable_BH();
  159.             //Disable_CL();
  160.             Enable_AL();
  161.             #if (DIRECTION == COUNTER_CLOCKWISE)
  162.                 Flag.BemfEdge = RISING;
  163.                 Phase = 4;
  164.             #else
  165.                 Flag.BemfEdge = FALLING;
  166.                 Phase = 2;
  167.             #endif
  168.         }
  169.         break;

  170.         case 4:                                                                                                                                                                                                                                                                                                /* CA相 */
  171.         {
  172.             //Disable_BH();
  173.             Enable_CH();
  174.             Enable_AL();
  175.             #if (DIRECTION == COUNTER_CLOCKWISE)
  176.                 Flag.BemfEdge = FALLING;
  177.                 Phase = 5;
  178.             #else
  179.                 Flag.BemfEdge = RISING;
  180.                 Phase = 3;
  181.             #endif
  182.         }
  183.         break;

  184.         case 5:                                                                                                                                                                                                                                                                                                /* CB相 */
  185.         {
  186.             Enable_CH();
  187.             //Disable_AL();
  188.             Enable_BL();
  189.             #if (DIRECTION == COUNTER_CLOCKWISE)
  190.                 Flag.BemfEdge = RISING;
  191.                 Phase = 0;
  192.             #else
  193.                 Flag.BemfEdge = FALLING;
  194.                 Phase = 4;
  195.             #endif
  196.         }
  197.         break;

  198.         default:
  199.             break;
  200.     }

  201.     Flag.ZeroCross = 0;
  202.     BlankingCount = BLANKING_COUNT;
  203.     ZeroCrossCount = 0;
  204. }

  205. void Stop_Running(void)
  206. {
  207.     Disable_PwmOutput();
  208.     Clear_TIM1_CC4_IF();
  209.     Disable_TIM1_CC4_IT();
  210.     Clear_TIM2_Update_IF();
  211.     Disable_TIM2_Update_IT();
  212.     State = Idle;

  213.     if(Flag.FailedStart)                                                                                                                                                                                                                                                                                        /* 输出错误标志 */
  214.     {
  215.         Flag.FailedStart = 0;
  216.         printf("Error: Failed to start!!!\n\r");
  217.     }

  218.     if(Flag.CurrentHigh)
  219.     {
  220.         Flag.CurrentHigh = 0;
  221.         printf("Error: Current is too large!!!\n\r");
  222.     }

  223.     if(Flag.SpeedHigh)
  224.     {
  225.         Flag.SpeedHigh = 0;
  226.         printf("Error: Motor speed is too high !!!\n\r");
  227.     }

  228.     if(Flag.SpeedLow)
  229.     {
  230.         Flag.SpeedLow = 0;
  231.         printf("Error: Motor speed is too low !!!\n\r");
  232.     }

  233.     if(Flag.LostZero)
  234.     {
  235.         Flag.LostZero = 0;
  236.         printf("Error: Sensor error !!!\n\r");
  237.     }

  238.     printf("Motor stop !!!\n\r");
  239. }
  240. //  ROUNDUP(    INDIRECT("E7") * 20      /    (    INDIRECT("D13")*   B7*B7   /   INDIRECT("F13")   /    INDIRECT("F13")   +   INDIRECT("F7")   )  /   INDIRECT("G7")            ,0     )
  241. void Accelerate_Motor(void)                                                                                                                                                                                                                                                                                // 加速
  242. {
  243.     u16 speed = 0;                                                                                                                                                                                                                                                                                                     // 新的目标速度
  244.     u32 ct = 0;                                                                                                                                                                                                                                                                                                        // 新的换向时间

  245.     speed = ((u32)AccelerateTime*AccelerateTime)/ACCELERATE_TIME;                                                                                                                        /* 计算新的目标速度 */
  246.     speed = ((u32)(END_RPM - START_RPM)*speed)/ACCELERATE_TIME;
  247.     speed += START_RPM;
  248.                
  249.     ct = (u32)TIM2_FREQ*20/speed/MOTOR_POLES;                                                                                                                                                                                                        /* 将速度转换为相应的换向时长 */
  250.                
  251.                 //ct = AccelerateCommutateTime*14/15-1;
  252.     if(ct > 65535)        AccelerateCommutateTime = 65535;
  253.     else                                                AccelerateCommutateTime = ct;
  254.        
  255.                

  256.     PwmDuty = ((u32)PWM_ACCELERATE_DELTA*AccelerateTime/ACCELERATE_TIME);                                                                                        /* 计算PWM增量 */
  257.     PwmDuty += (u16)((u32)PWM_ACCELERATE_START*FULL_DUTY/100);                                                                                                                                /* 更新PWM */
  258.     Update_PwmDuty(PwmDuty);

  259.     if((AccelerateCommutateTime <= TIM2_FREQ*20/ZERO_ACQUIRE_RPM/MOTOR_POLES)&&                                                                /* 开始捕获过零点 */
  260.        (Flag.AcquireZero == 0))
  261.     {
  262.                                 Flag.AcquireZero = 1;
  263.         ZeroAcquireCount = 0;
  264. //                                Open_LED7();
  265.                 }

  266.                 if(AccelerateCommutateTime <= TIM2_FREQ*20/END_RPM/MOTOR_POLES)                                                                                                                /* 加速到启动终止速度时,启动失败 */
  267.     {
  268.         State = Stop;
  269.         Flag.FailedStart = 1;
  270.                                 Open_LED6();
  271.                 }
  272. }

  273. void Check_ZeroCrossing(void)
  274. {
  275.     u16 t = 0;

  276.     if(BlankingCount > 0)                                                                                                                                                /* 等待消隐 */
  277.     {
  278.         BlankingCount --;
  279.         return;
  280.     }

  281.     if((Flag.BemfEdge == FALLING)&&(AdcBEMF < ZeroVref))                /* 判断BEMF电压是否过零 */
  282.         ZeroCrossCount ++;

  283.     if((Flag.BemfEdge == RISING)&&(AdcBEMF > ZeroVref))
  284.         ZeroCrossCount ++;
  285.        
  286.     //Open_LED7();
  287.     if (ZeroCrossCount > ZERO_SAMPLES-1)                                                                                /* 达到预期的过零次数 */
  288.     {
  289.                                 BEMF_REC[ix] = AdcBEMF;
  290.                                 ix++;
  291.                                 if(ix>MaxIX) ix = 0;
  292.         //Open_LED8();
  293.         ZeroPeriod = TIM3_Counter;                                                                                                        /* 从TIM3计数器读取2次过零点的周期 */
  294.         TIM3_Counter = 0;

  295.         t = ZeroPeriod >> 1;                                                                                                                                /* 计算30度换向时长 */
  296.         CommutateTime = ((u32)t * (30 - ADVANCE_ANGLE))/30;        /* 超前相位补偿 */

  297.         if(CommutateTime > ZERO_CHECK_DELAY)                                                                /* ADC过零检测延迟补偿 */
  298.                                           CommutateTime -= ZERO_CHECK_DELAY;
  299.         else
  300.             CommutateTime = 1;

  301.         if (State == Running)
  302.         {
  303.             Flag.ZeroCross = 1;

  304.             Disable_TIM2_Update_IT();
  305.             TIM2->ARR = CommutateTime;
  306.             TIM2_Counter = 0;
  307.             Clear_TIM2_Update_IF();
  308.             Enable_TIM2_Update_IT();
  309.                                                 Open_LED9();                                                                                                                                                // 标志着已经切换到闭环控制状态
  310.         }
  311.         else                                                                                                                                                                                                /* 电机加速到同步运转状态的判断 */
  312.         {
  313.             ZeroAcquireCount ++;
  314.             
  315.             if(ZeroAcquireCount > ZERO_ACQUIRE_COUNT-1)                        /* 进入过零点同步状态 */
  316.             {
  317.                 Flag.ZeroCross = 1;
  318.                 Disable_TIM2_Update_IT();
  319.                 Flag.AcquireZero = 0;
  320.                 State = Running;

  321.                 TIM2->ARR = CommutateTime;                                                                        /* 更新TIM2定时换向 */
  322.                 TIM2_Counter = 0;
  323.                 Clear_TIM2_Update_IF();
  324.                 Enable_TIM2_Update_IT();
  325. //                                                                Open_LED9();                                                                                                                                // 标志着已经从开环加速正在切换到闭环控制状态
  326.             }
  327.         }
  328.     }
  329. }

  330. /********************************************************************************************
  331. * Function Name  : void Get_MotorSpeed(void)
  332. * Description    : 计算电机速度程序
  333.                    RPM = 60/((60°换向周期(秒)*6)*(极数/2)) = 20/(T*P)
  334. * Input          : 无
  335. * Return         : 无
  336. *********************************************************************************************/
  337. void Get_MotorSpeed(void)
  338. {
  339.     static u16 t = 0;

  340.     t += ZeroPeriod;                                                                                                                                                        /* 计算2次60度换向周期的平均值 */
  341.     t = t >> 1;
  342.     MotorRpm = (u32)TIM2_FREQ*20/t/MOTOR_POLES;                                                /* RPM = 60/((60°换向周期(秒)*6)*(极数/2)) = 20/(T*P) */
  343. }

  344. void Control_Speed(void)
  345. {
  346.     u16 duty = 0;

  347.     duty = ((u32)AdcPotentiometer*FULL_DUTY)/4095;                                /* 将ADC转换结果线性转换为PWM的占空比 */
  348.     if(duty > PwmDuty)                                                                                                                                                /* 逐渐调整PWM占空比,避免占空比调整步长太大导致电机失速 */
  349.     {
  350.         PwmDuty += 4;
  351.         if(PwmDuty > FULL_DUTY)                PwmDuty = FULL_DUTY;
  352.     }
  353.     else if(duty < PwmDuty)
  354.     {
  355.         if(PwmDuty < 4)         PwmDuty = 0;
  356.         else                                 PwmDuty -= 4;
  357.     }
  358.     else     return;
  359.     Update_PwmDuty(PwmDuty);                                                                                                                        /* 更新PWM占空比 */
  360. }

  361. /********************************************************************************************
  362. * Function Name  : void Monitor_Speed(void)
  363. * Description    : 电机失速监控程序
  364. * Input          : 无
  365. * Return         : 无
  366. *********************************************************************************************/
  367. void Monitor_Speed(void)
  368. {
  369.     if(MotorRpm < MIN_SPEED)                                                                                                                        /* 检查电机速度是否过低 */
  370. ……………………

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

下载:
bldc.rar (3.46 KB, 下载次数: 180)

分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏4 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:268389 发表于 2018-4-19 21:03 | 只看该作者
正在做相关方向,参考一下,谢谢无私分享
回复

使用道具 举报

板凳
ID:324611 发表于 2018-7-9 11:00 | 只看该作者
好东西,学习下。
回复

使用道具 举报

地板
ID:324611 发表于 2018-7-9 11:01 | 只看该作者
正在研究BLCD相关的东西,学习下。
回复

使用道具 举报

5#
ID:427831 发表于 2018-11-16 17:16 | 只看该作者
led是8位IO口吗?没太看懂你的
回复

使用道具 举报

6#
ID:460143 发表于 2019-1-2 15:43 | 只看该作者
楼主可以提供电路图吗?
回复

使用道具 举报

7#
ID:460143 发表于 2019-1-2 16:15 | 只看该作者
程序中的两个头文件在哪里呢?
回复

使用道具 举报

8#
ID:691135 发表于 2020-2-10 22:51 | 只看该作者
正在做相关方向,参考一下,谢谢无私分享,如果有原理图配合程序那就更完美了。
回复

使用道具 举报

9#
ID:967978 发表于 2021-9-28 14:05 | 只看该作者
请问楼主有头文件吗?
回复

使用道具 举报

10#
ID:640527 发表于 2021-10-18 10:45 | 只看该作者
正要做这块,帮大忙了,非常感谢
回复

使用道具 举报

11#
ID:194006 发表于 2021-11-27 21:03 | 只看该作者
正在学习无刷驱动,谢谢分享
回复

使用道具 举报

12#
ID:826226 发表于 2022-1-7 18:14 | 只看该作者
有更完整源码吗?
回复

使用道具 举报

13#
ID:412301 发表于 2023-9-9 15:51 | 只看该作者
配上原理图就更完善了
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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