Arduino远程拖拉机控制项目

随着STEM教育的普及,机器人项目在许多学校和爱好者中变得越来越流行。这个项目利用Arduino和Visual Basic代码来控制一个Arduino风格的Orion启动机器人拖拉机(Makeblock;www.makeblock.com)。Orion板是一个Arduino克隆板,非常适合初学者使用,因为它用RJ-25连接代替了跳线,并且有自己的库来利用这些连接。各种模拟和数字端口都进行了颜色编码,方便使用。VB部分的代码控制游戏手柄,并通过蓝牙将操纵杆输出传输到Arduino/Orion控制器。Arduino代码提供了执行操纵杆指令的功能,并将指令回传到VB程序以确认。

目标: - 在VB.NET程序中集成游戏手柄 - 从VB程序到远程Arduino模块的蓝牙通信 - Arduino控制拖拉机 - 提供易于理解、注释丰富的代码

代码: 操纵杆控制可以通过两种方法实现。一种常见的预期方法是使用一个操纵杆,通过X和Y输入获取方向,并将其转换为各种方向向量。然而,由于远程机器人是拖拉机,采取了一种更简单但更真实的方法,每个游戏手柄上的操纵杆控制拖拉机的一条履带。这是一种历史上准确的转向方法。

游戏手柄通过Winmm.dll暴露。这是一个较旧的32位库,但对目的来说很好。下一个版本将利用DirectX游戏手柄接口。

首先,定义游戏手柄的结构:

Public Structure JOYINFOEX Public dwSize As Integer Public dwFlags As Integer Public dwXpos As Integer Public dwYpos As Integer Public dwZpos As Integer Public dwTpos As Integer Public dwUpos As Integer Public dwVpos As Integer Public dwButtons As Integer Public dwButtonNumber As Integer Public dwPOV As Integer End Structure

创建操纵杆并添加一个计时器来轮询操纵杆的变化:

Public Joypos1 As JOYINFOEX Joypos1.dwSize = 64 Joypos1.dwFlags = &HFF Timer1.Enabled = False

计时器事件轮询操纵杆,特别关注Y和T轴,这将决定左履带和右履带的方向信息。然后处理这些数据并发送到Arduino/Orion。由于操纵杆数据以整数0到65536发送,使用偏移量使"0"成为"中点"。然后处理操纵杆的位置,产生向上、中立和向下,分别用于前进、停止和后退,这些将传递给Arduino。-32到32的规模在这里是任意的,但将用于开发单个操纵杆向量在项目后续迭代中的使用。

Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick joyGetPosEx(0, Joypos1) lblYaxis.Text = "Y = " & (Joypos1.dwYpos.ToString - 32767) lblTaxis.Text = "T = " & (Joypos1.dwTpos.ToString - 32767) Dim intJoyConvY As Integer intJoyConvY = CInt(Math.Round(Joypos1.dwYpos)) If intJoyConvY > -1 Then If intJoyConvY <= 20000 Then intJoyConvY = -32 End If If intJoyConvY > 20000 Then If intJoyConvY <= 40000 Then intJoyConvY = 0 End If If intJoyConvY > 40000 Then intJoyConvY = 32 End If End If End If Dim intJoyConvT As Integer intJoyConvT = CInt(Math.Round(Joypos1.dwTpos))

仍在计时器事件中,轮询并解析两个游戏手柄轴,准备发送到Arduino

Dim RMotor As Integer Dim strCmd As String = "" Dim LMotor As Integer LMotor = intJoyConvY RMotor = intJoyConvT If LMotor = 32 And RMotor = 32 Then charCmd = "F" strCmd = "forward" End If If LMotor = -32 And RMotor = -32 Then charCmd = "B" strCmd = "backward" End If

最后,解析后的命令通过蓝牙发送到Arduino。游戏手柄每250毫秒(可调整以提高性能)轮询一次,并且只有数据变化时才发送,以避免通信过载。

Try If charCmd <> charOldCmd Then rtbMonitor.Text = "" SerialPort1.Write(charCmd) rtbMonitor.Text = charCmd & vbCrLf charOldCmd = charCmd Else rtbMonitor.Text = rtbMonitor.Text & "No Changes" & vbCrLf End If Catch ex As Exception MessageBox.Show(ex.Message & "Open Port Before Proceeding") End Try

蓝牙通信是通过串行端口进行的。Windows设备管理器的"端口"部分将识别正确的端口。使用Try Catch结构来捕获错误。发送到Arduino的输出和Arduino的反馈都在VB程序界面的文本框中捕获。

#include #include #include MeDCMotor leftMotor(M1); MeDCMotor rightMotor(M2); MeBluetooth bluetooth(PORT_3); int leftSpeed = 130; int rightSpeed = 130; double turnSpeed = 0.6; void loop() { if (bluetooth.available()){ char cmd = readBlueTooth(); bluetooth.println(cmd); switch (cmd){ case 'F': forward(); bluetooth.print(cmd); break; case 'B': backward(); bluetooth.print(cmd); break; case 'r': toRight(); bluetooth.print(cmd); break; case 'L': spinLeft(); bluetooth.print(cmd); break; } } } char readBlueTooth(){ char btInput; btInput = (char) bluetooth.read(); return btInput; } void forward(){ rightMotor.run(rightSpeed); leftMotor.run(leftSpeed); } void backward(){ leftMotor.run(-leftSpeed); rightMotor.run(-rightSpeed); } void toRight(){ leftMotor.run(leftSpeed); rightMotor.run(rightSpeed*turnSpeed); } void spinLeft(){ rightMotor.run(rightSpeed*turnSpeed); leftMotor.run(-leftSpeed*turnSpeed); }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485