找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 30398|回复: 50

用VC编程让电脑利用BlueTooth与NXT沟通——谁来回答18/19楼的问题

 火.. [复制链接]
发表于 2011-2-7 20:12:15 | 显示全部楼层 |阅读模式
本帖最后由 grant7788 于 2011-2-8 21:49 编辑

缘起:NXT是我春节前买给女儿的礼物,结果春节期间我和她一起疯玩。嘿嘿... 老夫聊发少年狂。
结果,有几个程序,是要用另一台NXT主机,来遥控的。比如SegWay这台自平衡机器人。
呃... 我就随便玩玩的,难道要另外掏一笔银子再买套主机?
不不不...
貌似,是通过Bluetooth通讯的?
那么,能不能,通过电脑的蓝牙,和NXT通讯呢?
嗯,PID调节的那个程序算是基本搞定了,下面就试试蓝牙控制NXT吧。
一步步来... 嘿嘿...

目录:
1. 找到NXT的Bluetooth接口在电脑中的表示方式
2. 第一个程序:通过Bluetooth读回NXT主机的电池状态
3. 输出字符串到NXT主机
4. 控制NXT端NXT-G程序中的Bluetooth logic
5. 实做:用PC程序通过Bluetooth遥控小车
6. 实做:用PC程序通过Bluetooth遥控SecWay自平衡机器人 (计划中)
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
 楼主| 发表于 2011-2-7 20:14:54 | 显示全部楼层

1. 找到NXT的Bluetooth接口在电脑中的表示方式

嗯,这一点我相信许多朋友已经知道了,NXT的Bluetooth,在电脑中(至少,在我的Windows XP SP3中),是虚拟成一个COM口的。
只要找到它对应的是COM多少,那么,应该,就可以通过串口编程的方式,对它进行控制了。
在我的电脑上,对应的是COM8。在你的电脑上也许会有不同。
相会大部分朋友都会了,具体方法先不讲了,有不会的朋友请单独提问。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 20:32:59 | 显示全部楼层

2. 第一个程序:通过Bluetooth读回NXT主机的电池状态

本帖最后由 grant7788 于 2011-2-7 20:42 编辑

话说楼主搜了一下,找到一个老外的例程。原文链接如下:http://www.extremenxt.com/vbpart1.htm

可是楼主对VB 2005不熟啊... 知识老化了不是么...
用VB6试一下吧,居然,有种种限制。也是,VB6对串口操作,简单还行,复杂的是比较麻烦一点儿。
算了,咱还是用VC6吧。这玩艺儿灵活啊。试了一下,还真行。
我写程序一般不大写界面的,大家只看实现方法吧,哈哈~

VC下对串口的操作,基本上是通过文件操作的方式来实现的。
CreateFile打开串口,
ReadFile从串口读回数据,
WriteFile把数据写到串口。
上面说“基本上”,其实,VC下还是可以通过端口操作的方式来控制串口的。
什么什么?那位同学说,Windows 95以后就不能用inport / outport了?
嗯,不错,还是比较有常识的。
可是,难道,不能写一个简单的设备驱动程序,来进行端口操作吗?
刚才说话的那个同学,这个,就是你今天的回家作业了!
  1. #include <windows.h>
  2. #include <winbase.h>
  3. #include <stdio.h>
  4. #include <conio.h>

  5. void main()
  6. {
  7.         HANDLE hCom;
  8.         BOOL iRetVal;

  9.         DWORD iErrCode;
  10.         LPVOID lpMsgBuf;

  11.         char byteOut[6];
  12.         char byteIn[7];
  13.         DWORD iBytes;
  14.         int sVolt;

  15.         int i;

  16.         printf("Press any key to start...\n");
  17.         getch();
  18.        
  19.         // 打开串口。在我的电脑上NXT主机的Bluetooth对应COM8
  20.         hCom=CreateFile("COM8", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  21.         if(hCom==(HANDLE)-1)
  22.         {
  23.                 printf("打开COM失败!\n");
  24.                 return;
  25.         }
  26.         printf("BlueTooth opened!\n");
  27.         printf("Press any key to continue...\n");
  28.         getch();
  29.        
  30.         COMMTIMEOUTS TimeOuts;
  31.         //设定读超时
  32.         TimeOuts.ReadIntervalTimeout=MAXDWORD;
  33.         TimeOuts.ReadTotalTimeoutMultiplier=0;
  34.         TimeOuts.ReadTotalTimeoutConstant=0;
  35.        
  36.         //设定写超时
  37.         TimeOuts.WriteTotalTimeoutMultiplier=100;
  38.         TimeOuts.WriteTotalTimeoutConstant=500;
  39.         iRetVal = SetCommTimeouts(hCom,&TimeOuts); //设置超时
  40.        
  41.         DCB dcb;
  42.         iRetVal = GetCommState(hCom,&dcb);
  43.         // 设定串口参数
  44.         dcb.BaudRate = 96000;        //波特率为9600
  45.         dcb.ByteSize = 7;                //每个字节有7位
  46.         dcb.Parity = 2;                        //偶校验
  47.         dcb.StopBits = 0;                //无停止位
  48.         iRetVal = SetCommState(hCom, &dcb);
  49.         if (iRetVal == 0)
  50.         {
  51.                 iErrCode = GetLastError();
  52.                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,         NULL, iErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
  53.                 printf("%s\n", lpMsgBuf);
  54.                 getch();
  55.                 CloseHandle(hCom);
  56.                 return;
  57.         }
  58.        
  59.         PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
  60.         printf("Bluetooth port opened!\n");

  61.         // 以下发命令到NXT主机
  62.         byteOut[0] = 0x2;        // 消息长度2字节
  63.         byteOut[1] = 0x0;        // NXT为0
  64.         byteOut[2] = 0x0;        // 需要回复。如不需要回复为0x80
  65.         byteOut[3] = 0xB;        // 0x0B为读回电池状态
  66.         iRetVal = WriteFile(hCom, byteOut, 4, &iBytes, NULL);
  67.         printf("Write to BlueTooth %d bytes!\n", iBytes);
  68.         printf("Press any key to continue...\n");
  69.         getch();

  70.         // 从NXT主机读回数据,前两字节代表消息长度
  71.         iRetVal = ReadFile(hCom, &byteIn[0], 1, &iBytes, NULL);        // 返回消息字节数
  72.         iRetVal = ReadFile(hCom, &byteIn[1], 1, &iBytes, NULL);        // NXT为0
  73.         printf("Byte 0 = %d\n", byteIn[0]);

  74.         for (i=2; i<=byteIn[0]+1; i++)
  75.         {
  76.                 iRetVal = ReadFile(hCom, &byteIn[i], 1, &iBytes, NULL); // 读回全部消息
  77.         }
  78.         sVolt = byteIn[5] + byteIn[6]*256;                // 换算成电压
  79.         printf("Volt = %d\n", sVolt);

  80.         printf("Press any key to close...\n");
  81.         getch();
  82.        
  83.         CloseHandle(hCom);
  84. }
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 20:34:22 | 显示全部楼层
本帖最后由 grant7788 于 2011-2-7 20:34 编辑

以上程序用VC 6.0,在Windows XP SP3下调试、运行通过。运行截图如下(点击看大图):
t1.jpg

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-2-7 20:47:18 | 显示全部楼层
我今天也搜索到这篇链接来着,为了知道NXT的蓝牙通信波特率,之前看乐高的蓝牙的开发文档,写的是460.8K,结果用串口调试工具通信没成功,期待楼主的后续文章。随便问句,楼主是从事什么职业的?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 20:55:55 | 显示全部楼层
糖伯虎 发表于 2011-2-7 20:47
我今天也搜索到这篇链接来着,为了知道NXT的蓝牙通信波特率,之前看乐高的蓝牙的开发文档,写的是460.8K,结 ...

呵呵,这个蓝牙通信的一些参数,我开始用了老外VB 2005里的参数,结果报错。
后来我打开蓝牙对应的COM口之后,直接把端口里存好的参数读回来,只改了波特率。

我的行业,算是游荡在IT边缘吧。做过几年技术,后来转向了产品/市场(product / marketing)。编程现在变成了我的业余爱好,呵呵。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 21:43:58 | 显示全部楼层

3. 输出字符串到NXT主机

上面的例子已经包含了与NXT主机的双向沟通了,输出字符串是单向的,其实比上面那个容易些。
代码附上:
  1. #include <windows.h>
  2. #include <winbase.h>
  3. #include <stdio.h>
  4. #include <conio.h>

  5. void main()
  6. {
  7.         HANDLE hCom;
  8.         BOOL iRetVal;
  9.        
  10.         DWORD iErrCode;
  11.         LPVOID lpMsgBuf;
  12.        
  13.         char byteOut[64];
  14.         char byteIn[7];
  15.         char strOut[] = "Hello, cmnxt!";
  16.        
  17.         int i;
  18.         DWORD iBytes;
  19.        
  20.         printf("Press any key to start...\n");
  21.         getch();
  22.        
  23.         // 打开串口。在我的电脑上NXT主机的Bluetooth对应COM8
  24.         hCom=CreateFile("COM8", GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
  25.         if(hCom==(HANDLE)-1)
  26.         {
  27.                 printf("打开COM失败!\n");
  28.                 return;
  29.         }
  30.         printf("BlueTooth opened!\n");
  31.         printf("Press any key to continue...\n");
  32.         getch();
  33.        
  34.         COMMTIMEOUTS TimeOuts;
  35.         //设定读超时
  36.         TimeOuts.ReadIntervalTimeout=MAXDWORD;
  37.         TimeOuts.ReadTotalTimeoutMultiplier=0;
  38.         TimeOuts.ReadTotalTimeoutConstant=0;
  39.        
  40.         //设定写超时
  41.         TimeOuts.WriteTotalTimeoutMultiplier=100;
  42.         TimeOuts.WriteTotalTimeoutConstant=500;
  43.         iRetVal = SetCommTimeouts(hCom,&TimeOuts); //设置超时
  44.        
  45.         DCB dcb;
  46.         iRetVal = GetCommState(hCom,&dcb);
  47.         // 设定串口参数
  48.         dcb.BaudRate = 96000;        //波特率为9600
  49.         dcb.ByteSize = 7;                //每个字节有7位
  50.         dcb.Parity = 2;                        //偶校验
  51.         dcb.StopBits = 0;                //无停止位
  52.         iRetVal = SetCommState(hCom, &dcb);
  53.         if (iRetVal == 0)
  54.         {
  55.                 iErrCode = GetLastError();
  56.                 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,         NULL, iErrCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &lpMsgBuf, 0, NULL);
  57.                 printf("%s\n", lpMsgBuf);
  58.                 getch();
  59.                 CloseHandle(hCom);
  60.                 return;
  61.         }
  62.        
  63.         PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
  64.         printf("Bluetooth port opened!\n");
  65.        
  66.         // 以下发命令到NXT主机
  67.         byteOut[0] = strlen(strOut) + 5;        // 消息长度
  68.         byteOut[1] = 0x0;                                        // NXT为0
  69.         byteOut[2] = 0x80;                                        // 不需要回复。如需要回复为0x0
  70.         byteOut[3] = 0x9;                                        // 0x09为通过Bluetooth发送信息给NXT
  71.         byteOut[4] = 0x0;                                        // Box Number ---- 1
  72.         byteOut[5] = strlen(strOut) + 1;        // 发送的字符串的字节数
  73.         for (i=0; i<strlen(strOut); i++)
  74.         {
  75.                 byteOut[6+i] = strOut[i];
  76.         }
  77.         byteOut[strlen(strOut)+6] = '\0';

  78.         iRetVal = WriteFile(hCom, byteOut, strlen(strOut)+7, &iBytes, NULL);
  79.         printf("Write to BlueTooth %d bytes!\n", iBytes);
  80.         printf("Press any key to exit...\n");
  81.         getch();
  82.        
  83.         CloseHandle(hCom);
  84. }
复制代码



如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 21:46:16 | 显示全部楼层
其实程序和前面那个几乎一样。只是花了点时间把要发的字符合并到byteOut里面。呵呵,我偷懒直接照搬了老外的程序。其实用C里的字符串操作函数会更精练。
要不,这个也留作家庭作业?

同样上传程序运行时的界面截图。点击看大图。
t2.jpg

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-2-7 22:14:40 | 显示全部楼层
LZ是高手,跟着学了,谢谢!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-2-7 22:20:21 | 显示全部楼层
回复 grant7788 的帖子

波特率你现在用的是9600吗?数据位7位?
奇偶校验位2位?
没有停止位?
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-2-7 23:01:24 | 显示全部楼层
请问WINDOS7能用蓝牙和NXT连接吗 我是WIN7系统 以前用NXt连电脑没连上 不知是啥原因今天请教下
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 23:03:35 | 显示全部楼层
糖伯虎 发表于 2011-2-7 22:20
回复 grant7788 的帖子

波特率你现在用的是9600吗?数据位7位?

波特率不是9600,是96000。
数据位7位。
2代表是偶校验 (0-4=no,odd,even,mark,space)
没有停止位。

我的理解是,真正传输的是bluetooth的协议,而bluetooth芯片的驱动把它虚拟成了COM口而已,
所以,不同的电脑、不同的操作系统、甚至不同的驱动程序,可能都会造成这几个参数的不同。
另外,你前面说的那个460.8k,应该是NXT主机中,ARM7主芯片和外部bluetooth控制芯片之间的通讯速率,不是主机上的这个虚拟串口的速率。
t3.jpg

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 23:04:15 | 显示全部楼层
strikefreedom 发表于 2011-2-7 23:01
请问WINDOS7能用蓝牙和NXT连接吗 我是WIN7系统 以前用NXt连电脑没连上 不知是啥原因今天请教下

我手上没有Windows 7,不是很清楚。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2011-2-7 23:05:00 | 显示全部楼层
本帖最后由 grant7788 于 2011-2-7 23:32 编辑
lmd 发表于 2011-2-7 22:14
LZ是高手,跟着学了,谢谢!

不客气,大家一起讨论才有提高。
汗个... 又遇到每小时发帖的上限了,只好编程回帖...

粗略看了一遍两份Spec.
(1. LEGO&#174; MINDSTORMS&#174; NXT Communication Protocol
2. LEGO&#174; MINDSTORMS&#174; NXT Direct Commands)

NXT的Bluetooth接口很好很强大。貌似可以用电脑通过Bluetooth直接控制NXT的所有动作。
比如... 在NXT小车上固定一个无线摄像头,然后跑个程序去分析一下传回的图像,并决定行走路线?
或者,电脑上播放MP3的同时,对音频进行分析,并根据分析的节奏控制机器人的舞蹈动作?
呵呵,朝这类的方向想,可以做的有趣的事情非常多。
基本的操作方式上面已经有了,有人有兴趣的话可以一起玩。

如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-2-7 23:50:38 | 显示全部楼层
LZ很牛啊!现在高手越来越多了!我开始努力学习!要不被淘汰了呵呵
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 马上注册

本版积分规则

QQ|手机版|中文乐高 ( 桂ICP备13001575号-7 )

GMT+8, 2024-3-29 00:35 , Processed in 0.122396 second(s), 21 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表