65.9K
CodeProject 正在变化。 阅读更多。
Home

C# 蓝牙监视器 for Lego Mindstorms NXT

emptyStarIconemptyStarIconemptyStarIconemptyStarIconemptyStarIcon

0/5 (0投票)

2015年8月19日

CPOL

6分钟阅读

viewsIcon

18721

downloadIcon

775

持续通过蓝牙监视 NXT 的程序

引言

Pierre Poliakoffbigbro 的启发,我编写了一个 C# 程序来与我的 Mindstorms NXT 通信,该程序持续显示电池电压和传感器值。这两个值是从 NXT 中读取的,分别在两个线程中进行,每个线程都使用 .NET 的 Thread 类创建,并在滚动文本框中显示。

背景

该项目包含一个名为 NXT BT Monitor 的 C# 程序和一个名为 NXCBTMON 的 NXC 程序。我使用 Visual Studio 2010 在 Windows 7 和 .NET 4.0 上开发了 C# 程序。对于 NXC 程序,我使用了 BricxCC 版本 3.3.8.9;我的 NXT 上的协议和固件版本分别是 1.124 和 1.31。NXT 光传感器连接到端口 3,NXT 电机连接到端口 A。我使用了带有 Windows 7 Broadcom 驱动程序的 Medialink 蓝牙适配器,但其他蓝牙适配器也能工作;在线 NXT 文档列出了与 NXT 兼容的适配器。与 NXT 不兼容的蓝牙驱动程序似乎是导致问题的最常见原因。

必备组件

假定读者熟悉 NXT 及其传感器和电机,C# 和 NXC 语言,Visual Studio 和 BricxCC IDE,以及在 Windows 7 和 NXT 上使用蓝牙的经验。John Hansen 和 Daniele Benedettelli 都撰写了关于 NXC 和 NXT 蓝牙的优秀书籍。您可能还想获取可以在线找到或通过联系 Lego 直接获得的“Mindstorms NXT 通信协议”、“Mindstorms NXT 直接命令”和“NXT 蓝牙支持”文档。这些文档描述了可以发送到 NXT 的各种命令以及返回的数据。调试蓝牙问题需要毅力和创造力,可能需要偶尔重启 NXT 电源,启动和停止 Visual Studio 或 BricxCC,甚至重启 Windows 7。NXT 必须靠近蓝牙适配器。随身携带一块新的 NXT 电池是必须的。请记住,一次只能有一个程序——BricxCC 或 NXT BT Monitor——连接到 NXT。

使用代码

运行在 NXT 上的程序 NXCBTMON 由两个文件组成:NXCBTMon.nxc 和 protocol.h。为 NXT 供电,使用 John Hansen 的出色 BricxCC IDE 构建并下载 NXCBTMON,然后关闭 BricxCC 并为 NXT 供电。

在 Visual Studio 中打开 C# 程序 NXTBTMonitor.sln 的解决方案文件。在 Visual Studio 中构建并运行 NXT BT Monitor。如果您连接了控制台窗口用于调试(如下所述),您会看到使用 WMI 通过 ManagementObjectSearcher 类获取可用 COM 端口可能需要几秒钟。(未来的一个增强功能是显示一个“请稍候”对话框,在 COM 端口查询运行时。)

为 NXT 供电,然后在 NXT BT Monitor 中,选择对应于您的蓝牙适配器的端口(可通过 Windows 控制面板 => 查看设备和打印机找到),然后单击“连接”按钮。状态应在几秒钟内从“已断开连接”变为“已连接”。如果连接不成功,您可能需要查看上面的故障排除建议。请注意,您选择的端口将保存为用户设置,并在下次运行程序时自动选择(请参阅 Settings.Settings 文件)。在 NXT BT Monitor 运行并连接到 NXT 后,您可以运行 NXCBTMON 开始向 NXT BT Monitor 发送传感器读数。

关注点

NXT BT Monitor 和 NXT 之间通信的关键类是 .NET 的 SerialPort 类。

private SerialPort bluetoothConnection = new SerialPort();

这个类有一个名为 ReadTimeout 的属性,它指定了读取操作在超时发生之前等待的毫秒数。NXT BT Monitor 在配置文件中有一个对应的参数 ReadTimeout,您可能需要对此进行调整。目前设置为两秒。在 NXT BT Monitor 连接到 NXT 后,将启动两个线程,一个用于监视光传感器,一个用于监视电池电压。线程休眠的时间可以通过配置文件中的 SensorThreadSleepBatteryThreadSleep 参数指定。从新线程更新控件的一个后果是,我们必须调用 BeginInvoke;有关 UpdateEditCallbackUpdateVoltageCallback 委托的代码请参阅。由于两个线程都可以访问串行端口对象,因此使用 .NET 的 lock 构造来一次只允许一个线程访问蓝牙端口。

NXCBTMON 有一个名为 ReadLightSensor() 的任务,它读取光传感器并将值发送到 NXT BT Monitor。NXT BT Monitor 的 SensorRead() 线程接收消息并显示值。同样,BatteryRefresh() 线程查询 NXT 的电池电压并显示它,包括文本和进度条。进度条将显示绿色、黄色或红色,具体取决于电压。单击“获取信息”按钮将查询 NXT 的名称、蓝牙地址和剩余用户闪存量(以字节为单位)。

单击“获取版本”按钮将查询 NXT 的协议和固件主次版本号。您可以通过在“发送”按钮上方的文本框中键入消息,然后单击按钮来将消息发送到 NXT 的邮箱。NXCBTMON 继而会在 NXT 的 LCD 屏幕上显示文本。目前 NXCBTMON 程序只读取邮箱 0。向 NXCBTMON 发送消息“start”将导致连接到端口 A 的电机启动。

NXT BT Monitor 中与 NXT 通信的代码封装在特定的类中。例如,单击“获取信息”按钮会导致 GetDeviceInfo 类被实例化,然后可以对其调用方法来获取信息。在每个类的注释中,我都提供了上述“Mindstorms NXT 通信协议”文档的相关信息和具有有意义名称的常量,以避免代码中出现“魔法数字”。例如,以下是 GetDeviceInfo.cs 的一个代码片段:

    // Reference: p. 14 of MINDSTORMS NXT Communication Protocol.pdf
    //
    // Transmit
    //   0: 0x01 Reply Required
    //   1: 0x9B Get Device Info

    // Receive
    //   0: 0x02
    //   1: 0x9B
    //   2: Status: if 0 success, else error
    //   3-17: NXT Name (14 Characters + Null terminator)
    //   18-24: BT address
    //   25: LSB of Bluetooth signal strength - 32 bit
    //   26: -
    //   27: -
    //   28: MSB of Bluetooth signal strength
    //   29: LSB of free user Flash - 32 bit
    //   30: -
    //   31: -
    //   32: MSB of free user Flash
    public class GetDeviceInfo
    {
        public const byte GetDeviceInfoCommandB0 = 0x01;
        public const byte GetDeviceInfoCommandB1 = 0x9B;
        public const int NameStart = 3;
        public const int NameEnd = 17;
        public const int BTAddrStart = 18;
        public const int BTAddrLen = 6;
...

性能监视器和调试

NXT BT Monitor 的一个有趣功能是能够将从 NXT 获取的电池电压和传感器读数显示在 Windows 性能监视器中。有 Windows 性能监视器经验并希望启用此功能的读者可以通过以管理员身份运行服务器资源管理器(下图所示)添加计数器,然后取消注释下方显示的相应代码行。

// PerfCounter.SetSensor1((long)sensor1);
// PerfCounter.SetVoltage(perCent);

这是性能监视器显示电池电压(绿色)和传感器值(红色)的屏幕截图。它们是通过单击性能监视器工具栏中的绿色加号添加的。

NXT BT Monitor 的另一个不错的特性是为 Windows Forms 项目附加了一个控制台,用于调试目的,使用 AllocConsole 和 .NET Interop。它默认启用;要禁用它,只需注释掉 Main 的前 7 行。

IntPtr ptr = GetForegroundWindow();
int pid;
GetWindowThreadProcessId(ptr, out pid);
Process process = Process.GetProcessById(pid);
AllocConsole();
AttachConsole(process.Id);
Console.WriteLine("{0} NXT BT Monitor started", DateTime.Now);

历史

版本 1.0.3.0 2015 年 8 月 17 日

© . All rights reserved.