了解如何使用您的 Arduino 控制樂高電機和伺服系統(tǒng),并構建您自己的 Android 應用程序來遠程控制您的模型。
背景
您是否擁有帶有電動機和伺服電機的超棒Lego Power Functions 模型之一?在本文中,我將向您展示如何使用 Arduino 和最少的電子元件來控制樂高模型。我將詳細解釋電路和編程,以便于初學者理解。
我們還將學習如何使用MIT 應用程序發(fā)明者來編寫我們自己的遠程控制 Android 應用程序。很快,您將在您的后院擁有自己的樂高火星探測器!
這是我的第一個 Arduino 項目,我兒子有一個漂亮的 Lego Technic 汽車模型(9398 4X4 Crawler ),帶有樂高動力功能:一個用于轉向的樂高伺服電機和兩個用于駕駛的樂高 L 電機。同時他也允許我在這個項目中使用這輛車。
了解電源功能接線
首先,購買一些樂高電源功能延長線。接下來,將它們切斷。我們將制作一些“分線”電纜,一端有樂高積木,另一端有別針。將引腳焊接在上面或類似的地方。以下是接線說明:
GND 代表接地,它是電池組(陽極)的負極端子 (-)。C1和C2可以切換極性,使電機和舵機切換方向。對于樂高伺服連接器,你需要將針腳焊接到所有四根電纜上。您可以使用淺灰色插頭。對于連接電池盒和面包板的電源線,我們只需要 +9 Volt 和 GND 但您必須使用深灰色插頭:
對于電機電纜,我們只需連接 C1 和 C2,您可以使用淺灰色插頭。
使用 L293D 芯片控制樂高電機
我們需要直流電機的變速控制和樂高伺服的位置控制。這是通過脈沖寬度調制 (PWM)實現(xiàn)的。Arduino的編程語言使PWM易于使用;只需調用analogWrite(pin, dutyCycle) ,其中 dutyCycle 是一個從 0 到 255 的值。PWM 引腳在您的 arduino 上標有 ~。
Arduino 輸出引腳為 5 伏特和最大值。30 毫安,而樂高電機需要 9 伏且每個拉力超過 100 毫安。我們需要某種介于兩者之間的“開關設備”。我們還希望能夠在兩個方向上運行直流電機。這些功能由所謂的H 橋解決。我們將使用L293D ,它在一個集成芯片上包含兩個 H 橋,這意味著我們可以將樂高電機 (M) 并聯(lián)連接到芯片的一側,將樂高伺服 (S) 連接到芯片的另一側。(如果您想獨立控制兩個電機,則需要第二個 L293D)。樂高伺服還需要連接到 GND 和樂高 +9 伏。
該芯片使 Lego +9 Volt 和 Arduino +5 Volt 完全分離。切勿將它們連接在一起,否則會損壞某些東西!但是您同時須將所有接地線連接在一起并與 L293D 接地引腳連接。
在我們的 Arduino 中,我們將使用引腳 9 來控制電機速度,使用引腳 2 和 5 來控制旋轉方向。樂高伺服像電機一樣被控制:我們連接引腳 3 用于位置,引腳 6 和 8 用于方向(左或右)。
在我們程序的頂部,我們將使用的 Arduino 引腳定義為常量。此外,我們定義了一些用于控制電機的變量:
// Motor control digital output pins defined as global constants
const int controlPin1A = 2; ? ? ? ? ? ? ? ?
const int controlPin2A = 5; ? ? ? ? ? ? ? ??
const int ENablePin = 9; ? ? ? ? ? ? ? ? ??
// Servo control digital output pins defined as global constants?
const int controlPin3A = 6; ? ? ? ? ? ? ?
const int controlPin4A = 8; ? ? ? ? ? ? ? ? ?
const int servoENablePin = 3; ?
? ? ? ??
// Motor control global variables:?
int motorSpeed = 0; ? ? ? ? ? ? ? ? ? ? ? ? ?// Motor speed 0..255
int motorDirection = 1; ? ? ? ? ? ? ? ? ? ? ?// Forward (1) or reverse (0)
// Servo control global variables:
int steering = 0; ? ? ? ? ? ? ? ? ? ? ? ? ? ?// Servo position 0..255
int steeringDirection = 0; ? ? ? ? ? ? ? ? ? // Left (0) and Right (1)
在設置中,我們使用pinmode()命令將這些引腳定義為輸出,然后使用digitalWrite ()將它們設置為 0 伏。?
void setup()?
{
? //other stuff....
?
? // Declare digital output pins:
? pinMode(controlPin1A, OUTPUT); ? ? ?// 1A
? pinMode(controlPin2A, OUTPUT); ? ? ?// 2A
? pinMode(ENablePin, OUTPUT); ? ? ? ? // EN1,2
? pinMode(controlPin3A, OUTPUT); ? ? ?// 3A
? pinMode(controlPin4A, OUTPUT); ? ? ?// 4A
? pinMode(servoENablePin, OUTPUT); ? ?// EN3,4
?
? digitalWrite(ENablePin, LOW); ? ? ? // motor off
? digitalWrite(servoENablePin, LOW); ?// steering centered
}
現(xiàn)在我們需要了解 L293D 芯片是如何控制電機的旋轉方向的。我們必須提供以下信號(高 == 5 伏;低 == 0 伏):
EN1,2 1A 2A
高 高 低 電機左轉(前進;motorDirection == 1)
高 低 高 電機右轉(反向;motorDirection == 0)
EN3,4 3A 4A
高 高 低 舵機左轉(steeringDirection == 0)
高 低 高 舵機右轉(steeringDirection == 1)
接下來我們準備編寫一個子程序來讀取方向和速度/位置的全局變量并控制電機和伺服:
void SetMotorControl()
{
?if (motorDirection == 1) ? ? ? ? ? ? ? //Forward
? ?{
? ? ? digitalWrite(controlPin1A, HIGH);
? ? ? digitalWrite(controlPin2A, LOW);
? ?}
?else ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Reverse
? ?{
? ? ? digitalWrite(controlPin1A, LOW);
? ? ? digitalWrite(controlPin2A, HIGH);
? ?}?
?analogWrite(ENablePin, motorSpeed); ? ?//Speed
?
?if (steeringDirection == 0) ? ? ? ? ? ?//Left
? ?{
? ? ? digitalWrite(controlPin3A, HIGH);
? ? ? digitalWrite(controlPin4A, LOW);
? ?}
?else ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //Right
? ?{
? ? ? digitalWrite(controlPin3A, LOW);
? ? ? digitalWrite(controlPin4A, HIGH);
? ?}?
?analogWrite(servoENablePin, steering); //Servo position
}
帶有操縱桿的簡單 RC Android 應用程序
接下來,讓我們構建一個簡單的 Android 應用程序來控制模型。
我們將使用 MIT app inventor 2。MIT App Inventor 是一個創(chuàng)新的初學者對編程和應用程序創(chuàng)建的介紹。Google 的 Mark Friedman 和麻省理工學院教授 Hal Abelson 共同領導了 App Inventor 的開發(fā)。它作為一項網(wǎng)絡服務運行,由麻省理工學院移動學習中心的工作人員管理。
在您的 Android 手機上,前往 Google Play 并安裝MIT AI2 Companion 應用程序。在您的計算機上,在 Firefox 或 Chrome 瀏覽器中打開我的RC 應用程序的鏈接。您必須使用您的 gmail 地址登錄并創(chuàng)建一個帳戶才能查看源代碼。如果您在手機上打開配套應用程序,您可以在瀏覽器中查看源代碼,對其進行更改并立即在手機上進行測試。
在瀏覽器中,您現(xiàn)在將看到應用程序的設計器視圖:
在底部,我們看到帶有藍色操縱桿球的橙色墊?,F(xiàn)在切換到 Blocks-view 來查看程序。該程序的核心是一個 when 塊,它跟蹤您的手指觸摸和拖動藍色操縱桿球的動作:
您的手指位置將會在兩個變量currentX和currentY中進行跟蹤,并用于計算兩個變量轉向和速度的值(范圍:-100..0..+100)。首先,程序會先檢查您的手指是否在墊外,并將值限制為 +/- 100。如果手指在墊內,程序會計算轉向和速度的值。接下來,程序生成以下形式的命令字符串:
“遙控,轉向,速度,\n”
該命令以用于遠程控制的“RC”開頭,后跟逗號。然后我們發(fā)送轉向和速度的值。命令末尾的換行符 (‘\n’) 是向 Arduino 發(fā)出命令完成的信號。該命令字符串通過藍牙發(fā)送到 Arduino。供您參考,該字符串也顯示在屏幕上。
將藍牙命令讀入 Arduino
為了讀取藍牙命令字符串,我們需要連接一個 HC-05 藍牙模塊:
我的這塊板子有 6 個引腳。但我們實際上只需要 4 個引腳。VCC 是(正)電源電壓,GND 是地。該模塊可承受 6 伏電源電壓,這意味著我們可以將其連接到 arduino 5 伏電源引腳。TXD 和 RXD 是串行信號。我們必須越線并將 TXD 連接到 arduino RXD(引腳 0),反之亦然。
注意: LEVEL:3.3V,這意味著 RXD不能直接連接到 5V arduino TXD(引腳 1)。我們必須構建一個帶有三個 1 kOhm 電阻的分壓器,以產生 5V 的 2/3 的輸出電壓。另一方面,3.3V 的 TXD 信號可以直接連接到 Arduino RXD。Arduino 會將 3.3V識別為高。
由于引腳 0 和 1 與 Arduino 的 USB 端口共享,因此在通過 USB 將程序上傳到開發(fā)板時,您必須斷開引腳 0 和 1 的 RXD 和 TXD 信號。如果您不斷開電纜,上傳將無法進行。
接下來,您必須將 HC-05 模塊與您的 Android 設備配對。打開藍牙;啟動應用程序;按“藍牙連接”;讓您的手機可見并尋找名為 HC-05 或類似設備的設備。選擇設備。您將被要求輸入代碼。按“1234”。當您返回操縱桿屏幕時,它應該以綠色顯示“已連接”。
現(xiàn)在,讓我們看一下代碼:
// Serial buffer size: calculate based on max input size expected for one command
#define INPUT_SIZE 30
?
?
void loop()?
{
? // Get next command from serial bluetooth (add 1 byte for final 0)
? char input[INPUT_SIZE + 1]; ? ? ? ? ? ? ? ? ?// array of type char (C-string)
? //read Serial until new line or buffer full or time out
? byte size = Serial.readBytesUntil('\n', input, INPUT_SIZE); ??
? // Add the final 0 to end the C-string
? input[size] = 0;
?
? // Split string which is of the form: ?"RC,steering,speed,\n\0"
? char* command = strtok(input, ","); ? ? ? ? ?// command (RC) ??
? // RCsteering in Range: -100 (left).. 0 .. 100 (right)
? char* RCsteering = strtok(NULL, ","); ? ? ? ?
? // RCspeed in Range: -100 (full speed reverse).. 0 .. 100 (full speed forward)
? char* RCspeed = strtok(NULL, ","); ? ? ? ? ??
? int iRCsteering = atoi(RCsteering); ? ? ? ? ?// convert string into integer
? int iRCspeed = atoi(RCspeed); ? ? ? ? ? ? ? ?// convert string into integer
?
? //rest of program
}
Android 應用程序發(fā)送的字符串被讀入一個特殊的字符串結構:一個帶有 null-termination 的 C 字符串。(0 字符告訴程序它已經到了字符串的末尾)。這是通過使用函數(shù) Serial.readBytesUntil(‘\n’, input, 。..)來完成的,該函數(shù)從串行接口(藍牙)讀取,直到獲得換行符(‘\n’)。這樣,我們會一直讀取字節(jié),直到在input中有完整的命令:
“遙控,轉向,速度,\n\0”。
處理輸入的一種非常有效的方法是字符串標記函數(shù),它使用逗號作為分隔符將字符串分成幾部分。第一次調用 strtok() 返回“RC”。然后通過將 NULL 傳遞給 strtok() 來讀取命令的后續(xù)部分。返回值存儲在RCsteering和RCspeed中。這些變量實際上是指向input中位置的指針。atoi()函數(shù)最終將它們轉換為整數(shù)。現(xiàn)在,我們有:
iRC 轉向 == -100(左)。. 0 。. +100(右)
iRCspeed == -100(后退)。. 0 。. +100(前進)
現(xiàn)在差不多完成了。在將它們傳遞給我們的例程 SetMotorControl() 之前,我們必須將這些值乘以 2.55(請記住,電機速度在 0..255 范圍內)。你現(xiàn)在可以在 CODE 部分研究程序的其余部分,構建電路并測試您的遙控樂高模型。
未來?
既然您有一個 Arduino 控制您的樂高模型,您可能希望將該模型用作機器人平臺:
添加一些超聲波 ping 傳感器,編寫您自己的避障邏輯并制作您自己的自動駕駛機器人火星探測器。
或者給遙控器增加更多指令,給模型增加更多功能。
評論
查看更多