上周總算做成了點(diǎn)事,其實(shí)很簡(jiǎn)單,就是用Arduino實(shí)現(xiàn)了步進(jìn)電機(jī)的正轉(zhuǎn)和反轉(zhuǎn)。因?yàn)榭偸呛苊Γ酝系浆F(xiàn)在才有時(shí)間補(bǔ)上攻略。感慨一下,IT民工真辛苦啊,有位同事的昵稱已經(jīng)改成 “還是古代好,切掉小JJ就可以當(dāng)公務(wù)員了”。 好吧,祝這位朋友心想事成,我還是堅(jiān)持當(dāng)民工好了
在步進(jìn)電機(jī)實(shí)驗(yàn)前,從網(wǎng)上找到了一個(gè)關(guān)于步進(jìn)電機(jī)驅(qū)動(dòng)的文檔,使用的是L298N的驅(qū)動(dòng)芯片。這個(gè)文檔里面有些錯(cuò)誤,導(dǎo)致我浪費(fèi)了大量時(shí)間。也許不同的電機(jī)和芯片版本也許有區(qū)別吧,請(qǐng)大家慎重使用。先借用一下原理圖:

錯(cuò)誤的L298N步進(jìn)電機(jī)驅(qū)動(dòng)芯片原理圖
其中IN1~IN4以及ENA,ENB在之前的一篇關(guān)于直流電機(jī)驅(qū)動(dòng)中有介紹過(guò),分別對(duì)應(yīng)輸入的六個(gè)管腳。這個(gè)圖里有兩處錯(cuò)誤,首先可以看到有兩個(gè)ENA,其中一個(gè)應(yīng)該是ENB;另外這兩個(gè)EN都是接地的,但是經(jīng)我實(shí)驗(yàn)看來(lái),應(yīng)該接+5V的電壓才對(duì)。
所以正確的原理圖應(yīng)該是這樣的:

正確的L298N原理圖
下面是對(duì)應(yīng)的接線圖:
亂七八糟的接線圖
接線之后按照說(shuō)明書(shū)里的時(shí)序圖寫(xiě)了一段程序,呼呼,一次就通過(guò)了電機(jī)的正轉(zhuǎn)實(shí)驗(yàn)??墒窃谄髨D實(shí)現(xiàn)反轉(zhuǎn)的時(shí)候,總是不成功。在焦頭爛額之后,終于開(kāi)始懷疑文檔是否正確。事實(shí)證明,大家做任何事情都要相信偉大的黨而不是萬(wàn)惡的“文檔”,下面是錯(cuò)誤的反轉(zhuǎn)時(shí)序圖和經(jīng)我驗(yàn)證可行的時(shí)序圖:

步進(jìn)電機(jī)驅(qū)動(dòng)的時(shí)序圖
基于以上時(shí)序圖,我寫(xiě)了一段代碼,讓步進(jìn)電機(jī)實(shí)現(xiàn)下面的動(dòng)作:
正轉(zhuǎn)一圈 -> 暫停1秒鐘 -> 反轉(zhuǎn)一圈 -> 暫停一秒鐘 ->循環(huán)
代碼如下:
- int LeftI1 = 28; //連接電機(jī)驅(qū)動(dòng)板的I1接口
- int LeftI2 = 22; //連接電機(jī)驅(qū)動(dòng)板的I2接口
- int LeftEA = 8; //連接電機(jī)驅(qū)動(dòng)板的EA接口
- int RightI1 = 36; //連接電機(jī)驅(qū)動(dòng)板的I1接口
- int RightI2 = 42; //連接電機(jī)驅(qū)動(dòng)板的I2接口
- int RightEB = 6; //連接電機(jī)驅(qū)動(dòng)板的EB接口
- int StepCount = 0;
- int StepDelayTime=1500;
- void setup()
- {
- pinMode(LeftI1, OUTPUT); //I1和I2都是數(shù)字信號(hào)
- pinMode(LeftI2, OUTPUT); //通過(guò)設(shè)置I1和I2來(lái)控制電機(jī)旋轉(zhuǎn)方向
- pinMode(LeftEA, OUTPUT); //按占空比方式輸出的模擬信號(hào)
- pinMode(RightI1, OUTPUT); //I1和I2都是數(shù)字信號(hào)
- pinMode(RightI2, OUTPUT); //通過(guò)設(shè)置I1和I2來(lái)控制電機(jī)旋轉(zhuǎn)方向
- pinMode(RightEB, OUTPUT); //按占空比方式輸出的模擬信號(hào)
- Serial.begin(9600); //設(shè)置波特率
- }
- void ForwardInit()
- {
- digitalWrite(LeftEA, HIGH);
- digitalWrite(RightEB,HIGH );
- digitalWrite(LeftI1, LOW);
- digitalWrite(LeftI2,HIGH );
- digitalWrite(RightI1,HIGH);
- digitalWrite(RightI2, HIGH);
- StepCount=0;
- }
- void BackwardInit()
- {
- digitalWrite(LeftEA, HIGH);
- digitalWrite(RightEB,HIGH );
- digitalWrite(LeftI1, LOW);
- digitalWrite(LeftI2,LOW );
- digitalWrite(RightI1,LOW);
- digitalWrite(RightI2, HIGH);
- StepCount=0;
- }
- void ForwardOneStep()
- {
- delayMicroseconds(StepDelayTime);
- switch(StepCount)
- {
- case 0:
- digitalWrite(RightI2,LOW);
- digitalWrite(LeftI1,HIGH);
- break;
- case 1:
- digitalWrite(RightI1,LOW);
- digitalWrite(RightI2,HIGH);
- break;
- case 2:
- digitalWrite(LeftI2,LOW);
- digitalWrite(RightI1,HIGH);
- break;
- case 3:
- digitalWrite(LeftI1,LOW);
- digitalWrite(LeftI2,HIGH);
- break;
- }
- StepCount=(StepCount + 1) % 4;
- }
- void BackwardOneStep()
- {
- delayMicroseconds(StepDelayTime);
- switch(StepCount)
- {
- case 0:
- digitalWrite(RightI2,LOW);
- digitalWrite(LeftI1,HIGH);
- break;
- case 1:
- digitalWrite(LeftI1,LOW);
- digitalWrite(LeftI2,HIGH);
- break;
- case 2:
- digitalWrite(LeftI2,LOW);
- digitalWrite(RightI1,HIGH);
- break;
- case 3:
- digitalWrite(RightI1,LOW);
- digitalWrite(RightI2,HIGH);
- break;
- }
- StepCount=(StepCount + 1) % 4;
- }
- void loop()
- {
- while(1)
- {
- ForwardInit();
- for(int i=0;i<200;i++)
- {
- ForwardOneStep();
- }
- delay(1000);
- BackwardInit();
- for(int i=0;i<200;i++)
- {
- BackwardOneStep();
- }
- delay(1000);
- }
- }
除了實(shí)現(xiàn)了動(dòng)作之外,我還搭車實(shí)驗(yàn)了下面幾件事情:
1,步進(jìn)電機(jī)的轉(zhuǎn)角相當(dāng)精確,我捆了根電線當(dāng)指針,反復(fù)轉(zhuǎn)了幾百圈之后,指針的位置幾乎沒(méi)有變化
2,扭矩還挺大,我選用的是標(biāo)稱扭矩是3.4Kg.cm的步進(jìn)電機(jī),用鉛酸蓄電池供電,旋轉(zhuǎn)時(shí)我用爪子完全不能把它捏住(NXT的電機(jī)貌似沒(méi)有這么強(qiáng)勁)。
3,經(jīng)我測(cè)試,每個(gè)脈沖之間的間距最好大于1500μs(1.5ms),如果間距太小的話,就會(huì)出現(xiàn)失步的情況。
思考問(wèn)題:基本上來(lái)說(shuō),每個(gè)步進(jìn)電機(jī)都需要一個(gè)驅(qū)動(dòng)板(L298N)和一個(gè)控制板(Arduino或其它單片機(jī))。如果需要控制多個(gè)電機(jī)的話(小愛(ài)也許會(huì)有20多個(gè)關(guān)節(jié)),買(mǎi)這么多板子成本就太高了。實(shí)際上,每個(gè)脈沖間距之間有1500微秒的空閑時(shí)間,對(duì)CPU來(lái)說(shuō)簡(jiǎn)直是漫漫長(zhǎng)夜。所以我覺(jué)得可以用類似于操作系統(tǒng)多任務(wù)的思想來(lái)生成時(shí)序,充分利用脈沖間距之間的剩余價(jià)值,這樣就可以只用一塊Arduino實(shí)驗(yàn)板來(lái)控制多個(gè)電機(jī)了。
呵呵,又想多了,等下周有空再試試吧!