<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計(jì)應(yīng)用 > 基于51單片機(jī)的六足仿生機(jī)器人

          基于51單片機(jī)的六足仿生機(jī)器人

          作者: 時(shí)間:2018-08-06 來源:網(wǎng)絡(luò) 收藏

          一、整體框架:

          (1)設(shè)計(jì)功能:

          本文引用地址:http://www.ex-cimer.com/article/201808/385490.htm

          ①能完成多方向行走以及其他的自定義的動(dòng)作。(前進(jìn),后撤,左右轉(zhuǎn),避障);

          ②可自動(dòng)避障;

          ③通過手機(jī)藍(lán)牙下令他的下一步動(dòng)作。

          (2)功能框架:


          (3)使用器材:

          ①STC89C52單片機(jī)、74LS04(反相器);

          ②藍(lán)牙串口通信模塊;

          ③超聲波測(cè)距模塊;

          ④9G舵機(jī)18個(gè);

          ⑤PVC線槽若干(模具);

          ⑥PCB轉(zhuǎn)印板;

          ⑦螺絲螺母若干。

          ⑦keil3軟件

          二、工作原理:

          (1)藍(lán)牙串口通訊模塊:

          藍(lán)牙串口通訊模塊接收手機(jī)藍(lán)牙軟件發(fā)送字符串信號(hào),單片機(jī)通過串口通訊協(xié)議處理藍(lán)牙模塊接收到的信息,再根據(jù)信息的內(nèi)容來判斷機(jī)器人將進(jìn)行的下一步行動(dòng)。

          (2)超聲波測(cè)距模塊:

          超聲波模塊向某一方向發(fā)射超聲波,在發(fā)射時(shí)刻的同時(shí)開始計(jì)時(shí)(傳出低電平),超聲波在空氣中傳播,途中碰到障礙物就立即返回來,超聲波接收器收到反射波就立即停止計(jì)時(shí)(回到高電平),根據(jù)低電平的長短來計(jì)算測(cè)量距離。(超聲波在空氣中的傳播速度為340m/s,根據(jù)計(jì)時(shí)器記錄的時(shí)間t,就可以計(jì)算出發(fā)射點(diǎn)距障礙物的距離(s),即:s=340t/2)

          (3)舵機(jī)控制:

          控制電路板接受來自信號(hào)線的控制信號(hào),控制電機(jī)轉(zhuǎn)動(dòng),電機(jī)帶動(dòng)一系列齒輪組,減速后傳動(dòng)至輸出舵盤。舵機(jī)的輸出軸和位置反饋電位計(jì)是相連的,舵盤轉(zhuǎn)動(dòng)的同時(shí),帶動(dòng)位置反饋電位計(jì),電位計(jì)將輸出一個(gè)電壓信號(hào)到控制電路板,進(jìn)行反饋,然后控制電路板根據(jù)所在位置決定電機(jī)轉(zhuǎn)動(dòng)的方向和速度,從而達(dá)到目標(biāo)停止。舵機(jī)的控制信號(hào)周期為20MS的脈寬調(diào)制(PWM)信號(hào),其中脈沖寬度從0.5-2.5MS,相對(duì)應(yīng)的舵盤位置為0-180度,呈線性變化。也就是說,給他提供一定的脈寬,它的輸出軸就會(huì)保持一定對(duì)應(yīng)角度上,無論外界轉(zhuǎn)矩怎么改變,直到給它提供一個(gè)另外寬度的脈沖信號(hào),它才會(huì)改變輸出角度到新的對(duì)應(yīng)位置上。

          在我們的作品中,18路舵機(jī)分成2組,分別用一個(gè)內(nèi)部定時(shí)器來控制,產(chǎn)生對(duì)應(yīng)舵機(jī)的PWM信號(hào)(首先定時(shí)器1生成第一個(gè)舵機(jī)的脈寬,再生成第二個(gè)舵機(jī)的,到第9個(gè)舵機(jī)為止,然后定時(shí)器2以同樣方式生成剩余的9個(gè)舵機(jī)的PWM信號(hào),以此往復(fù))。

          三、制作過程:

          (1)仿真原理圖:


          (2)PCB制作:


          (3)硬件搭建:

          《a》肢體制作:

          材料:PVC線槽,PVC板

          ①模型制作:(純手工割出來的)


          ②舵機(jī)改造:


          ③整體:


          四、調(diào)試以及問題解決:

          ①結(jié)構(gòu)問題:

          我們認(rèn)為,整體的外形結(jié)構(gòu)是決定作品成敗的關(guān)鍵。經(jīng)過多種材料的試驗(yàn),最終我們選擇了容易裁剪、硬度基本滿足的PVC線槽來改裝拼接肢體,軀體使用更厚的塑料板。經(jīng)歷一周的純手工加工改造后,完成了整個(gè)模型的制作。

          ②供電問題:

          由于我們使用的是9G舵機(jī),性能較差,扭力不夠,無法支撐起我們?cè)O(shè)計(jì)的電源與穩(wěn)壓模塊,最后放棄了內(nèi)嵌的電源,使用實(shí)驗(yàn)室的可調(diào)電源箱通過電線來供電,無法獨(dú)立開來也是我們的唯一遺憾。

          ③機(jī)器抖動(dòng)問題

          由于89C52只有6個(gè)內(nèi)部中斷,遠(yuǎn)遠(yuǎn)無法滿足18個(gè)舵機(jī)的控制,并且其他功能模塊也要使用到內(nèi)部中斷。所以我們將18路舵機(jī)分成了2組,初始時(shí)一個(gè)接一個(gè)舵機(jī)(每個(gè)舵機(jī)20ms周期)來發(fā)送PWM,但這也產(chǎn)生了發(fā)送一次18路PWM的總周期長度太大(18*20=360ms),足以產(chǎn)生被人眼所察覺的抖動(dòng)。經(jīng)過反復(fù)研究,讓當(dāng)前舵機(jī)的PWM信號(hào)在上一個(gè)PWM信號(hào)的低電平處開始產(chǎn)生高電平(在上一個(gè)PWM的高電平結(jié)束后)如下圖,大大縮短了18路舵機(jī)一次動(dòng)作的總周期長度(經(jīng)過18路后,總周期長度為一個(gè)PWM的周期長度約20ms),使抖動(dòng)無法被人眼所觀察。

          代碼挺多,給出主要的舵機(jī)控制代碼,代碼看不懂沒關(guān)系,后面有解釋:

          #include《reg52.h》

          #include《intrins.h》

          #include《dongzuo.h》

          #define ucharunsigned char

          #define uintunsigned int

          //PWM

          sbit PWM0 = P1^0;

          sbit PWM1 = P1^1;

          sbit PWM2 = P1^2;

          sbit PWM3 = P1^3;

          sbit PWM4 = P1^4;

          sbit PWM5 = P1^5;

          sbit PWM6 = P3^4;

          sbit PWM7 = P3^5;

          sbit PWM8 = P3^6;

          sbit PWM9 = P3^7;

          sbit PWM10 = P2^0;

          sbit PWM11 = P2^1;

          sbit PWM12 = P2^2;

          sbit PWM13 = P2^3;

          sbit PWM14 = P2^4;

          sbit PWM15 = P2^5;

          sbit PWM16 = P2^6;

          sbit PWM17 = P2^7;

          //超聲波測(cè)距

          sfr T2MOD = 0XC9; //定時(shí)器2模式控制寄存器地址

          sbit Trig =P3^2;

          sbit Echo =P3^3;

          unsigned intdistance;

          uchar DZCS =0x11; //控制動(dòng)作

          uchar buf;

          uchar sd=3;

          bit flag=0; //是否發(fā)送字符

          bit CSB =0; //超聲波啟動(dòng)控制位

          bit HZ=0; //后退后左轉(zhuǎn)控制位

          uchar PWMscan =0;

          uchar PWMscan1 =0;

          uchar PWMval[]={//初始姿態(tài)

          0xf8,0x8f,0xf7,0x05,0xf9,0x8c,/*5*/ 0xfa,0x0d,0xf8,0x0b,0xf9,0x67,/*b*/ 0xfa,0xd4,0xf7,0x94,0xf9,0xcb,/*11*/

          0xfa,0xad,0xfc,0xdd,0xfb,0x58,/*17*/ 0xfa,0xe9,0xfc,0xfc,0xfb,0x39,/*1d*/ 0xfc,0x18,0xfc,0xca,0xfb,0x00/*23*/

          };

          void delay(uint a)

          {

          uchar j;

          for(a;a》0;a--)

          for(j=0;j《112;j++)

          ;

          }

          void task00()

          {

          if(PWMscan==1) //第1路PWM。

          {

          PWM0=1;

          TH0=PWMval[0];

          TL0=PWMval[1];

          }

          else if(PWMscan==2) //第2路PWM。

          {

          PWM0=0;

          PWM1=1;

          TH0=PWMval[2];

          TL0=PWMval[3];

          }

          else if(PWMscan==3) //第3路PWM。

          {

          PWM1=0;

          PWM2=1;

          TH0=PWMval[4];

          TL0=PWMval[5];

          }

          else if(PWMscan==4) //第4路PWM。

          {

          PWM2=0;

          PWM3=1;

          TH0=PWMval[6];

          TL0=PWMval[7];

          }

          else if(PWMscan==5) //第5路PWM。

          {

          PWM3=0;

          PWM4=1;

          TH0=PWMval[8];

          TL0=PWMval[9];

          }

          else if(PWMscan==6) //第6路PWM。

          {

          PWM4=0;

          PWM5=1;

          TH0=PWMval[10];

          TL0=PWMval[11];

          }

          else if(PWMscan==7) //第7路PWM。

          {

          PWM5=0;

          PWM6=1;

          TH0=PWMval[12];

          TL0=PWMval[13];

          }

          else if(PWMscan==8) //第8路PWM。

          {

          PWM6=0;

          PWM7=1;

          TH0=PWMval[14];

          TL0=PWMval[15];

          }

          else if(PWMscan==9) //第9路PWM。

          {

          PWM7=0;

          PWM8=1;

          TH0=PWMval[16];

          TL0=PWMval[17];

          }

          else if(PWMscan==10) //給一定低電平,將周期拉長

          {

          PWM8=0;

          TH0=0xFF;

          TL0=0xd2;

          PWMscan=0;

          TR0 = 0; //關(guān)定時(shí)器0,開定時(shí)器1

          TR1 = 1;

          }

          PWMscan++;

          }

          void task01()

          {

          if(PWMscan1==1) //第10路PWM。

          {

          PWM9=1;

          TH1=PWMval[18];

          TL1=PWMval[19];

          }

          else if(PWMscan1==2) //第11路PWM。

          {

          PWM9=0;

          PWM10=1;

          TH1=PWMval[20];

          TL1=PWMval[21];

          }

          else if(PWMscan1==3) //第12路PWM。

          {

          PWM10=0;

          PWM11=1;

          TH1=PWMval[22];

          TL1=PWMval[23];

          }

          else if(PWMscan1==4) //第13路PWM。

          {

          PWM11=0;

          PWM12=1;

          TH1=PWMval[24];

          TL1=PWMval[25];

          }

          else if(PWMscan1==5) //第14路PWM。

          {

          PWM12=0;

          PWM13=1;

          TH1=PWMval[26];

          TL1=PWMval[27];

          }

          else if(PWMscan1==6) //第15路PWM。

          {

          PWM13=0;

          PWM14=1;

          TH1=PWMval[28];

          TL1=PWMval[29];

          }

          else if(PWMscan1==7) //第16路PWM。

          {

          PWM14=0;

          PWM15=1;

          TH1=PWMval[30];

          TL1=PWMval[31];

          }

          else if(PWMscan1==8) //第17路PWM。

          {

          PWM15=0;

          PWM16=1;

          TH1=PWMval[32];

          TL1=PWMval[33];

          }

          else if(PWMscan1==9) //第18路PWM。

          {

          PWM16=0;

          PWM17=1;

          TH1=PWMval[34];

          TL1=PWMval[35];

          }

          else if(PWMscan1==10) //給一定低電平,將周期拉長

          {

          PWM17=0;

          TH1=0xFf;//b1 //這是一個(gè)大概的值,由于每一組的PWMval的總和(PWMval中定時(shí)器的間隔的總和就是一個(gè)周期)不一致,

          //所以會(huì)導(dǎo)致周期不一定是20ms,但大概可以控制在20ms左右,也是因?yàn)橹芷诘牟还潭ǎ圆判枰?/p>

          TL1=0xd2;//e0 //調(diào)整每一個(gè)舵機(jī)的實(shí)際的占空比。

          PWMscan1=0;

          TR0 = 1;//開定時(shí)器0

          TR1 = 0;//關(guān)定時(shí)器1

          }

          PWMscan1++;

          }

          void TImer0()interrupt 1

          {

          task00();//控制前9路PWM

          }

          void TImer1()interrupt 3

          {

          task01();//控制后9路PWM

          }

          在實(shí)際過程中,或許是由于舵機(jī)的質(zhì)量問題,又或者是其他問題,舵機(jī)的角度控制總是難以運(yùn)用原理上的公式來控制角度,都是實(shí)際操作,手動(dòng)調(diào)整高電平的寬度,當(dāng)達(dá)到合適的值的時(shí)候,然后再把相應(yīng)的代碼記錄下來。

          單片機(jī)的高電平寬度是通過定時(shí)器的兩個(gè)寄存器控制的,所以操作舵機(jī)的轉(zhuǎn)動(dòng)就變成操作定時(shí)器的寄存器,再具體一點(diǎn)就是要得到TH、TL兩個(gè)值。(定時(shí)器高低位的差值對(duì)應(yīng)高電平的寬度)

          在代碼上,在控制第幾路舵機(jī)的時(shí)候,TH、TL的值已經(jīng)定死了為哪一個(gè)PWMval[?],比如第18路:

          TH1=PWMval[34];

          TL1=PWMval[35];

          這將決定此時(shí)第18路舵機(jī)的轉(zhuǎn)動(dòng)角度是多少,那么怎么控制下一次該舵機(jī)的轉(zhuǎn)動(dòng)角度呢?答案很簡單,就是把PWMval[34];PWMval[35];的值修改一下就可以了,其他的舵機(jī)同樣是這個(gè)道理。所以,機(jī)器人的一個(gè)姿態(tài)就可以變?yōu)檫@樣:機(jī)器人姿態(tài)→18路舵機(jī)的角度→18個(gè)TH、TL的值→一個(gè)36個(gè)元素的數(shù)組PWMval的值。

          所以,一個(gè)動(dòng)作姿態(tài)就可以用這樣一個(gè)函數(shù)來確定:

          void DZ(ucharPWM[])//動(dòng)作

          {

          uchar i;

          for(i=0;i《36;i++)

          PWMval[i]=PWM[i];

          }

          明白了這個(gè)之后,就是對(duì)每一個(gè)姿態(tài)收集數(shù)據(jù)了,在制作過程,我是把TH和TL的兩個(gè)值顯示在數(shù)碼管上,然后記錄下來的。

          后面又加入了藍(lán)牙控制模塊,超聲波測(cè)距,發(fā)現(xiàn)的定時(shí)器不太夠用,改成了52系列的單片機(jī),還一個(gè)定時(shí)器即用藍(lán)牙模塊,又用超聲波測(cè)距,現(xiàn)在想來真佩服自己。給出控制代碼,大家自行研究:

          //***************************中斷初始化**************************

          void Init()

          {

          TMOD |= 0x11;//定時(shí)器0、1

          ET0 = 1;//使能定時(shí)器0中斷

          TR0 = 1;//開啟定時(shí)器0,定時(shí)器1中斷在定時(shí)器0開始后才打開

          ET1 = 1;//使能定時(shí)器1中斷

          IT1 = 0;//外部中斷1,低電平觸發(fā) (邊沿高變低)

          EX1 = 1;//開外部中斷1

          //定時(shí)器2用于波特率的產(chǎn)生

          SCON=0x50;

          PCON=0x00;

          RCAP2H=0xFF;

          RCAP2L=0xDC;//設(shè)置波特率為9600

          T2CON=0x34;//將定時(shí)器2設(shè)置為波特率發(fā)生器(接收和發(fā)送都用TImer2) //此處包括啟動(dòng)T2

          ES=1; //串口中斷

          EA = 1;//開總中斷

          }

          void TImer0()interrupt 1

          {

          task00();//控制前9路PWM

          }

          void timer1()interrupt 3

          {

          task01();//控制后9路PWM

          }

          void serial() interrupt 4

          {

          EA=0; //其余中斷全停

          if(RI)

          {

          RI=0; //清除串行接受標(biāo)志位

          flag=1;

          buf=SBUF; //從串口緩沖區(qū)取得數(shù)據(jù) (i-0x30)將ASCLL碼轉(zhuǎn)換成數(shù)字

          switch(buf)

          {

          case 0x00: DZCS=0x00;break; //向前走

          case 0x01: DZCS=0x01;break; //向后走

          case 0x02: DZCS=0x02;break; //左轉(zhuǎn)

          case 0x03: DZCS=0x03;break; //右轉(zhuǎn)

          case 0x04: DZCS=0x04;break; //橫著左

          case 0x05: DZCS=0x05;break; //橫著右

          case 0x06: DZCS=0x06;break; //揮爪子

          case 0x07: sd++;break; //減速,其實(shí)就是每個(gè)姿態(tài)中的延時(shí)不一樣

          case 0x08: sd--;break; //加速

          case 0xff: CSB=!CSB;break; //啟動(dòng)關(guān)閉超聲波壁障

          default:

          DZCS=0x11;break; //

          }

          }

          EA = 1; //打開總中斷

          }

          void start()// 超聲波測(cè)距啟動(dòng)函數(shù)

          {

          uchar i;

          Trig=1;

          for(i=0;i《20;i++)

          {

          _nop_();

          }

          Trig=0;

          }

          void count()// 超聲波測(cè)距函數(shù)

          {

          unsigned int time,timeH,timeL;

          timeH=TH1;

          timeL=TL1;

          time=timeH*256+timeL;

          distance=time*1.7/100;

          }

          void Inter()interrupt 2//外部中斷1在次完成測(cè)距以及相應(yīng)的后續(xù)操作

          {

          EA =0;

          ET0=0; //關(guān)定時(shí)器中斷0

          TH1=0;

          TL1=0;

          TR1 =1; //檢測(cè)到距離開啟定時(shí)器1

          while(!Echo); //當(dāng)echo為零時(shí)等待,中斷flag跳出等待

          TR1 =0; //關(guān)閉定時(shí)器1

          count(); //計(jì)算距離

          if(((10《distance)(distance《30))||HZ) //當(dāng)距離小于5cm時(shí),變換動(dòng)作哦(在中斷中變換平面感應(yīng)

          {

          DZCS=0x02; //向左

          HZ=0;

          }

          if(distance《10) //當(dāng)距離小于10cm時(shí),變換動(dòng)作哦(在中斷中變換曲面感應(yīng)

          {

          DZCS=0x01; //后退

          HZ=1; //后退后左轉(zhuǎn)標(biāo)志

          }

          if(distance》30) //當(dāng)距離小于40cm時(shí),變換動(dòng)作哦(在中斷中變換

          {

          DZCS=0x00; //向前

          HZ=0;

          }

          TR1=1;

          ET0=1;

          EA = 1;

          }

          void main()

          {

          Init();

          while(1)

          {

          uchar DZCST;//,i;

          if(CSB)

          start();

          if(DZCST!=DZCS)//動(dòng)作發(fā)生改變,則回到平衡

          DZ(PH1);

          if(sd==0)

          sd=1;

          switch(DZCS)

          {

          case0x00:DZXQ(sd);break;

          case0x01:DZXH(sd);break;

          case0x02:DZXZ(sd);break;

          case0x03:DZXY(sd);break;

          case0x04:DZHZZ(sd);break;

          case0x05:DZHZY(sd);break;

          case0x06:DZZZ(sd);break;

          default:

          DZ(PH1);

          }

          DZCST=DZCS;

          }

          }

          『本文轉(zhuǎn)載自網(wǎng)絡(luò),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系刪除』



          關(guān)鍵詞: 51單片機(jī) MCU

          評(píng)論


          相關(guān)推薦

          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();