前言
本人大四學(xué)生,電賽生涯已經(jīng)走到盡頭,一路上踩過不少坑,但運(yùn)氣也不錯(cuò)拿了兩年省一,思來想去,決定開始寫博客,將電賽經(jīng)驗(yàn)分享一二,能力有限,高手輕噴。
往期的博客講述了 K210 的感光元件模塊 sensor 的配置,機(jī)器視覺模塊 image 中部分函數(shù)的使用(目前是用 find_blobs 函數(shù)實(shí)現(xiàn)一些尋找不同顏色的目標(biāo)點(diǎn),尋找不同顏色的線,后面會(huì)更新更多 image 模塊中的函數(shù)使用方法),以及按鍵、LCD、LED的使用。
sensor 的學(xué)習(xí)筆記傳送門
【K210】K210學(xué)習(xí)筆記一——sensor
image 的學(xué)習(xí)筆記傳送門
【K210】K210學(xué)習(xí)筆記二——image
按鍵、LCD、LED的使用 的學(xué)習(xí)筆記傳送門
【K210】K210學(xué)習(xí)筆記三——按鍵、LCD、LED的使用
本文著重于 K210 的定時(shí)器配置及使用方法,結(jié)合往期代碼,做一個(gè)簡單的巡線小車。無需將目標(biāo)信息傳輸?shù)絊TM32,僅用K210上的定時(shí)器輸出PWM即可完成。主要講一下是怎么樣使用定時(shí)器的,另外跟隨目標(biāo)的邏輯是怎么樣的。若要將識(shí)別信息傳輸至STM32,可看本人往期博客,了解串口發(fā)送與接收,傳送門如下。
串口通信 傳送門
【串口通信】K210與STM32串口通信、K210與OpenMV串口通信
定時(shí)器
定時(shí)器配置
配置定時(shí)器需要導(dǎo)入一些模塊,這里連同PWM的模塊也一起導(dǎo)入,后面的配置就不需要導(dǎo)入了。
from machine import Timer, PWM # 從 machine 模塊中導(dǎo)入 定時(shí)器模塊 Timer 脈寬調(diào)制模塊 PWM
與往期一樣的,定義一個(gè)類來保存定時(shí)器的一些屬性,我個(gè)人喜歡定義類來保存,因?yàn)檫@樣可以提高效率,提高代碼可讀性,變量名稱看起來不會(huì)很怪,可以一下子知道這個(gè)變量是什么。
#__________________________________________________________________
# 定時(shí)器的使用
# 定義定時(shí)器屬性類
class timer_property():
cnt = 0 # 定時(shí)器計(jì)數(shù)值
cnt_max = 0 # 定時(shí)器計(jì)數(shù)值上限
period = 0 # 定時(shí)器周期
freq = 0 # 定時(shí)器頻率
然后就是實(shí)例化類,我是打算將定時(shí)器0配置為一個(gè)計(jì)數(shù)器,每次觸發(fā)定時(shí)器中斷,這個(gè)計(jì)數(shù)器的值加1,加到上限值,就將計(jì)數(shù)器的值置0,這樣我們就可以在 while 循環(huán)中,判斷這個(gè)計(jì)數(shù)器的值是否等于0,從而控制一些不需要高頻率執(zhí)行的函數(shù)的執(zhí)行周期(比如各種打印信息) ,這種方法會(huì)比之前博文中使用的計(jì)數(shù)器自增控制周期的方法 更準(zhǔn)確。但會(huì)存在一定的誤差的,這是因?yàn)槭窃?while 循環(huán)中做的判斷,while 循環(huán)的周期是不一定的(周期就是fps 比如fps等于20 則代表一秒會(huì)有20個(gè)循環(huán)),如果圖像識(shí)別的速度很慢(數(shù)據(jù)量大),那么 while 循環(huán)的周期就很長,可能一秒就只有幾次。
# 定時(shí)器0 配置_______________________________________________________
# 定時(shí)器0 實(shí)例化類
timer0 = timer_property() # 實(shí)例化定時(shí)器屬性類 timer_property() 為 timer0
timer0.cnt_max = 9 # 設(shè)定 定時(shí)器0 的計(jì)數(shù)值上限為 9
timer0.period = 100 # 設(shè)定 定時(shí)器0 的周期為 100
我在回調(diào)函數(shù)中只是做一個(gè)計(jì)數(shù)器值自增的操作,你也可以將需要間隔一定時(shí)間做的函數(shù)放到回調(diào)函數(shù)中,但需要注意的是,這個(gè)函數(shù)千萬不能占用太長的時(shí)間,否則得不償失。這也就是為什么我只在回調(diào)函數(shù)中做一個(gè)簡單的計(jì)數(shù)器值自增,將實(shí)際要控制執(zhí)行周期的函數(shù)放到 while 循環(huán)中的原因。
# 定時(shí)器0 定義回調(diào)函數(shù)
def timer0_back(tim0):
if timer0.cnt < timer0.cnt_max: # 若 定時(shí)器0 的計(jì)數(shù)值小于 定時(shí)器0 的計(jì)數(shù)值上限
timer0.cnt = timer0.cnt + 1 # 計(jì)數(shù)值自增
else:
timer0.cnt = 0 # 超出計(jì)數(shù)值上限 則計(jì)數(shù)值重置為0
然后就是定時(shí)器的初始化,這里配置的是定時(shí)器0,通道0,模式為周期性(模式有一次性、周期性、PWM,一般都是周期性或PWM,一次性使用的很少),周期的單位為ms,周期為設(shè)定值 timer0.period這個(gè)變量在之前被設(shè)置為100,也就是說,定時(shí)器0的周期是100ms。
# 定時(shí)器0 初始化
tim0 = Timer(Timer.TIMER0, # 定時(shí)器編號(hào) 定時(shí)器0
Timer.CHANNEL0, # 定時(shí)器通道 通道0
mode = Timer.MODE_PERIODIC, # 定時(shí)器模式 周期性
unit = Timer.UNIT_MS, # 定時(shí)器周期單位 ms
period = timer0.period, # 定時(shí)器周期 timer0.period 若 unit 為 Timer.UNIT_MS 則周期為 timer0.period ms
callback = timer0_back) # 定時(shí)器觸發(fā)中斷后執(zhí)行的回調(diào)函數(shù) timer0_back
定時(shí)器使用方法
使用方法就很簡單了,在 while 循環(huán)中,做一個(gè)判斷,當(dāng)定時(shí)器0的計(jì)數(shù)器值被重置為0的時(shí)候,執(zhí)行函數(shù)即可。我這里控制的是打印各參數(shù)信息的函數(shù),因?yàn)槲也恍枰@些參數(shù)發(fā)送的太快,發(fā)送太快我也看不清。你可以用它來控制你想控制的其他函數(shù),比如可以用來控制串口發(fā)送,如果這里加一句串口發(fā)送函數(shù)的話,那么這個(gè)串口發(fā)送函數(shù)就是1秒發(fā)送一次。
if timer0.cnt == 0: # 如果 timer0.cnt 等于 0 此步驟的目的是控制打印周期 不要打印的太快
print_sensor() # 打印sensor參數(shù)
print_blobs_property(black,"Black-") # 打印黑色色塊參數(shù)
print_blobs_property(red, "Red- ") # 打印紅色色塊參數(shù)
測試
將K210連接到MaixPy IDE,然后運(yùn)行即可,在串行終端可以看到這些參數(shù)差不多間隔1s就會(huì)被打印一次。
小車簡單巡線
PWM配置
首先還是定義一個(gè)電機(jī)類,來保存電機(jī)的信息,推薦大家養(yǎng)成這個(gè)習(xí)慣,對(duì)大家有好處。
# 定時(shí)器1 配置_______________________________________________________
# 電機(jī)類定義
class motor_property():
motor1 = 0 # 電機(jī)1 占空比
motor2 = 0 # 電機(jī)2 占空比
motor3 = 0 # 電機(jī)3 占空比
motor4 = 0 # 電機(jī)4 占空比
motor1_pin = 0 # 電機(jī)1 引腳
motor2_pin = 0 # 電機(jī)2 引腳
motor3_pin = 0 # 電機(jī)3 引腳
motor4_pin = 0 # 電機(jī)4 引腳
control_x = 0 # 被控坐標(biāo) x
control_y = 0 # 被控坐標(biāo) y
然后是實(shí)例化電機(jī)類,這里我只寫了電機(jī)1和電機(jī)2,如果你要做四驅(qū)小車,可以再寫電機(jī)3和電機(jī)4。 然后PWM輸出引腳(也就是電機(jī)所接的引腳)我是設(shè)置電機(jī)1的引腳為14,電機(jī)2的引腳為13。這個(gè)是K210開發(fā)板上紅燈和綠燈的引腳,主要是當(dāng)前放暑假在家,手頭上沒有小車,所以這里先用LED來觀察一下效果,看看邏輯是否正確,回校后我會(huì)在小車上進(jìn)行測試,并更新此博文。
# 實(shí)例化電機(jī)類
motor = motor_property() # 實(shí)例化電機(jī)類 motor_property() 為 motor
motor.motor1 = 50 # 電機(jī)1的占空比 初始設(shè)置為 50%
motor.motor2 = 50 # 電機(jī)2的占空比 初始設(shè)置為 50%
motor.motor1_pin = 14 # 電機(jī)1的引腳 14為紅燈引腳 這里先用燈的亮滅觀察效果
motor.motor2_pin = 13 # 電機(jī)2的引腳 13為綠燈引腳 這里先用燈的亮滅觀察效果
然后實(shí)例化一個(gè)定時(shí)器屬性類,保存一下PWM占空比的頻率信息。這里設(shè)置是1K,如果你需要改成其他數(shù)值也可以,比如10K。
# 定時(shí)器1 實(shí)例化類
timer1 = timer_property() # 實(shí)例化定時(shí)器屬性類 timer_property() 為 timer1
timer1.freq = 1000 # 設(shè)定 定時(shí)器1 的頻率為 1000
然后就是PWM定時(shí)器的設(shè)置,這里我用的是定時(shí)器1,我這里只設(shè)置了兩個(gè)通道,如果你要做四驅(qū)車,就復(fù)制一下這個(gè)代碼,改個(gè)名字即可。
# 定時(shí)器1 通道0 初始化
tim1_ch0 = Timer(Timer.TIMER1, # 定時(shí)器編號(hào) 定時(shí)器1
Timer.CHANNEL0, # 定時(shí)器通道 通道0
mode = Timer.MODE_PWM) # 定時(shí)器模式 PWM
# 定時(shí)器1 通道1 初始化
tim1_ch1 = Timer(Timer.TIMER1, # 定時(shí)器編號(hào) 定時(shí)器1
Timer.CHANNEL1, # 定時(shí)器通道 通道1
mode = Timer.MODE_PWM) # 定時(shí)器模式 PWM
然后是創(chuàng)建電機(jī)對(duì)象,需要注意的就是這里要跟上面的那些參數(shù)名字對(duì)應(yīng)的上。
# 創(chuàng)建對(duì)象 電機(jī)1 通道為 定時(shí)器1的通道0 頻率為 定時(shí)器1的頻率 占空比為 電機(jī)1的占空比 引腳為 電機(jī)1的引腳
motor1 = PWM(tim1_ch0, freq = timer1.freq, duty = motor.motor1, pin = motor.motor1_pin)
# 創(chuàng)建對(duì)象 電機(jī)2 通道為 定時(shí)器1的通道1 頻率為 定時(shí)器1的頻率 占空比為 電機(jī)2的占空比 引腳為 電機(jī)2的引腳
motor2 = PWM(tim1_ch1, freq = timer1.freq, duty = motor.motor2, pin = motor.motor2_pin)
控制小車巡線的方法
控制小車巡線就太簡單了,將攝像頭識(shí)別到的坐標(biāo),和要被控制到的坐標(biāo)值傳入即可,轉(zhuǎn)換成0到50之間的值,然后控制電機(jī)轉(zhuǎn)速即可。這不單單是巡線可以這樣做,你也可以控制小車跟隨其他目標(biāo),比如你可以拿一個(gè)紅色的紙,放到攝像頭的左邊,小車就會(huì)往左邊開。
# 定義電機(jī)占空比控制函數(shù)
def motor_control(motor, x):
val = 0
if x < motor.control_x: # 若 當(dāng)前坐標(biāo) 小于 被控坐標(biāo)x 即當(dāng)前狀態(tài)小車在目標(biāo)的 左邊
val = (motor.control_x - x) * 0.3125 # 獲取坐標(biāo)差值 并轉(zhuǎn)換為 0~50 之間的值
motor.motor1 = 50 - val # 減小 電機(jī)1 占空比 電機(jī)1為左電機(jī) 使小車右轉(zhuǎn)
motor.motor2 = 50 + val # 增大 電機(jī)2 占空比 電機(jī)2為右電機(jī) 使小車右轉(zhuǎn)
elif x > motor.control_x: # 若 當(dāng)前坐標(biāo) 大于 被控坐標(biāo)x 即當(dāng)前狀態(tài)小車在目標(biāo)的 右邊
val = (x - motor.control_x) * 0.3125 # 獲取坐標(biāo)差值 并轉(zhuǎn)換為 0~50 之間的值
motor.motor1 = 50 + val # 增大 電機(jī)1 占空比 電機(jī)1為左電機(jī) 使小車左轉(zhuǎn)
motor.motor2 = 50 - val # 減小 電機(jī)2 占空比 電機(jī)2為右電機(jī) 使小車左轉(zhuǎn)
motor.motor1 = int(motor.motor1) # 將 電機(jī)1占空比 轉(zhuǎn)換為 整數(shù)
motor.motor2 = int(motor.motor2) # 將 電機(jī)1占空比 轉(zhuǎn)換為 整數(shù)
具體實(shí)現(xiàn)是這樣實(shí)現(xiàn)的,首先會(huì)拍攝一張圖片,然后在這張圖片中找紅色色塊,獲取紅色色塊的坐標(biāo)值,然后設(shè)定將該坐標(biāo)值控制到160。通過電機(jī)占空比控制函數(shù)獲取占空比,將占空比重新裝載即可,邏輯就是。
比如我識(shí)別到紅色色塊的坐標(biāo)為20,而我要控制它走到160的位置,20說明小車當(dāng)前在該紅色目標(biāo)的右邊,那么我就要控制它左轉(zhuǎn),同樣的,如果識(shí)別到的坐標(biāo)是300,那就說明小車在目標(biāo)左邊,右轉(zhuǎn)即可,如此一來便可完成巡線或者是目標(biāo)跟蹤。
#__________________________________________________________________
# 主函數(shù)
while(True):
clock.tick() # 跟蹤運(yùn)行時(shí)間
img = sensor.snapshot() # 拍攝一張照片
#opv_find_blobs(black,1) # 找黑色色塊 led標(biāo)志為1 表示黑色
opv_find_blobs(red,2) # 找紅色色塊 led標(biāo)志為2 表示紅色
point_control(key) # 按鍵控制下的目標(biāo)點(diǎn)獲取函數(shù)
lcd.display(img) # LCD 顯示圖像
lcd_key() # LCD 顯示按鍵信息及目標(biāo)點(diǎn)信息
#led_control(red.led_flag) # LED 標(biāo)記色塊識(shí)別情況
motor.control_x = 160 # 控制目標(biāo)處于 x軸中心點(diǎn) 160
motor_control(motor,red.cx) # 電機(jī)占空比控制函數(shù)獲取電機(jī)控制占空比
motor1.duty(motor.motor1) # 將獲取到的電機(jī)1占空比 裝載
motor2.duty(motor.motor2) # 將獲取到的電機(jī)2占空比 裝載
if timer0.cnt == 0: # 如果 timer0.cnt 等于 0 此步驟的目的是控制打印周期 不要打印的太快
print_sensor() # 打印sensor參數(shù)
print_blobs_property(black,"Black-") # 打印黑色色塊參數(shù)
print_blobs_property(red, "Red- ") # 打印紅色色塊參數(shù)
#__________________________________________________________________
測試
這部分先用LED燈的情況來模擬,后面會(huì)裝到小車上進(jìn)行測試,后續(xù)會(huì)更新此博文。
可以看到位置差不多在160附近的時(shí)候,motor1和motor2的占空比為50左右,表示直走。
此時(shí)兩個(gè)燈亮的程度基本相當(dāng),呈現(xiàn)黃色,說明邏輯正確。
可以看到位置差不多在280附近的時(shí)候,motor1的占空比為87,motor2的占空比為12,表示右轉(zhuǎn)。
此時(shí)綠燈較亮,綠燈是13號(hào)引腳,被電機(jī)2占空比控制,因?yàn)闊羰堑碗娖近c(diǎn)亮,因此電機(jī)2占空比為12,綠燈較亮,說明邏輯正確。
可以看到位置差不多在47附近的時(shí)候,motor1的占空比為14,motor2的占空比為85,表示左轉(zhuǎn)。
此時(shí)紅燈較亮,紅燈是14號(hào)引腳,被電機(jī)1占空比控制,因?yàn)闊羰堑碗娖近c(diǎn)亮,因此電機(jī)1占空比為14,紅燈較亮,說明邏輯正確。
小車的測試等待我回學(xué)校后更新!文章來源:http://www.zghlxwxcb.cn/news/detail-434889.html
完整源碼
完整源碼如下所示,大家可以復(fù)制該源碼,進(jìn)行測試,下一次學(xué)習(xí)筆記將會(huì)記錄K210串口的配置,雖然往期教程已經(jīng)做過了,但下期我將會(huì)重制一下,爭取讓代碼更加好用,我們下期再見~!
等下一期做完串口,K210這一系列可能不會(huì)日更,后期我會(huì)著手于寫K210跑訓(xùn)練模型,以及怎么訓(xùn)練模型的教程,難度比現(xiàn)在來得大,因此更新的速度會(huì)放緩。
但我一定會(huì)保持質(zhì)量,做到句句有注釋,句句有原因,思路清晰, 喜歡我的教程的,希望能換到你們的一個(gè)關(guān)注。文章來源地址http://www.zghlxwxcb.cn/news/detail-434889.html
# Timer_V1.0 - By: FITQY - 周二 8 月 23 日 2022
#__________________________________________________________________
# 導(dǎo)入模塊
import sensor, time, image # 導(dǎo)入感光元件模塊 sensor 跟蹤運(yùn)行時(shí)間模塊 time 機(jī)器視覺模塊 image
import utime # 導(dǎo)入延時(shí)模塊 utime
from fpioa_manager import fm # 從 GPIO 模塊中導(dǎo)入 引腳注冊模塊 fm
from Maix import GPIO # 從 Maix 模塊中導(dǎo)入 模塊 GPIO
import lcd # 導(dǎo)入 LCD 模塊
from machine import Timer, PWM # 從 machine 模塊中導(dǎo)入 定時(shí)器模塊 Timer 脈寬調(diào)制模塊 PWM
#__________________________________________________________________
# 感光元件設(shè)置
sensor.reset() # 重置并初始化感光元件 默認(rèn)設(shè)置為 攝像頭頻率 24M 不開啟雙緩沖模式
#sensor.reset(freq=24000000, dual_buff=True) # 設(shè)置攝像頭頻率 24M 開啟雙緩沖模式 會(huì)提高幀率 但內(nèi)存占用增加
sensor.set_pixformat(sensor.RGB565) # 設(shè)置圖像格式為 RGB565 (彩色) 除此之外 還可設(shè)置格式為 GRAYSCALE 或者 YUV422
sensor.set_framesize(sensor.QVGA) # 設(shè)置圖像大小為 QVGA (320 x 240) 像素個(gè)數(shù) 76800 K210最大支持格式為 VGA
sensor.set_auto_exposure(1) # 設(shè)置自動(dòng)曝光
#sensor.set_auto_exposure(0, exposure=120000) # 設(shè)置手動(dòng)曝光 曝光時(shí)間 120000 us
sensor.set_auto_gain(0, gain_db = 12) # 設(shè)置畫面增益 17 dB 影響實(shí)時(shí)畫面亮度
sensor.set_auto_whitebal(0, rgb_gain_db = (0,0,0)) # 設(shè)置RGB增益 0 0 0 dB 影響畫面色彩呈現(xiàn)效果 在 K210 上無法調(diào)節(jié)增益 初步判定是感光元件 ov2640 無法支持
#sensor.set_contrast(0) # 設(shè)置對(duì)比度 0 這個(gè)參數(shù)無法讀取 且調(diào)這個(gè)參數(shù)對(duì)畫面似乎不會(huì)產(chǎn)生影響 暫時(shí)注釋
#sensor.set_brightness(0) # 設(shè)置亮度 0 這個(gè)參數(shù)無法讀取 且調(diào)這個(gè)參數(shù)對(duì)畫面似乎不會(huì)產(chǎn)生影響 暫時(shí)注釋
#sensor.set_saturation(0) # 設(shè)置飽和度 0 這個(gè)參數(shù)無法讀取 且調(diào)這個(gè)參數(shù)對(duì)畫面似乎不會(huì)產(chǎn)生影響 暫時(shí)注釋
sensor.set_vflip(1) # 打開垂直翻轉(zhuǎn) 如果是 01Studio 的 K210 不開啟會(huì)導(dǎo)致畫面方向與運(yùn)動(dòng)方向相反
sensor.set_hmirror(1) # 打開水平鏡像 如果是 01Studio 的 K210 不開啟會(huì)導(dǎo)致畫面方向與運(yùn)動(dòng)方向相反
sensor.skip_frames(time = 2000) # 延時(shí)跳過2s 等待感光元件穩(wěn)定
#__________________________________________________________________
# 創(chuàng)建時(shí)鐘對(duì)象
clock = time.clock() # 創(chuàng)建時(shí)鐘對(duì)象 clock
#__________________________________________________________________
# 打印sensor參數(shù)
def print_sensor():
print("Exposure: "+str(sensor.get_exposure_us())) # 打印 曝光時(shí)間
print("Gain: "+str(sensor.get_gain_db())) # 打印 畫面增益
print("RGB: "+str(sensor.get_rgb_gain_db())) # 打印 RGB 增益
#__________________________________________________________________
# 目標(biāo)點(diǎn)輸入類 舉例 對(duì)標(biāo) 2022 年 TI 杯送貨無人機(jī) 中的目標(biāo)點(diǎn)輸入部分
class point_input():
point1 = 0 # 目標(biāo)點(diǎn) 1
point2 = 0 # 目標(biāo)點(diǎn) 2
cross = 0 # 穿圈模式標(biāo)志位
send = 0 # 目標(biāo)點(diǎn)發(fā)送標(biāo)志位
point = point_input() # 實(shí)例化目標(biāo)點(diǎn)輸入類 point_input() 為 point
# 按鍵控制下的目標(biāo)點(diǎn)獲取函數(shù)
def point_control(ckey):
if ckey.control == 1: # 按鍵確認(rèn)及發(fā)送控制標(biāo)志位為1 即 按鍵3 按下
ckey.control = 0 # 重置標(biāo)志位
if ckey.cs == 0: # 如果當(dāng)前為模式 0
point.send = 1 # 目標(biāo)點(diǎn)發(fā)送標(biāo)志置為 1 串口開始發(fā)送
elif ckey.cs == 1: # 如果當(dāng)前為模式 1
point.point1 = ckey.cinput # 將按鍵輸入值賦值給目標(biāo)點(diǎn) 1
elif ckey.cs == 2: # 如果當(dāng)前為模式 2
point.point2 = ckey.cinput # 將按鍵輸入值賦值給目標(biāo)點(diǎn) 2
elif ckey.cs == 3: # 如果當(dāng)前為模式 3
point.cross = ckey.cinput # 將按鍵輸入值賦值給 穿圈模式標(biāo)志位
if ckey.csflag == 1: # 如果檢測到按鍵模式切換
ckey.csflag = 0 # 重置按鍵模式切換標(biāo)志位
ckey.cinput = 0 # 重置按鍵輸入值
#__________________________________________________________________
# 按鍵的使用
# 定義按鍵控制類
class key_control(): # 定義按鍵控制類
cnt = 0 # 按鍵計(jì)數(shù)值
cs = 0 # 按鍵模式選擇標(biāo)志位
csmax = 0 # 按鍵模式上限
csflag = 0 # 按鍵模式切換標(biāo)志位
cinput = 0 # 按鍵輸入值保存位
control = 0 # 按鍵確認(rèn)及發(fā)送控制標(biāo)志位
# 實(shí)例化按鍵類
key = key_control() # 實(shí)例化按鍵控制類 key_control() 為 key
key.csmax = 4 # 按鍵模式上限為 4 即最多有 4 個(gè)模式
# 注冊按鍵引腳
fm.register(16, fm.fpioa.GPIOHS0, force = True) # 配置 16 腳為 KEY0 使用高速 GPIO 口 強(qiáng)制注冊
fm.register(18, fm.fpioa.GPIOHS1, force = True) # 配置 18 腳為 KEY1 使用高速 GPIO 口 強(qiáng)制注冊
fm.register(19, fm.fpioa.GPIOHS2, force = True) # 配置 19 腳為 KEY2 使用高速 GPIO 口 強(qiáng)制注冊
fm.register(20, fm.fpioa.GPIOHS3, force = True) # 配置 20 腳為 KEY3 使用高速 GPIO 口 強(qiáng)制注冊
# 創(chuàng)建按鍵對(duì)象
KEY0 = GPIO(GPIO.GPIOHS0, GPIO.IN, GPIO.PULL_UP) # 創(chuàng)建按鍵對(duì)象 KEY0
KEY1 = GPIO(GPIO.GPIOHS1, GPIO.IN, GPIO.PULL_UP) # 創(chuàng)建按鍵對(duì)象 KEY1
KEY2 = GPIO(GPIO.GPIOHS2, GPIO.IN, GPIO.PULL_UP) # 創(chuàng)建按鍵對(duì)象 KEY2
KEY3 = GPIO(GPIO.GPIOHS3, GPIO.IN, GPIO.PULL_UP) # 創(chuàng)建按鍵對(duì)象 KEY3
# 中斷回調(diào)函數(shù) KEY0 控制按鍵模式選擇
def key0_switch(KEY0):
utime.sleep_ms(10) # 延時(shí) 10ms 消除按鍵抖動(dòng)
if KEY0.value() == 0: # 確認(rèn) 按鍵0 按下
key.csflag = 1 # 標(biāo)記按鍵模式切換
if key.cs < key.csmax: # 控制按鍵模式選擇 自增
key.cs = key.cs + 1
else: # 若達(dá)到上限 則重新從 0 開始
key.cs = 0
# 中斷回調(diào)函數(shù) KEY1 按鍵輸入值自增
def key1_switch(KEY1):
utime.sleep_ms(10) # 延時(shí) 10ms 消除按鍵抖動(dòng)
if KEY1.value() == 0: # 確認(rèn) 按鍵1 按下
key.cinput = key.cinput + 1 # 按鍵輸入值自增
# 中斷回調(diào)函數(shù) KEY2 按鍵輸入值自減
def key2_switch(KEY2):
utime.sleep_ms(10) # 延時(shí) 10ms 消除按鍵抖動(dòng)
if KEY2.value() == 0: # 確認(rèn) 按鍵2 按下
key.cinput = key.cinput - 1 # 按鍵輸入值自減
# 中斷回調(diào)函數(shù) KEY3 按鍵確認(rèn)及發(fā)送控制標(biāo)志位
def key3_switch(KEY3):
utime.sleep_ms(10) # 延時(shí) 10ms 消除按鍵抖動(dòng)
if KEY3.value() == 0: # 確認(rèn)按鍵按下
key.control = 1 # 按鍵確認(rèn)及發(fā)送控制標(biāo)志位
# 開啟中斷 下降沿觸發(fā)
KEY0.irq(key0_switch, GPIO.IRQ_FALLING) # 開啟 按鍵0 外部中斷 下降沿觸發(fā)
KEY1.irq(key1_switch, GPIO.IRQ_FALLING) # 開啟 按鍵1 外部中斷 下降沿觸發(fā)
KEY2.irq(key2_switch, GPIO.IRQ_FALLING) # 開啟 按鍵2 外部中斷 下降沿觸發(fā)
KEY3.irq(key3_switch, GPIO.IRQ_FALLING) # 開啟 按鍵3 外部中斷 下降沿觸發(fā)
#__________________________________________________________________
# LCD 的使用
# LCD 初始化
lcd.init() # lcd初始化
# LCD 按鍵信息及目標(biāo)點(diǎn)信息顯示函數(shù)
def lcd_key():
lcd.draw_string(0, 0, "key_cs: "+str(key.cs), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 15, "cinput: "+str(key.cinput), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 30, "point1: "+str(point.point1), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 45, "point2: "+str(point.point2), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 60, "cross : "+str(point.cross), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 75, "red_cx: "+str(red.cx), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 90, "motor1: "+str(motor.motor1), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 105,"motor2: "+str(motor.motor2), lcd.BLUE, lcd.WHITE)
lcd.draw_string(0, 120,"FPS : "+str(clock.fps()), lcd.BLUE, lcd.WHITE)
#__________________________________________________________________
# LED 的使用
# 注冊LED引腳
fm.register(14, fm.fpioa.GPIO2, force = True) # 配置 14 腳為 LED_R 強(qiáng)制注冊
fm.register(13, fm.fpioa.GPIO1, force = True) # 配置 13 腳為 LED_G 強(qiáng)制注冊
fm.register(12, fm.fpioa.GPIO0, force = True) # 配置 12 腳為 LED_B 強(qiáng)制注冊
# 創(chuàng)建LED對(duì)象
LED_R = GPIO(GPIO.GPIO2, GPIO.OUT) # 創(chuàng)建 LED_R 對(duì)象
LED_G = GPIO(GPIO.GPIO1, GPIO.OUT) # 創(chuàng)建 LED_G 對(duì)象
LED_B = GPIO(GPIO.GPIO0, GPIO.OUT) # 創(chuàng)建 LED_B 對(duì)象
# LED控制函數(shù)
def led_control(led_flag): # LED控制函數(shù) 根據(jù)傳入 led_flag 點(diǎn)亮對(duì)應(yīng)的燈
if led_flag == 0: # 傳入?yún)?shù)為 0 所有燈打開
LED_R.value(0)
LED_G.value(0)
LED_B.value(0)
elif led_flag == 1: # 傳入?yún)?shù)為 1 所有燈關(guān)閉
LED_R.value(1)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 2: # 傳入?yún)?shù)為 2 紅燈常亮
LED_R.value(0)
LED_G.value(1)
LED_B.value(1)
elif led_flag == 3: # 傳入?yún)?shù)為 3 綠燈常亮
LED_R.value(1)
LED_G.value(0)
LED_B.value(1)
elif led_flag == 4: # 傳入?yún)?shù)為 4 藍(lán)燈常亮
LED_R.value(1)
LED_G.value(1)
LED_B.value(0)
else: # 其他情況 紫燈
LED_R.value(0)
LED_G.value(1)
LED_B.value(0)
#__________________________________________________________________
# 定時(shí)器的使用
# 定義定時(shí)器屬性類
class timer_property():
cnt = 0 # 定時(shí)器計(jì)數(shù)值
cnt_max = 0 # 定時(shí)器計(jì)數(shù)值上限
period = 0 # 定時(shí)器周期
freq = 0 # 定時(shí)器頻率
# 定時(shí)器0 配置_______________________________________________________
# 定時(shí)器0 實(shí)例化類
timer0 = timer_property() # 實(shí)例化定時(shí)器屬性類 timer_property() 為 timer0
timer0.cnt_max = 9 # 設(shè)定 定時(shí)器0 的計(jì)數(shù)值上限為 9
timer0.period = 100 # 設(shè)定 定時(shí)器0 的周期為 100
# 定時(shí)器0 定義回調(diào)函數(shù)
def timer0_back(tim0):
if timer0.cnt < timer0.cnt_max: # 若 定時(shí)器0 的計(jì)數(shù)值小于 定時(shí)器0 的計(jì)數(shù)值上限
timer0.cnt = timer0.cnt + 1 # 計(jì)數(shù)值自增
else:
timer0.cnt = 0 # 超出計(jì)數(shù)值上限 則計(jì)數(shù)值重置為0
# 定時(shí)器0 初始化
tim0 = Timer(Timer.TIMER0, # 定時(shí)器編號(hào) 定時(shí)器0
Timer.CHANNEL0, # 定時(shí)器通道 通道0
mode = Timer.MODE_PERIODIC, # 定時(shí)器模式 周期性
unit = Timer.UNIT_MS, # 定時(shí)器周期單位 ms
period = timer0.period, # 定時(shí)器周期 timer0.period 若 unit 為 Timer.UNIT_MS 則周期為 timer0.period ms
callback = timer0_back) # 定時(shí)器觸發(fā)中斷后執(zhí)行的回調(diào)函數(shù) timer0_back
# 定時(shí)器1 配置_______________________________________________________
# 電機(jī)類定義
class motor_property():
motor1 = 0 # 電機(jī)1 占空比
motor2 = 0 # 電機(jī)2 占空比
motor3 = 0 # 電機(jī)3 占空比
motor4 = 0 # 電機(jī)4 占空比
motor1_pin = 0 # 電機(jī)1 引腳
motor2_pin = 0 # 電機(jī)2 引腳
motor3_pin = 0 # 電機(jī)3 引腳
motor4_pin = 0 # 電機(jī)4 引腳
control_x = 0 # 被控坐標(biāo) x
control_y = 0 # 被控坐標(biāo) y
# 實(shí)例化電機(jī)類
motor = motor_property() # 實(shí)例化電機(jī)類 motor_property() 為 motor
motor.motor1 = 50 # 電機(jī)1的占空比 初始設(shè)置為 50%
motor.motor2 = 50 # 電機(jī)2的占空比 初始設(shè)置為 50%
motor.motor1_pin = 14 # 電機(jī)1的引腳 14為紅燈引腳 這里先用燈的亮滅觀察效果
motor.motor2_pin = 13 # 電機(jī)2的引腳 13為綠燈引腳 這里先用燈的亮滅觀察效果
# 定時(shí)器1 實(shí)例化類
timer1 = timer_property() # 實(shí)例化定時(shí)器屬性類 timer_property() 為 timer1
timer1.freq = 1000 # 設(shè)定 定時(shí)器1 的頻率為 1000
# 定時(shí)器1 通道0 初始化
tim1_ch0 = Timer(Timer.TIMER1, # 定時(shí)器編號(hào) 定時(shí)器1
Timer.CHANNEL0, # 定時(shí)器通道 通道0
mode = Timer.MODE_PWM) # 定時(shí)器模式 PWM
# 定時(shí)器1 通道1 初始化
tim1_ch1 = Timer(Timer.TIMER1, # 定時(shí)器編號(hào) 定時(shí)器1
Timer.CHANNEL1, # 定時(shí)器通道 通道1
mode = Timer.MODE_PWM) # 定時(shí)器模式 PWM
# 創(chuàng)建對(duì)象 電機(jī)1 通道為 定時(shí)器1的通道0 頻率為 定時(shí)器1的頻率 占空比為 電機(jī)1的占空比 引腳為 電機(jī)1的引腳
motor1 = PWM(tim1_ch0, freq = timer1.freq, duty = motor.motor1, pin = motor.motor1_pin)
# 創(chuàng)建對(duì)象 電機(jī)2 通道為 定時(shí)器1的通道1 頻率為 定時(shí)器1的頻率 占空比為 電機(jī)2的占空比 引腳為 電機(jī)2的引腳
motor2 = PWM(tim1_ch1, freq = timer1.freq, duty = motor.motor2, pin = motor.motor2_pin)
# 定義電機(jī)占空比控制函數(shù)
def motor_control(motor, x):
val = 0
if x < motor.control_x: # 若 當(dāng)前坐標(biāo) 小于 被控坐標(biāo)x 即當(dāng)前狀態(tài)小車在目標(biāo)的 左邊
val = (motor.control_x - x) * 0.3125 # 獲取坐標(biāo)差值 并轉(zhuǎn)換為 0~50 之間的值
motor.motor1 = 50 - val # 減小 電機(jī)1 占空比 電機(jī)1為左電機(jī) 使小車右轉(zhuǎn)
motor.motor2 = 50 + val # 增大 電機(jī)2 占空比 電機(jī)2為右電機(jī) 使小車右轉(zhuǎn)
elif x > motor.control_x: # 若 當(dāng)前坐標(biāo) 大于 被控坐標(biāo)x 即當(dāng)前狀態(tài)小車在目標(biāo)的 右邊
val = (x - motor.control_x) * 0.3125 # 獲取坐標(biāo)差值 并轉(zhuǎn)換為 0~50 之間的值
motor.motor1 = 50 + val # 增大 電機(jī)1 占空比 電機(jī)1為左電機(jī) 使小車左轉(zhuǎn)
motor.motor2 = 50 - val # 減小 電機(jī)2 占空比 電機(jī)2為右電機(jī) 使小車左轉(zhuǎn)
motor.motor1 = int(motor.motor1) # 將 電機(jī)1占空比 轉(zhuǎn)換為 整數(shù)
motor.motor2 = int(motor.motor2) # 將 電機(jī)1占空比 轉(zhuǎn)換為 整數(shù)
#__________________________________________________________________
# 尋找色塊
# 定義類
class color_property():
cx = 0 # 色塊 x軸 中心坐標(biāo)
cy = 0 # 色塊 y軸 中心坐標(biāo)
flag = 0 # 色塊標(biāo)志位 1 找到 0 未找到
color = 0 # 色塊顏色標(biāo)志位 例如 你可以用 1 來表示 黑色
density = 0 # 色塊密度比 反映色塊鎖定程度 值越大 鎖定程度越好
pixels_max = 0 # 色塊像素最大值
led_flag = 0 # LED標(biāo)志位 方便調(diào)試用
color_threshold = (0, 0, 0, 0, 0, 0) # 色塊顏色閾值
color_roi = (0,0,320,240) # 色塊尋找區(qū)域(感興趣區(qū)域)
color_x_stride = 1 # 色塊 x軸 像素最小寬度 色塊如果比較大可以調(diào)大此參數(shù) 提高尋找速度
color_y_stride = 1 # 色塊 y軸 像素最小寬度 色塊如果比較大可以調(diào)大此參數(shù) 提高尋找速度
color_pixels_threshold = 100 # 色塊 像素個(gè)數(shù)閾值 例如調(diào)節(jié)此參數(shù)為100 則可以濾除色塊像素小于100的色塊
color_area_threshold = 100 # 色塊 被框面積閾值 例如調(diào)節(jié)此參數(shù)為100 則可以濾除色塊被框面積小于100的色塊
color_merge = True # 是否合并尋找到的色塊 True 則合并 False 則不合并
color_margin = 1 # 色塊合并間距 例如調(diào)節(jié)此參數(shù)為1 若上面選擇True合并色塊 且被找到的色塊有多個(gè) 相距1像素 則會(huì)將這些色塊合并
# 實(shí)例化類
# 黑色
black = color_property()
black.color_threshold = (0, 50, -10, 10, -10, 10)
black.color_roi = (0,0,320,240)
black.color_x_stride = 1
black.color_y_stride = 1
black.color_pixels_threshold = 100
black.color_area_threshold = 100
black.color_merge = True
black.color_margin = 1
# 紅色
red = color_property()
red.color_threshold = (0, 100, 20, 127, -10, 127)
#red.color_roi = (0,0,320,240)
red.color_roi = (0,110,320,20)
red.color_x_stride = 1
red.color_y_stride = 1
#red.color_pixels_threshold = 100
#red.color_area_threshold = 100
red.color_pixels_threshold = 10
red.color_area_threshold = 10
red.color_merge = True
red.color_margin = 1
# 綠色 預(yù)留
green = color_property()
# 藍(lán)色 預(yù)留
blue = color_property()
# 定義尋找色塊函數(shù)
def opv_find_blobs(color,led_flag):
color.pixels_max = 0 # 重置 色塊 最大像素?cái)?shù)量
color.flag = 0 # 重置 色塊 標(biāo)志位
color.led_flag = 0 # 重置 led 標(biāo)志位
for blobs in img.find_blobs([color.color_threshold], # 色塊顏色閾值
roi = color.color_roi, # 色塊尋找區(qū)域(感興趣區(qū)域)
x_stride = color.color_x_stride, # 色塊 x軸 像素最小寬度 色塊如果比較大可以調(diào)大此參數(shù) 提高尋找速度
y_stride = color.color_y_stride, # 色塊 y軸 像素最小寬度 色塊如果比較大可以調(diào)大此參數(shù) 提高尋找速度
pixels_threshold = color.color_pixels_threshold, # 色塊 像素個(gè)數(shù)閾值 例如調(diào)節(jié)此參數(shù)為100 則可以濾除色塊像素小于100的色塊
area_threshold = color.color_area_threshold, # 色塊 被框面積閾值 例如調(diào)節(jié)此參數(shù)為100 則可以濾除色塊被框面積小于100的色塊
merge = color.color_merge, # 是否合并尋找到的色塊 True 則合并 False 則不合并
margin = color.color_margin): # 色塊合并間距 例如調(diào)節(jié)此參數(shù)為1 若上面選擇True合并色塊 且被找到的色塊有多個(gè) 相距1像素 則會(huì)將這些色塊合并
img.draw_rectangle(blobs[0:4]) # 圈出找到的色塊
if color.pixels_max < blobs.pixels(): # 找到面積最大的色塊
color.pixels_max = blobs.pixels()
color.cx = blobs.cx() # 將面積最大的色塊的 x軸 中心坐標(biāo)值 賦值給 color
color.cy = blobs.cy() # 將面積最大的色塊的 y軸 中心坐標(biāo)值 賦值給 color
color.flag = 1 # 標(biāo)志畫面中有找到色塊
color.density = blobs.density() # 將面積最大的色塊的 色塊密度比 賦值給 color
color.led_flag = led_flag # 將控制led顏色的標(biāo)志位的值 賦值給 color
if color.flag == 1: # 標(biāo)記畫面中被找到的最大色塊的中心坐標(biāo)
img.draw_cross(color.cx,color.cy, color=127, size = 15)
img.draw_circle(color.cx,color.cy, 15, color = 127)
# 定義打印色塊參數(shù)函數(shù)
def print_blobs_property(color,name):
print(name,"cx:",color.cx,"cy:",color.cy,"flag:",color.flag,"color:",color.color,"density:",color.density,"led_flag:",color.led_flag)
#__________________________________________________________________
# 調(diào)試區(qū)
led_control(1) # 關(guān)閉一下所有燈 再進(jìn)入 while 循環(huán) 使顯示結(jié)果正確
#__________________________________________________________________
# 主函數(shù)
while(True):
clock.tick() # 跟蹤運(yùn)行時(shí)間
img = sensor.snapshot() # 拍攝一張照片
#opv_find_blobs(black,1) # 找黑色色塊 led標(biāo)志為1 表示黑色
opv_find_blobs(red,2) # 找紅色色塊 led標(biāo)志為2 表示紅色
point_control(key) # 按鍵控制下的目標(biāo)點(diǎn)獲取函數(shù)
lcd.display(img) # LCD 顯示圖像
lcd_key() # LCD 顯示按鍵信息及目標(biāo)點(diǎn)信息
#led_control(red.led_flag) # LED 標(biāo)記色塊識(shí)別情況
motor.control_x = 160 # 控制目標(biāo)處于 x軸中心點(diǎn) 160
motor_control(motor,red.cx) # 電機(jī)占空比控制函數(shù)獲取電機(jī)控制占空比
motor1.duty(motor.motor1) # 將獲取到的電機(jī)1占空比 裝載
motor2.duty(motor.motor2) # 將獲取到的電機(jī)2占空比 裝載
if timer0.cnt == 0: # 如果 timer0.cnt 等于 0 此步驟的目的是控制打印周期 不要打印的太快
print_sensor() # 打印sensor參數(shù)
print_blobs_property(black,"Black-") # 打印黑色色塊參數(shù)
print_blobs_property(red, "Red- ") # 打印紅色色塊參數(shù)
#__________________________________________________________________
到了這里,關(guān)于【K210】K210學(xué)習(xí)筆記四——定時(shí)器的使用的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!