前面提到了分辨颜色的三部曲,今天给大家介绍一下NXT和电脑之间的蓝牙通讯。其中在NXT端使用的是Lejos自带的Bluetooth类,在PC端使用的开发工具是VS2008,使用的语言是c#。
有些人鄙视这种连接PC的做法,在他们的眼里,连接了PC以后,乐高就变成了一个遥控玩具。其实对编程开发来说,用Java还是用c#并没有本质的区别。魔方的算法也可以写成Java的版本,无奈的是NXT的内存不足,只能把这种体力活交给电脑了。
1. 蓝牙配对
正所谓千里姻缘一线牵,首先我们要给NXT和PC安排一个相亲大会。NXT已经内置了蓝牙模块,要把它设置成打开并且可见的状态。设置方法请看Lejos的中文教程“蓝牙菜单”。现在很多笔记本也自带了蓝牙模块,如果没有的话,必须买一个蓝牙适配器。注意WinXP开始就都已经自带蓝牙驱动了,如果你的电脑安装了第三方的蓝牙驱动,最好先删除。
蓝牙适配器
准备好定情信物以后,就该安排PC和NXT见面了。PC比较主动,由他开负责寻找:
控制面板中旋转“添加新的蓝牙设备”,可以找到当前可见的NXT
找到NXT后,两人会羞答答的先来个握手协议,接下来是交换电话号码。Lejos设置的蓝牙连接密码是1234。
输入蓝牙连接密码
你看他们一个是能力超强,名车豪宅,另一个能歌善舞,秀色可餐。简直就是一拍即合啊。到此牵线完毕,以后他们就可以直接通讯了。我们查看一下电脑上的NXT属性,可以看到有个带“DevB”的端口,这个相当于是他们之间的私人电话,记下来后面会用到。
注意看端口号
2. C#中使用蓝牙通讯
其实配对以后,蓝牙就被模拟成了一个端口,我们可以用最简单的端口通讯来收发信息。首先,在每次启动时,需要连接端口:
BluetoothConnection = new SerialPort(); ConnectButton.Enabled = false; BluetoothConnection.PortName = PortList.SelectedItem.ToString(); BluetoothConnection.Open(); BluetoothConnection.ReadTimeout = 10000; BluetoothConnection.DataReceived += new SerialDataReceivedEventHandler(BlueToothDataReceived);
然后可以通过这个端口来发送信息。需要注意的是,在发送的原始数据之前,需要添加两个表示长度的字节,Byte[0]+Byte[1]*255=length。所以发送数据的函数如下:
private void BlueToothDataSend(byte[] data)
{
int length = data.Length;
byte[] readData = new byte[length + 2];
readData[0] = (byte)(length % 255);
readData[1] = (byte)(length / 255);
for (int i = 0; i < length; i++)
{
readData[i + 2] = data[i];
}
BluetoothConnection.Write(readData, 0, length + 2);
Status = "发送数据字节数:" + length;
}
收到数据的时候,也是类似的情况,头两个字节表示了数据的长度,然后才是真正的数据内容:
private void BlueToothDataReceived(object o, SerialDataReceivedEventArgs e)
{
int length = BluetoothConnection.ReadByte();
length += BluetoothConnection.ReadByte() * 256;
byte[] data = new byte[length];
BluetoothConnection.Read(data, 0, length);
for (int i = 0; i < length; i++)
{
BlueToothReceivedData += string.Format("data[{0}] = {1}\r\n", i, data[i]);
}
}
断开蓝牙连接的命令如下:
BluetoothConnection.Close(); BluetoothConnection.Dispose(); BluetoothConnection = null;
3. Lejos中使用蓝牙通讯
在Lejos中使用蓝牙有几点区别:首先,Lejos中不支持收到消息的事件触发(我怀疑用多线程可以实现,不过对Java不太熟悉,没有调试成 功)所以在需要接受PC信息时,只能挂起等候消息传来;其次,虽然PC发来的信息头两个字节表示长度,但是Lejos接收时,是从第三个字节开始显示的; 另外,Lejos发送蓝牙信息时,不需要添加那两个字节的长度信息。
下面是建立蓝牙连接的方式:
public static void Connect() throws Exception
{
LCD.clear();
LCD.drawString("Waiting BTC...",0,0);
btc = Bluetooth.waitForConnection();
LCD.drawString("Connected",0,2);
LCD.refresh();
dis = btc.openDataInputStream();
dos = btc.openDataOutputStream();
}
接受蓝牙信息:
public static byte[] ReadBytes() throws Exception
{
byte[] buffer = new byte[255];
int length = btc.read(buffer, buffer.length);
if(length==-2)
{
//lost data, re-sync
btc.read(null, 255);
return new byte[0];
}
else
{
byte[] data = new byte[length];
for(int i=0;i<length;i++)
{
data[i] = buffer[i];
}
return data;
}
}
发送蓝牙信息
public static void WriteBytes(byte[] data) throws Exception
{
for(int i=0;i<data.length;i++)
{
dos.writeByte(data[i]);
}
dos.flush();
}
关闭蓝牙连接
public static void Disconnect() throws Exception
{
if(btc!=null)
{
WriteBytes(new byte[]{(byte)255,(byte)255,(byte)255});
Thread.sleep(100);
dos.close();
dis.close();
btc.close();
}
}
4. 蓝牙通讯小实验
下面进行一个小实验,在PC上运行一个程序。
当发送1时,NXT初始化魔方底盘位置;
当发送2时,NXT初始化颜色传感器位置;
当发送3时,NXT读取颜色信息,并回传给电脑;
当发送其他数字时,NXT断开蓝牙连接,并退出程序
蓝牙连接通讯实验
大部分函数在前面都介绍过了,只需要在main函数中指定操作即可:
BlueTooth.Connect();
byte[] colorData = new byte[6];
while(true)
{
byte[] readData = BlueTooth.ReadBytes();
if(readData.length > 0)
{
int action = readData[0];
switch(action)
{
case 1:
Robot.FixBasePosition();
break;
case 2:
Robot.FixColorSensorPosition();
break;
case 3:
colorData[0] = (byte) color.getRed();
colorData[1] = (byte) color.getGreen();
colorData[2] = (byte) color.getBlue();
colorData[3] = (byte) (color.getRawRed() / 3);
colorData[4] = (byte) (color.getRawGreen() / 3);
colorData[5] = (byte) (color.getRawBlue() / 3);
BlueTooth.WriteBytes(colorData);
break;
default:
BlueTooth.Disconnect();
return;
}
}
Thread.sleep(1000);
}
好了,其余部分自己看代码吧,搭车赠送一个生成三维魔方图形的小程序。点此查看运行在NXT中Java源代码代码;点此下载运行在电脑上的C#程序源代码。
原文链接:解魔方的机器人攻略22 – 蓝牙通讯
Tags:解魔方机器人