dede企業(yè)網(wǎng)站模板下載sem和seo的區(qū)別
一、作品簡(jiǎn)介
作者:賀沅、聶開發(fā)、王興文、石宇航、盛余慶
單位:黑龍江科技大學(xué)
指導(dǎo)老師:邵文冕、苑鵬濤
1. 項(xiàng)目背景
受新冠疫情的影響,大學(xué)校園內(nèi)都采取封閉式管理來降低傳染的風(fēng)險(xiǎn),導(dǎo)致學(xué)生不能外出,學(xué)校工作人員不能入校。通過封閉式的管理以此來盡最大可能保證學(xué)生在當(dāng)前新冠傳染和大規(guī)模人群被感染的情況下的安全,在此種情況下出現(xiàn)了取件困難、取件效率低、快遞堆積在驛站等諸多快遞服務(wù)問題,嚴(yán)重時(shí)也導(dǎo)致了快遞無法進(jìn)校。同時(shí)也嚴(yán)重提升了在校學(xué)生們的感染風(fēng)險(xiǎn),嚴(yán)重影響了同學(xué)們的日常生活需要。

? ?? ? 為了解決在??爝f取件的問題,我們?cè)O(shè)計(jì)了一種由行走機(jī)構(gòu)、抓取機(jī)構(gòu)、控制系統(tǒng)和視覺系統(tǒng)組成的校園智能無人快遞小車,以實(shí)現(xiàn)”無接觸“式、消毒式快遞配送,解決快遞取件效率低的問題,減小了人力和物力,使得快遞處理簡(jiǎn)單高效快捷,在快遞的最后一站充分降低學(xué)生拿快遞時(shí)新冠病毒感染風(fēng)險(xiǎn),同時(shí)避免了校外人員入校傳播病毒的風(fēng)險(xiǎn)。
2. 項(xiàng)目進(jìn)展
2.1技術(shù)路線

? ?? ? 如上圖所示,我們所設(shè)計(jì)的快遞附件機(jī)器人由機(jī)器人本體與被檢測(cè)物(貨物)組成。其總體流程如下:機(jī)器人通過一部分檢測(cè)模塊識(shí)別貨物所在位置;將該信息反饋于快遞附件機(jī)器人的控制板模塊,控制板模塊則命令驅(qū)動(dòng)模塊驅(qū)動(dòng),行走模塊按照指定路線進(jìn)行運(yùn)動(dòng),等待抓取模塊完成操作,抓取操作完成后控制模塊驅(qū)動(dòng)小車的行走模塊進(jìn)行下一步運(yùn)動(dòng)。
2.2設(shè)計(jì)路線
2.3項(xiàng)目創(chuàng)新點(diǎn)
2.3.1結(jié)構(gòu)部分
? ?? ? 采用了連桿機(jī)構(gòu),其運(yùn)動(dòng)副一般均為低副。低副兩運(yùn)動(dòng)副元素為面接觸,壓強(qiáng)較小,可承受較大的載荷;可以方便地用來達(dá)到增力、擴(kuò)大行程和實(shí)現(xiàn)遠(yuǎn)距離傳動(dòng)的優(yōu)勢(shì),可方便機(jī)械臂抓取高層快遞,我們采用中型球型件代替普通連桿使傳動(dòng)更穩(wěn)定,且具有各部件之間不易松動(dòng)的特點(diǎn);采用齒輪傳動(dòng)結(jié)構(gòu),通過6個(gè)齒輪進(jìn)行傳動(dòng)能保證穩(wěn)定傳動(dòng)的同時(shí)具有準(zhǔn)確的傳動(dòng)比,可以實(shí)現(xiàn)平行軸、相交軸、交錯(cuò)軸等空間任意兩軸間傳動(dòng)的優(yōu)點(diǎn)。


2.3.2運(yùn)動(dòng)部分
? ?? ? 運(yùn)動(dòng)部分通過四個(gè)直流馬達(dá)支架將四個(gè)直流馬達(dá)固定并配合四個(gè)輪胎組成運(yùn)動(dòng)機(jī)構(gòu),采用差速法控制小車轉(zhuǎn)向,采用循跡進(jìn)行路線規(guī)劃,使用pwm進(jìn)行調(diào)速,具有速度快的特點(diǎn),且采用提取取件碼第一位數(shù)字的方式,判斷快遞架位置和小車取完快遞從后門出發(fā),具有高效、快捷的優(yōu)點(diǎn),減少了空間的占用和取件的時(shí)間。
2.3.3視覺部分
? ?? ? 采用了圖像畸變矯正處理、輪廓提取算法和神經(jīng)網(wǎng)絡(luò)模型訓(xùn)練,解決了圖像顯示不清晰,識(shí)別率不夠高問題的同時(shí),實(shí)現(xiàn)了在不同光照條件下快遞編號(hào)的識(shí)別,且有較高的準(zhǔn)確率。
3. 項(xiàng)目總結(jié)
? ?? ? 為了解決受新冠疫情影響、學(xué)校封閉式管理、學(xué)生不能外出取件、快遞取件難、快遞在快遞站堆積的問題,我們?cè)O(shè)計(jì)了一種由行走機(jī)構(gòu)、抓取機(jī)構(gòu)、控制系統(tǒng)和視覺系統(tǒng)組成的校園智能無人快遞小車,以實(shí)現(xiàn)”無接觸“式、消毒式快遞配送,這樣避免了校外人員入校傳播病毒的潛在風(fēng)險(xiǎn),由智能快遞付件機(jī)器人幫忙取校外快遞,僅需對(duì)小車和快遞進(jìn)行消毒處理,簡(jiǎn)化了消毒流程,減少了人力、物力的開銷,方便快捷了學(xué)生生活,減少了快遞長(zhǎng)時(shí)間不取退回的現(xiàn)象。
二、功能介紹
1. 產(chǎn)品結(jié)構(gòu)圖
? ?? ? 智能快遞付件機(jī)器人由行走機(jī)構(gòu)、控制模塊、抓取機(jī)構(gòu)和視覺模塊組成,整個(gè)系統(tǒng)由兩個(gè)12v鋰電池分別對(duì)控制模塊和視覺模塊進(jìn)行供電,以延長(zhǎng)機(jī)器人的使用時(shí)間間隔??刂颇K以Basra為主控,實(shí)現(xiàn)對(duì)機(jī)器人的行走、控制、抓取、視覺等過程的控制。機(jī)器人搭載了無線藍(lán)牙和語音識(shí)別模塊,在實(shí)現(xiàn)了藍(lán)牙遠(yuǎn)程操控的同時(shí)也能夠完成操作參數(shù)的動(dòng)態(tài)調(diào)整等操作;行走機(jī)構(gòu)采用探索者套件中的輪胎與聯(lián)軸器相互配合,由直流減速電機(jī)驅(qū)動(dòng),在電機(jī)轉(zhuǎn)動(dòng)下控制小車行走。通過循跡進(jìn)行路線規(guī)劃;抓取機(jī)構(gòu)采用連桿機(jī)構(gòu)控制機(jī)械爪,對(duì)快遞進(jìn)行抓取;視覺模塊采用Edge impulse對(duì)數(shù)字模型進(jìn)行神經(jīng)網(wǎng)絡(luò)訓(xùn)練來實(shí)現(xiàn)快遞編號(hào)的識(shí)別,并與下位機(jī)實(shí)現(xiàn)通信。

2. 主要功能
? ?? ? ① 可自主抵達(dá)相應(yīng)的快遞架
? ?? ? ② 可對(duì)所需要取的快遞進(jìn)行識(shí)別
? ?? ? ③ 可實(shí)現(xiàn)遠(yuǎn)程操作與抓取參數(shù)調(diào)整
? ?? ? ④ 可實(shí)現(xiàn)識(shí)別與抓取時(shí)的狀況監(jiān)控
3. 結(jié)構(gòu)介紹
? ?? ? 本作品總體結(jié)構(gòu)由探索者套件拼裝,分為主板平面、運(yùn)動(dòng)機(jī)構(gòu)、機(jī)械臂、抓取結(jié)構(gòu)、載物臺(tái)、電源倉。
3.1主板平面
? ?? ? 使用四個(gè)7*11孔平板和兩塊5*7孔平板構(gòu)成的搭載主體平臺(tái),作為承載機(jī)械臂和載物臺(tái)、連接運(yùn)動(dòng)機(jī)構(gòu)主體,同時(shí)放置開發(fā)板和傳感器等其他元器件。
3.2運(yùn)動(dòng)機(jī)構(gòu)
? ?? ? 通過四個(gè)直流馬達(dá)支架將四個(gè)直流馬達(dá)固定并配合四個(gè)輪胎組成運(yùn)動(dòng)機(jī)構(gòu),采用差速法控制小車轉(zhuǎn)向。
3.3機(jī)械臂
? ?? ? 使用4個(gè)輸出支架和兩個(gè)雙足連桿搭建機(jī)械臂在主板平面上的支座,使用四個(gè)大舵機(jī)支架連接大舵機(jī),機(jī)械臂的底盤舵機(jī)裝上大舵機(jī)輸出頭后與大臂的舵機(jī)支架連接,再將兩個(gè)大舵機(jī)U型支架反向連接作為機(jī)械臂大臂,一端連接大臂舵機(jī)一端連接小臂舵機(jī)。


? ?? ? ① 機(jī)械臂小臂:由與抓取機(jī)構(gòu)連接的舵機(jī)和舵機(jī)架構(gòu)成,另一端連接大舵機(jī)U型支架,可實(shí)現(xiàn)正轉(zhuǎn)70°,反轉(zhuǎn)55°,可小范圍調(diào)整抓取機(jī)構(gòu)抓取角度。
? ?? ? ② 機(jī)械臂大臂:由兩個(gè)大舵機(jī)U型支架反向連接形成,正轉(zhuǎn)110°反轉(zhuǎn)70°,調(diào)整抓取結(jié)構(gòu)置前置后,置前時(shí)抓取,置后時(shí)放置。
? ?? ? ③ 機(jī)械臂底盤:由支座和舵機(jī)支架構(gòu)成,可使機(jī)械手左右轉(zhuǎn)動(dòng),調(diào)整抓取機(jī)構(gòu)在水平方向上的位置。
3.4抓取結(jié)構(gòu)
? ?? ? 抓取結(jié)構(gòu)的運(yùn)動(dòng)采用了齒輪傳動(dòng)結(jié)構(gòu)和連桿結(jié)構(gòu),使用六個(gè)30齒齒輪兩兩疊加構(gòu)成三個(gè)雙層齒輪、使用5×7 孔平板作為機(jī)械爪零件主板,四個(gè)機(jī)械手指和四個(gè)機(jī)械手40mm驅(qū)動(dòng)、兩個(gè)3×5 折彎、中型球型件構(gòu)成,滑動(dòng)零件連接處使用軸套連接,以便抓取機(jī)構(gòu)活動(dòng)順暢,且不易松動(dòng)。抓機(jī)構(gòu)自由度在0-55,如下圖所示:

? ?? ? ① 連桿結(jié)構(gòu):由中型球型件和大舵機(jī)輸出頭組成,將舵機(jī)產(chǎn)生的扭力,通過連桿傳到齒輪上使齒輪轉(zhuǎn)動(dòng),并且由于使用的連桿是弧形,中間不會(huì)因?yàn)橛|碰到零件主板而導(dǎo)致活動(dòng)不順暢。
? ?? ? ② 傳動(dòng)結(jié)構(gòu):傳動(dòng)結(jié)構(gòu)通過三組齒輪嚙合將扭力均勻施加到兩側(cè)與齒輪連接的機(jī)械手40mm驅(qū)動(dòng)上,帶動(dòng)機(jī)械手指,使機(jī)械手實(shí)現(xiàn)張合功能。
3.5載物臺(tái)
? ?? ? 使用一塊7×11 孔平板、四塊3×5 折彎、和兩個(gè)大輪組成的載物平臺(tái),每個(gè)圓板為一個(gè)載物平臺(tái),每次可裝載兩件物品,如下圖所示,載物臺(tái)下方留有一定的空腔,作為電池倉,用于放置電源,在一定程度上節(jié)約了空間且載物臺(tái)抬高可減少機(jī)械臂運(yùn)行路程,使機(jī)械臂方便、快速放置快遞,提高了運(yùn)行效率。

4. 電控部分
4.1控制板的選擇
? ?? ? 在開發(fā)板上我們選擇Basra,Basra是一款基于Arduino開源方案設(shè)計(jì)的一款開發(fā)板,Basra的處理器核心是ATmega328,同時(shí)具有14路數(shù)字輸入/輸出口(其中6路可作為PWM輸出),6路模擬輸入,一個(gè)16MHz晶體振蕩器,一個(gè)USB口,一個(gè)電源插座,一個(gè)ICSPheader和一個(gè)復(fù)位按鈕。主CPU采用AVRATMEGA328型控制芯片,支持C語言編程方式。該系統(tǒng)的硬件電路包括:電源電路、串口通信電路、MCU基本電路、燒寫接口、顯示模塊、AD/DA轉(zhuǎn)換模塊、輸入模塊、IIC存儲(chǔ)模塊等其他電路模塊電路。控制板尺寸不超過60*60mm,便于安裝。CPU硬件軟件全部開放,除能完成對(duì)小車控制外,還能使用本實(shí)驗(yàn)板完成單片機(jī)所有基礎(chǔ)實(shí)驗(yàn)。供電范圍寬泛,支持5v~9v的電壓,干電池或鋰電池都適用。控制板含3A6V的穩(wěn)壓芯片,可為舵機(jī)提供6v額定電壓。

4.2傳感器的選擇
? ?? ? 灰度傳感器又稱黑標(biāo)傳感器,可以幫助進(jìn)行黑線的跟蹤,可以識(shí)別白色背景中的黑色區(qū)域,或懸崖邊緣。尋線信號(hào)可以提供穩(wěn)定的輸出信號(hào),使尋線更準(zhǔn)確更穩(wěn)定。有效距離在0.7cm~3cm之間。
? ?? ? 工作電壓:4.7~5.5V,
? ?? ? 工作電流:1.2mA。
? ?? ? ① 固定孔,便于用螺絲將模塊固定于機(jī)器人上;
? ?? ? ② 四芯輸入線接口,連接四芯輸入線;
? ?? ? ③ 黑標(biāo)/白標(biāo)傳感器元件,用于檢測(cè)黑線/白線信號(hào)。

4.3語音模塊
? ?? ? 語音處理技術(shù)是下一代多模式交互的人機(jī)界面設(shè)計(jì)中的核心技術(shù)之一。隨著消費(fèi)類電子產(chǎn)品中對(duì)于高性能、高穩(wěn)健性的語音接口需求的快速增加,嵌入式語音處理技術(shù)快速發(fā)展。
? ?? ? 根據(jù)市場(chǎng)對(duì)嵌入式語音識(shí)別系統(tǒng)的需求,探索者推出了新的語音識(shí)別模塊。該模塊采用了基于helios-adsp新一代中大詞匯語音識(shí)別協(xié)處理方案的語音識(shí)別專用芯片HBR740,非特定人語音識(shí)別技術(shù)可對(duì)用戶的語音進(jìn)行識(shí)別,支持中文音素識(shí)別,可任意指定中文識(shí)別詞條(小于8個(gè)漢字),單次識(shí)別可支持1000條以上的語音命令,安靜環(huán)境下,標(biāo)準(zhǔn)普通話,識(shí)別率大于95%,可自動(dòng)檢測(cè)環(huán)境噪聲,噪聲環(huán)境下也能保證較好的識(shí)別率。
4.4電動(dòng)機(jī)的選擇
? ?? ? 我們經(jīng)過討論確定選用輪式驅(qū)動(dòng),但是考慮到只是為了完成自主行走功能,實(shí)驗(yàn)也無需越障爬坡,所以我們選擇雙軸直流電機(jī)作為與輪子配合的驅(qū)動(dòng)電機(jī)。

? ?? ? 除了驅(qū)動(dòng)機(jī)器人需要引用電機(jī),檢測(cè)功能也會(huì)需要電機(jī)。由于舵機(jī)的可控性強(qiáng),可以在工作范圍內(nèi)精確控制電機(jī)的轉(zhuǎn)動(dòng)角度,而快遞機(jī)器人的主要工作就是“識(shí)別快遞、精確定位、作出處理”,所以舵機(jī)能夠?yàn)橹悄芸爝f付件機(jī)器人的工作提供極大的便利。四個(gè)舵機(jī)使得機(jī)器人有了四個(gè)自由度,工作范圍由線性轉(zhuǎn)變?yōu)槊嫘?#xff0c;大大提高了機(jī)器人的工作效率。
5. 視覺部分
5.1 訓(xùn)練神經(jīng)網(wǎng)絡(luò)模型
通過對(duì)大量的圖像收集,在Edge Impulse進(jìn)行圖像分類、統(tǒng)一貼標(biāo)簽和訓(xùn)練對(duì)應(yīng)的數(shù)據(jù)集,以此完成在識(shí)別過程中的識(shí)別不穩(wěn)定以及減少錯(cuò)誤信息的傳遞,多次調(diào)整圖片訓(xùn)練數(shù)據(jù)集來提高匹配準(zhǔn)確率。




5.2 灰度轉(zhuǎn)化(輪廓提取)以及畸變圖像處理? ?
① 灰度轉(zhuǎn)化
? ?? ? 通過灰度變換來使圖像對(duì)比度擴(kuò)展,圖像清晰,特征明顯,有選擇的突出圖像感興趣的特征或者去抑制圖像中不需要的特征,進(jìn)而更加有效的改變圖像的直方圖分布,使得像素的分布更加均勻,從而提高圖像識(shí)別精度。


? ?? ? 以12數(shù)字為例,1代表通道第一層,2代表第二個(gè)(從左到右)。先進(jìn)行整體分開顯示,再進(jìn)行判斷快遞所在的位置,來傳回下位機(jī)具體的信息返回值。為了提升識(shí)別的準(zhǔn)確值,在與訓(xùn)練模型匹配時(shí),再去使用輪廓提取的方法,提取出數(shù)字的形狀。
② 輪廓提取算法
? ?? ? 使用閉運(yùn)算的方法,即梯度=膨脹-腐蝕,得到圖像的輪廓外形,通過使用findcontour ()函數(shù),對(duì)灰度圖處理過后的圖像,找取邊界點(diǎn)的坐標(biāo),存儲(chǔ)到contours參數(shù)中,運(yùn)用drawcontours繪制輪廓線。
下面是findcontour函數(shù)的六個(gè)參數(shù)值:

③ 畸變矯正處理
? ?? ? 在測(cè)試識(shí)別時(shí)出現(xiàn)了識(shí)別精度低,圖像信息獲取不全,識(shí)別效率低等問題,為此我們采用圖像畸變矯正處理,以提高識(shí)別精度和效率。
? ?? ? 畸變矯正處理是像差的一種,在人們的感官上看原本直線變成了曲線,但是圖像的信息不會(huì)丟失,調(diào)用openmv官方庫中的庫函數(shù)進(jìn)行圖像的處理。對(duì)鏡頭進(jìn)行了畸變矯正,以去除鏡頭濾波造成的圖像魚眼效果。

5.3 取件抓取視覺流程圖
三、程序代碼
1. 示例程序
1.1上位機(jī)程序
① data_collection.py
import sensor, lcdfrom Maix import GPIOfrom fpioa_manager import fmfrom board import board_infoimport os, sysimport timeimport imageimport KPU as kpusensor.reset()sensor.set_pixformat(sensor.RGB565)sensor.set_framesize(sensor.QVGA)set_windowing = (224,224)sensor.set_windowing(set_windowing)sensor.set_hmirror(0)sensor.run(1)#####Other####deinit_flag = False #用于在拍照的時(shí)候?qū)olo模型卸載,等到循環(huán)重新開始時(shí)再加載,減少內(nèi)存消耗################## lcd config ####lcd.init(type=1, freq=15000000)lcd.rotation(2)#### boot key ####boot_pin = 16fm.register(boot_pin, fm.fpioa.GPIOHS0)key = GPIO(GPIO.GPIOHS0, GPIO.PULL_UP)####################################KPU#######task = kpu.load("/sd/number.kmodel")f=open("num_anchors.txt","r") #修改錨點(diǎn)處anchor_txt=f.read()L=[]for i in anchor_txt.split(","): #直接讀出來的i是str類型L.append(float(i))anchor=tuple(L)f.close()a = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)f=open("num_labels.txt","r") #修改錨點(diǎn)處labels_txt=f.read()labels = labels_txt.split(",")f.close()###################### main ####def capture_main(key):global deinit_flag,anchor,taskdef draw_string(img, x, y, text, color, scale, bg=None , full_w = False):if bg:if full_w:full_w = img.width()else:full_w = len(text)*8*scale+4img.draw_rectangle(x-2,y-2, full_w, 16*scale, fill=True, color=bg)img = img.draw_string(x, y, text, color=color,scale=scale)return imgdef del_all_images():os.chdir("/sd")images_dir = "cap_images"if images_dir in os.listdir():os.chdir(images_dir)types = os.listdir()for t in types:os.chdir(t)files = os.listdir()for f in files:os.remove(f)os.chdir("..")os.rmdir(t)os.chdir("..")os.rmdir(images_dir)# del_all_images()os.chdir("/sd")dirs = os.listdir()images_dir = "cap_images" #cap_images_1last_dir = 0for d in dirs: #把每個(gè)已經(jīng)存在的以cap_images開頭的目錄遍歷一遍得到本次拍照的總目錄序號(hào)if d.startswith(images_dir):if len(d) > 11:n = int(d[11:])if n > last_dir:last_dir = n'''這一段的作用是每次上電都重新創(chuàng)建一個(gè)新的最大文件夾'''#images_dir = "{}_{}".format(images_dir, last_dir+1)#print("save to ", images_dir)#if images_dir in os.listdir():##print("please del cap_images dir")#img = image.Image()#img = draw_string(img, 2, 200, "please del cap_images dir", color=lcd.WHITE,scale=1, bg=lcd.RED)#lcd.display(img)#sys.exit(1)#os.mkdir(images_dir)'''這一段的作用是每次上電只有手動(dòng)才重新創(chuàng)建一個(gè)新的最大文件夾,默認(rèn)是從已經(jīng)創(chuàng)建的編號(hào)最大的文件夾開始'''images_dir = "{}_{}".format(images_dir, last_dir)if not images_dir in os.listdir():os.mkdir(images_dir)'''開機(jī)檢測(cè)第二級(jí)目錄的起始位置'''os.chdir("/sd/{}".format(images_dir))dirs = os.listdir()last_type = 0for d in dirs: #把每個(gè)已經(jīng)存在的以cap_images開頭的目錄遍歷一遍得到本次拍照的總目錄序號(hào)n = int(d[0:])if n > last_type:last_type = nif not str(last_type) in os.listdir(): #不存在要重新創(chuàng)建os.chdir("/sd")os.mkdir("{}/{}".format(images_dir, str(last_type)))'''開機(jī)檢測(cè)第三級(jí)目錄的起始位置'''os.chdir("/sd/{}/{}".format(images_dir,last_type))dirs = os.listdir()last_image = -1for d in dirs: #把每個(gè)已經(jīng)存在的以cap_images開頭的目錄遍歷一遍得到本次拍照的總目錄序號(hào)n = int(d[len(str(last_type))+1:][:-4]) #去除.jpgif n > last_image:last_image = nos.chdir("/sd")last_cap_time = 0 #用于記錄按鍵松手前按下時(shí)候的系統(tǒng)時(shí)間last_btn_status = 1 #用于松手檢測(cè)save_dir = last_type #change type 第二級(jí)目錄,默認(rèn)跟上次開機(jī)目錄一樣save_count = last_image + 1 #保存的第幾張圖片while(True):if deinit_flag:task = kpu.load("/sd/number.kmodel")a = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)deinit_flag = Falseimg0 = sensor.snapshot()code = kpu.run_yolo2(task, img0)if code:for i in code:a=img0.draw_rectangle(i.rect(),(0,255,0),2)lcd.draw_string(i.x()+45, i.y()-5, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.GREEN)b=str(labels[i.classid()])b.replace(" ","")if set_windowing:img = image.Image()img = img.draw_image(img0, (img.width() - set_windowing[0])//2, img.height() - set_windowing[1]) #//2取整else:img = img0.copy()if key.value() == 0:time.sleep_ms(30)if key.value() == 0 and (last_btn_status == 1) and (time.ticks_ms() - last_cap_time > 500):last_btn_status = 0last_cap_time = time.ticks_ms()else:#2秒內(nèi)直接拍照,四秒內(nèi)提示切換數(shù)字種類,6秒內(nèi)提示切換總目錄,8秒后切換總目錄if time.ticks_ms() - last_cap_time > 4000 and time.ticks_ms() - last_cap_time <6000:img = draw_string(img, 2, 200, "release to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)elif time.ticks_ms() - last_cap_time > 8000:img = draw_string(img, 2, 200, "release to change images directory", color=lcd.WHITE,scale=1, bg=lcd.RED)elif time.ticks_ms() - last_cap_time <= 8000 and time.ticks_ms() - last_cap_time >6000:img = draw_string(img, 2, 200, "release to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)img = draw_string(img, 2, 160, "keep push to images directory", color=lcd.WHITE,scale=1, bg=lcd.RED)elif time.ticks_ms() - last_cap_time <= 4000:img = draw_string(img, 2, 200, "release to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)if time.ticks_ms() - last_cap_time > 2000:img = draw_string(img, 2, 160, "keep push to change type", color=lcd.WHITE,scale=1, bg=lcd.RED)else:time.sleep_ms(30)if key.value() == 1 and (last_btn_status == 0):a = kpu.deinit(task)del taskdeinit_flag = Trueif time.ticks_ms() - last_cap_time >= 4000 and time.ticks_ms() - last_cap_time < 8000:img = draw_string(img, 2, 200, "change object type", color=lcd.WHITE,scale=1, bg=lcd.RED)lcd.display(img)time.sleep_ms(1000)save_dir += 1save_count = 0dir_name = "{}/{}".format(images_dir, save_dir)os.mkdir(dir_name)elif time.ticks_ms() - last_cap_time >= 8000:img = draw_string(img, 2, 200, "change images directory", color=lcd.WHITE,scale=1, bg=lcd.RED)lcd.display(img)time.sleep_ms(1000)last_dir += 1save_dir = 0save_count = 0images_dir = "{}_{}".format('cap_images', last_dir)os.mkdir(images_dir)print("save to ", images_dir)dir_name = "{}/{}".format(images_dir, save_dir)os.mkdir(dir_name)else:draw_string(img, 2, 200, "capture image {}".format(save_count), color=lcd.WHITE,scale=1, bg=lcd.RED)lcd.display(img)f_name = "{}/{}/{}.jpg".format(images_dir, save_dir, str(save_dir)+'_'+str(save_count))img0.save(f_name, quality=95) #報(bào)錯(cuò)ENOENT表示路徑不存在save_count += 1last_btn_status = 1img = draw_string(img, 2, 0, "will save to {}/{}/{}.jpg".format(images_dir, save_dir, str(save_dir)+'_'+str(save_count)), color=lcd.WHITE,scale=1, bg=lcd.RED, full_w=True)lcd.display(img)del imgdel img0def main():try:capture_main(key)except Exception as e:print("error:", e)import uios = uio.StringIO()sys.print_exception(e, s)s = s.getvalue()img = image.Image()img.draw_string(0, 0, s)lcd.display(img)main()
② shijue.py
import sensorimport imageimport lcdimport KPU as kpulcd.init()sensor.reset()sensor.set_pixformat(sensor.RGB565)sensor.set_framesize(sensor.QVGA)sensor.set_windowing((224, 224))sensor.set_hmirror(0)sensor.run(1)task = kpu.load(0x300000)anchor=[] #放你的標(biāo)簽labels = [] #放anchora = kpu.init_yolo2(task, 0.6, 0.3, 5, anchor)while(True):img = sensor.snapshot()code = kpu.run_yolo2(task, img)if code:for i in code:a=img.draw_rectangle(i.rect(),(0,255,0),2)a = lcd.display(img)for i in code:lcd.draw_string(i.x()+45, i.y()-5, labels[i.classid()]+" "+'%.2f'%i.value(), lcd.WHITE,lcd.GREEN)else:a = lcd.display(img)a = kpu.deinit(task)
1.2下位機(jī)程序
① jixiebi.ino
#include<Servo.h>//使用servo庫Servo base,fArm,rArm,claw;//創(chuàng)建4個(gè)servo對(duì)象//base(底座舵機(jī)11)fArm(第三關(guān)節(jié)3)rArm(第二關(guān)節(jié)12)claw(爪4)#include <SoftwareSerial.h>//實(shí)例化軟串口,設(shè)置虛擬輸入輸出串口。SoftwareSerial BT(2, 3); // 設(shè)置數(shù)字引腳2是arduino的RX端,3是TX端VoiceRecognition Voice;//聲明一個(gè)語音識(shí)別對(duì)象#define Led 8 //定義LED控制引腳#define pi 3.1415926void dateProcessing();void armDataCmd(char serialCmd);//實(shí)現(xiàn)機(jī)械臂在openmv指示下工作void armLanYaCmd(char serialCmd);void servoCmd(char serialCmd,int toPos);//電機(jī)旋轉(zhuǎn)功能函數(shù)void vel_segmentation(int fromPos,int toPos,Servo arm_servo);void reportStatus();//電機(jī)狀態(tài)信息控制函數(shù)void Arminit();void GrabSth();//建立4個(gè)int型變量存儲(chǔ)當(dāng)前電機(jī)角度值,設(shè)定初始值int basePos=70;int rArmPos=90;int fArmPos=30;int clawPos=45;int data2dArray[4][5] = { //建立二維數(shù)組用以控制四臺(tái)舵機(jī){0, 45, 90, 135, 180},{45, 90, 135, 90, 45},{135, 90, 45, 90, 135},{180, 135, 90, 45, 0}};//存儲(chǔ)電機(jī)極限值const int PROGMEM baseMin=0;const int PROGMEM baseMax=180;const int PROGMEM rArmMin=0;//留一定裕度空間const int PROGMEM rArmMax=180;//留一定裕度空間const int PROGMEM fArmMin=0;const int PROGMEM fArmMax=270;const int PROGMEM clawMin=0;const int PROGMEM clawMax=54;const int PROGMEM Dtime = 15;//機(jī)械臂運(yùn)動(dòng)延遲時(shí)間,通過改變?cè)撝祦砜刂茩C(jī)械臂運(yùn)動(dòng)速度//機(jī)械臂運(yùn)動(dòng)角速度為:π*1000/(180*Dtime) rad/sbool mode = 0;//mode = 1:指令模式;mode = 0:藍(lán)牙模式const int PROGMEM moveStep = 5;//按下按鍵,舵機(jī)的位移量void serialEvent(){while (Serial.available ()) {[char inChar = (char)Serial.read();shuju += inChar;if (inChar == (' n'){[stringComplete = true;}}}void yuyin();{switch(Voice.read()) //判斷識(shí)別{case 0: //若是指令“kai deng”digitalWrite(Led,HIGH); //點(diǎn)亮LEDbreak;case 1: //若是指令“guan deng”digitalWrite(Led,LOW);//熄滅LEDbreak;default:break;}}void setup() {// put your setup code here, to run once:Serial.begin(9600); //設(shè)置arduino的串口波特率與藍(lán)牙模塊的默認(rèn)值相同為9600BT.begin(9600); //設(shè)置虛擬輸入輸出串口波特率與藍(lán)牙模塊的默認(rèn)值相同為9600Serial.println("HELLO"); //如果連接成功,在電腦串口顯示HELLO,在藍(lán)牙串口顯示helloBT.println("hello");pinMode(Led,OUTPUT); //初始化LED引腳為輸出模式digitalWrite(Led,LOW); //LED引腳低電平Voice.init(); //初始化VoiceRecognition模塊Voice.addCommand("kai deng",0); //添加指令,參數(shù)(指令內(nèi)容,指令標(biāo)簽(可重復(fù)))Voice.addCommand("qidongixiebi",0);Voice.addCommand("guan deng",1); //添加指令,參數(shù)(指令內(nèi)容,指令標(biāo)簽(可重復(fù)))Voice.addCommand("tingzhi",1);Voice.start();//開始識(shí)別base.attach(12);delay(200);rArm.attach(9);delay(200);fArm.attach(5);delay(200);claw.attach(6);delay(200);// Serial.begin(9600);dateProcessing();base.write(90);delay(10);fArm.write(140);delay(10);rArm.write(90);delay(10);claw.write(30);delay(10);}void loop() {// put your main code here, to run repeatedly:if(Serial.available()>0){ //判斷串口緩沖區(qū)是否有數(shù)值char serialCmd = Serial.read(); //將Arduino串口輸入的字符賦給serialCmdSerial.println(serialCmd); //在串口監(jiān)視器打印出輸入的字符serialCmdBT.println(serialCmd); //藍(lán)牙模塊的串口(在手機(jī)屏幕上顯示)打印出電腦輸入的字符serialCmd}//藍(lán)牙模塊有數(shù)據(jù)輸入,就顯示在電腦上if(BT.available()>0){int ch = BT.read(); //讀取藍(lán)牙模塊獲得的數(shù)據(jù)Serial.println(ch);}if(Serial.available()>0){char serialCmd=Serial.read();//read函數(shù)為按字節(jié)讀取,要注意!delay(10);if(mode == 1){armDataCmd(serialCmd);//openmv控制}else{armLanYaCmd(serialCmd);//藍(lán)牙控制機(jī)械臂}}}void dateProcessing(){//數(shù)據(jù)處理}void armDataCmd(char serialCmd){//實(shí)現(xiàn)機(jī)械臂在openmv指令下工作if(serialCmd == 'b' || serialCmd == 'c' || serialCmd == 'f' || serialCmd == 'r'){Serial.print("serialCmd = ");Serial.print(serialCmd);int servoData = Serial.parseInt();//讀取指令中的電機(jī)轉(zhuǎn)角servoCmd(serialCmd,servoData);}else{{//x的位置int X location;int Y location;//Y的位置//Y的位置int B location;string X str;String Y str;x location = foundstr('X');Y location = foundstr('Y');x str=shujuduan(X location+1,Y location); //x到y(tǒng)的位置Xlocation = foundstr('Y');B location = foundstr('B');Y str=shujuduan(Y location+1,B location); //Y到B的位置Centerx-x str.toInt();//轉(zhuǎn)成可以用的整型CenterY=Y str.toInt();Serial.print("Centerx:");Serial.print(Centerx);Serial.print("Centery: ");Serial.printIn(Centery);for (j1 = 0; j1 < 180; j1++)j1 *= RAD2ANG;j3 = acos(pow(a, 2) + pow(b, 2) + pow(Ll, 2) - pow(L2, 2) - pow(L3, 2) - 2 * a*L1*sin(1) - 2 * b*L1*cos(j1)) / (2 * L2*L3);//if (abs(ANG2RAD(j3)) >= 135) [ j1 = ANG2RAD(j1); continue; }m = L2 * sin(j1) + L3 * sin(j1)*cos(j3) + L3 * cos(j1)*sin(j3);n = L2 * cos(j1) + L3 * cos (j1)*cos(j3) - L3 * sin(j1)*sin(j3);t = a - Ll *sin(jl);p = pow(pow(n,2) + pow(m,2),0.5);q = asin(m / p);j2 = asin(t / p) - q;x1 = (Ll * sin(j1) + L2 * sin(jl + j2) + L3 * sin(jl + j2 + j3))*cos(j0);y1 =(Ll *sin(jl) + L2 *sin(jl + j2) + L3 * sin(jl + j2 + j3))*sin(jo);zl = Ll * cos(j1) + L2 * cos(jl + j2) + L3 * cos(jl + j2 + j3);j1 = ANG2RAD(j1) ;j2 = ANG2RAD(j2);j3 = ANG2RAD(j3) ;if (xl<(x + 0.1) && x1 >(x - 0.1) && yly + 0.1) && yl >ly - 0.1) && zl(z + 0.1) && 21 >(2 - 0.1))if(j0>0&&j0<180&&j1>0&&j1<180&&j2>0&&j2<180&&j3>0&&j3<180){Serial.println(ANG2RAD(j0));Serial.println( j1);Serial.println( j2);Serial.println( j3);Serial.println( x1);Serial.println( yl);Serial.println( z1);for (int i = 0; i <= 4; i++){ base.write(data2dArray[0][i]); //base舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第1“行”元素delay(100); rArm.write(data2dArray[1][i]); //rArm舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第2“行”元素delay(100); fArm.write(data2dArray[2][i]); //fArm舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第3“行”元素delay(100); claw.write(data2dArray[3][i]); //claw舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第4“行”元素delay(500); }for (int i = 4; i >= 0; i--){base.write(data2dArray[0][i]); //base舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第1“行”元素delay(100); rArm.write(data2dArray[1][i]); //rArm舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第2“行”元素delay(100); fArm.write(data2dArray[2][i]); //fArm舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第3“行”元素delay(100); claw.write(data2dArray[3][i]); //claw舵機(jī)對(duì)應(yīng)data2dArray數(shù)組中第4“行”元素delay(500); }}}}void armLanYaCmd(char serialCmd){//實(shí)現(xiàn)機(jī)械臂在藍(lán)牙模式下工作int baseJoyPos;int rArmJoyPos;int fArmJoyPos;int clawJoyPos;switch(serialCmd){case 'a'://小臂正轉(zhuǎn)fArmJoyPos = fArm.read() - moveStep;servoCmd('f',fArmJoyPos);delay(10);break;case 's'://底盤左轉(zhuǎn)baseJoyPos = base.read() + moveStep;servoCmd('b',baseJoyPos);delay(10);break;case 'd'://大臂正轉(zhuǎn)rArmJoyPos = rArm.read() + moveStep;servoCmd('r',rArmJoyPos);delay(10);break;case 'w'://鉗子閉合clawJoyPos = claw.read() - moveStep;servoCmd('c',clawJoyPos);delay(10);break;case '4'://小臂反轉(zhuǎn)fArmJoyPos = fArm.read() + moveStep;servoCmd('f',fArmJoyPos);delay(10);break;case '5'://底盤右轉(zhuǎn)baseJoyPos = base.read() - moveStep;servoCmd('b',baseJoyPos);delay(10);break;case '6'://大臂反轉(zhuǎn)rArmJoyPos = rArm.read() - moveStep;servoCmd('r',rArmJoyPos);delay(10);break;case '8'://鉗子張開clawJoyPos = claw.read() + moveStep;servoCmd('c',clawJoyPos);delay(10);break;case 'i': //輸出電機(jī)狀態(tài)信息reportStatus();delay(10);break;case 'l'://電機(jī)位置初始化Arminit();delay(10);break;case 'g'://抓取功能GrabSth();delay(10);break;case 'm':Serial.println("meArm has been changed into Instruction Mode");mode = 1;break;default:Serial.println();Serial.println("【Error】出現(xiàn)錯(cuò)誤!");Serial.println();break;}}void servoCmd(char serialCmd,int toPos){//電機(jī)旋轉(zhuǎn)功能函數(shù)Serial.println("");Serial.print("Command:Servo ");Serial.print(serialCmd);Serial.print(" to ");Serial.print(toPos);Serial.print(" at servoVelcity value ");Serial.print(1000*pi/(180*Dtime));Serial.println(" rad/s.");int fromPos;//起始位置switch(serialCmd){case 'b':if(toPos >= baseMin && toPos <= baseMax){fromPos = base.read();vel_segmentation(fromPos,toPos,base);basePos = toPos;Serial.print("Set base servo position value: ");Serial.println(toPos);Serial.println();break;}else{Serial.println("【W(wǎng)arning】Base Servo Position Value Out Of Limit!");Serial.println();return;}break;case 'r':if(toPos >= rArmMin && toPos <= rArmMax){fromPos = rArm.read();vel_segmentation(fromPos,toPos,rArm);rArmPos = toPos;Serial.print("Set rArm servo position value: ");Serial.println(toPos);Serial.println();break;}else{Serial.println("【W(wǎng)arning】Base Servo Value Position Out Of Limit!");Serial.println();return;}break;case 'f':if(toPos >= fArmMin && toPos <= fArmMax){fromPos = fArm.read();vel_segmentation(fromPos,toPos,fArm);fArmPos = toPos;Serial.print("Set fArm servo position value: ");Serial.println(toPos);Serial.println();break;}else{Serial.println();Serial.println("【W(wǎng)arning】Base Servo Value Position Out Of Limit!");Serial.println();return;}break;case 'c':if(toPos >= clawMin && toPos <= clawMax){fromPos = claw.read();vel_segmentation(fromPos,toPos,claw);clawPos = toPos;Serial.print("Set claw servo position value: ");Serial.println(toPos);Serial.println();break;}else{Serial.println("【W(wǎng)arning】Base Servo Position Value Out Of Limit!");Serial.println();return;}break;}}void vel_segmentation(int fromPos,int toPos,Servo arm_servo){//速度控制函數(shù)//該函數(shù)通過對(duì)位置的細(xì)分和延時(shí)實(shí)現(xiàn)電機(jī)速度控制//這樣的控制平均角速度大約為:1°/15ms = 1.16 rad/sif(fromPos < toPos){for(int i=fromPos;i<=toPos;i++){arm_servo.write(i);delay(Dtime);}}else{for(int i=fromPos;i>=toPos;i--){arm_servo.write(i);delay(Dtime);}}}void reportStatus(){//電機(jī)狀態(tài)信息控制函數(shù)Serial.println();Serial.println("---Robot-Arm Status Report---");Serial.print("Base Position: ");Serial.println(basePos);Serial.print("Claw Position: ");Serial.println(clawPos);Serial.print("rArm Position: ");Serial.println(rArmPos);Serial.print("fArm Position: ");Serial.println(fArmPos);Serial.println("-----------------------------");Serial.println("Motor Model:Micro Servo 9g-SG90");Serial.println("Motor size: 23×12.2×29mm");Serial.println("Work temperature:0-60℃");Serial.println("Rated voltage: 5V");Serial.println("Rated torque: 0.176 N·m");Serial.println("-----------------------------");}void Arminit(){//電機(jī)初始化函數(shù)//將電機(jī)恢復(fù)初始狀態(tài)char ServoArr[4] = {'c','f','r','b'};for(int i=0;i<4;i++){servoCmd(ServoArr[i],90);}delay(200);Serial.println("meArm has been initized!");Serial.println();}void GrabSth(){//抓取函數(shù)//抓取功能int GrabSt[4][2] = {{'b',135},{'r',150},{'f',30},{'c',40}};for(int i=0;i<4;i++){servoCmd(GrabSt[i][0],GrabSt[i][1]);}}
② sketch_nov05a.ino
char serial_data;// 將從串口讀入的消息存儲(chǔ)在該變量中#define STOP 0#define RUN 1#define BACK 2#define LEFT 3#define RIGHT 4VoiceRecognition Voice;//聲明一個(gè)語音識(shí)別對(duì)象int a1 = 6;//左電機(jī)1int a2 = 7;//左電機(jī)2int b1 = 8;//右電機(jī)1int b2 = 9;//右電機(jī)2int sensorLeft = 3; //從車頭方向的最右邊開始排序 探測(cè)器int sensorRight = 2;int ENA = 10;//L298N使能端左int ENB = 11;//L298N使能端右int SL;//左邊灰度傳感器int SR;//右邊灰度傳感器void setup(){Serial.begin(9600);pinMode(a1, OUTPUT);pinMode(a2, OUTPUT);pinMode(b1, OUTPUT);pinMode(b2, OUTPUT);pinMode(ENA, OUTPUT);pinMode(ENB, OUTPUT);pinMode(sensorLeft, INPUT);//尋跡模塊引腳初始化pinMode(sensorRight, INPUT);Voice.init();//初始化VoiceRecognition模塊Voice.addCommand("lu kou yi",1);//添加指令,參數(shù)(指定內(nèi)容,指令標(biāo)簽)Voice.addCommand("lu kou er",2);//添加指令,參數(shù)(指定內(nèi)容,指令標(biāo)簽)Voice.addCommand("lu kou san",3);//添加指令,參數(shù)(指定內(nèi)容,指令標(biāo)簽)Voice.addCommand("lu kou si",4);//添加指令,參數(shù)(指定內(nèi)容,指令標(biāo)簽)Voice.start();}void loop(){digitalWrite(ENA,HIGH);digitalWrite(ENB,HIGH);SL = digitalRead(sensorLeft);SR = digitalRead(sensorRight);switch(Voice.read())//判斷識(shí)別{case 1://指令是 lu kou yicrossing1();delay(3000);WORK(STOP);//停下通過openmv識(shí)別delay(5000);WORK(RUN);//識(shí)別完畢繼續(xù)前進(jìn)delay(2000);//前進(jìn)兩秒后停止WORK(STOP);serial_data = Serial.read();//當(dāng)抓取完成后發(fā)送一個(gè)wif( serial_data == 'w' ){WORK(BACK);}if(SR == HIGH & SL == HIGH)//再次識(shí)別到黑線時(shí)右轉(zhuǎn){WORK(RIGHT);}tracing();//繼續(xù)前進(jìn)break;case 2://指令是 lu lou ercrossing2();delay(3000);WORK(STOP);//停下通過openmv識(shí)別delay(5000);WORK(RUN);//識(shí)別完畢繼續(xù)前進(jìn)delay(2000);//前進(jìn)兩秒后停止準(zhǔn)備抓取WORK(STOP);serial_data = Serial.read();//當(dāng)抓取完成后發(fā)送一個(gè)wif( serial_data == 'w' ){WORK(BACK);}if(SR == HIGH & SL == HIGH)//再次識(shí)別到黑線時(shí)左轉(zhuǎn){WORK(LEFT);}tracing();//繼續(xù)前進(jìn)break;case 3:tracing();if(SR == HIGH & SL == HIGH){crossing3();}delay(3000);WORK(STOP);//停下通過openmv識(shí)別delay(5000);WORK(RUN);//識(shí)別完畢繼續(xù)前進(jìn)delay(2000);//前進(jìn)兩秒后停止準(zhǔn)備抓取WORK(STOP);serial_data = Serial.read();//當(dāng)抓取完成后發(fā)送一個(gè)wif( serial_data == 'w' ){WORK(BACK);}if(SR == HIGH & SL == HIGH)//再次識(shí)別到黑線時(shí)右轉(zhuǎn){WORK(RIHGT);}tracing();//繼續(xù)前進(jìn)break;case 4:tracing();if(SR == HIGH & SL == HIGH){crossing4();}delay(3000);WORK(STOP);//停下通過openmv識(shí)別delay(5000);WORK(RUN);//識(shí)別完畢繼續(xù)前進(jìn)delay(2000);//前進(jìn)兩秒后停止準(zhǔn)備抓取WORK(STOP);serial_data = Serial.read();//當(dāng)抓取完成后發(fā)送一個(gè)wif( serial_data == 'w' ){WORK(BACK);}if(SR == HIGH & SL == HIGH)//再次識(shí)別到黑線時(shí)左轉(zhuǎn){WORK(LEFT);}tracing();//繼續(xù)前進(jìn)}}void WORK(int cmd){switch(cmd){case RUN:Serial.println("RUN"); //輸出狀態(tài)digitalWrite(a1, HIGH);digitalWrite(a2, LOW);analogWrite(leftPWM, 200);digitalWrite(b1, HIGH);digitalWrite(b2, LOW);analogWrite(rightPWM, 200);break;case BACK:Serial.println("BACK"); //輸出狀態(tài)digitalWrite(a1, LOW);digitalWrite(a2, HIGH);analogWrite(leftPWM, 200);digitalWrite(b1, LOW);digitalWrite(b2, HIGH);analogWrite(rightPWM, 200);break;case LEFT:Serial.println("TURN LEFT"); //輸出狀態(tài)digitalWrite(a1, HIGH);digitalWrite(a2, LOW);analogWrite(leftPWM, 100);digitalWrite(b1, LOW);digitalWrite(b2, HIGH);analogWrite(rightPWM, 200);break;case RIGHT:Serial.println("TURN RIGHT"); //輸出狀態(tài)digitalWrite(a1, LOW);analogWrite(leftPWM,200);digitalWrite(a2, HIGH);digitalWrite(b1, HIGH);digitalWrite(b2, LOW);analogWrite(rightPWM,100);break;default:Serial.println("STOP"); //輸出狀態(tài)digitalWrite(a1, LOW);digitalWrite(a2, LOW);digitalWrite(b1, LOW);digitalWrite(b2, LOW);}}void crossing1()//路口1函數(shù){if (SL == LOW && SR == LOW)//左右兩邊都沒有檢測(cè)到黑線{WORK(RUN);}if (SL == HIGH & SR == LOW)//左側(cè)檢測(cè)到黑線{WORK(LEFT);}if (SR == HIGH & SL == LOW)//右側(cè)檢測(cè)到黑線{WORK(RIGHT);}if (SR == HIGH & SL == HIGH)//左右兩邊都檢測(cè)到黑線{WORK(RIGHT);}}void crossing2()//路口2函數(shù){if (SL == LOW && SR == LOW)//左右兩邊都沒有檢測(cè)到黑線{WORK(RUN);}if (SL == HIGH & SR == LOW)//左側(cè)檢測(cè)到黑線{WORK(LEFT);}if (SR == HIGH & SL == LOW)//右側(cè)檢測(cè)到黑線{WORK(RIGHT);}if (SR == HIGH & SL == HIGH)//左右兩邊都檢測(cè)到黑線{WORK(LEFT);}}void crossing3()//路口3函數(shù){if (SL == LOW && SR == LOW)//左右兩邊都沒有檢測(cè)到黑線{WORK(RUN);}if (SL == HIGH & SR == LOW)//左側(cè)檢測(cè)到黑線{WORK(LEFT);}if (SR == HIGH & SL == LOW)//右側(cè)檢測(cè)到黑線{WORK(RIGHT);}if (SR == HIGH & SL == HIGH)//左右兩邊都檢測(cè)到黑線{WORK(LEFT);void crossing4()//路口函數(shù){if (SL == LOW && SR == LOW)//左右兩邊都沒有檢測(cè)到黑線{WORK(RUN);}if (SL == HIGH & SR == LOW)//左側(cè)檢測(cè)到黑線{WORK(LEFT);}if (SR == HIGH & SL == LOW)//右側(cè)檢測(cè)到黑線{WORK(RIGHT);}if (SR == HIGH & SL == HIGH)//左右兩邊都檢測(cè)到黑線{WORK(RIGHT);void tracing(){if (SL == LOW && SR == LOW)//左右兩邊都沒有檢測(cè)到黑線{WORK(RUN);}if (SL == HIGH & SR == LOW)//左側(cè)檢測(cè)到黑線{WORK(LEFT);}if (SR == HIGH & SL == LOW)//右側(cè)檢測(cè)到黑線{WORK(RIGHT);}if (SR == HIGH & SL == HIGH)//左右兩邊都檢測(cè)到黑線{WORK(RUN);}}
更多詳細(xì)資料請(qǐng)參考?【S021】智能快遞付件機(jī)器人