步進電機驅動技術3:基於ULN2003的步進電機驅動
在我們的專案中,經常使用到低電壓小功率的步進電機,此類步進電機若採用驅動器控制不斷成本高也過於複雜,我們可以直接使用場效電晶體或者達林頓管來實現對其的驅動。在本篇中,我們就來討論一下基於ULN2003A達林頓管實現對步進電機的驅動。
1、功能概述
我們先來了解一下基本的功能。ULN2003A達林頓管為7個輸出通道,當導通時該通道連線到負端,所以非常適合於驅動4相5線步進電機。
1.1、ULN2003A達林頓管
ULN2003A 器件是高電壓大電流達林頓電晶體陣列。每 款器件均由7個NPN 達林頓對組成,這些達林頓對具有高壓輸出,帶有用於開關感性負載的共陰極鉗位二極體。 單個達林頓對的集電極電流額定值為500mA。將達林 頓對並聯可以提供更高的電流。應用包括繼電器驅動器、電錘驅動器、燈驅動器、顯示驅動器(LED 和氣體放電)、線路驅動器和邏輯緩衝器。其基本結構圖如下:
1.2、步進電機基本原理
在我們的測試中,我們使用4相5線步進電機。所謂4相5線步進電機就是該電機具有4組線圈5根連線線,實際上可能不只5根線,但公共端不管抽出多少根線,實際狀態與1根無異。
我們一般將這4組線圈記為A相、B相、C相和D相,當然,也可以用別的稱呼,只要便於標記分別就好。4相5線步進電機一般採用單極性直流電源供電。只要對步進電機的各相繞組按合適的時序通電,就能使步進電機步進轉動。一般電機都會提供控制表,具體如下所示:
結合ULN2003A結構和4相5線步進電機的驅動要求,我們可以設計ULN2003A達林頓管驅動4相5線步進電機的驅動電路。
1.3、步進電機驅動模式
步進電機的驅動雖然按照電機的驅動表就可以實現,但實際的驅動方式有多種,常見的如單波驅動方式、全步驅動方式、半步驅動方式以及微步驅動方式等。這裡我們可以看一看前面三種比較簡單的驅動方式。
單波驅動方式又稱之為單四拍工作方式。此種方式按固定次序依次驅動每一個線圈以達到使電機轉動的目的。其波形如下:
全步驅動方式又稱之為雙四拍工作方式。此種方式按固定次序依次驅動兩組線圈以達到使電機轉動的目的。其波形如下:
半步驅動方式又稱之為八拍工作方式。此種模式實際上是前兩種模式的組合,以固定的次序依次激勵一組或兩組線圈以達到驅動電機的目的。其波形如下:
上述波形即是在單波驅動方式、全步驅動方式以及半步驅動方式下使用示波器抓取的A相和C相的波形圖,基本可以展示這幾種驅動工作方式波形特徵。
2、驅動設計與實現
我們已經瞭解了ULN2003A驅動4相5線步進電機的基本工作情況,接下來我們就需要據此來實現ULN2003A驅動4相5線步進電機驅動程式的設計與實現。
2.1、物件定義
我們依然是基於物件來實現相關的操作。所以我們首先要定義物件,出於適用性考慮,我們要定義物件的型別並將具體的物件例項化,接下來我們就來抽象物件型別和例項化物件的操作。
2.1.1、物件的抽象
對於一個物件最主要包括屬性與方法兩方面內容,所以我們先來考慮驅動一個步進電機物件具有哪些屬性和方法,並抽象出較為通用的步進電機的物件型別。
首先,我們來考慮物件的屬性情況。對電機的操作包括啟停命令、方向命令、執行狀態、實際運轉方向、節拍數、週期等,這些資訊控制電機的運轉並表徵其具體工作狀態,所以我們將其作為物件的屬性。驅動模式和執行模式用以配置電機的具體工作方式,所以我們也將其作為物件的屬性,以完成物件的配置。
其次我們再來考慮物件的方法問題。對相位的具體操作與具體的硬體平臺有關,根據對應的引腳定義相應的相位引腳。這依賴於具體的硬體和軟體操作平臺,所以我們將其定義為物件的方法。為了控制操作時序,我們需要延時處理,而延時操作函式同樣依賴於具體的軟硬體平臺,所以我們也將其定義為物件的方法,通過回撥函式的方式來實現。
根據上述對物件屬性和方法的分析,我們可以定義步進電機物件的型別如下:
/*定義步進電機物件型別*/
typedef struct StepperObject {
uint8_t startStop; //啟動停止命令
uint8_t runStatus; //執行狀態
uint8_t directSet; //方向設定
uint8_t directRun; //當前方向
uint8_t beat; //當前節拍
uint8_t period; //速度控制週期
DriveModeType driveMode; //驅動模式
StepperModeType runMode; //執行模式
void (*PhaseAction)(uint8_t cmd);
void (*Delayms)(uint32_t period);
}StepperObjectType;
2.1.2、物件初始化
我們定義了物件型別,可以實現基於物件的操作,但定義的物件變數需要進行初始化才能讓不同的物件按照我們的配置的方式去執行。所以在開始物件的使用之前我們先對其進行初始化,這就需要我們設計一個物件的初始化函式。
這個初始化函式,將構造一個具體的操作物件。對於步進電機來說,我們需要初始化其相關的引數,如:工作模式、執行模式以及相位操作函式等。具體的初始化函式如下:
/*步進電機物件初始化*/
void StepperInitialization(StepperObjectType *stepper, //步進電機物件
DriveModeType driveMode, //驅動模式
StepperModeType runMode, //執行模式
uint8_t period, //速度控制週期
StepperPhaseActionType action, //相位操作回撥函式
StepperDelaymsType delayms //延時操作回撥函式
)
{
if((stepper==NULL)||(action==NULL)||(delayms==NULL))
{
return;
}
stepper->PhaseAction=action;
stepper->Delayms=delayms;
stepper->driveMode=driveMode;
stepper->runMode=runMode;
stepper->period=period>0?period:1;
}
2.2、物件操作
接下來我們考慮對步進電機物件所要進行的操作問題。我們已經將相位的具體面向硬體平臺的操作定義為物件的方法。我們需要實現物件在不同的模式下節拍操作的控制。具體實現如下:
//步進電機節拍操作
static void StepperAction(StepperObjectType *stepper)
{
uint8_t Command[BEAT_NUM]={0x01,0x03,0x02,0x06,0x04,0x0C,0x08,0x09};
RunBeatType beat=BEAT_NUM;
if(stepper->beat>=BEAT_NUM)
{
stepper->beat=0;
if(stepper->driveMode==Full_Step)
{
stepper->beat=1;
}
}
beat=stepper->directRun>0?((RunBeatType)(7-stepper->beat)):((RunBeatType)stepper->beat);
if(beat>=BEAT_NUM)
{
return;
}
stepper->PhaseAction(Command[beat]);
stepper->beat++;
if((stepper->driveMode==Full_Step)||(stepper->driveMode==Single_Wave))
{
stepper->beat++;
}
stepper->Delayms(stepper->period);
}
3、驅動的應用
我們已經設計並實現了基於ULN2003A的步進電機驅動程式,接下來我們實現一個例項來驗證這一驅動程式設定是否符合要求。
3.1、宣告並初始化物件
在開始一切操作之前,首先我們需要一個物件。前面的設計中,我們已經定義了一個StepperObjectType物件型別,所以我們使用它定義一個物件變數。
StepperObjectType chamber;
定義了chamber物件變數之後,還沒有辦法使用,因為我們需要對其進行初始化。前面我們已經設計了物件初始化函式,我們需要使用這一函式來初始化chamber物件變數。初始化函式需要如下引數:
StepperObjectType *stepper, //步進電機物件
DriveModeType driveMode, //驅動模式
StepperModeType runMode, //執行模式
uint8_t period, //速度控制週期
StepperPhaseActionType action, //相位操作回撥函式
StepperDelaymsType delayms //延時操作回撥函式
第1個引數為我們需要初始化的步進電機物件。而驅動模式、執行模式為列舉,根據實際使用要求輸入即可。而速度週期為初始速度設定,只要不是0的整數就可以。主要需要考慮的是後面兩個函式指標。其原型定義如下:
typedef void (*StepperPhaseActionType)(uint8_t cmd);
typedef void (*StepperDelaymsType)(uint32_t period);
根據函式指標的原型定義,以及我們專案中具體用到的硬體配置,我們可以實現相位操作函式為:
/*步進電機相位操作*/
static void PhaseOperation(uint8_t cmd)
{
GPIO_PinState AP,BP,CP,DP;
AP=(GPIO_PinState)(cmd&0x01);
BP=(GPIO_PinState)((cmd>>1)&0x01);
CP=(GPIO_PinState)((cmd>>2)&0x01);
DP=(GPIO_PinState)((cmd>>3)&0x01);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_9, BP);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_11, DP);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_13, AP);
HAL_GPIO_WritePin(GPIOE, GPIO_PIN_14, CP);
}
而延時函式我們直接使用HAL_Delay,所以我們就可以實現步進電機物件的初始化操作如下:
/*步進電機物件初始化*/
StepperInitialization(&chamber, //步進電機物件
Half_Step, //驅動模式
Mode_Speed, //執行模式
10, //速度控制週期
PhaseOperation, //相位操作回撥函式
HAL_Delay //延時操作回撥函式
);
3.2、基於物件進行操作
初始化之後,我們就可以使用該物件來實現我們想要的操作了。我們設計一個應用函式呼叫相關驅動實現操作。
我們可以實現位置控制模式如下:
StepperPositionControl(&chamber,5000,Direct_CW);
我們可以實現速度控制模式如下:
StepperSpeedControl(&chamber);
當然具體的操作模式需要在初始化函式中配置。
4、結論
在本篇中我們設計並實現了基於ULN2003A的步進電機驅動程式。我們設計的測試示例執行正常。事實上該驅動在我們的專案中已經實際使用,到目前為止執行還算穩定。
我們開篇說是面向低電壓的小功率的步進電機,但實際上如果我們通過ULN2003A控制MOS管是可以實現高電壓大功率的步進電機的,但我們是直接使用ULN2003A達林頓管所以才限定為低電壓小功率的步進電機。
使用驅動是需要注意,該驅動方式不支援很高的執行速度。速度高時會出現力矩過小而堵轉的情形。我們實驗中所採用的電機一般控制在250Hz以下都可以穩定執行。