2.編寫代碼
對于本實驗來說,有涉及到UI開發,我們依然采用Python自帶的Tkinter庫,其有很好的移植性,并且其提供了Canvas畫布,我們可以靈活的渲染所需要的圖形。示例代碼如下:
#coding:utf-8
# 導入UI子產品
import tkinter as Tkinter
#SMBus (System Management Bus,系統管理總線)
import smbus #在程式中導入“smbus”子產品
import RPi.GPIO as GPIO # 導入樹莓派GPIO子產品
import time # 導入定時器子產品
import threading
# 首頁面設定
top = Tkinter.Tk()
top.geometry('500x300')
top.title("操縱杆控制圓球")
# 目前圓球的坐标
currentX = 0
currentY = 0
# 目前圓球的顔色是否紅色
currentColor = True
# 進行視窗的初始化
canvas = Tkinter.Canvas(top, width=500, height=300, borderwidth=0, highlightthickness=0)
canvas.grid()
# 進化畫布的初始化
circle = canvas.create_oval(currentX, currentY, 100, 100, fill="red", outline="")
# 定義移動圓球的方法
def moveCircle(c, x, y):
global currentX, currentY
moveX = x
moveY = y
if x >= 0:
if x + currentX > 400:
moveX = 400 - currentX
currentX = 400
else:
currentX += x
else:
if x + currentX < 0:
moveX = -currentX
currentX = 0
if y >= 0:
if y + currentY > 200:
moveY = 200 - currentY
currentY = 200
currentY += y
if y + currentY < 0:
moveY = -currentY
currentY = 0
currentY += y
canvas.move(c, moveX, moveY)
# 定義改變圓球顔色的方法
def changeColor(c):
global currentColor
canvas.itemconfig(c, fill= 'red' if currentColor else 'blue')
currentColor = not currentColor
bus = smbus.SMBus(1) #建立一個smbus執行個體
# 通過PCF8591讀取模拟信号
# 搖杆X引腳的模拟資料
def readX():
#發送一個控制位元組到裝置 表示要讀取AIN0通道的資料
bus.write_byte(0x48,0x40)
bus.read_byte(0x48) # 空讀一次,消費掉無效資料
return bus.read_byte(0x48) # 傳回某通道輸入的模拟值A/D轉換後的數字值
# 搖杆Y引腳的模拟資料
def readY():
#發送一個控制位元組到裝置 表示要讀取AIN1通道的資料
bus.write_byte(0x48,0x41)
# 通過GPIO讀取數字信号
# 設定使用的引腳編碼模式
GPIO.setmode(GPIO.BOARD)
# 按鍵使用引腳 BCM 17
BTN = 11
# 引腳初始化 設定下拉高電平
GPIO.setup(BTN, GPIO.IN, pull_up_down=GPIO.PUD_UP)
# 建立定時器函數,用來檢查搖杆動作
def fun_timer():
global timer
x = readX()
y = readY()
press = GPIO.input(BTN)
print('X:', x)
print('Y:', y)
print('按鈕:', press)
if x <= 10:
moveCircle(circle, -10, 0)
if x >= 245:
moveCircle(circle, 10, 0)
if y <= 10:
moveCircle(circle, 0, -10)
if y >= 245:
moveCircle(circle, 0, 10)
timer = threading.Timer(0.2, fun_timer)
timer.start()
timer = threading.Timer(0.2, fun_timer)
timer.start()
# 定義GPIO輸入端口的回調
def btnCallback(channel):
if not GPIO.input(channel):
changeColor(circle)
# 添加輸入引腳電平變化的回調函數
GPIO.add_event_detect(BTN, GPIO.FALLING, callback=btnCallback, bouncetime=200)
top.mainloop()
上面的代碼有些長,但是有詳盡的注釋,關于UI開發方面的内容不是我們本系列部落格的重點,這裡我們不做過多介紹。moveCircle函數是核心的圓球移動函數,内部通過邊界判定邏輯可以確定圓球不會移動到視圖界面外。changeColor方法用來修改圓球的顔色,這裡我們讓每次按鍵後在紅綠顔色間進行切換。readX和readY函數我們無需做過多介紹了,其通過PCF8591的AIN0和AIN1來傳輸搖杆的橫縱坐标信号。GPIO的相關操作我們也非常熟悉了,我們通過注冊回調函數來監聽操作杆按鈕按下的行為。
在樹莓派上運作上面的代碼,嘗試操作下,感受下使用操縱杆控制頁面元素的喜悅吧。
3.一點擴充
觀察上面的示例代碼,你會發現,我們使用了一些臨界值來作為觸發方向動作的門檻值,例如10,245這種,這是因為PCF8591是8位的數模轉換子產品,即其轉換出的數字量在0-255之間(包括0和255),對于本實驗來說,我們并沒有讓搖杆元件傳輸的模拟量發揮正真的作用,想一下,你是否能夠根據操作杆的旋轉程度來調整圓球移動的速度呢?動手試試吧!