概述 此系統(tǒng)采用IAP15F2K60S2單片機(jī)作為主控芯片,控制直流電機(jī)的轉(zhuǎn)動(dòng),帶動(dòng)小車移動(dòng),使用超聲波傳感器來(lái)測(cè)量小車位移,實(shí)現(xiàn)小車行進(jìn)指定位移的功能。顯示部分使用LCD1602液晶屏。
主要由單片機(jī)控制器、直流電機(jī)驅(qū)動(dòng)電路、超聲波傳感器測(cè)距電路、顯示電路、鎖定裝置等部分組成。
核心在于如何能夠驅(qū)動(dòng)電機(jī)穩(wěn)定又準(zhǔn)確轉(zhuǎn)動(dòng),以及如何構(gòu)建適當(dāng)?shù)姆答佅到y(tǒng)來(lái)確保小車位移的準(zhǔn)確性。
反饋控制系統(tǒng)如圖2.1所示;系統(tǒng)通過(guò)按鍵模塊將目標(biāo)位移值輸入反饋控制鏈中,當(dāng)前位移值與目標(biāo)值作差;控制系統(tǒng)對(duì)差值控制,在某一閾值之前,系統(tǒng)保持高速前進(jìn),到達(dá)閾值之后,使得小車能夠逐漸減速并且最終能夠在目標(biāo)值處停下。其中使用超聲波測(cè)距作為負(fù)反饋,在密閉的空間內(nèi)能夠擁有很好地精度,也能確定小車當(dāng)前的位移,是良好的反饋系統(tǒng)。
圖2.1 反饋控制系統(tǒng)框圖
圖2.2 系統(tǒng)連接框圖
以模型小車為載體,各個(gè)模塊都需要安裝在小車上。系統(tǒng)的連接如圖2.2所示,按鍵模塊對(duì)應(yīng)位移控制系統(tǒng)的輸入,CUP對(duì)應(yīng)著系統(tǒng)的程序部分,超聲波測(cè)距對(duì)應(yīng)著反饋部分。驅(qū)動(dòng)部分接收來(lái)自MCU的命令,通過(guò)ENA的PWM的占空比以調(diào)節(jié)小車的行進(jìn)。直流電機(jī)控制著傳動(dòng)系統(tǒng),驅(qū)動(dòng)小車的位移。具體的連線圖參考圖2.3.
按鍵模塊接收輸入信息和控制命令,系統(tǒng)通過(guò)測(cè)距模塊采集距離信息,經(jīng)過(guò)反饋算法之后,將通過(guò)ENA、IN1和IN2的狀態(tài)自動(dòng)控制直流電機(jī)轉(zhuǎn)動(dòng)等,最終使得小車的行進(jìn)距離與輸入值相等。
圖2.3 電路連線圖
一、 電機(jī)驅(qū)動(dòng)
1、 模塊簡(jiǎn)介該模塊主控芯片為L(zhǎng)298N,一種雙H橋電機(jī)驅(qū)動(dòng)芯片,其中每個(gè)H橋可以提供2A的電流,功率部分的供電電壓范圍是2.5-48v,邏輯部分5v供電,接受5vTTL電平。其實(shí)質(zhì)類似于一個(gè)單刀雙擲開(kāi)關(guān),不過(guò)能夠提供較大的電流。 該模塊共有13個(gè)接口,此次項(xiàng)目將會(huì)使用到的共有8個(gè):兩個(gè)使能接口IN1、IN2,12V供電接口,GND接口,5V電源接口,驅(qū)動(dòng)接口C、D,PWM控制接口ENA。本系統(tǒng)中12V供電接口接入的是9V電池,作為整個(gè)系統(tǒng)的供電;5V接口作為電源輸出為單片機(jī)及其它外設(shè)供電;C、D接口與直流電機(jī)相連,當(dāng)IN1、IN2接口接入的數(shù)值是10時(shí),電機(jī)正轉(zhuǎn),01電機(jī)反轉(zhuǎn),00及11電機(jī)不轉(zhuǎn)。 表3.1 L298N控制 2、功能實(shí)現(xiàn)控制小車行進(jìn)速度的方法就是,通過(guò)調(diào)節(jié)控制接口ENA的PWM波占空比,來(lái)控制電機(jī)轉(zhuǎn)動(dòng)與否以及時(shí)長(zhǎng),如此控制小車的勻速減速等工作狀態(tài)。 這里使用定時(shí)器來(lái)實(shí)現(xiàn)PWM波的輸出:每當(dāng)定時(shí)時(shí)間來(lái)臨,計(jì)數(shù)單位加一,達(dá)到一百就置零;而當(dāng)計(jì)數(shù)單位小于占空比時(shí),PWM輸出口置1,否則清零。代碼參考附錄L298N.c。
二、 超聲波測(cè)距
1、模塊簡(jiǎn)介選用常見(jiàn)的HC-SR04超聲波模塊,該模塊使用直流5.0V供電,可探測(cè)距離為2cm-450cm,精度能夠達(dá)到0.2cm,各參數(shù)基本符合此次項(xiàng)目的設(shè)計(jì)。該模塊共有四個(gè)接口,其中VCC、GND為電源接口,TRIG控制接口、Echo為數(shù)據(jù)接口。 使用步驟有三: (1) 觸發(fā)測(cè)距:IO口TRIG觸發(fā),至少給10us的高電平信號(hào); (2) 模塊內(nèi)部自動(dòng)發(fā)送8個(gè)40KHz的方波,自動(dòng)檢測(cè)是否有信號(hào)返回; (3) 有信號(hào)返回,Echo輸出一個(gè)高電平,高電平持續(xù)的時(shí)間就是超聲波從發(fā)射到接收的時(shí)間。 可以根據(jù)超聲波傳輸?shù)臅r(shí)間計(jì)算出測(cè)量的距離: 2 t即為高電平持續(xù)的時(shí)間,c為聲速340m/s。 2、功能實(shí)現(xiàn)程序里,利用外部中斷來(lái)接受來(lái)自Echo的高電平,上升沿定時(shí)器1開(kāi)始計(jì)數(shù),下降沿定時(shí)器計(jì)數(shù)結(jié)束。將計(jì)數(shù)時(shí)間乘以音速,再除以2便可得到測(cè)距的結(jié)果。 值得注意的是:此超聲波測(cè)距模塊測(cè)得的距離并不是那么準(zhǔn)確,導(dǎo)致前后數(shù)據(jù)的差值較大。鑒于此,在獲得距離之前,先進(jìn)行五次測(cè)距,取它們的平均值作為當(dāng)前測(cè)得的距離。另外這部分的重要性是毋庸置疑的,在實(shí)驗(yàn)過(guò)程之初,沒(méi)有進(jìn)行均值濾波之前,小車在到達(dá)目標(biāo)1cm左右的位置時(shí),小車會(huì)來(lái)回的抖動(dòng)。一方面是由于當(dāng)時(shí)控制的頻率太高,而另一方面正是由于測(cè)得的距離有著十足的誤差。代碼請(qǐng)參考附錄wave.c。
三、 控制算法為了實(shí)現(xiàn)速度的閉環(huán)控制,這里使用了業(yè)內(nèi)常常使用到了PID算法來(lái)控制PWM波的占空比,通過(guò)對(duì)偏差的比例、積分、微分進(jìn)行控制,使偏差趨于零的過(guò)程。 系統(tǒng)每隔1ms進(jìn)行一次采樣,之后進(jìn)行一次PID算法。 PID控制一般有兩種寫(xiě)法,一個(gè)是位置式,另一個(gè)是增量式。位置式需要進(jìn)行累加的操作,而此系統(tǒng)的主控芯片為IAP15F2K61S2,其存儲(chǔ)與計(jì)算能力一般,于是這里采用增量式。 增量式程序: //PID控制 //move 與 deta的關(guān)系,最終使得 move = objective if(caiyang_FLAG_) { deta_ID[2]=deta;//采樣 PWM_deta=Kp*(deta_ID[2]-deta_ID[1])+Ki*deta_ID[2]+Kd*(deta_ID[2]-2*deta_ID[1]+deta_ID[0]); PWM_ID[1]= PWM_ID[0]+PWM_deta; PWM=(uint)PWM_ID[1]; //準(zhǔn)備下一輪控制 PWM_ID[0]=PWM_ID[1]; deta_ID[0]=deta_ID[1]; deta_ID[1]=deta_ID[2]; } if(deta>0) Z_F= 1; else Z_F= 2; mada(); 此外,為了解決系統(tǒng)到達(dá)位置之后的原地抖動(dòng)問(wèn)題,以及消除到達(dá)之后受到人為遮擋會(huì)引起小車強(qiáng)烈反應(yīng)的情況。又引入了消抖算法:小車位于指定位置±0.5cm的距離1秒鐘以上時(shí),視為調(diào)節(jié)結(jié)束,小車停止運(yùn)動(dòng)。這里使用定時(shí)器來(lái)確定一秒的時(shí)間。 代碼如下: START是能直接控制小車是否運(yùn)動(dòng)的標(biāo)志,STOP是記錄小車能否保持±0.5cm的標(biāo)志。 if(deta<= 0.5 && deta >= -0.5) sanmiao = 1; //一旦deta的絕對(duì)值小于0.5,電機(jī)暫停控制 if(sanmiao == 1) { if(deta > 0.5 ||deta < -0.5) {//跳出暫停 STOP = 0; sanmiao_flag =0; sanmiao = 0; } else { STOP = 1; } } 定時(shí)器處理函數(shù)里面: if(sanmiao== 1 ) { if(sanmiao_flag++ == 10000) { sanmiao_flag = 0; sanmiao = 0; if(STOP == 1) START = 0; } } 四、 其他功能模塊1、4*4按鍵模塊:4*4矩陣功能如下: 1 2 3 A 4 5 6 B 7 8 9 C * 0 # D, 其中A按鍵控制讀入初始距離,B按鍵一鍵開(kāi)始,C按鍵停止運(yùn)動(dòng),D按鍵切換前進(jìn)后退,*按鍵重新輸入,#按鍵確認(rèn)輸入,各數(shù)字按鍵進(jìn)行數(shù)字讀入。
2、 電源模塊由于小車需要移動(dòng),系統(tǒng)必須使用移動(dòng)電源。而普通電池電量不夠充足,而且質(zhì)量太大,影響電機(jī)的運(yùn)轉(zhuǎn)。故系統(tǒng)使用一節(jié)9V可充電電池供電,利用L298N的5V電源接口給單片機(jī)及其外設(shè)供電,電機(jī)驅(qū)動(dòng)模塊使用9V供電。
3、 顯示模塊顯示部分使用LCD1602液晶顯示屏,也叫1602字符型液晶,它是一種專門(mén)用來(lái)顯示字母、數(shù)字、符號(hào)等的點(diǎn)陣型液晶模塊。它由若干個(gè)5X7或者5X11等點(diǎn)陣字符位組成。 共有16個(gè)接口,其中VSS、VDD、VO、A、K是電源接口,VSS、K接單片機(jī)的GND,VDD、A接單片機(jī)的VCC,VO接上變阻器;RS、RW、EN作為使能接口;其余8個(gè)引腳作為數(shù)據(jù)接口,以便顯示不同的ASCII或者自定義的字符。 實(shí)驗(yàn)中顯示初始距離、設(shè)定位移、當(dāng)前距離以及實(shí)時(shí)誤差。
單片機(jī)源程序如下:
- /*******
- 位移控制系統(tǒng)設(shè)計(jì):小車
- 設(shè)計(jì)編寫(xiě):汪佳鋅
- 開(kāi)始時(shí)間:2019/6/4
- 結(jié)束時(shí)間:2019/6/8
- 最終時(shí)間:2019/6/8
- 功 能:按鍵輸入指定位移,小于4米;
- 小車行進(jìn)到指定距離(位置);
- 使用模塊:矩陣按鍵、超聲波、電機(jī)驅(qū)動(dòng)、顯示模塊;
- KBD_key.c\wave.c\L298N.c\LCD1602.c
- 按鍵功能:按鍵A:位置初始化;
- 數(shù)字按鍵 1,2,3,4,5,6,7,8,9,0:輸入數(shù)字,百十個(gè)CM
- 按鍵#:確認(rèn)輸入;
- 按鍵*:重新輸入;
- 按鍵A:位置初始化;
- 按鍵B:一鍵開(kāi)始;
- 按鍵C:手動(dòng)停止;
- 按鍵D: '+'/'-';
- 1、2、3、A
- 4、5、6、B
- 7、8、9、C
- *、0、#、D
- 顯示區(qū)域:1:
- 2:
- *******/
- #include <STC15F2K60S2.h>
- #include <intrins.h>
- #include "timer0.h"
- #include "L298N.h"
- #include "wave.h"
- #include "LCD1602.h"
- #include "KBD_keys.h"
- #define MAX 400
- //#ifndef uchar
- //typedef unsigned char uchar;
- //#endif
- //#ifndef uchar
- //typedef unsigned int uint;
- //#endif
- enum keyState {state0,state1,state2};
- bit key_FLAG_=1,mada_FLAG_=0,caiyang_FLAG_,wave_FLAG_,dsp_FLAG_,//定時(shí)器FLAG
- QJ_HT=1,//前進(jìn)、后退
- sanmiao=1,//一秒消抖
- STOP=0, //一秒消抖就停止運(yùn)動(dòng)
- START=0; //開(kāi)始、停止
- uint key_flag=0,countB=0,caiyang_flag,wave_flag,dsp_flag,
- sanmiao_flag,
- T; //超聲波測(cè)距返回的時(shí)間
- uchar Z_F, //馬達(dá)的狀態(tài):0代表停,1正轉(zhuǎn),2反轉(zhuǎn);
- key_value=44, //指按下了哪個(gè)按鍵;
- add=0, //按鍵的指針,三位數(shù) 150、010、007
- PWM=0; //0~100表示占空比
- uchar aim[]={0,0,0}; //按鍵的輸入
- float distance_caiyang=0,
- deta=20, // -------------------------- 墻壁
- //deta = 當(dāng)前位置-目標(biāo)位置,也是程序的控制對(duì)象 ---------------- d 終點(diǎn) 目標(biāo)位置distance_aim
- distance=0, //當(dāng)前位置 o d i
- distance_init=0, //初始位置 b eta s
- distance_aim=0, //目標(biāo)位置=初始位置-目標(biāo)位移 j ^--^ tance 現(xiàn)在 當(dāng)前位置
- objective=0; //目的位移CM e |
- // ctive |
- //使用PID算法:P比例,I微分,D積分; -------------------------- 起點(diǎn) 初始位置distance_init
- float deta_ID[3]; //用于微分和積分
- float PWM_deta,Kp,Ki,Kd,zhongjian;
- uchar PWM_ID[2];
- void display(void);
- void control();
- void main()
- {
- uchar p=0;
-
- Kp = 0.06;
- Ki = 0.25;
- Kd = 0.01;
- deta_ID[0]=deta_ID[1]=0;
- PWM_ID[0]=0;
-
- Timer0_init();
- LCD_init();
- while(1)
- {
- //按鍵掃描,
- if(key_FLAG_)
- {
- key_FLAG_ = 0;
- key_value = key_scan();
- if(key_value != 44)
- {
- key_hand(key_value);
- }
- }
- //測(cè)距,六次取平均值
- if(wave_FLAG_)
- {
- wave_FLAG_ = 0;
- send_wave();
- zhongjian += distance_caiyang;
- if(p++ == 5)
- {
- distance=zhongjian/6;
- zhongjian = 0;
- p=0;
- }
- }
- //顯示
- if(dsp_FLAG_)
- {
- dsp_FLAG_ = 0;
- display();
- }
- //電機(jī)控制
- control();
- // PWM = 50;
- // Z_F = 1;
- mada();
- }
- }
- void control()
- {
- distance_aim = distance_init - objective;
- deta = distance-distance_aim;
- //deta = distance-distance_init+objective;
- if(START == 1 && objective <= MAX && objective >= -MAX)
- {
- //控制部分
- if(deta <= 0.5 && deta >= -0.5)
- sanmiao = 1;
- //一旦deta的絕對(duì)值小于0.5,電機(jī)暫停控制
- if(sanmiao == 1)
- {
- if(deta > 0.5 || deta < -0.5)
- {//跳出暫停
- STOP = 0;
- sanmiao_flag = 0;
- sanmiao = 0;
- }
- else
- {
- STOP = 1;
- }
- }
- else//
- {
- //分段控制
- if(deta >= 100)
- { PWM = 70;Z_F = 1;}
- else if(deta >= 50)
- { PWM = 50;Z_F = 1;}
- else if(deta >= 10)
- { PWM = 30;Z_F = 1;}
- else if(deta > 5)
- { PWM = 10;Z_F = 1;}
- else if(deta > 0.5)
- { PWM = 5;Z_F = 1;}
- else if(deta >= -0.5 && deta <= 0.5)
- { //START = 0;
- PWM = 0;Z_F = 0;}
- else if(deta >= -5)
- { PWM = 5 ;Z_F = 2;}
- else if(deta >= -10 && deta < -5)
- { PWM = 10;Z_F = 2;}
- else if(deta >= -50)
- { PWM = 30;Z_F = 2;}
- else if(deta >= -100)
- { PWM = 50;Z_F = 2;}
- else
- { PWM = 70;Z_F = 2;}
- //PID控制
- //move 與 deta的關(guān)系,最終使得 move = objective
- // if(caiyang_FLAG_)
- // {
- // deta_ID[2]=deta;//采樣
- //
- // PWM_deta=Kp*(deta_ID[2]-deta_ID[1])+Ki*deta_ID[2]+Kd*(deta_ID[2]-2*deta_ID[1]+deta_ID[0]);
- //
- // PWM_ID[1] = PWM_ID[0]+PWM_deta;
- // PWM=(uint)PWM_ID[1];
- // //準(zhǔn)備下一輪控制
- // PWM_ID[0]=PWM_ID[1];
- // deta_ID[0]=deta_ID[1];
- // deta_ID[1]=deta_ID[2];
- // }
- // if(deta>0)
- // Z_F = 1;
- // else
- // Z_F = 2;
-
- }
- }
- else
- {
- Z_F = 0;
- ENB = 0;
- ENA = 0;
- }
- //一秒無(wú)變化,停止運(yùn)動(dòng)
-
- }
- void key_hand(uchar key_value)
- {
- switch(key_value)
- {
- case 1:
- case 2:
- case 3:aim[add]=key_value;add++;break;
- case 4:distance_init = distance;break;
-
- case 5:
- case 6:
- case 7:aim[add]=key_value-1;add++;break;
- case 8:START = 1;
- sanmiao = 0; //開(kāi)始、停止
- objective = aim[0]*100+aim[1]*10+aim[2]; //確認(rèn)輸入
- if(QJ_HT == 0)//后退
- {
- objective = -objective;}
- distance_init = distance; //位置初始化
- break;//
-
- case 9:
- case 10:
- case 11:aim[add]=key_value-2;add++;break;
- case 12:START = 0;
- break;
-
- case 13:aim[0]=aim[1]=aim[2]=0;add=0;QJ_HT = 1;break;//重新輸入
- case 14:aim[add]=0;add++;break;
- case 15:objective = aim[0]*100+aim[1]*10+aim[2];//確認(rèn)輸入
- if(QJ_HT == 0)//后退
- { objective = -objective;}
- break;
- case 16:QJ_HT = ~QJ_HT;break; //輸入前進(jìn)或后退
- default:break;
- }
- if(add == 3)
- add = 0;
- }
- void display()
- {
- LCD_write_com(0x80);
- if(START == 1)
- LCD_write_data('T');
- else
- LCD_write_data('P');
- LCD_write_data(':');
- display_32(distance_init);
- LCD_write_data(' ');
- if(QJ_HT == 1)
- LCD_write_data('+');
- else
- LCD_write_data('-');
- LCD_write_data('0'+aim[0]);
- LCD_write_data('0'+aim[1]);
- LCD_write_data('0'+aim[2]);
- LCD_write_data('C');
- LCD_write_data('M');
- Delayms(1);
-
- LCD_write_com(0x80+0x40);
- if(objective >MAX || objective < -MAX)
- {
- LCD_write_string(2,1,"INPUT ERROR! ");
- }
- else
- {
- display_32(distance);
- LCD_write_data(' ');
- display_32(deta);
- }
- Delayms(1);
- }
- void Timer0_handle(void) interrupt 1
- {
- if(sanmiao == 1 )
- {
- if(sanmiao_flag++ == 10000)
- {
- sanmiao_flag = 0;
- sanmiao = 0;
- if(STOP == 1)
- START = 0;
- else
- START = 1;
- }
- }
- if(dsp_flag++ == 30) //LCD顯示3ms
- {
- dsp_FLAG_=1;
- dsp_flag =0;
- ……………………
- …………限于本文篇幅 余下代碼請(qǐng)從51黑下載附件…………
復(fù)制代碼
0.png (9.29 KB, 下載次數(shù): 29)
下載附件
2019-6-20 04:10 上傳
所有資料51hei提供下載:
工程程序.rar
(65.19 KB, 下載次數(shù): 26)
2019-6-19 21:00 上傳
點(diǎn)擊文件名下載附件
工程程序 下載積分: 黑幣 -5
|