c2c電子商務(wù)網(wǎng)站開發(fā)百度熱門關(guān)鍵詞
本教程基于韋東山百問網(wǎng)出的 DShanMCU-RA6M5開發(fā)板 進(jìn)行編寫,需要的同學(xué)可以在這里獲取: https://item.taobao.com/item.htm?id=728461040949
配套資料獲取:https://renesas-docs.100ask.net
瑞薩MCU零基礎(chǔ)入門系列教程匯總: https://blog.csdn.net/qq_35181236/article/details/132779862
第36章 步進(jìn)電機(jī)控制實(shí)驗(yàn)
36.1 24BYJ-48步進(jìn)電機(jī)工作原理
本書使用的步進(jìn)電機(jī)型號(hào)是28BYJ-48,它是一款常見的步機(jī)電機(jī),其名稱的含義為外徑28毫米四相八拍式永磁減速型步進(jìn)電機(jī)。型號(hào)的含義如下:
- 28:步進(jìn)電機(jī)的有效最大外徑是28毫米
- B:表示是步進(jìn)電機(jī)
- Y:表示是永磁式
- J:表示是減速型(減速比1:64)
- 48:表示四相八拍
先說什么是“4相永磁式”的概念,28BYJ-48 的內(nèi)部結(jié)構(gòu)示意圖如下所示。
先看里圈,它上面有8個(gè)齒,分別標(biāo)注為0~7,這個(gè)叫做轉(zhuǎn)子,顧名思義,它是要轉(zhuǎn)動(dòng)的。轉(zhuǎn)子的每個(gè)齒上都帶有永久的磁性,是一塊永磁體,這就是“永磁式”的概念。
再看外圈,這個(gè)是定子,它是保持不動(dòng)的,實(shí)際上它是跟電機(jī)的外殼固定在一起的。定子有ABCD四組共32個(gè)齒,每個(gè)齒上都纏上了一個(gè)線圈繞組。A組有8個(gè)線圈繞組,它們是串聯(lián)在一起的,這8個(gè)線圈繞組會(huì)同時(shí)導(dǎo)通或關(guān)斷。B、C、D組也是一樣的,如此就形成了4相,在圖中分別標(biāo)注為 A-B-C-D,這就是“4相”的概念。相鄰定子之間的夾角為360/32=11.25度。
步進(jìn)電機(jī)一共有5根線引出,紅色是公共端,接5v電源,其他四根分別對(duì)應(yīng)A,B,C ,D 四個(gè)繞組的另外一端。怎樣讓電機(jī)轉(zhuǎn)動(dòng)起來呢?
假設(shè)初始狀態(tài)時(shí)A導(dǎo)通,A組的8個(gè)線圈繞組都有磁力,吸引住8個(gè)轉(zhuǎn)子,8個(gè)轉(zhuǎn)子和8個(gè)A組定子對(duì)齊,如上圖所示。
然后讓A斷開,B導(dǎo)通,此時(shí)B組的8個(gè)線圈繞組會(huì)把距離它最近的8個(gè)轉(zhuǎn)子吸引過來,使得轉(zhuǎn)子和B組的定子對(duì)齊。以0號(hào)轉(zhuǎn)子為例,它從正對(duì)著A定子的位置,順時(shí)針旋轉(zhuǎn)到正對(duì)著B定子的位置,順時(shí)針旋轉(zhuǎn)了11.25度。
緊接著,讓B斷開,C導(dǎo)通,此時(shí)C組的8個(gè)線圈繞組會(huì)把距離它最近的8個(gè)轉(zhuǎn)子吸引過來,使得轉(zhuǎn)子和C組的定子對(duì)齊。以0號(hào)轉(zhuǎn)子為例,它從正對(duì)著B定子的位置,順時(shí)針旋轉(zhuǎn)到正對(duì)著C定子的位置,再次順時(shí)針旋轉(zhuǎn)了11.25度。當(dāng)我們依次單獨(dú)導(dǎo)通ABCD時(shí),電動(dòng)機(jī)就順時(shí)針轉(zhuǎn)到起來了。
單獨(dú)導(dǎo)通ABCD的某一組線圈繞組時(shí),轉(zhuǎn)子旋轉(zhuǎn)11.25度,這個(gè)值就叫做步進(jìn)角度。
而上述這種工作模式就是步進(jìn)電機(jī)的單四拍模式。同樣的道理,如果想讓轉(zhuǎn)子逆時(shí)針轉(zhuǎn)動(dòng),可以依次單獨(dú)導(dǎo)通DCBA。
我們?cè)賮斫榻B一種具有更優(yōu)性能的工作模式,那就是在單四拍的每兩個(gè)節(jié)拍之間再插入一個(gè)雙繞組導(dǎo)通的中間節(jié)拍,組成八拍模式。
比如,在順時(shí)針轉(zhuǎn)動(dòng)過程中,從 A 相導(dǎo)通到 B 相導(dǎo)通的中間,加入一個(gè) A 相和 B 相同時(shí)導(dǎo)通的節(jié)拍,這個(gè)時(shí)候,由于 A、B 兩個(gè)繞組的定子齒對(duì)它們附近的轉(zhuǎn)子齒同時(shí)產(chǎn)生相同的吸引力,這將0號(hào)轉(zhuǎn)子處于 A、B 兩個(gè)定子中間,也就是新插入的這個(gè)節(jié)拍使轉(zhuǎn)子轉(zhuǎn)過了上述單四拍模式中步進(jìn)角度的一半,即5.625度。這樣一來,就使轉(zhuǎn)動(dòng)精度增加了一倍,而轉(zhuǎn)子轉(zhuǎn)動(dòng)一圈則需要8*8=64拍了。另外,新增加的這個(gè)中間節(jié)拍,還會(huì)在原來單四拍的兩個(gè)節(jié)拍引力之間又加了一把引力,從而可以大大增加電機(jī)的整體扭力輸出,使電機(jī)更“有勁”了,而且更平順。
下表給出八拍模式下電機(jī)繞組激勵(lì)時(shí)序(電機(jī)引線顏色可能因廠家不同而不同):
本文將以八拍模式展開編程演示,當(dāng)按照下表的數(shù)值,連續(xù)給電機(jī)提供激勵(lì)時(shí),電機(jī)就逆時(shí)針轉(zhuǎn)起來。
28BYJ-48為減速電機(jī),電機(jī)輸出的轉(zhuǎn)速并不等于轉(zhuǎn)子的轉(zhuǎn)速。下圖是這個(gè)28BYJ-48步進(jìn)電機(jī)的拆解圖,從圖中可以看到,位于最中心的那個(gè)白色小齒輪才是步進(jìn)電機(jī)的轉(zhuǎn)子輸出,64個(gè)節(jié)拍只是讓這個(gè)小齒輪轉(zhuǎn)了一圈,然后它帶動(dòng)那個(gè)淺藍(lán)色的大齒輪,這就是一級(jí)減速。
右上方的白色齒輪的結(jié)構(gòu),除電機(jī)轉(zhuǎn)子和最終輸出軸外的3個(gè)傳動(dòng)齒輪都是這樣的結(jié)構(gòu),由一層多齒和一層少齒構(gòu)成,而每一個(gè)齒輪都用自己的少齒層去驅(qū)動(dòng)下一個(gè)齒輪的多齒層,這樣每2個(gè)齒輪都構(gòu)成一級(jí)減速,一共就有了4級(jí)減速。
36.2 電機(jī)驅(qū)動(dòng)板工作原理
根據(jù)28BYJ-48電機(jī)原理,我們只需要將開發(fā)板的四個(gè)引腳(通常為GPIO)分別連接到電機(jī),再按照電機(jī)的驅(qū)動(dòng)邏輯給出一定的激勵(lì)信號(hào)。但是開發(fā)板的GPIO驅(qū)動(dòng)能力有限,需要在開發(fā)板和電機(jī)之間加入驅(qū)動(dòng)電路,本教程選擇了雙路有刷直流馬達(dá)驅(qū)動(dòng)芯片MX1508,驅(qū)動(dòng)電路原理圖見下圖:
開發(fā)板的GPIO0~GPIO3引腳直接連接MX1508的INA1、INB1、INA2、INB2。MX1508的輸出端OUTA1、OUTB1、OUTA2、OUTB2分別接到步進(jìn)電機(jī)28BYJ-48的A、B、C、D四個(gè)線圈。所以,可以通過開發(fā)板的4個(gè)GPIO引腳,間接控制電機(jī)的ABCD。并不是使用4個(gè)GPIO簡(jiǎn)單地控制ABCD,它們不是一一對(duì)應(yīng)的關(guān)系。
需要先了解MX1508芯片內(nèi)部電路和基本工作模式:
- 待機(jī)模式
在待機(jī)模式下,INAx=INBx=L。包括驅(qū)動(dòng)功率管在內(nèi)的所有內(nèi)部電路都處于關(guān)斷狀態(tài)。電路消耗極低極低的電流。此時(shí)馬達(dá)輸出端 OUTAx 和 OUTBx 都為高阻狀態(tài)(記為Z)。
- 正轉(zhuǎn)模式
正轉(zhuǎn)模式的定義為:INAx=H,INBx=L,此時(shí)馬達(dá)驅(qū)動(dòng)端 OUTAx 輸出高電平,馬達(dá)驅(qū)動(dòng)端 OUTBx 輸出低電平時(shí),馬達(dá)驅(qū)動(dòng)電流從 OUTAx 流入馬達(dá),從 OUTBx 流到地端,此時(shí)馬達(dá)的轉(zhuǎn)動(dòng)定義為正轉(zhuǎn)模式。
- 反轉(zhuǎn)模式
反轉(zhuǎn)模式的定義為:INAx=L,INBx=H,此時(shí)馬達(dá)驅(qū)動(dòng)端 OUTBx 輸出高電平,馬達(dá)驅(qū)動(dòng)端 OUTAx 輸出低電平時(shí),馬達(dá)驅(qū)動(dòng)電流從 OUTBx 流入馬達(dá),從 OUTAx 流到地端,此時(shí)馬達(dá)的轉(zhuǎn)動(dòng)定義為反轉(zhuǎn)模式。
- 剎車模式
剎車模式的定義為:INAx=H,INBx=H,此時(shí)馬達(dá)驅(qū)動(dòng)端 OUTAx 以及 OUTBx 都輸出低電平,馬達(dá)內(nèi)存儲(chǔ)的能量將通過 OUTAx 端 NMOS 管或者 OUTBx 端 NMOS 快速釋放,馬達(dá)在短時(shí)間內(nèi)就會(huì)停止轉(zhuǎn)動(dòng)。注意在剎車模式下電路將消耗靜態(tài)功耗。
- PWM 模式A
當(dāng)輸入信號(hào) INAx 為 PWM 信號(hào),INBx=0 或者 INAx=0,INBx 為 PWM 信號(hào)時(shí),馬達(dá)的轉(zhuǎn)動(dòng)速度將受到 PWM信號(hào)占空比的控制。在這個(gè)模式下,馬達(dá)驅(qū)動(dòng)電路是在導(dǎo)通和待機(jī)模式之間切換,在待機(jī)模式下,所有功率管都處于關(guān)斷狀態(tài),馬達(dá)內(nèi)部儲(chǔ)存的能量只能通過功率 MOSFET 的體二極管緩慢釋放。
當(dāng)輸入信號(hào) INAx 為 PWM 信號(hào),INBx=1 或者 INAx=1,INBx 為 PWM 信號(hào)時(shí),馬達(dá)的轉(zhuǎn)動(dòng)速度將受到 PWM信號(hào)占空比的控制。在這個(gè)模式下,馬達(dá)驅(qū)動(dòng)電路輸出在導(dǎo)通和剎車模式之間,在剎車模式下馬達(dá)存儲(chǔ)的能量通過低邊的 NMOS 管快速釋放。
綜上所述,MX1508的真值表如下:
上述真表中,OUTAx/OUTBx輸出Z(高阻態(tài))、H(高電平)時(shí),連接到的電機(jī)線圈繞組都不會(huì)導(dǎo)通,效果是一樣的。
為了讓ABCD輸出8個(gè)節(jié)拍,可以按照下圖控制GPIO0~GPIO3:
以第1個(gè)節(jié)拍為例,想讓D輸出0,ABC輸出高電平或是高阻態(tài),怎么辦?換句話說,想讓OUTB2=L,OUTA2、OUTA1、OUTB1等于H或Z,怎么辦?
根據(jù)真值表,設(shè)置INA2=H、INB2=L,可以讓OUTA2=H、OUTB2=L:
繼續(xù)根據(jù)真值表,設(shè)置INA1=L、INB1=L,可以讓OUTA1=Z、OUTB1=Z:
所以,要讓D輸出0,ABC輸出高電平或是高阻態(tài)時(shí),需要:INA1=L、INB1=L、INA2=H、INB2=L。即:GPIO0=0、GPIO1=0、GPIO2=1、GPIO3=0,用二進(jìn)制表示即為:0b0100,即0x04。
將8個(gè)節(jié)拍對(duì)應(yīng)的GPIO值存到數(shù)組中:
S_CW[8]= {0x04,0x0c,0x08,0x09,0x01,0x03,0x02,0x06};
把4個(gè)GPIO配置為輸出后,將數(shù)組的值循環(huán)寫到GPIO輸出寄存器,就可以讓電機(jī)轉(zhuǎn)動(dòng)起來。按照反向的順序循環(huán)寫GPIO輸出寄存器,就可以實(shí)現(xiàn)電機(jī)反轉(zhuǎn)。調(diào)節(jié)兩個(gè)節(jié)拍間的周期,可以改變電機(jī)轉(zhuǎn)速。
根據(jù)電機(jī)的參數(shù):空載牽入頻率≥600Hz?可知,兩個(gè)節(jié)拍之間的時(shí)間間隔不宜小于1.6ms。
36.3 模塊配置
本次實(shí)驗(yàn)實(shí)質(zhì)上驅(qū)動(dòng)的外設(shè)只有一個(gè),那就是GPIO。但是為了更好的驅(qū)動(dòng)電機(jī),本次實(shí)驗(yàn)還使用了UART:讓用戶輸入角度、速度,并使用定時(shí)器來實(shí)現(xiàn)精準(zhǔn)延時(shí)。
本實(shí)驗(yàn)使用的步進(jìn)電機(jī)模塊會(huì)接到擴(kuò)展板的GPIO組,會(huì)使用到4個(gè)GPIO來接電機(jī)驅(qū)動(dòng)板的INA/B/C/D,擴(kuò)展板GPIO組原理圖如下圖所示:
本實(shí)驗(yàn)使用的是GPIO0~3,所以需要在RASC中將這4個(gè)IO對(duì)應(yīng)的引腳配置為通用輸出模式,請(qǐng)讀者參考本書前文對(duì)于GPIO的配置來配置這4個(gè)引腳。
36.4 外設(shè)驅(qū)動(dòng)程序
本次實(shí)驗(yàn)使用到的IO設(shè)備、串口設(shè)備和定時(shí)器設(shè)備在《30.3 設(shè)備對(duì)象封裝》中已經(jīng)將結(jié)果,使用到的方法基本一致,請(qǐng)讀者參考前文了解設(shè)備對(duì)象封裝的概念和方法,以及下載本書配套資料調(diào)閱源碼學(xué)習(xí)。
36.5 電機(jī)驅(qū)動(dòng)程序
36.5.1 電機(jī)設(shè)備對(duì)象
對(duì)于電機(jī),用戶需要的操作是:啟停、設(shè)定轉(zhuǎn)動(dòng)角度(角度、速度)。根據(jù)這些需求,封裝出電機(jī)的結(jié)構(gòu)體(dev_motor.h):
typedef struct StepMotor{char *name;MotorStatus status;int (*Init)(struct StepMotor *ptdev);int (*Start)(struct StepMotor *ptdev);int (*Stop)(struct StepMotor *ptdev);int (*SetAngle)(struct StepMotor *ptdev, int speed, int value);
}StepMotorDevice;
然后在dev_motor.c里構(gòu)造一個(gè)StepMotor結(jié)構(gòu)體,并給上層代碼提高獲得這個(gè)結(jié)構(gòu)體的函數(shù),代碼如下:
static struct StepMotor gMotor = {.name = "Step Motor",.status = 0,.Init = StepMotorDevInit,.Start = StepMotorDevStart,.Stop = StepMotorDevStop,.SetAngle = StepMotorDevSetAngle
};struct StepMotor *MotorGetDevice(void)
{return &gMotor;
}
36.5.2 初始化函數(shù)
初始化函數(shù)中要實(shí)現(xiàn)的就是獲取4個(gè)IO設(shè)備對(duì)象,代碼如下:
static int StepMotorDevInit (struct StepMotor *ptdev)
{if(NULL == ptdev) return -EINVAL;gINAIO = IODeviceFind("Step Motor INA");if(NULL == gINAIO) return -ENODEV;gINBIO = IODeviceFind("Step Motor INB");if(NULL == gINBIO) return -ENODEV;gINCIO = IODeviceFind("Step Motor INC");if(NULL == gINCIO) return -ENODEV;gINDIO = IODeviceFind("Step Motor IND");if(NULL == gINDIO) return -ENODEV;return ESUCCESS;
}
36.5.3 開啟轉(zhuǎn)動(dòng)
本書并沒有在Start函數(shù)中讓步進(jìn)電機(jī)轉(zhuǎn)動(dòng),僅僅是修改狀態(tài)表示電機(jī)處于開啟狀態(tài),代碼如下;
static int StepMotorDevStart(struct StepMotor *ptdev)
{if(NULL == ptdev) return -EINVAL;if(ptdev->status == isStop){ptdev->status = isRunning;return ESUCCESS;}return -EIO;
}
36.5.4 停止轉(zhuǎn)動(dòng)
將電機(jī)狀態(tài)標(biāo)志賦值為0,并且讓步進(jìn)電機(jī)的4個(gè)IO都輸出低電平。代碼如下:
static int StepMotorDevStop (struct StepMotor *ptdev)
{if(NULL == ptdev) return -EINVAL;if(ptdev->status == isRunning){ptdev->status = isStop;gINAIO->Write(gINAIO, 0);gINBIO->Write(gINBIO, 0);gINCIO->Write(gINCIO, 0);gINDIO->Write(gINDIO, 0);return ESUCCESS;}return -EIO;
}
36.5.5 設(shè)定轉(zhuǎn)速和轉(zhuǎn)動(dòng)角度
通過前面的講解可以知道,24BYJ-48步進(jìn)電機(jī)內(nèi)部收到64個(gè)節(jié)拍會(huì)轉(zhuǎn)動(dòng)1圈,轉(zhuǎn)子通過減速齒輪驅(qū)動(dòng)輸出軸轉(zhuǎn)動(dòng)1/64圈。那么要想輸出軸轉(zhuǎn)動(dòng)1圈,就需要給步進(jìn)電機(jī)4096個(gè)節(jié)拍(64*64=4096)。如果想要轉(zhuǎn)動(dòng)指定角度angle,那么對(duì)應(yīng)的拍數(shù)計(jì)算公式就是:
step=angle*4096/360
另外還可以順序、逆序使用S_CW[8]數(shù)組的值來驅(qū)動(dòng)電機(jī)以實(shí)現(xiàn)反轉(zhuǎn)、正轉(zhuǎn)。而電機(jī)轉(zhuǎn)速則表現(xiàn)在每拍之間的間隔時(shí)間,間隔越長,轉(zhuǎn)速越慢。
根據(jù)這些原理,就可以將設(shè)置步進(jìn)電機(jī)轉(zhuǎn)角和轉(zhuǎn)速的功能封裝到一個(gè)函數(shù)中了:
static const uint8_t EightBeat[8] = {0x04,0x0c,0x08,0x09,0x01,0x03,0x02,0x06};
static int StepMotorDevSetAngle(struct StepMotor *ptdev, int speed, int value)
{if(NULL == ptdev) return -EINVAL;if(1 > speed) return -EINVAL;int nAbsValue = (value>=0)?value:-value;unsigned int step = (unsigned int)(nAbsValue*4096/360);unsigned int phase = 0;if(isStop == ptdev->status)ptdev->Start(ptdev);for(unsigned int i=0; i<step; i++){if(value>0)phase = (i&0x07);elsephase = (7-(i&0x07));gINAIO->Write(gINAIO, ((EightBeat[phase]&0x08)==0)?0:1);gINBIO->Write(gINBIO, ((EightBeat[phase]&0x04)==0)?0:1);gINCIO->Write(gINCIO, ((EightBeat[phase]&0x02)==0)?0:1);gINDIO->Write(gINDIO, ((EightBeat[phase]&0x01)==0)?0:1);mdelay(speed);}ptdev->Stop(ptdev);return ESUCCESS;
}
36.6 測(cè)試程序
本次實(shí)驗(yàn)的方法是:讓用戶通過串口輸入角度、速度,然后控制步進(jìn)電機(jī)轉(zhuǎn)動(dòng)。代碼如下:
void DeviceTest(void)
{UartDevicesRegister();TimerDevicesRegister();IODevicesRegister();StepMotorDevice *pMotor = MotorGetDevice();if(NULL == pMotor){xprintf("Failed to Find Motor Device!\r\n");return;}pMotor->Init(pMotor);pMotor->Start(pMotor);while(1){xprintf("Enter value(+- 0~360 degree) and speed(Greater than 1ms) parameters you want: \r\n\t");int value = 0, speed = 0;scanf("%d%d", &value, &speed);xprintf("\tValue:%d\tSpeed:%d\r\n", value, speed);pMotor->SetAngle(pMotor, speed, value);}
}
36.7 測(cè)試結(jié)果
將程序燒寫到開發(fā)板中運(yùn)行,打開串口助手,插上步進(jìn)電機(jī)后,通過串口助手輸入轉(zhuǎn)角和轉(zhuǎn)速:
步進(jìn)電機(jī)就會(huì)逆時(shí)針或者順時(shí)針轉(zhuǎn)動(dòng)指定的角度