版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡介
第四章Boe-Bot機(jī)器人巡航控制與觸覺導(dǎo)航第一節(jié)Boe-Bot機(jī)器人巡航控制一、基本的機(jī)器人動作
圖4-1規(guī)定了機(jī)器人的前后左右四個方向,當(dāng)機(jī)器人向前走時,它的左輪會逆時針旋轉(zhuǎn),而右輪則順時針旋轉(zhuǎn),4-1Boe-Bot機(jī)器人及其驅(qū)動方向指示
當(dāng)機(jī)器人向前走時,它的左輪會逆時針旋轉(zhuǎn),而右輪則順時針旋轉(zhuǎn)。如果還沒有領(lǐng)會這一點(diǎn),觀察一下圖4-2,看能否使自己相信這是真的。從機(jī)器人的左邊看,當(dāng)它向前走時輪子是逆時針旋轉(zhuǎn)的;從右邊看另一個輪子則是順時針旋轉(zhuǎn)的。
圖4-2向前運(yùn)動時兩個輪子的旋轉(zhuǎn)
回憶一下前面內(nèi)容,PULSOUT命令的參數(shù)Duration控制了伺服電機(jī)旋轉(zhuǎn)的速度和方向。FOR…NEXT循環(huán)的參數(shù)StratValue和EndValue控制傳遞給電機(jī)的脈沖數(shù)量。由于每個脈沖的時間是相同的,因而EndValue也控制伺服電機(jī)運(yùn)行的時間。這個例子使機(jī)器人向前走三秒鐘。程序示例:'RoboticswiththeBoe-Bot-BoeBotForwardThreeSeconds.bs2'MaketheBoeBotrroolforwardforthreeseconds'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!:"counterVARWordFREQOUT4,2000,3000'Signalprogramstart/reset.FORcounter=1TO122'Runservosfor3secondsPULSOUT13,850PULSOUT12,650PAUSE20NEXTEND
該程序使機(jī)器人向前走了3秒鐘我們可以通過修改程序中的參數(shù)值,改變機(jī)器人的運(yùn)行時間,并將PULSOUT命令中的Duration參數(shù)值進(jìn)行修改,看看機(jī)器人的運(yùn)行速度,并以不同的組合實(shí)現(xiàn)機(jī)器人的行走不同方向,如向前、原地轉(zhuǎn)彎、繞軸轉(zhuǎn)彎等。PULSOUT13,650PULSOUT12,850向后走PULSOUT13,650PULSOUT12,750PULSOUT13,750PULSOUT12,850原地左轉(zhuǎn)原地右轉(zhuǎn)該你了調(diào)節(jié)距離和速度
將FOR…NEXT循環(huán)的EndValue參數(shù)值由122調(diào)到61,使機(jī)器人運(yùn)行時間是剛才的一半,運(yùn)行距離也是一半。程序示例,我們將各個方向組合在一起,命令機(jī)器人行走。'RoboticswiththeBoe-Bot-ForwardLeftRightBackward.bs2'Moveforward,left,right,thenbackwardfortestingandtuning.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!:"counterVARWordFREQOUT4,2000,3000'Signalprogramstart/reset.FORcounter=1TO64'ForwardPULSOUT13,850PULSOUT12,650PAUSE20NEXTPAUSE200FORcounter=1TO24'Rotateleft-about1/4turnPULSOUT13,650PULSOUT12,650PAUSE20NEXTPAUSE200FORcounter=1TO24'Rotateright-about1/4turnPULSOUT13,850PULSOUT12,850PAUSE20NEXTPAUSE200FORcounter=1TO64'BackwardPULSOUT13,650PULSOUT12,850PAUSE20NEXTEND該你了使機(jī)器人繞一個輪子旋轉(zhuǎn)。二、調(diào)整基本運(yùn)動
設(shè)想正寫一個程序使機(jī)器人全速向前運(yùn)動十五秒鐘。如果當(dāng)機(jī)器人應(yīng)該向前直線運(yùn)動時有輕微的向左或向右偏移怎么辦呢?不需要拆開機(jī)器人的后半部分并用螺絲刀重新調(diào)整電機(jī)。你可以簡單地修改程序使Boe-Bot的兩個輪子以相同的速度運(yùn)行。螺絲起子調(diào)節(jié)叫做“硬件調(diào)節(jié)”,程序調(diào)節(jié)叫做“軟件調(diào)節(jié)”。
當(dāng)Boe-Bot車用該向前走時,一組鉤長的距離來檢查它是否偏左或偏右,可以簡單的修改程序使Boe-Bot的兩個輪子以相同的速度運(yùn)行,程序示例,觀察在向前走的10秒鐘Boe-Bot是否偏移。表3-1PULSOUTDuration組合P13P12描述運(yùn)動狀況850650全速,P13電機(jī)逆時針,P12電機(jī)順時針
650850850850650650750850650750750750兩個電機(jī)都靜止,因?yàn)樵诘谒墓?jié)所做的中心點(diǎn)調(diào)整760740770730850700800650該你了
調(diào)整電機(jī)的速度使Boe-Bot的運(yùn)動軌跡是一條直線。Duration越接近750,點(diǎn)擊旋轉(zhuǎn)越慢,如果Boe-Bot輕微左偏,要么左輪太慢,要么右輪太快,但因?yàn)锽oe-Bot為全速行駛,因此可減小右輪速度,即使右輪的Duration接近750,要使Boe-Bot走直線必須作多次嘗試。更改程序,使Boe-Bot車向后走10秒鐘,重復(fù)直線運(yùn)動的測試。
我們可以通過調(diào)節(jié)Boe-Bot車旋轉(zhuǎn)期望的角度,用FOR….NEXT循環(huán)控制旋轉(zhuǎn)角度。這是程序ForwardLeftRightBackward.bs2的向左旋轉(zhuǎn)子程序。FORcounter=1TO24'Rotateleft-about1/4turnPULSOUT13,650PULSOUT12,750PAUSE20NEXT
比如說Boe-Bot轉(zhuǎn)動90°多一點(diǎn)的情況。試試FORcounter=1TO23,或者用偶數(shù)個循環(huán)FORcounter=1TO22。如果旋轉(zhuǎn)的角度不夠,可以增加FOR…NEXT循環(huán)的EndValue參數(shù)值來增加旋轉(zhuǎn)四分之一周所需的時間如果發(fā)現(xiàn)一個值使旋轉(zhuǎn)超過90°,而另一個使旋轉(zhuǎn)小于90°,嘗試選擇一個使其旋轉(zhuǎn)更多的值,然后稍微減小電機(jī)速度。在向左旋轉(zhuǎn)的情況下,兩個PULSOUT命令的Duration參數(shù)值都要從650改到接近750。在直線運(yùn)動中,這也是一個迭代法。該你了——90°旋轉(zhuǎn)
更改程序ForwardLeftRightBackward.bs2使其做精確的90°旋轉(zhuǎn)。
三、計(jì)算運(yùn)動距離我們知道:時間=距離/速度,可以用機(jī)器人做同樣的練習(xí),只要掌握了距離是多少,則
但這里必須要測試Boe-Bot車的速度,我們把Boe-Bot車放在尺子旁邊,讓Boe-Bot車向前走1秒鐘,測試Boe-Bot車走了多遠(yuǎn),得到它的速度。輸入、保存并運(yùn)行程序ForwardOneSecond.bs2。'RoboticswiththeBoe-Bot-ForwardOneSecond.bs2'MaketheBoe-Botrollforwardforonesecond.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!"counterVARWordFREQOUT4,2000,3000'Signalprogramstart/reset.FORcounter=1TO41PULSOUT13,850PULSOUT12,650PAUSE20NEXTEND
在前面的學(xué)習(xí)中,我們認(rèn)識到在一個FOR…NEXT循環(huán)中,每次執(zhí)行兩個電機(jī)的PULSOUT命令和一個PAUSE命令需要24.6ms(0.024s)的時間。此數(shù)的倒數(shù)就是每秒鐘傳遞給每個電機(jī)的脈沖數(shù)。倒數(shù)即是交換一個分?jǐn)?shù)的分子和分母。取得倒數(shù)的另一個方法是用1除這個數(shù),換句話說,(1/0.024)s/pulse=40.65pulses/s.因?yàn)槟阒繠oe-Bot車向前移動的時間(2.22s)和BASICStamp每秒發(fā)給伺服電機(jī)的脈沖數(shù)(40.65pulses/s),就可以用這些數(shù)來計(jì)算發(fā)給電機(jī)的脈沖數(shù)。這個數(shù)就是FOR…NEXT循環(huán)中的EndValue參數(shù)值
'RoboticswiththeBoe-Bot-ForwardOneSecond.bs2例――51厘米所需的時間例――20英寸所需的時間以9英寸/秒的速度,你的Boe-Bot車以23cm/s的速度,你的Boe-Bot必須必須用2.22s才能走20英寸運(yùn)行2.22s才能運(yùn)行51cm。.
四勻變速運(yùn)動
勻變速是漸漸增加或減小電機(jī)速度的一種方式,而不是驟起或驟停。這種方法可以增加Boe-Bot機(jī)器人的電池和電機(jī)的壽命。編寫勻變速運(yùn)動的程序勻變速運(yùn)動的關(guān)鍵是給PULSOUT命令的Duration參數(shù)賦予變量。圖4-4顯示的是一個FOR…NEXT循環(huán)它能使Boe-Bot機(jī)器人的速度由停止到全速。FOR…NEXT循環(huán)每重復(fù)執(zhí)行一次,pulseCount變量就增加1。第一次循環(huán)后,pulseCount變量的值是1,就像是在執(zhí)行命令PULSOUT13,751和PULSOUT12,749。第二次循環(huán)后,pulseCount變量的值是2,象在執(zhí)行命令PULSOUT13,752和PULSOUT12,748。隨著pulseCount變量值的增,電機(jī)的速度也在逐漸增加。到循環(huán)執(zhí)行100次后,pulseCount變量的值是100,就象在行電機(jī)全速運(yùn)轉(zhuǎn)的命令PULSOUT13,850和PULSOUT12,650回顧第二章任務(wù)5,F(xiàn)OR…NEXT循環(huán)也可以由高向低記數(shù)。你可以通過使用FORpulseCount=100TO1來實(shí)現(xiàn)速度的逐漸減小。這是一個使用FOR…NEXT循環(huán)來實(shí)現(xiàn)速度逐漸增加到全速然后減小的例子。示例程序:StartAndStopWithRamping.bs2
'---[Title]----------------------------------------------------'RoboticswiththeBoe-Bot-StartAndStopWithRamping.bs2'Rampup,goforward,rampdown.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!"pulseCountVARWord'FOR...NEXTloopcounter.'---[Initialization]------------------------------------------FREQOUT4,2000,3000'Signalprogramstart/reset.'-----[MainRoutine]--------------------------------------------'Rampupforward.FORpulseCount=1TO100'Looprampsupfor100pulses.
PULSOUT13,750+pulseCount'Pulse=1.5ms+pulseCount.PULSOUT12,750–pulseCount'Pulse=1.5ms–pulseCount.PAUSE20'Pausefor20ms.NEXT'Continueforwardfor75pulses.FORpulseCount=1TO75'Loopsends75forward.pulses.PULSOUT13,850'1.7mspulsetoleftservoPULSOUT12,650'1.3mspulsetorightservo.PAUSE20'Pausefor20ms.NEXT'Rampdownfromgoingforwardtoafullstop.FORpulseCount=100TO1'Looprampsdownfor100pulses.PULSOUT13,750+pulseCount'Pulse=1.5ms+pulseCount.PULSOUT12,750-pulseCount'Pulse=1.5ms-pulseCount.PAUSE20'Pausefor20msNEXTEND'Stopuntilreset該你了
創(chuàng)建一個程序,將加速或減速與其他的動作結(jié)合起來。下面是一個逐漸增加速度后走而不是向前走的例子。加速向后走與向前走的唯一不同之處在于PULSOUT13命令中pulseCount的值由750逐漸減小,而向前走是逐漸增加的,相應(yīng)的,PULSOUT12命令中pulseCount的值由750減少改為逐步增加。
RampuptofullspeedgoingbackwardsFORpulseCount=1TO100PULSOUT13,750-pulseCountPULSOUT12,750+pulseCountPAUSENEXT
通過增加兩個PULSOUT命令中pulseCount的值到750來創(chuàng)建一個在旋轉(zhuǎn)中勻變速的程序。通過逐漸減小兩個PULSOUT命令中pulseCount的值,可以沿另一個方向勻變速旋轉(zhuǎn)。這是一個勻變速旋轉(zhuǎn)四分之一周的例子。在伺服電機(jī)不得不減速之前沒機(jī)會增加到全速。
FORpulseCount=0TO30PULSOUT13,750+pulseCountPULSOUT12,750+pulseCountPAUSE20NEXT'RampdownrightrotateFORpulseCount=30TO0PULSOUT13,750+pulseCountPULSOUT12,750+pulseCountPAUSE20NEXT從任務(wù)1中打開程序ForwardLeftRightBackward.bs2,存為ForwardLeftRightBack更改新的程序,使Boe-Bot機(jī)器人的每一個動作能夠勻加速和勻減速。提示:你可以使用上面的代碼片段和StartAndStopWithRamping.bs2程序中相似的片段。五、用子程序簡化導(dǎo)航
1、子程序一個PBASIC子程序有兩個部分。一部分是子程序調(diào)用,它告訴程序跳到可重復(fù)執(zhí)行代碼部分,執(zhí)行后回到調(diào)用點(diǎn)。另一部分是實(shí)際的子程序,它以作為自己的名字的標(biāo)號為子程序的起點(diǎn),以RETURN命令結(jié)束。這個標(biāo)號和RETURN命令之間的命令組成一個代碼段,執(zhí)行你想讓子程序做的工作。
上圖是包括一個子程序調(diào)用和一個子程序的PBASIC程序的一部分。子程序調(diào)用是GOSUBMy_Subroutine命令。實(shí)際的子程序是從標(biāo)號My_Subroutine到RETURN命令之間的部分。它是這樣工作的:當(dāng)程序運(yùn)行到GOSUBMy_Subroutine命令時,它會尋找標(biāo)號My_Subroutine:,如箭頭(1)所示,程序跳到My_Subroutine處并開始執(zhí)行命令。程序從標(biāo)號處向下逐行執(zhí)行命令,在調(diào)試終端你會看到“Commandinsubroutine”信息。PAUSE1000會使程序中斷一秒鐘,然后程序執(zhí)行到RETURN命令處,箭頭(2)顯示了GOSUB命令執(zhí)行后如何立即跳回。在這種情況下,DEBUG命令顯示信息“Aftersubroutine”。程序示例:OneSubroutine.bs2'RoboticswiththeBoe-Bot-OneSubroutine.bs2.'Thisprogramdemonstratesasimplesubroutinecall'{$STAMPBS2}'{$PBASIC2.5}DEBUG"Beforesubroutine",CRPAUSE1000GOSUBMy_Subroutine:DEBUG"Aftersubroutine",CRENDMy_Subroutine:DEBUG"Commandinsubroutine",CRPAUSE1000RETURN
監(jiān)視調(diào)試終端,按幾次復(fù)位按鈕。每一次你應(yīng)該得到和命令右邊相同的三個信息
下面是有兩個子程序的例子,一個產(chǎn)生高音另一個產(chǎn)生低音。在DO和LOOP之間的命令依次調(diào)用子程序,驗(yàn)證次程序并關(guān)注其結(jié)果。'RoboticswiththeBoe-Bot-TwoSubroutine.bs2'Thisprogramdnmonstratesthatasubroutineisareusableblockofcommands.'{$STAMPBS2}'{$PBASIC2.5}DOGOSUBHIGH-PitchDEBUG"Backinmain",CRPAUSE1000GOSUBLOW-PitchDEBUG"Backinmainagain",CRPAUSE1000DEBUG"Repeat...",CR,CRLOOPHIGH-Pitch:DEBUG"Highpitch",CRFREQOUT4,2000,3500RETURNLOW-Pitch:DEBUG"Lowpitch",CRFREQOUT4,2000,2000
讓我們試著將前,左,右和后四個導(dǎo)航程序放在子程序中,下面是一個例子。示例程序:
MovementsWithSubroutines.bs2'RoboticswiththeBoe-Bot-MoventsWithSubroutines.bs2'Makeforward,left,right,andbackwardmovements.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!:"counterVARWordFREQOUT4,2000,3000'Signalprogramstart/reset.GOSUBForwardGOSUBLeftGOSUBRightGOSUBBackwardENDForward:FORcounter=1TO64'ForwardPULSOUT13,850PULSOUT12,650PAUSE20NEXTPAUSE200RETURNLeft:FORcounter=1TO24'Rotateleft-about1/4turnPULSOUT13,650PULSOUT12,650PAUSE20NEXTPAUSE200RETURNRight:FORcounter=1TO24'Rotateright-about1/4turnPULSOUT13,850PULSOUT12,850PAUSE20NEXTPAUSE200RETURNBackward:FORcounter=1TO64'BackwardPULSOUT13,650PULSOUT12,850PAUSE20NEXTRETURN
我們還可以用其他的方法來實(shí)現(xiàn)這些動作,如用一個子程序和一些變量來實(shí)現(xiàn)。我們可以注意到,目前為止每個機(jī)器人動作都用相同的代碼塊來完成,比較下面兩個片段:'Forwardfullspeed'RampdownfromfullspeedbackwardsFORcounter=1TO64FORpulseCount=100TO1PULSOUT13,850PULSOUT13,750-pulseCountPULSOUT12,650PULSOUT12,650+pulseCountPAUSE20PAUSE20NEXTNEXT
使這兩個代碼塊做不同操作的是變量StartValue和EndValue以及PULSOUT的參數(shù)Duration的改變。這些變量是可變的,這些變量可以在程序運(yùn)行的過程中被重復(fù)更改來產(chǎn)生不同的動作。下面的程序重復(fù)同樣的子程序而不是使用帶有特定的PULSOUT命令參數(shù)Duration的單獨(dú)的子程序。產(chǎn)生不同動作的關(guān)鍵是在調(diào)用子程序前將變量設(shè)為適當(dāng)?shù)闹怠?/p>
程序示例:
'RoboticswiththeBoe-Bot-MoventsWithVariablesAndOneSubroutine.bs2'Makeanavigationroutinethatacceptsparameters.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!:"counterVARWordpulseLeftVARWordpulseRightVARWordpulseCountVARWordFREQOUT4,2000,3000'Signalprogramstart/reset.'ForwardpulseLeft=850:pulseRight=650:pulseCount=64:GOSUBNavigate'LeftturnpulseLeft=650:pulseRight=650:pulseCount=24:GOSUBNavigate'RightturnpulseLeft=850:pulseRight=850:pulseCount=24:GOSUBNavigate'BackwardpulseLeft=650:pulseRight=850:pulseCount=64:GOSUBNavigateENDNavigate:FORcounter=1TOpulseCountPULSOUT13,pulseLeftPULSOUT12,pulseRightPAUSE20NEXTPAUSE200RETURN
這個程序中的指令以一種新的方式排列。每個變量聲明和GOSUB命令在同一行用冒號分隔開,而不是在不同的行。這里,冒號的功能和回車鍵一樣,分隔開每個PBASIC指令。這種方式允許所有指定動作的新變量值放在一起,并且和子程序調(diào)用在同一行。六:在EEPROM中建立復(fù)雜動作
EEPROM意為電可擦除可編程只讀存儲器,BASICStemp中能夠容納2048字節(jié)的信息,EEPROM存儲器與RAM(隨機(jī)存取存儲器)變量存儲器在幾個方面不同:1、EEPROM存儲一個值要花費(fèi)更多時間,有時需要幾毫秒。2、EEPROM可以接受寫操作的次數(shù)是一個有限數(shù),大約10百萬次,而RAM能無限次的讀寫。3、EEPROM的主要功能是存儲程序,數(shù)據(jù)可以存在剩余的部分。可以通過單擊BASICStamp編輯器中的Run菜單,選擇“MemoryMap”來瀏覽BASICStamp的EEPROM的內(nèi)容。圖4-6顯示了程序MovementsWithSubroutines.bs2的存儲圖。
注意左邊的EPROM精簡圖。底部的小框圖的陰影部分顯示了程序MovemntsWithSubroutines.bs2占用的內(nèi)存數(shù)量。在這兒,聲明成字變量的“counter”變量在RAM圖的寄存器0中。這個個程序在輸入的時候似乎比較大,但是它只占用了可用的2048字節(jié)程序存儲區(qū)的136個字節(jié)。這里還有足夠的空間來存放一串相當(dāng)長的指令。因?yàn)樵趦?nèi)存中一個字符占用一個字節(jié),因此還有可以存放1912個單字符指令的空間。EEPROM指南到目前為止我們已經(jīng)試過三種不同的編程方法來使Boe-Bot車向前走,左轉(zhuǎn),右轉(zhuǎn)和向后走。每種方法都有它的優(yōu)點(diǎn),但是如果你要讓機(jī)器人執(zhí)行一個更長,更復(fù)雜的動作作時用這些方法都很麻煩。下面要介紹的一個例子將在子程序中使用熟悉的代碼塊來實(shí)現(xiàn)每個簡單的動作,每個動作都用一個單字母代碼來表示,一長串代碼字母存儲在EEPROM中,然后在程序執(zhí)行過程中讀出并解碼。避免了重復(fù)執(zhí)行一長串子程序或者每個GOSUB命令執(zhí)行前更改變量。這種編程方法需要一些新的PBASIC指令:DATA指令,READ和SELECT...CASE...ENDSELECT命令,在試驗(yàn)示例程序之前,讓我們先學(xué)習(xí)一下這些新的指令。每個基本動作都由一個與子程序相符的單字母代碼來代替F代表Forward,B代表Backward,L代表Left_Turn,R代表RightTurn,復(fù)雜的Boe-bot運(yùn)動可以很快的用這些代碼設(shè)計(jì)字母出來。一串字母的最后一個字母是Q,意思是動作完成后退出(Quit)。下載程序時用DATA指令把這個字母串存在EEPROM中。如下所示:DATA"FLFFRBLBBQ"每個字母被存在EEPROM中的一個字節(jié)里,由地址0開始(除非我們告訴它在哪里),READ命令能夠在程序運(yùn)行的時候從EEPROM中讀出這個字母串。這些值可以這樣從DO…LOOP循環(huán)中讀出:
DOUNTIL(instruction="Q")READaddress,instructionaddress=address+1'PBASICcodeblockomittedhere.LOOPaddress變量是每個存放代碼字母的EEPROM字節(jié)的地址。Instruction變量擁有字節(jié)的實(shí)際值,即代碼字符。注意每執(zhí)行一次循環(huán),address變量的值增加1。這就使每個字母從地址0開始從EEPROM字節(jié)中連續(xù)的讀出。DO…LOOP命令有可選的條件,這對于不同的情況是很便利的。DONUTIL(condition)…LOOP允許循環(huán)重復(fù)執(zhí)行直到確定的情況發(fā)生。DOWHILE(condition)...LOOP允許當(dāng)某一個條件存在循環(huán)重復(fù)執(zhí)行。我們的例子將使用DO…LOOPUNTIL。在這種情況下DO…LOOP循環(huán)重復(fù)執(zhí)行直到從EEPROM中讀到Q字符。
SELECT...CASE...ENDSELECT指令用來選擇一個變量并求值,然后執(zhí)行CASE列中對應(yīng)的代碼塊下面的代碼塊將根據(jù)instruction變量中的字母值調(diào)用合適的子程序:SELECTinstructionCASE"F":GOSUBForwardCASE"B":GOSUBBackwardCASE"R":GOSUBRight_TurnCASE"L":GOSUBLeft_TurnENDSELECT程序示例:EepromNavigation.bs2,機(jī)器人按矩形行走'RoboticswiththeBoe-Bot-EepromNavigation.bs2'NavigationusingcharactersstoredinEEPROM.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"ProgramRunning!:"'-[Variables]------------------------------------------------------pulseCountVARWord'StoresnumbeiofpulsesaddressVARByte'StoresEEPROMaddress.instructionVARByte'StoresEEPROMinstruction.'--[EEPROMData]----------------------------------------------------'Address:0123456789'Thesetwocommentedlinesshow'/////'EEPROMaddressofeathdatum.DATA"FLFFRBLBBQ"'Navigationinstruction.'----[Initialization]----------------------------------------------FREQOUT4,2000,3000'Signalprogramstart/reset.'-----[MainRoutine]------------------------------------------------DOUNTIL(instruction="Q")READaddress,instruction'Dataataddressininstruction.address=address+1'Add1toaddressfornextread.SELECTinstruction'Calladifferentsubroutine.CASE"F":GOSUBForward'foreachpossiblecharactorCASE"B":GOSUBBackward'thatcanbefetchedfromCASE"L":GOSUBLeft_Turn'EEPROMCASE"R":GOSUBRight_TurnENDSELECTLOOPEND'Stopexecutinguntilreset'---[SubroutineForward]------------------------------------------Forward:'ForwardSubroutineFORpulseCount=1TO64'Send64forwardpulses.PULSOUT13,850'1.7mspulsestoleftservo.PULSOUT12,650'1.3mspulsestorightservo.PAUSE20'Pausefor20ms.NEXTRETURN'ReturntoMainRoutineloop.'-----[Subroutine_Backward]----------------------------------------Backward:'Backwardsubroutine.FORpulseCount=1TO64'Send64backwardpulses.PULSOUT13,650'1.3mspulsestoleftservo.PULSOUT12,850'1.7mspulsestorightservo.PAUSE20'Pausefor20ms.NEXTRETURN'ReturntoMainRoutineloop.'-----[Subroutine_Left_Turn]----------------------------------------Left_Turn:'Left_TurnsubroutineFORpulseCount=1TO24'Send24leftrotatepulses.PULSOUT13,650'1.3mspulsestoleftservo.PULSOUT12,650'1.3mspulsestorightservo.PAUSE20'Pausefor20ms.NEXTRETURN'ReturntoMainRoutineloop.'-----[Subroutine_Right_Turn]----------------------------------------Right_Turn:'Right_TurnsubroutineFORpulseCount=1TO24'Send24rightrotatepulses.PULSOUT13,850'1.7mspulsestoleftservo.PULSOUT12,850'1.7mspulsestorightservo.PAUSE20'Pausefor20ms.NEXTRETURN'ReturntoMainRoutineloop.該你了
程序進(jìn)行完畢后,在BASICStamp編輯器中單擊Run菜單并選擇MemoryMap,就可以看到詳細(xì)的EEPROM圖,我們存放的指令將以藍(lán)色高亮顯示,顯示的數(shù)據(jù)是十六進(jìn)制的ASCII碼與我們在DATA指令中輸入的字符一致。
單擊圖中左下角的DisplayASCII復(fù)選框,它顯示的是你使用DATA指令記錄的實(shí)際字符,不是ASCII碼。
這個程序在EEPROM中存儲了10個字符。這10個字符被READ命令的address參數(shù)訪問。address變量聲明成一個字節(jié)變量,因而可以訪問256個地址,包含我們需要的10個地址。如果address被重聲明為一個自變量,你理論上可以訪問65535個地址。記住如果你的程序越長,EEPROM中可以用來存儲數(shù)據(jù)的地址會越少可以更改現(xiàn)有的數(shù)據(jù)串為一系列新的方向。你也可以增加另外的DATA指令。這些數(shù)據(jù)被連續(xù)存儲.但應(yīng)注意:DATA指令中最后的字符應(yīng)該是“Q”.
下一個例看起來很復(fù)雜,但是它是一個非常有效的設(shè)計(jì)Boe-Bot運(yùn)動的方法。這個例子使用了EEPROM數(shù)據(jù)存儲區(qū),但是沒有使用子程序,而是使用單個的用變量代替FOR...NEXT循環(huán)的EndValue和PULSOUTDuration的代碼塊。缺省的,DATA指令在EEPROM中存儲字節(jié)信息,要存儲字長的數(shù)據(jù)項(xiàng),可以增加Word修飾符在DATA指令中。每個字長數(shù)據(jù)項(xiàng)需要占用EEPROM中的兩個字節(jié)的存儲位置,因此每個數(shù)據(jù)要通過每個數(shù)據(jù)的另一個地址來訪問。當(dāng)使用多個DATA指令時,最方便的方法是給每個指令加標(biāo)簽。這樣,READ命令就可以根據(jù)標(biāo)簽得到數(shù)據(jù),不用你計(jì)算在EEPROM中每串?dāng)?shù)據(jù)開始的地址??聪旅娴拇a片段:'addressOffset02468Pulses_CountDATAWord64,Word24,Word24,Word64,Word0Pulses_LeftDATAWord850,Word650,Word850,Word650Pulses_RightDATAWord650,Word650,Word850,Word850
每個DATA指令以自己的標(biāo)簽開始。Word修飾符在每個用逗號分開得數(shù)據(jù)項(xiàng)之前。這三個數(shù)據(jù)串將被依次存儲在EEPROM中。我們不用計(jì)算出數(shù)據(jù)項(xiàng)的地址,因?yàn)闃?biāo)簽和addressOffset變量會自動去做。READ命令用每個標(biāo)簽算出EEPROM中數(shù)據(jù)串開始的地址,然后增加addressOffset變量的值就知道要移動多少來找到正確的數(shù)據(jù)項(xiàng)(DataItem)。找到DataItem.后Address將被存儲在READ命令的Variable變量中。注意,Word修飾符應(yīng)該放在存儲從EEPROM中取出的值的變量之前。DOREADPulses_Count+addressOffset,WordpulseCountREADPulses_Left+addressOffset,WordpulseLeftREADPulses_Right+addressOffset,WordpulseRightaddressOffset=addressOffset+2'PBASICcodeblockomittedhere.LOOPUNTIL(pulseCount=0)
第一次執(zhí)行完循環(huán)后,addressOffset=0。第一個READ命令將從Pulses_Count標(biāo)簽的第一個地址中得到一個值64,并把它放在pulseCount變量中。第二個READ命令從Pulses_Left標(biāo)簽指定的第一個地址中得到值850,并把它放在pulseLeft變量中。第三個EAD命令從Pulses_Right標(biāo)簽指定的第一個地址得到值650,并把它放在pulseRight變中。注意,這些是上面代碼片段第“0”列的三個值,當(dāng)這些變量值被放在下面的代碼塊中時,F(xiàn)ORcounter=1TOpulseCountFORcounter=1TO64PULSOUT13,pulseLeftPULSOUT13,850PULSOUT12,pulseRightPULSOUT12,650PAUSE20becomesPAUSE20NEXTNEXT然后FOR...NEXT代碼執(zhí)行第二、第三和第四個循環(huán)。
程序示例:EepromNavigationWithWordValues.bs2.'RoboticswiththeBoe-Bot-EepromNavigationWithWordValues.bs2'Storelistsofwordvaluesthatdictate.'{$STAMPBS2}'Stampdirective.'{$PBASIC2.5}'PBASICdirective.DEBUG"ProgramRunning!“'--[Variables]-----------------------------------------------counterVARWordpulseCountVARWord'Storesnumberofpulses.addressOffsetVARByte'Storesoffsetfromlabel.instructionVARByte'StoresEEPROMinstruction.pulseRightVARWord'Storesservopulsewidths.pulseLeftVARWord'--[EEPROMData]--------------------------------------------'addressOffset02468Pulses_CountDATAWord64,Word24,Word24,Word64,Word0Pulses_LeftDATAWord850,Word650,Word850,Word650Pulses_RightDATAWord650,Word650,Word850,Word850'–[Initialization]---------------------------------FREQOUT4,2000,3000'Signalprogramstart/reset.'--[MainRoutine]-----------------------------------DOREADPulses_Count+addressOffset,WordpulseCountREADPulses_Left+addressOffset,WordpulseLeftREADPulses_Right+addressOffset,WordpulseRightaddressOffset=addressOffset+2FORcounter=1TOpulseCountPULSOUT13,pulseLeftPULSOUT12,pulseRightPAUSE20NEXTLOOPUNTIL(pulseCount=0)END'Stopexecutinguntilreset.挑戰(zhàn)課題!1、用下面的代碼代替DATA指示,運(yùn)行程序,觀察Boe-Bot會做些什么。Pulses_CountDATAWord60,Word80,Word100,Word110,Word110,Word100,Word80,Word60,Word0Pulses_LeftDATAWord850,Word800,Word785,Word760,Word750,Word740,Word715,Word700,Word650,Word750Pulses_RightDATAWord650,Word700,Word715,Word740,Word750,Word760,Word785,Word800,Word850,Word7502、寫個程序讓Boe-Bot能沿著(1)直徑為1m的圓形軌跡運(yùn)行(2)邊長為1m的正三角形軌跡行走。(3)走“8”形軌跡。總結(jié)這章節(jié)介紹了Boe-Bot的許多基本操作:前進(jìn)、后退、左轉(zhuǎn)、右轉(zhuǎn)、以中心旋轉(zhuǎn)。這些操作是由PULSOUT指令中的Duration參數(shù)所控制,而每個動作的時間是由FOR…NEXT循環(huán)中的StartValue和Endvalue參數(shù)所控制。第二章介紹的是硬件的調(diào)整,用螺絲起子來校正Boe-Bot的伺服機(jī)。而這章節(jié)是注重在軟件方面的調(diào)整,尤其是當(dāng)兩個伺服馬達(dá)的轉(zhuǎn)速不等時,必須對PULSOUT指令中的Duration參數(shù)進(jìn)行修改,降低轉(zhuǎn)速較快的伺服馬達(dá),如果兩輪的轉(zhuǎn)速沒有配合好,做了這個修改就可以讓Boe-Bot的軌跡從曲線變成直線。至于調(diào)整Boe-Bot的旋轉(zhuǎn)角度,則可以從FOR…NEXT循環(huán)中的StartValue與EndValue參數(shù)著手。為了寫程序讓Boe-Bot行走事先決定好的距離,可以先用尺測量出Boe-Bot行走一秒的距離,有了這個距離與每秒鐘的脈沖數(shù)就可以計(jì)算出特定距離所需要的脈沖數(shù)。Ramping是一種逐漸加速與逐漸減速的方式,這種方式對于伺服馬達(dá)是較適合的操作,所以建議在Boe-Bot的起始與結(jié)束時使用這種操作。逐漸加速的方法是在FOR…NEXT循環(huán)中聲明一個Counter參數(shù),在PULSOUT指令中的Duration參數(shù)從750開始增加與減少。
子程序是一種事先寫好程序的方法,可供PBASIC重復(fù)使用。使用子程序就不需要為每一個操作都寫一個完整的FOR…NEXT循環(huán),因?yàn)槊總€子程序中就會包含一個FOR…NEXT循環(huán),在需要子程序時就以GOSUB呼叫子程序。子程序以標(biāo)記為開始,以RETURN指令作為結(jié)束。在主程序中以GOSUB指令呼叫子程序,當(dāng)子程序執(zhí)行完畢后就會執(zhí)行RETURN指令,下一個被執(zhí)行的指令就是緊接在GOSUB指令后的程序。BASICStamp的EEPROM儲存現(xiàn)在執(zhí)行的程序,不過你可以利用程序中任何未使用的部分來儲存數(shù)值,這是儲存預(yù)存操作程序的好方式。DATA指令可將數(shù)值存入EEPROM,預(yù)設(shè)模式是以byte存入,若在數(shù)據(jù)前面加上Word,就可使用EEPROM內(nèi)存中的2個byte儲存數(shù)值,數(shù)值得大小可提升至65535。我們用READ指令來將存入EEPROM的數(shù)值讀取出來。如果你要使用的是字符變量是Word格式,記得在變數(shù)前面加上Word。
SELECT…CASE…ENDSELECT敘使用來選擇一個特定的變量,然后開始評估它屬于那種情形,之后才執(zhí)行某種情形下相對應(yīng)的程序。附加的DO…LOOP循環(huán)這個功能相當(dāng)?shù)姆奖?,可以在很多情況下達(dá)到我們的目的;DOUNTIL(情況)…LOOP和DO…LOOPUNTIL(情況)允許循環(huán)不斷重復(fù),直到某種條件發(fā)生才跳出循環(huán)。第二節(jié)Boe-Bot機(jī)器人觸覺導(dǎo)航
本章中,我們將在Boe-Bot車上安裝并測試一個稱為胡須的觸覺開關(guān)。并對Boe-Bot機(jī)器人編程來監(jiān)視觸覺開關(guān)的狀態(tài),以及決定當(dāng)它遇到障礙物時如何去做。最終的結(jié)果就是通過觸覺給機(jī)器人自動導(dǎo)航——即觸覺導(dǎo)航。胡須:是因?yàn)檫@些緩沖開關(guān)看起來象胡須,也象觸角。安裝好的胡須如圖5-1所示。胡須讓機(jī)器人有能力通過接觸來判斷周邊的環(huán)境,很象螞蟻的觸角,或是貓的胡須。一、安裝并測試機(jī)器人的胡須1、胡須的電路及裝配斷開主板和電機(jī)的電源,元件清單:須狀金屬絲、平頭M4-40螺絲釘、?″圓形套管、3-pin公-公接頭、220Ω電阻(紅-紅-棕)、10kΩ電阻(棕-黑-橙)。安裝步驟:(1)拆掉連接主板到前面支架的兩顆螺釘;(2)參考圖5-3,螺釘依次穿過尼龍墊圈、螺釘穿過主板上的圓孔之后,擰進(jìn)主板下面的支架中,但不要擰緊;(3)把須狀金屬絲帶勾的部分?jǐn)Q在螺釘上,將螺釘擰緊在支架上,調(diào)整胡須的位置使它們橫向交叉但不接觸。。電路:把圖所示的胡須電路添加到壓電式揚(yáng)聲器和你曾在前面學(xué)習(xí)中搭建并測試過的伺服電機(jī)電路中,確定兩條胡須比較靠近,但又不接觸面包板上的3-pin頭。推薦保持3mm的距離。2、測試胡須
觀察胡須電路示意圖,每條胡須都是一個機(jī)械式的、接地常開的單刀單擲開關(guān)。胡須接地(Vss)是因?yàn)橹靼逋鈬腻兘鹂锥歼B接到Vss。金屬支架和螺絲釘提供電氣連接給胡須。通過編程讓BASICStamp微控制器探測什么時候胡須被觸動。連接到每個開關(guān)電路的I/O腳監(jiān)視著10K上拉電阻上的電壓變化。圖5-8說明是如何工作的。當(dāng)胡須沒有被觸動,連接胡須的I/O管腳的電壓是5V;當(dāng)胡須被觸動時,I/O短接到地,所以I/O管腳的電壓是0V。PBASIC程序開始運(yùn)行時,所有的I/O插腳缺省為輸入。也就是說,連接到胡須的I/O管腳會自動作為輸入。作為輸入,如果I/O腳上的電壓為5V(胡須沒有被觸動),則其寄存器存儲1;如果電壓為0V(胡須被觸動),則存儲0。調(diào)試終端可以顯示這些數(shù)值。
接下來的示例程序是用來測試胡須的功能是否正常。通過顯示存儲在P7和P5的輸入寄存器(IN7和IN5)中的二進(jìn)制數(shù)字,程序?qū)⒏嬖V你BASICStamp是否檢測到胡須的狀態(tài)。當(dāng)輸入寄存器存儲的值為1,說明胡須沒有被觸動;當(dāng)存儲值為0時,胡須被觸動。程序示例:TestWhiskers.bs2
'RoboticswiththeBoe-Bot-TestWhiskers.bs2'DisplaywhattheI/Opinsconnectedtothewhiskerssense.'{$STAMPBS2}'Stampdirective.'{$PBASIC2.5}'PBASICdirective.DEBUG"WHISKERSTATES",CR,"LeftRight",CR,"------------"DODEBUGCRSRXY,0,3,"P5=",BIN1IN5,"P7=",BIN1IN7PAUSE50LOOP注意調(diào)試終端的顯示值;此時P7和P5的顯示值應(yīng)該都為1。檢查圖5-5,弄清哪條胡須是左胡須,哪條是右胡須。(1)把右胡須按到3-pin轉(zhuǎn)接頭上,注意調(diào)試終端的數(shù)值,數(shù)值應(yīng)該為:P5=1P7=0(2)把左胡須按到3-pin轉(zhuǎn)接頭上,注意調(diào)試終端的數(shù)值,數(shù)值應(yīng)該為:P5=0P7=1(3)同時把兩個胡須按到各自的3-pin轉(zhuǎn)接頭上,此時數(shù)值應(yīng)該為:P5=0P7=0(4)如果兩個胡須都通過測試,你可以繼續(xù)下面的內(nèi)容;否則檢查程序或電路中存在的錯誤。
3、實(shí)地測試胡須假設(shè)你以后不得不脫機(jī)測試胡須。不能用到調(diào)試終端,我們可以對BASICStamp編程,讓它發(fā)送一些和其接收到的輸入信號相符合的輸出信號。利用含有一對LED的電路和基于胡須的輸入讓LED亮或滅的程序來實(shí)現(xiàn)。所需元件:220Ω電阻(紅-紅-棕)、紅色LED(1)搭建LED胡須測試電路斷開電源,按圖示搭建電路(2)對LED胡須測試電路編程
重新連接主板的電源,將程序TestWhiskers.bs2另存為TestWhiskersWithLeds.bs2在PAUSE50和LOOP命令之間插入以下兩段IF...THEN語句IF(IN7=0)THENHIGH1ELSELOW1ENDIFIF(IN5=0)THENHIGH10ELSELOW10ENDIF這是IF...THEN條件判斷語句。第一個IF...THEN語句當(dāng)連接到P7的胡須被觸動(IN7=0)時,設(shè)置P1為高電平LED亮,ELSE部分當(dāng)胡須沒有被觸動時,設(shè)置P1為低電平LED滅。第二個IF...THEN語句對連接到P5的胡須和P10的LED做同樣的事情。運(yùn)行程序TestWhiskersWithLeds.bs2輕輕的觸動胡須,測試該程序。每個胡須接觸到自己的3-pin轉(zhuǎn)接頭時,紅色LED會變亮。'RoboticswiththeBoe-Bot-TestWhiskersWithLeds.bs2'DisplaywhattheI/Opinsconnectedtothewhiskerssense.'{$STAMPBS2}'{$PBASIC2.5}DEBUG"WHISKERSTATES",CRDEBUG"LeftRight",CRDEBUG"-------------"DODEBUGCRSRXY,0,3,"P5=",BIN1IN5"P7=",BIN1IN7PAUSE50IF(IN7=0)THENHIGH1ELSELOW1ENDIFIF(IN5=0)THENHIGH10ELSELOW10ENDIFLOOP二、通過胡須導(dǎo)航在Boe-Bot車行走過程中,如果有胡須被觸動,那就意味著碰到了什么。導(dǎo)航程序需要接受這些輸入信息,判斷它的意義,調(diào)用一系列使Boe-Bot車倒退、旋轉(zhuǎn)并朝不同的方向行走的動作子程序,完成胡須導(dǎo)航。PBASIC語言中有個條件判斷命令語句IF…THEN,其句法是:IF(condition)THEN…{ELSEIF(condition)}…{ELSE}…ENDIF句中“…”的意思是,你可以在關(guān)鍵詞之間放置一個代碼段(由一條或多條命令組成)。下面的示例程序會基于胡須的輸入做出選擇,然后調(diào)用相關(guān)子程序使Boe-Bot車采取行動。子程序同你在第四章里用到的類似。這是IF…THEN怎樣使用:IF(IN5=0)AND(IN7=0)THENGOSUBBack_Up'Bothwhiskersdetectobstacle,GOSUBTurn_Left'backup&U-turn(lefttwice)GOSUBTurn_LeftELSEIF(IN5=0)THEN'LeftwhiskercontactsGOSUBBack_Up'Backup&turnrightGOSUBTurn_RightELSEIF(IN7=0)THEN'RightwhiskercontactsGOSUBBack_Up'Backup&turnleftGOSUBTurn_LeftELSE'Bothwhiskers1,nocontactsGOSUBForward_Pulse'Applyaforwardpulse&ENDIF'checkagain示例程序:RoamingWithWhiskers.bs2這個示例程序示范了一種利用IF…THEN語句評估胡須的輸入并決定調(diào)用哪個導(dǎo)航子程序的方法。重新打開主板和伺服電機(jī)的電源輸入、保存并運(yùn)行程序RoamingWithWhiskers.bs2嘗試讓Boe-Bot車行走,當(dāng)在其路線上遇到障礙物時,它將后退、旋轉(zhuǎn)并向另一個方向行走。
'-----[Title]--------------------------------------------------------------'RoboticswiththeBoe-Bot-RoamingWithWhiskers.bs2'Boe-Botuseswhiskerstodetectobjects,andnavigatesaroundthem.'{$STAMPBS2}'Stampdirective.'{$PBASIC2.5}'PBASICdirective.DEBUG"ProgramRunning!“'-----[Variables]----------------------------------------------------------pulseCountVARByte'FOR...NEXTloopcounter.'-----[Initialization]-----------------------------------------------------FREQOUT4,2000,3000'Signalprogramstart/reset.'-----[MainRoutine]-------------------------------------------------------DOIF(IN5=0)AND(IN7=0)THEN'BothwhiskersdetectobstacleGOSUBBack_Up'Backup&U-turn(lefttwice)GOSUBTurn_LeftGOSUBTurn_LeftELSEIF(IN5=0)THEN'LeftwhiskercontactsGOSUBBack_Up'Backup&turnrightGOSUBTurn_RightELSEIF(IN7=0)THEN'RightwhiskercontactsGOSUBBack_Up'Backup&turnleftGOSUBTurn_LeftELSE'Bothwhiskers1,nocontactsGOSUBForward_Pulse'ApplyaforwardpulseENDIF'andcheckagainLOOP'-----[Subroutines]--------------------------------------------------------Forward_Pulse:'Sendasingleforwardpulse.PUL
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 小學(xué)生校園誠信建設(shè)制度
- 2025年10月日歷表(含農(nóng)歷-周數(shù)-方便記事備忘)
- 上半年班級團(tuán)支部工作參考計(jì)劃范文
- 班組質(zhì)量培訓(xùn)課件
- 共青團(tuán)入團(tuán)考試題
- 食品生產(chǎn)預(yù)包裝培訓(xùn)課件
- 二年級數(shù)學(xué)(上)計(jì)算題專項(xiàng)練習(xí)匯編
- 復(fù)工安全教育內(nèi)容課件
- 中班安全科學(xué)課件
- 《葡萄酒知識普及》課件
- 耕作學(xué)智慧樹知到期末考試答案章節(jié)答案2024年中國農(nóng)業(yè)大學(xué)
- 2024年中國消防救援學(xué)院第二批面向應(yīng)屆畢業(yè)生招聘28人歷年【重點(diǎn)基礎(chǔ)提升】模擬試題(共500題)附帶答案詳解
- 食品加工代工配方保密協(xié)議
- QCT1067.5-2023汽車電線束和電器設(shè)備用連接器第5部分:設(shè)備連接器(插座)的型式和尺寸
- (完整版)儀表選型
- T-CCAA 39-2022碳管理體系 要求
- 《YST 550-20xx 金屬熱噴涂層剪切強(qiáng)度的測定》-編制說明送審
- 2024-2030年中國氣槍行業(yè)市場深度分析及發(fā)展前景預(yù)測報(bào)告
- 數(shù)字化技術(shù)在促進(jìn)幼兒語言發(fā)展中的應(yīng)用
- 江西省上饒市2023-2024學(xué)年高一上學(xué)期期末教學(xué)質(zhì)量測試物理試題(解析版)
- 提高感染性休克集束化治療達(dá)標(biāo)率
評論
0/150
提交評論