有沒有想過我們的世界是如何走向沉浸式現(xiàn)實的。我們不斷尋找新的方式和方法來使用虛擬現(xiàn)實、混合現(xiàn)實、增強現(xiàn)實等與周圍環(huán)境進行交互。每天都有新設(shè)備出現(xiàn),這些快節(jié)奏的技術(shù)給我們留下了深刻的印象。
這些沉浸式技術(shù)用于游戲、互動活動、娛樂和許多其他應(yīng)用。在本教程中,我們將了解這種交互方法,它為您提供了一種與系統(tǒng)交互的新方法,而不是使用無聊的鼠標(biāo)。我們的游戲愛好者一定知道,幾年前任天堂的一家游戲公司推出了一種 3D 交互方法的想法,該方法在稱為 Wii 控制器的手持控制器的幫助下與他們的控制臺進行交互。它使用加速度計來定位您的游戲手勢并將其無線發(fā)送到系統(tǒng)。

受這個想法的啟發(fā),我們將制作一個“空中鼠標(biāo)”,只需通過在空中移動控制臺就可以與系統(tǒng)交互,但我們不會使用 3 維坐標(biāo)參考,我們只會使用 2 維坐標(biāo)參考,所以我們可以模仿計算機鼠標(biāo)的動作,因為鼠標(biāo)在 X 和 Y 兩個維度上工作。
這款無線 3D Air Mouse背后的概念非常簡單,我們將使用加速度計來獲取“Air mouse”沿 x 和 y 軸的動作和運動的加速度值,然后根據(jù)加速度計我們將控制鼠標(biāo)光標(biāo)并在計算機上運行的 python 軟件驅(qū)動程序的幫助下執(zhí)行某些操作。
先決條件
Arduino Nano(任何型號)
加速度計 ADXL335 模塊
藍牙 HC-05 模塊
按按鈕
Python 安裝的計算機
電路原理圖


要通過手部的動作控制計算機,您需要一個加速度計,它可以沿 X 軸和 Y 軸發(fā)出加速度,并使整個系統(tǒng)無線化,藍牙模塊用于將信號無線傳輸?shù)侥南到y(tǒng)。
這里使用了 ADXL335 加速度計,它是一個基于 MEMS 的三軸模塊,輸出沿 X、Y 和 Z 軸的加速度,但如前所述,用于控制鼠標(biāo),我們只需要沿 X 和 Y 軸的加速度。
這里加速度計的 Xout 和 Yout 引腳連接到 Arduino 的 Analog、A0 和 A1 引腳,用于將信號從 Arduino 傳輸?shù)较到y(tǒng)此處使用藍牙模塊 HC-05,因為藍牙通過 Tx 和 Rx 工作引腳連接,因此我們使用軟件串行引腳 D2 和 D3。它是使用軟件串行連接的,因為如果我們將藍牙與硬件串行連接并開始通過 python 控制臺獲取讀數(shù),它將顯示不匹配波特率的錯誤,因為藍牙將以自己的波特率與 python 通信。通過使用包括 Arduino 在內(nèi)的不同微控制器完成各種基于藍牙的項目,了解有關(guān)使用藍牙模塊的更多信息。
這里我們使用了三個按鈕 - 一個用于觸發(fā) Air 鼠標(biāo),另外兩個用于左右單擊,如下圖所示:

空中鼠標(biāo)的流程
流程圖顯示了基于 Arduino 的 Air Mouse 的處理流程:

1.系統(tǒng)不斷檢查機械扳機是否被按下,直到?jīng)]有按下,我們可以用電腦鼠標(biāo)正常工作。
2.當(dāng)系統(tǒng)檢測到按鍵按下時,鼠標(biāo)的控制權(quán)轉(zhuǎn)移到空中鼠標(biāo)。
3. 按下觸發(fā)按鈕時,系統(tǒng)開始將鼠標(biāo)的讀數(shù)傳輸?shù)接嬎銠C。系統(tǒng)讀數(shù)包括加速度計讀數(shù),以及左鍵和右鍵的讀數(shù)。
4.系統(tǒng)讀數(shù)由1字節(jié)或8位的數(shù)據(jù)流組成,其中前三位為X坐標(biāo),后三位為Y坐標(biāo),倒數(shù)第二位為獲取狀態(tài)位鼠標(biāo)左鍵的狀態(tài),最后一位是獲取右鍵狀態(tài)的狀態(tài)位。
5.前三位的取值,即X坐標(biāo)的范圍為100《=Xcord《=999,而Y坐標(biāo)的取值范圍為100《=Ycord《=800。右鍵單擊和左鍵單擊的值是二進制值 0 或 1,其中 1 表示單擊,0 表示用戶未單擊。
6. 為了不讓按鈕的彈跳影響光標(biāo)的位置,每次點擊鼠標(biāo)的觸發(fā)按鈕后都會保持 4 秒的已知延遲。
7. 空中鼠標(biāo)的左右點擊,我們必須先按下左鍵或右鍵,然后按下觸發(fā)鍵移動到我們想要的空中鼠標(biāo)位置。
為空中鼠標(biāo)編程 Arduino
應(yīng)將 Arduino 編程為讀取 X 軸和 Y 軸的加速度值。最后給出了完整的程序,下面是代碼中的重要片段。
設(shè)置全局變量
如前所述,我們將使用軟件串行引腳連接藍牙模塊。因此,要設(shè)置軟件串行,我們需要聲明軟件串行庫并設(shè)置 Tx 和 Rx 的引腳。在 Arduino Nano 和 Uno 中,引腳 2 和 3 可以作為軟件串行工作。接下來,我們從軟件串行庫中聲明藍牙對象,以設(shè)置 Tx 和 Rx 的引腳。
?
#include const int rxpin = 2, txpin = 3; 軟件串行藍牙(rxpin,txpin); 常量 int x=A0; 常量 int y=A1; 整數(shù) xh, yh; int xcord,ycord; 常量 int 觸發(fā)器 = 5; 詮釋 lstate = 0; int rstate = 0; 常量 int lclick = 6; 常量 int rclick = 7; 常量 int led = 8;
?
無效設(shè)置()
在setup函數(shù)中,我們將設(shè)置變量來告訴程序它們將作為輸入還是輸出。觸發(fā)按鈕將被設(shè)置為輸入上拉,左右點擊被聲明為輸入并設(shè)置為高以使其充當(dāng)輸入上拉。
還將串行和藍牙通信的波特率設(shè)置為 9600。
?
無效設(shè)置()
{
pinMode(x,INPUT);
pinMode(y,輸入);
pinMode(觸發(fā)器,INPUT_PULLUP)
pinMode(lclick,INPUT);
pinMode(rclick,輸入);
pinMode(LED,輸出);
數(shù)字寫入(lclick,HIGH);
digitalWrite(rclick,HIGH);
序列號.開始(9600);
藍牙.開始(9600);
}
?
無效循環(huán)()
因為我們需要觸發(fā)按鈕來告訴我們何時需要向系統(tǒng)發(fā)送數(shù)據(jù)流,所以我們在while循環(huán)中設(shè)置了整個代碼,它將持續(xù)監(jiān)控上拉觸發(fā)器的數(shù)字狀態(tài),當(dāng)它變低時它會將其進一步傳遞以進行處理。
由于我們已經(jīng)連接了一個 LED 來讓我們知道按下觸發(fā)按鈕時系統(tǒng)的狀態(tài),我們最初將 LED 在while循環(huán)之外設(shè)置為低電平,因為它是默認(rèn)條件,而在while循環(huán)內(nèi)部設(shè)置為高電平,這將點亮 LED每當(dāng)按下觸發(fā)按鈕時。
為了讀取左右單擊按鈕的狀態(tài),我們?nèi)致暶髁藘蓚€變量lclick和rclick?,它們的值最初設(shè)置為 0。
并在循環(huán)中,根據(jù)左右按鈕的數(shù)字狀態(tài)設(shè)置這些變量的值,以檢查按鈕是否被按下。
我們將使用模擬讀取函數(shù)讀取加速度計的 X 和 Y 輸出引腳的值,并將這些值映射到屏幕大小,以使鼠標(biāo)指針在整個屏幕上移動。由于屏幕大小是屏幕中的像素,我們需要相應(yīng)地設(shè)置它,并且由于我們需要輸出值是三位數(shù),我們特意將 X 的范圍設(shè)置為 100<=X<=999 和類似的Y 的值為 100<=Y<=800。請記住,像素是從左上角讀取的,即左上角的值是 (0,0),但是由于我們已經(jīng)為 x 和 y 聲明了三位數(shù)字,我們的值將從點 (100,100) 讀取。
此外,在Serial.print和bluetooth.print函數(shù)的幫助下,在串行和藍牙上打印坐標(biāo)值和點擊狀態(tài),它們有助于通過藍牙在串行監(jiān)視器和系統(tǒng)上獲取值。
最后,由于按鈕的彈跳,可能會重復(fù)單個值,這會導(dǎo)致鼠標(biāo)光標(biāo)停留在單個位置上,因此為了擺脫這種情況,我們必須添加此延遲。
?
無效循環(huán)()
{
數(shù)字寫入(領(lǐng)導(dǎo),低);
而(digitalRead(觸發(fā)器)==LOW)
{
digitalWrite(LED,HIGH);
lstate = digitalRead(lclick);
rstate = digitalRead(rclick);
xh=模擬讀?。▁);
yh=analogRead(y);
xcord=map(xh,286,429,100,999);
ycord=map(yh,282,427,100,800);
串行打?。▁cord);
Serial.print(ycord);
if (lstate == LOW)
Serial.print(1);
否則
Serial.print(0);
if (rstate == LOW)
Serial.print(1);
否則
Serial.print(0);
藍牙.print(xcord);
藍牙.print(ycord);
if (lstate == LOW)
bluetooth.print(1);
否則
bluetooth.print(0);
if (rstate == LOW)
bluetooth.print(1);
否則
bluetooth.print(0);
延遲(4000);
} }
?
計算機的Python 驅(qū)動程序腳本
到目前為止,我們已經(jīng)完成了硬件及其固件部分,現(xiàn)在要讓空中鼠標(biāo)工作,我們需要一個驅(qū)動程序腳本,可以將空中鼠標(biāo)的信號解碼為光標(biāo)移動,所以為此,我們選擇了Python。Python是一種腳本語言,這里的腳本是指它可以幫助我們控制其他程序,因為這里我們控制的是鼠標(biāo)光標(biāo)。
因此,打開您的 python shell 并使用以下命令安裝以下庫:
?
pip install 串行 pip install pyautogui
?
serial是 python的庫,它可以幫助我們從串行接口(例如 com 端口)獲取數(shù)據(jù),還可以讓我們對其進行操作,而pyautogui是 python 的庫,用于控制 GUI 功能,在本例中為鼠標(biāo)。
現(xiàn)在我們來看看驅(qū)動的代碼,首先我們需要導(dǎo)入serial和pyautogui庫,然后從serial庫中,我們必須設(shè)置通信的com端口,波特率為9600,與Bluetooth.serial相同。為此,您必須將藍牙模塊連接到系統(tǒng),然后在系統(tǒng)設(shè)置中檢查它連接到哪個 com 端口。
接下來的事情是讀取從藍牙到系統(tǒng)的串行通信,并在 while 1 的幫助下保持其連續(xù)運行,使其余代碼保持連續(xù)循環(huán)。
如前所述,Arduino 發(fā)送 8 位,前 6 位用于坐標(biāo),后 2 位用于單擊按鈕的狀態(tài)。因此,在ser.read的幫助下讀取所有位并將其長度設(shè)置為 8 位。
接下來,通過切片將光標(biāo)坐標(biāo)和點擊的位分割,然后進一步將光標(biāo)位分別切割為 X 和 Y 坐標(biāo)。左鍵和右鍵也一樣。
現(xiàn)在從通信中,我們得到一個字節(jié)字符串,我們需要將其轉(zhuǎn)換為整數(shù),以便它們適合坐標(biāo),我們通過解碼它們?nèi)缓髮⑺鼈冾愋娃D(zhuǎn)換為整數(shù)來做到這一點。
現(xiàn)在要移動光標(biāo),我們使用 pyautogui?moveto函數(shù),該函數(shù)將這些整數(shù)坐標(biāo)作為參數(shù)并將光標(biāo)移動到該位置。
接下來檢查點擊,我們使用最后兩位和 pyautogui 的 click 函數(shù)來做到這一點,它的默認(rèn)點擊是左一個,但是我們可以通過將按鈕值聲明為右來將其設(shè)置為右,我們也可以定義點擊次數(shù)通過將 clicks 參數(shù)設(shè)置為 2 將其設(shè)置為雙擊。
以下是要在計算機上運行的完整 Python 代碼:
?
導(dǎo)入串口
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
k=ser.read(8)
cursor=k[:6]
click=k[6:]
x=cursor[:3]
y= cursor[3:]
l=click[0]
r=click[1]
xcor=int(x.decode('utf-8'))
ycor=int(y.decode('utf-8'))
pyautogui.moveTo (xcor,ycor)
如果 l==49:
pyautogui.click(clicks=2)
elif r==49:
pyautogui.click(button='right', clicks=2)
?
測試 Arduino 空中鼠標(biāo)
因此,要操作 Air Mouse,請為其連接電源。它可以來自 Arduino Nano USB 插槽或來自使用 7805 IC 的 5v 穩(wěn)壓電源。然后通過設(shè)置藍牙連接到的 com 端口來運行 python 驅(qū)動程序腳本。當(dāng)腳本運行時,您會看到藍牙閃爍的時間滯后,這意味著它已連接到您的系統(tǒng)。然后操作它點擊觸發(fā)按鈕,你會看到坐標(biāo)的位置會改變,如果你想要左擊或右擊,然后先按下左或右按鈕和觸發(fā)按鈕,你會看到點擊的動作光標(biāo)位置的改變。

Python腳本:
導(dǎo)入串口
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
k=ser.read(8)
cursor=k[:6]
click=k[6:]
x=cursor[:3]
y= cursor[3:]
l=click[0]
r=click[1]
xcor=int(x.decode('utf-8'))
ycor=int(y.decode('utf-8'))
pyautogui.moveTo (xcor,ycor)
如果 l==49:
pyautogui.click(clicks=2)
elif r==49:
pyautogui.click(button='right', clicks=2)
Arduino代碼:
#include
const int rxpin = 2, txpin = 3;
軟件串行藍牙(rxpin,txpin);
常量 int x=A0;
常量 int y=A1;
整數(shù) xh, yh;
int xcord,ycord;
常量 int 觸發(fā)器 = 5;
詮釋 lstate = 0;
int rstate = 0;
常量 int lclick = 6;
常量 int rclick = 7;
常量 int led = 8;
無效設(shè)置()
{
pinMode(x,INPUT);
pinMode(y,輸入);
pinMode(觸發(fā)器,INPUT_PULLUP);
pinMode(lclick,輸入);
pinMode(rclick,輸入);
pinMode(LED,輸出);
數(shù)字寫入(lclick,HIGH);
digitalWrite(rclick,HIGH);
序列號.開始(9600);
藍牙.開始(9600);
}
無效循環(huán)()
{
數(shù)字寫入(領(lǐng)導(dǎo),低);
而(digitalRead(觸發(fā)器)==LOW)
{
digitalWrite(LED,HIGH);
lstate = digitalRead(lclick);
rstate = digitalRead(rclick);
xh=模擬讀?。▁);
yh=analogRead(y);
xcord=map(xh,286,429,100,999);
ycord=map(yh,282,427,100,800);
串行打?。▁cord);
Serial.print(ycord);
if (lstate == LOW)
Serial.print(1);
否則
Serial.print(0);
if (rstate == LOW)
Serial.print(1);
否則
Serial.print(0);
藍牙.print(xcord);
藍牙.print(ycord);
if (lstate == LOW)
bluetooth.print(1);
否則
bluetooth.print(0);
if (rstate == LOW)
bluetooth.print(1);
否則
bluetooth.print(0);
延遲(4000);
}
}
Python驅(qū)動腳本
導(dǎo)入串口
import pyautogui
ser=serial.Serial('com3',9600)
while 1:
k=ser.read(8)
cursor=k[:6]
click=k[6:]
x=cursor[:3]
y= cursor[3:]
l=click[0]
r=click[1]
xcor=int(x.decode('utf-8'))
ycor=int(y.decode('utf-8'))
pyautogui.moveTo (xcor,ycor)
如果 l==49:
pyautogui.click(clicks=2)
elif r==49:
pyautogui.click(button='right', clicks=2)
?
電子發(fā)燒友App


























評論