久久久久久久999_99精品久久精品一区二区爱城_成人欧美一区二区三区在线播放_国产精品日本一区二区不卡视频_国产午夜视频_欧美精品在线观看免费
標題:
無刷無感電機過零檢測單片機源程序
[打印本頁]
作者:
Hanney
時間:
2018-3-30 09:18
標題:
無刷無感電機過零檢測單片機源程序
附件中的源文件是無感三相電機零速定位,開環加速以前閉環控制(含過零檢測的程序)
單片機源程序如下:
#include "hardware.h"
#include "bldc.h"
u16 Temp = 0;
volatile State_TypeDef State = Idle;
Task_TypeDef Task;
Flag_TypeDef Flag;
vu16 ADC_VALUE[ADC_NUMBER*ADC_BUFFER]={0};
u16 SysTime = 0; /* 系統時間 */
u8 Phase = 0; /* 通電繞組 */
u16 PwmDuty = 0; /* PWM占空比 */
u8 AlignRotorCount = 0; /* 電機啟動時鎖定轉子的次數 */
u8 BlankingCount = 0; /* 消隱時長 */
//u8 ZeroBeforeCount = 0; /* 過零點之前的檢測次數 */
u8 ZeroCrossCount = 0; /* 到達過零點的檢測次數 */
u8 ZeroAcquireCount = 0; /* 進入到同步運行狀態前的過零點次數 */
u16 CommutateTime = 0; /* 過零檢測到到換向的時間 */
u16 AccelerateCommutateTime = 0; /* 電機加速的換向的時間 */
u16 AdcPotentiometer = 0; /* 電位器ADC轉換結果 */
u16 AdcBEMF = 0; /* BEMF電壓ADC轉換結果 */
u16 AdcCurrent = 0; /* 電流放大器ADC轉換結果 */
u16 AdcVbus = 0; /* 電源電壓ADC轉換結果 */
u16 ZeroVref = 0; /* 過零檢測基準電壓,等于電源電壓的一半 */
u8 SpeedErrorCount = 0; /* 電機速度異常次數 */
u16 ZeroPeriod = 1000; /* 過零周期即60度換向時間 */
u16 MotorRpm = 0; /* 電機轉速,單位RPM */
u16 AccelerateTime = 0; /* 電機加速運轉的時間 */
//u16 PhaseAdvance = 0; /* 超前相位 */
u16 Current = 0; /* 電流值 */
u16 Iref = 0; /* 電流放大器輸出偏置 */
#define MaxIX 999 //最大記錄條數
vu16 BEMF_REC[MaxIX+1]={0}; // 反電動勢記錄
u16 ix = 0; // 記錄下標
/********************************************************************************************
* Function Name : void Scan_Key(void)
* Description : 按鍵掃描程序,用于啟動或者停止電機運轉
* Input : 無
* Return : 無
*********************************************************************************************/
void Scan_Key(void)
{
if(Key_Status() == PRESS)
{
if(State == Idle)
{
while(Key_Status() != RELEASE);
State = Start;
}
else
{
while(Key_Status() != RELEASE);
State = Stop;
}
}
}
void Start_Motor(void)
{
Close_LED7();
Close_LED8();
Close_LED9();
Flag.AcquireZero = 0;
Flag.ZeroCross = 0;
SpeedErrorCount = 0;
AccelerateTime = 0;
AlignRotorCount = 3; /* 初始化電機轉子定位次數 */
Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
Phase = 0;
Commutate();
TIM_CtrlPWMOutputs(TIM1, ENABLE);
State = AlignRotor;
SysTime = 0;
Task.AlignRotor = 0;
printf("Start AlignRotor !!!\n\r");
}
/********************************************************************************************
* Function Name : void AlignMotorRotor(void)
* Description : 轉子定位程序
* Input : 無
* Return : 無
*********************************************************************************************/
void Align_MotorRotor(void)
{
if(AlignRotorCount > 0)
{
Phase = 0;
Commutate();
Update_PwmDuty((u32)ALIGN_ROTOR_PWM*FULL_DUTY/100);
AlignRotorCount --;
if (AlignRotorCount == 0)
{
Update_PwmDuty((u32)PWM_ACCELERATE_START*FULL_DUTY/100); //更新初始加速占空比
AccelerateCommutateTime = TIM2_FREQ*20/START_RPM/MOTOR_POLES; //設計初始加速時間參數
/* 啟動TIM2,進入到加速狀態 */
TIM2_Counter = 0;
Clear_TIM2_Update_IF();
Enable_TIM2_Update_IT();
Clear_TIM1_CC4_IF();
Enable_TIM1_CC4_IT();
State = Accelerate;
//State = Stop;
}
}
}
void Commutate(void)
{
Disable_AH();
Disable_AL();
Disable_BH();
Disable_BL();
Disable_CH();
Disable_CL();
switch(Phase)
{
case 0: /* AB相 */
{
//Disable_CH();
Enable_AH();
Enable_BL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = FALLING;
Phase = 1;
#else
Flag.BemfEdge = RISING;
Phase = 5;
#endif
}
break;
case 1: /* AC相 */
{
Enable_AH();
//Disable_BL();
Enable_CL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = RISING;
Phase = 2;
#else
Flag.BemfEdge = FALLING;
Phase = 0;
#endif
}
break;
case 2: /* BC相 */
{
//Disable_AH();
Enable_BH();
Enable_CL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = FALLING;
Phase = 3;
#else
Flag.BemfEdge = RISING;
Phase = 1;
#endif
}
break;
case 3: /* BA相 */
{
Enable_BH();
//Disable_CL();
Enable_AL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = RISING;
Phase = 4;
#else
Flag.BemfEdge = FALLING;
Phase = 2;
#endif
}
break;
case 4: /* CA相 */
{
//Disable_BH();
Enable_CH();
Enable_AL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = FALLING;
Phase = 5;
#else
Flag.BemfEdge = RISING;
Phase = 3;
#endif
}
break;
case 5: /* CB相 */
{
Enable_CH();
//Disable_AL();
Enable_BL();
#if (DIRECTION == COUNTER_CLOCKWISE)
Flag.BemfEdge = RISING;
Phase = 0;
#else
Flag.BemfEdge = FALLING;
Phase = 4;
#endif
}
break;
default:
break;
}
Flag.ZeroCross = 0;
BlankingCount = BLANKING_COUNT;
ZeroCrossCount = 0;
}
void Stop_Running(void)
{
Disable_PwmOutput();
Clear_TIM1_CC4_IF();
Disable_TIM1_CC4_IT();
Clear_TIM2_Update_IF();
Disable_TIM2_Update_IT();
State = Idle;
if(Flag.FailedStart) /* 輸出錯誤標志 */
{
Flag.FailedStart = 0;
printf("Error: Failed to start!!!\n\r");
}
if(Flag.CurrentHigh)
{
Flag.CurrentHigh = 0;
printf("Error: Current is too large!!!\n\r");
}
if(Flag.SpeedHigh)
{
Flag.SpeedHigh = 0;
printf("Error: Motor speed is too high !!!\n\r");
}
if(Flag.SpeedLow)
{
Flag.SpeedLow = 0;
printf("Error: Motor speed is too low !!!\n\r");
}
if(Flag.LostZero)
{
Flag.LostZero = 0;
printf("Error: Sensor error !!!\n\r");
}
printf("Motor stop !!!\n\r");
}
// ROUNDUP( INDIRECT("E7") * 20 / ( INDIRECT("D13")* B7*B7 / INDIRECT("F13") / INDIRECT("F13") + INDIRECT("F7") ) / INDIRECT("G7") ,0 )
void Accelerate_Motor(void) // 加速
{
u16 speed = 0; // 新的目標速度
u32 ct = 0; // 新的換向時間
speed = ((u32)AccelerateTime*AccelerateTime)/ACCELERATE_TIME; /* 計算新的目標速度 */
speed = ((u32)(END_RPM - START_RPM)*speed)/ACCELERATE_TIME;
speed += START_RPM;
ct = (u32)TIM2_FREQ*20/speed/MOTOR_POLES; /* 將速度轉換為相應的換向時長 */
//ct = AccelerateCommutateTime*14/15-1;
if(ct > 65535) AccelerateCommutateTime = 65535;
else AccelerateCommutateTime = ct;
PwmDuty = ((u32)PWM_ACCELERATE_DELTA*AccelerateTime/ACCELERATE_TIME); /* 計算PWM增量 */
PwmDuty += (u16)((u32)PWM_ACCELERATE_START*FULL_DUTY/100); /* 更新PWM */
Update_PwmDuty(PwmDuty);
if((AccelerateCommutateTime <= TIM2_FREQ*20/ZERO_ACQUIRE_RPM/MOTOR_POLES)&& /* 開始捕獲過零點 */
(Flag.AcquireZero == 0))
{
Flag.AcquireZero = 1;
ZeroAcquireCount = 0;
// Open_LED7();
}
if(AccelerateCommutateTime <= TIM2_FREQ*20/END_RPM/MOTOR_POLES) /* 加速到啟動終止速度時,啟動失敗 */
{
State = Stop;
Flag.FailedStart = 1;
Open_LED6();
}
}
void Check_ZeroCrossing(void)
{
u16 t = 0;
if(BlankingCount > 0) /* 等待消隱 */
{
BlankingCount --;
return;
}
if((Flag.BemfEdge == FALLING)&&(AdcBEMF < ZeroVref)) /* 判斷BEMF電壓是否過零 */
ZeroCrossCount ++;
if((Flag.BemfEdge == RISING)&&(AdcBEMF > ZeroVref))
ZeroCrossCount ++;
//Open_LED7();
if (ZeroCrossCount > ZERO_SAMPLES-1) /* 達到預期的過零次數 */
{
BEMF_REC[ix] = AdcBEMF;
ix++;
if(ix>MaxIX) ix = 0;
//Open_LED8();
ZeroPeriod = TIM3_Counter; /* 從TIM3計數器讀取2次過零點的周期 */
TIM3_Counter = 0;
t = ZeroPeriod >> 1; /* 計算30度換向時長 */
CommutateTime = ((u32)t * (30 - ADVANCE_ANGLE))/30; /* 超前相位補償 */
if(CommutateTime > ZERO_CHECK_DELAY) /* ADC過零檢測延遲補償 */
CommutateTime -= ZERO_CHECK_DELAY;
else
CommutateTime = 1;
if (State == Running)
{
Flag.ZeroCross = 1;
Disable_TIM2_Update_IT();
TIM2->ARR = CommutateTime;
TIM2_Counter = 0;
Clear_TIM2_Update_IF();
Enable_TIM2_Update_IT();
Open_LED9(); // 標志著已經切換到閉環控制狀態
}
else /* 電機加速到同步運轉狀態的判斷 */
{
ZeroAcquireCount ++;
if(ZeroAcquireCount > ZERO_ACQUIRE_COUNT-1) /* 進入過零點同步狀態 */
{
Flag.ZeroCross = 1;
Disable_TIM2_Update_IT();
Flag.AcquireZero = 0;
State = Running;
TIM2->ARR = CommutateTime; /* 更新TIM2定時換向 */
TIM2_Counter = 0;
Clear_TIM2_Update_IF();
Enable_TIM2_Update_IT();
// Open_LED9(); // 標志著已經從開環加速正在切換到閉環控制狀態
}
}
}
}
/********************************************************************************************
* Function Name : void Get_MotorSpeed(void)
* Description : 計算電機速度程序
RPM = 60/((60°換向周期(秒)*6)*(極數/2)) = 20/(T*P)
* Input : 無
* Return : 無
*********************************************************************************************/
void Get_MotorSpeed(void)
{
static u16 t = 0;
t += ZeroPeriod; /* 計算2次60度換向周期的平均值 */
t = t >> 1;
MotorRpm = (u32)TIM2_FREQ*20/t/MOTOR_POLES; /* RPM = 60/((60°換向周期(秒)*6)*(極數/2)) = 20/(T*P) */
}
void Control_Speed(void)
{
u16 duty = 0;
duty = ((u32)AdcPotentiometer*FULL_DUTY)/4095; /* 將ADC轉換結果線性轉換為PWM的占空比 */
if(duty > PwmDuty) /* 逐漸調整PWM占空比,避免占空比調整步長太大導致電機失速 */
{
PwmDuty += 4;
if(PwmDuty > FULL_DUTY) PwmDuty = FULL_DUTY;
}
else if(duty < PwmDuty)
{
if(PwmDuty < 4) PwmDuty = 0;
else PwmDuty -= 4;
}
else return;
Update_PwmDuty(PwmDuty); /* 更新PWM占空比 */
}
/********************************************************************************************
* Function Name : void Monitor_Speed(void)
* Description : 電機失速監控程序
* Input : 無
* Return : 無
*********************************************************************************************/
void Monitor_Speed(void)
{
if(MotorRpm < MIN_SPEED) /* 檢查電機速度是否過低 */
……………………
…………限于本文篇幅 余下代碼請從51黑下載附件…………
復制代碼
下載:
bldc.rar
(3.46 KB, 下載次數: 183)
2018-3-30 09:16 上傳
點擊文件名下載附件
過零檢測
下載積分: 黑幣 -5
作者:
DHuang
時間:
2018-4-19 21:03
正在做相關方向,參考一下,謝謝無私分享
作者:
mcu_mpu
時間:
2018-7-9 11:00
好東西,學習下。
作者:
mcu_mpu
時間:
2018-7-9 11:01
正在研究BLCD相關的東西,學習下。
作者:
kr123crg
時間:
2018-11-16 17:16
led是8位IO口嗎?沒太看懂你的
作者:
HZCHZC
時間:
2019-1-2 15:43
樓主可以提供電路圖嗎?
作者:
HZCHZC
時間:
2019-1-2 16:15
程序中的兩個頭文件在哪里呢?
作者:
bowaterbo
時間:
2020-2-10 22:51
正在做相關方向,參考一下,謝謝無私分享,如果有原理圖配合程序那就更完美了。
作者:
YG0068
時間:
2021-9-28 14:05
請問樓主有頭文件嗎?
作者:
lnsfxycmz
時間:
2021-10-18 10:45
正要做這塊,幫大忙了,非常感謝
作者:
kavin21513
時間:
2021-11-27 21:03
正在學習無刷驅動,謝謝分享
作者:
云游天
時間:
2022-1-7 18:14
有更完整源碼嗎?
作者:
hgy1013
時間:
2023-9-9 15:51
配上原理圖就更完善了
歡迎光臨 (http://www.zg4o1577.cn/bbs/)
Powered by Discuz! X3.1
主站蜘蛛池模板:
91精品国产91久久久久游泳池
|
一区二区三区欧美
|
欧美视频
|
免费成人在线网站
|
成人欧美一区二区三区在线播放
|
手机av免费在线
|
国产精品久久性
|
久久一区二区三区四区五区
|
日韩精品一区二区三区中文字幕
|
91香蕉
|
日韩一区二区三区在线看
|
日韩在线一区二区三区
|
精品国产一区探花在线观看
|
一区2区
|
av在线一区二区三区
|
中文字幕日韩在线观看
|
男女网站免费
|
亚洲在线一区二区
|
欧美性猛交一区二区三区精品
|
免费观看一级特黄欧美大片
|
巨大荫蒂视频欧美另类大
|
国产成人免费视频网站高清观看视频
|
黄色成人av
|
中文字幕日韩专区
|
亚洲一区有码
|
成人污污视频
|
毛片综合
|
色婷婷综合网站
|
久久69精品久久久久久久电影好
|
波多野结衣一区二区
|
九九热久久免费视频
|
日韩欧美在线观看视频
|
欧美 日韩 中文
|
青青久久av北条麻妃海外网
|
81精品国产乱码久久久久久
|
欧美一区二区三区免费电影
|
国产区一区
|
欧美a√
|
日韩另类
|
在线观看国产91
|
久久综合伊人一区二区三
|