Posts Tagged ‘Lejos’

NXT2.0的颜色传感器

这几天尝试着把NXT2.0的颜色传感器换到萝卜头身上。因为新传感器自带光源,这样对环境光的依赖性会比较小。摸索了几天,终于实验成功了。现在在日光,灯光和昏暗条件下,基本都能读出颜色。缺点是这个传感器对颜色块的区域要求比较高,必须对准了才好用,这对于魔方的小方块来说真是有点痛苦。

再次提醒一下各位,原来的lejos API是有bug的,程序猎人同学已经帮大家编译了一个新的版本,请替换\lejos_nxj\lib目录中classed.jar文件即可:
http://www.diy-robots.com/RubikSolver/classes.jar

这个传感器共有红绿蓝三种灯,但是不能随意组合。下面的例子表示如何读取一个色块的红色分量。

ColorLightSensor color = new ColorLightSensor(SensorPort.S1, ColorLightSensor.TYPE_COLORRED);
int red = color.getRedComponent();

如果你只是想让红色的灯亮起来,可以这样:

//方法1:指定TYPE_COLORRED,然后用setFloodlight(true);
ColorLightSensor color = new ColorLightSensor(SensorPort.S1, ColorLightSensor.TYPE_COLORRED);
color.setFloodlight(true);
//方法2:直接设置灯的颜色;
color.setFloodlight(Colors.Color.RED);

蓝色和绿色的操作和红色类似。需要注意的是,我们没法任意组合两种颜色,例如你点亮了红灯,绿灯就自动关掉了。
另外,设置TYPE_COLORFULL也不能同时点亮三种灯,反而是全部灭的。那么如果我们想同时读三种颜色,可以用下面两种方法:

//方法1:readValues函数,注意arr长度为4
int[] arr = new int[4];
color.setType(ColorLightSensor.TYPE_COLORFULL);
color.readValues(arr);
LCD.clear();
LCD.drawString("r=" + arr[0], 0, 0);
LCD.drawString("g=" + arr[1], 0, 1);
LCD.drawString("b=" + arr[2], 0, 2);
LCD.drawString("n=" + arr[3], 0, 3);

//方法2:getColor函数,注意arr长度为3
arr = color.getColor();
LCD.clear();
LCD.drawString("r=" + arr[0], 0, 0);
LCD.drawString("g=" + arr[1], 0, 1);
LCD.drawString("b=" + arr[2], 0, 2);

请注意,调用readValues方法之前必须使用setType函数,否则灯不会亮。返回的数组长度是4,据我估计是在这一瞬间,传感器依次把红绿蓝三种灯依次闪了一遍,并依次记下当前的光强,最后一个参数表示COLOR.NULL,也就是不亮灯情况下的环境光强。
getColor函数的返回结果只有三个,有兴趣的同学可以参考lejos的源代码,这两个函数其实基本上是一样的,貌似只是取了数组的前三个,然后输出结果:

public int[] getColor() {
	int temp_type =  this.type;
	setType(ColorLightSensor.TYPE_COLORFULL);
	int [] all_vals = new int[4];
	readValues(all_vals);
	int [] rgb_vals = new int[3];
	System.arraycopy(all_vals, 0, rgb_vals, 0, 3);
	this.setType(temp_type);
	return rgb_vals;
}

这里用了一个临时的temp_type变量来记录传感器原来的设置,读完颜色后需要再还原,另外还额外需要一个数组复制的过程。理论上来说,这些操作的时间开销都是非常小的。但是不知道为什么,getColor函数的调用时间比readValues多很多,从我循环调用的测试来看,时间相差接近10倍,真是太邪门了。

总结一下,NXT2.0的颜色传感器貌似比原来那个更酷一点,取色的区域略小,但是功能更多一点。因为API的问题,开发起来会稍微麻烦点,不过毕竟不用再看环境光的脸色了,不错!

行百里者半九十

一月份的时候,网友bigapple建议大家一起翻译Lejos NXT的中文入门教程。当时很多同学报名领了任务,两周内就翻译了一大半。之后因为工作忙,我领的四篇只翻译了三篇半,最后半截始终没有完成(大苹果也是剩一篇^_^ )。

看来古人说的“行百里者半九十”真是非常贴切,事情越接近成功,越要集中精力认真对待。眼前就有另外一个例子:我的萝卜头攻略按照计划再两三篇就该收尾了,但是一直懒得把它们写完。好像很多人都是这样,坚持了很久,终于坚持不住放弃了,其实离成功只有一步之遥而已。

今天晚上老婆突然告诉我,翻译要坚持翻完,她这几天悄悄的帮我翻译了三篇。现在只剩下最后的2.5篇了。真是非常感谢老婆!我一定会坚持把这个Lejos教程和萝卜头的攻略都写完!

翻译好的教程看这里,其中标记了ok的就是翻好的:
http://www.diy-robots.com/resources/LejosNxtTutorial_cn/index.aspx

解魔方的机器人攻略19 – 让魔方动起来

一星期没更新,原因就不多说了,总之请见谅。从今天开始继续发攻略 :)

我原来的代码又多又乱还没有注释,自己看着都眼晕,找点代码晕的跟坐过山车似的。现在正在把它们重新整理优化,再加上注释。我打算整理一部分就发一部分攻略,攻略发完了也就整理完了。另外,这几天有很多网友正帮忙翻译lejos的中文教程,我在整理的过程中也学到了不少东西,有兴趣的同学还可以加入。

下面开始正题。假设现场的观众们按照前面的攻略,已经把萝卜头搭建好了。第一段程序先让魔方能动起来,实现的功能是:

  • 按Left键,魔方底座旋转90度
  • 按Right键,爪子抓住魔方,然后底座带动最下面的层旋转90度
  • 按Enter键,爪子把魔方翻转90度
  • 按Escape键,程序退出

下面介绍需要用到的一些知识点

1,创建传感器和电机的实例:

//Define Sensors
 static UltrasonicSensor distance=new UltrasonicSensor(SensorPort.S1);
 static LightSensor light = new LightSensor(SensorPort.S2);
 static ColorSensor color = new ColorSensor(SensorPort.S3);
 //Define Motors
 static Motor paw=Motor.A;
static Motor monitor=Motor.B;
 static Motor bottom=Motor.C;

这部分对应的是我们的接线方式:
传感器1口接超声波传感器,也就是眼睛
传感器2口接亮度传感器
传感器3口接颜色传感器
电机A口接爪子的电机
电机B口接颜色传感器的电机
电机C口接魔方底座的电机

2,创建一个Robot类,这个类用于控制机器人结构上的各种动作,下面三个方法分别对应上面说的三个功能:

public static class Robot
{
 public static void RotateBottomSide(int nQuarter)
 {   }

 public static void RotateBottom(int nQuarter)
 {   }

 public static void RotatePaw()throws Exception
 {   }
}

这里使用了关键字static,因为萝卜头只有一个实例,所以把它设置成静态类。静态类可以直接使用静态方法,不需要创建实例,还是看一段代码对比下:

//创建实例的用法
Robot instance = new Robot();
instance.rotate();
//静态类的用法
Robot.rotate();

3,设置了一些参数

//如果爪子部分改装了那个3:1的减速齿轮,设置成true,不明白的请看 http://www.diy-robots.com/?p=147 最后两张图
 static boolean HasReducer = true;
 //爪子抓住魔方时的电机角度
 static int PawHoldPosition = 56;
 //爪子翻动魔方时的电机角度
 static int PawTurnOverPosition = 110;
 //底座旋转90时,电机的旋转角度(因为齿轮组的原因)
 static int BaseOneQuarter = 315;
 //当底座旋转魔方底面时,因为魔方的阻力,需要先多转一个小角度,然后再转回来,这是用来修正误差的角度
 static int BaseRotateFix = 40;

4,控制电机(motor)的几个函数

paw.setSpeed(400); //设置转速
paw.rotateTo(nPawHoldPosition); //旋转到一个指定角度(绝对定位)
bottom.rotate(-nFixAngle);    //旋转一定角度(相对定位)

更多的电机相关函数,请点这里看刚刚翻译好的教程。

5,亮度传感器的一个函数,用于把它的灯打开或者关闭。这里是关闭它,省的晃眼睛,需要的时候再开 :)

light.setFloodlight(false);

好了,最终解魔方的动作,都是通过调用这几个函数来完成的。事实上如果你足够无聊的话,现在就可以通过NXT上的几个按键来控制萝卜头玩魔方了。
该吃早饭了,大家自己看看源代码吧。
http://www.diy-robots.com/RubikSolver/SourceCode/NXT/RubikSolverV2.java_20100115.txt

Lejos NXT 入门教程

感谢网友bigapple的建议,目前正在征集志愿者翻译Lejos NXT的入门教程,参与翻译的朋友:bigapple , 弹力女超人, zxzxy1988,lifanxi, YODA

翻译后的页面在这里

另外还有一个需要感谢的朋友是程序猎人,他已经翻译了很多篇,可惜博客暂时无法访问了。

有兴趣的朋友也可以点这里报名一起参加翻译,谢谢

解魔方的机器人攻略16 – 如何调试

今天已经是2010年了,祝大家新年快乐,新的一年学习好,工作好,身体好,感情好。。。总之一切都好!新年的第一天继续发攻略,希望是一个好的开始 :)

兵法说“代码未动,调试先行”。对于刚接触嵌入式开发的同学来说,把代码写进NXT简直就是杯具,没有断点,不能跟踪,程序挂掉了都不知道是哪里的问题。难怪有些公司招聘程序员的时候,提的要求是“能摸黑写代码”。。。

下面是一个简单的例子,它实现的功能是:每按一次Enter按钮,就显示当前的距离读数,按Escape按钮时退出程序。通过这个例子,你可以知道如何用NXT的面板按钮或传感器来做断点工具,用LCD显示屏来跟踪数据。因为不舍得把萝卜头全拆了,所以用好拆的部分来做例子,先凑合看看:)

import lejos.nxt.*;
import lejos.nxt.comm.*;

/**
 * First Sample: Read distance by the control of buttons
 * @author ChenWu
 * @see LCD
 * @see UltrasonicSensor
 * @see Button
 */
public class DebugSample
{
 static UltrasonicSensor distance=new UltrasonicSensor(SensorPort.S1);

 public static void main (String[] aArg) throws Exception
 {
  while(!Button.ESCAPE.isPressed())
  {
   LCD.drawString("Distance=" + distance.getDistance()+"  ",0,3);

   //Remove this while condition if you want to get dynamic value
   while(!Button.ESCAPE.isPressed() && !Button.ENTER.isPressed())
   {
    Thread.sleep(100);
   }
  }
 }
}

把文件保存为 DebugSample.java,在命令提示符中运行下面的命令,把程序写入NXT:
nxjc DebugSample.java
nxj -r DebugSample

把程序写入NXT,这个步骤也可以在Eclipse中完成

把程序写入NXT,这个步骤也可以在Eclipse中完成

这段程序很短,有经验的老鸟们应该一目了然了。新同学请看下面的说明,没Java基础的请自己先补习一下吧 :)

1.  头两行import是导入Lejos的函数库,导入之后才能调用lejos的各种API。

2.  NXT的显示屏幕是一个分辨率为100×64的LCD屏幕,LCD屏幕一共可以显示8行16列ASCII字符,可以用内置的LCD对象来控制显示内容。例如显示一串字符的命令是:
LCD.drawString(“string”,x,y);
这个命令表示显示string的开始位置坐标是(x,y),下标从0开始。例如(0,3)表示从第4行的第1列开始显示。

显示的时候如果原来的位置有文字,会被覆盖掉,但是不会清除其他地方的文字。(我的程序里面distance后面加了两个空格,理由请自己思考一下)另外几个常用的方法是 drawInt 和 clear,更多的方法可以参考相应的API文档

如果你想显示非标准的字体,甚至是一副图片,可以使用Image类,通过二进制数组进行像素级别的控制

3.  UltrasonicSensor 也是Lejos的内置对象,封装了超声波测距传感器的各种方法和属性。用distance.getDistance()函数就可以返回一个整数,这个数表示眼睛到物体之间的厘米,理论上范围是1到255。如果我们把眼睛捂上,或者距离超过255cm,它的读数都是255。

4.  SensorPort.S1表示该传感器是接在1号接口上(看NXT主机下面1~4的编号)

5.  Button用来响应面板上各按键的交互事件,button的对应关系看下面这个图

Button的对应关系

Button的对应关系

Button.ESCAPE.isPressed() 用来判断按键是否被按下了。另外一个常用的方式是 Button.ESCAPE.waitForPress(); 程序运行到这句函数时会被挂起,直到按钮按下时才会继续执行后面的语句。

6. 如果你觉得每次都按一下Enter键很烦,可以把中间的那个while条件注释掉(当然对应的一对大括号也要去掉)。这样一来屏幕就会动态显示当前的实时距离,按下Escape键时退出。

7. Thread.sleep(100)表示程序运行到这里时,会暂停100毫秒然后继续执行后面的代码。它的作用是让你有读数的时间,否则屏幕上的读数会飞快的变换,根本看不清。

看看效果如何:

按下Enter时,刷新距离读数,按下Escape时,程序退出

按下Enter时,刷新距离读数,按下Escape时,程序退出

cnBeta有位网友认为这个距离传感器是冗余设计,正好我在这里介绍一下这个“眼睛”的作用:

1. 用来判断转台上有没有魔方,放了魔方的时候测量的距离是14~15,没有魔方的时候是18~20。通过这个值先变大,然后再变小,就可以知道是有人先把魔方拿走,然后再放回来,于是激活下一轮扫描颜色

2. 用来做断点调试使用。在搭建萝卜头的初期,它的胳膊经常骨折,颜色也经常读错。为了便于调试,我把眼睛设置成了一个中断开关。当我需要它暂停的时候,就用手捂住它的眼睛,它就会停下来,把手移开,它又可以继续工作。使用的代码如下:

public static void WaitForNextAction()throws Exception
{
 while(distance.getDistance()>150)
 {
  Thread.sleep(100);
 }
 return;
}

通过这个例子,你可以了解如何在制作乐高机器人的过程中进行单步调试。如果你有其他的好方法,请一定在这里留言,让大家一起分享,多谢多谢! :)

今天就先介绍这些,感谢新年第一天还来光临小站的热心朋友,祝大家新年好!

解魔方的机器人攻略14 – 安装Lejos(下)

第四步:安装Lejos

登陆 Lejos 主页点击 NXT 图片进入 Lejos 下载页面,点击 NXJ 的下载链接;

下载完成后将下载的压缩包解压到指定文件夹。这里注意你所指定的文件夹路径中不要包含空格;比如 C:\Program Files\legos 这个路径就不正确,因为文件夹“Program Files”中包含了一个空格。在使用 Java 开发的过程中空格总会引起这样或那样的问题,所以为了避免不必要的麻烦保存路径中一定不要包含任何空格。

接下来添加运行 Lejos 所需要的系统环境变量,变量添加的方法与添加 JDK 环境变量的方法相同,请参照第一步中的方法打开环境变量窗口进行设置。

添加环境变量: NXJ_HOME,变量值是 Lejos 的安装目录,即解压后 lejos_nxj 的全路径,完成后点击确定;

向环境变量 Path 的变量值后追加 ;%NXJ_HOME%\bin;

重新打开一个命令提示符窗口(原有的命令提示符窗口在设置环境变量以后必须重新打开才能生效)。输入nxj然后回车,用来验证Lejos是否已经安装成功。

验证Lejos安装是否成功

验证Lejos安装是否成功

第五步:安装Libusb

Lejos 需要使用 Libusb 与 NXT 进行通讯。它的安装文件在 Lejos 的安装目录下 lejos_nxj\3rdparty\lib。

运行 Libusb 的安装程序 libusb-win32-filter-bin-0.1.12.1.exe ,点击 Install 开始安装。

这个程序安装以后会自动执行测试程序。

注意!!这个驱动程序在Vista或者Windows7下很可能导致电脑的USB端口全部失效,这种情况下只能卸载。

且慢,现在的鼠标和键盘可能都是USB的,怎么卸载呢?我上次遇到这个问题的时候,被折磨了一个上午,不断的萌生着重装系统或者是砸烂电脑的念头,最后解决方法很简单,借一个古老的PS2鼠标卸载搞定。

正确的装法是在xp兼容模式下安装:在exe文件上鼠标右键单击,选择属性,然后参考下图。我的电脑是英文版的系统,大家凑合对照一下:

在XP兼容模式下安装USB连接驱动

在XP兼容模式下安装USB连接驱动

第六步:刷新NXT的Firmware注意:当你安装 Lejos 后 NXT 原来的标准系统将被覆盖,NXT 中所有的数据也将全部删除,所以开始安装前一定要备份好有用的数据。再注意:据也许可靠的小道消息说,NXT刷新Firmware的次数是有限的。有一个叫做LOCK BIT的数据位,每刷新一次Firmware这个值就会减一。最多刷新100次以后,这个位就会降到0,所以请不要没事刷着玩 ^_^如果想重新安装 NXT 默认的操作系统你可以使用 LEGO Mindstorms software 重新安装 LEGO 的标准系统(具体步骤请参照 Lego 玩具说明书)。 首先把NXT切换到固件上载模式(firmware upload mode),只有在这个模式下才能升级Firmware。切换方式是在开机状态下,用牙签或者曲别针持续按下 NXT 主机背面的重启按钮4秒钟以上。进入NXT的固件上载模式。

进入固件上载模式后,NXT的屏幕上什么也不显示,但是会连续发出微弱的滴答声;

这时候用 USB 线连接 NXT 和计算机,当计算机识别 NXT 的固件上载模式后(看USB图标提示),在“命令提示符”中输入 nxjflash 并回车;

跟刷手机完全不一样,NXT的升级固件非常神速,大概只需要几秒钟;

上载完成后 Lejos NXJ 会自动启动,出现欢迎界面与开始菜单;

在 Lejos 运行的过程中,包括正在运行程序时,同时按下桔色和灰色的按钮(Enter+Space)就可以立即将 NXT 关闭。如果要重新启动只要按下桔黄色的按钮。如果 NXT 突然死机的话,将电池全部取出后重新安上启动即可。

到此我们就完成了Lejos的安装!下面试着运行我们的第一个程序测试一下。

按下桔黄色按钮启动NXT电源,打开命令提示符窗口,切换目录到Lejos自带的样例目录并输入以下代码(请自行修改安装目录):

CD D:\lejos_nxj\samples\Tune (设置程序路径)

d: (切换到指定盘符)

nxjc Tune.java(在电脑上编译程序)

nxj –r Tune(把编译好的程序写入NXT)

几秒钟后NXT会发出一声悦耳的声音,表示程序已经上载成功,你可以在NXT上选择执行这个程序。

如果操作成功的话,你会听到一组声音,并看到“Hello World”的字样。

经历了这么多繁琐的步骤,你的第一个程序终于顺利在 NXT 上运行成功啦

解魔方的机器人攻略13 – 安装Lejos(上)

Firmware(固件)相当于是机器人的操作系统,乐高NXT出厂时已经内置了一套Firmware,并且配备了非常强大的LabVIEW开发平台。基于这种LabVIEW平台,即使是完全不懂编程的小盆友们,也可以成功的做出一些复杂的功能。

LabView软件

LabView软件

 对于萝卜头来说,因为解魔方需要用到一些算法和复杂的功能,很难仅用LabView实现。后来据西觅亚的朋友说,LabView也有开发接口,有兴趣的童鞋可以自己研究一下,我买回来直接就升级Firmware了,懒得再刷回去了。 :)

目前乐高的开发平台很多,本文提到的Lejos 是一个基于 Java 的小型操作系统,习惯windows开发的朋友也可以使用一款微软开发的Microsoft Robotics Studio。安装Lejos以后,我们就可以用常见的Java开发工具来编写机器人的控制程序了。以下是安装Lejos0.6 的步骤(现在已经有0.7的版本,安装方式差不多)

第一步:安装 Java 开发工具包 JDK(Java Development Kit)
首先登陆到 Sun 公司的官方网站下载 Java 开发工具包,这里要求你下载并安装 JDK1.5 或更高的版本,因为Lejos NXJ  0.6 需要在 JDK1.5 或更高版本上方可运行。而且在后续的攻略中,还会介绍如何借助 Eclipse3 平台开发 NXT 的 java 程序,运行 Eclipse 也需要 JDK1.5 或更高的版本的支持。
进入 JDK 下载页面,点击 Download;
选择 Windows 操作系统和默认的多国语言(Multi-Language),然后点击 Continue(下一步);
点击 jdk1.5 下载链接,将安装文件保存至本地;
下载完成后,运行刚刚下载的安装程序,开始安装 JDK;
安装过程中会提示安装 JDK 和 JRE ,我们默认安装全部功能,点击 下一步 继续运行安装程序;
安装成功后会提示安装完成,点击 完成 按钮结束 JDK 的安装。

第二步:设置环境变量
环境变量可以理解为缩写和快捷方式。例如我们把JDK安装在C:\Program Files\Java\jdk1.6.0_07,运行java代码的时候,每次都要输入这一长串路径。为了避免这种麻烦,我们可以定义一个环境变量 %Java_Home%等于这个路径,这样写命令时,只要写这个缩写就可以了。
首先在“我的电脑”上点击右键,选择属性;
在“系统属性”窗口中选择高级选项卡,点击下面的“环境变量”按钮,弹出环境变量窗口;
在环境变量窗口中点击“新建”按钮添加环境变量;
设置变量名为: JAVA_HOME,变量值为 JDK 的安装目录(默认安装是C:\Program Files\Java\jdk1.5.0_15);
填写完成后点击 确定 按钮,关闭对话框;
再选中环境变量 Path,然后点击“编辑”按钮,弹出“编辑系统变量”对话框;
在变量值后追加 JDK 的bin子目录 ;%JAVA_HOME%\bin (多个环境变量值要用 ; 号隔开)
编辑完成后点击确定,关闭对话框。
 
我们来验证一下刚刚设置的环境变量是否生效。
打开: 开始=>程序=>附件=>命令提示符 (或者用快捷键Windows+R,输入cmd然后回车)
在命令提示符里输入Javac并回车,如果能看到下图所示的信息,就表示JDK和环境变量都设置成功了。

验证JDK是否安装成功

验证JDK是否安装成功

第三步:安装乐高USB驱动程序
如果你的计算机上已经安装了 LEGO 随机附带的 LEGO MINDSTORMS NXT 软件,那么你可以直接进入下一步。因为 LEGO MINDSTORMS NXT 软件的安装过程中已经包含了下面所要安装的 USB 驱动程序。
登陆乐高官方网站下载最新的驱动程序;
下载完成后将压缩包解压,执行里面的 setup.exe 安装 USB 驱动程序;
驱动安装完成后会提示你重新启动计算机,点击 Restart 重新启动计算机;
 
下面验证驱动安装是否正确,计算机重新启动后用 USB 线将 NXT 与电脑连接,确认连接后启动 NXT。右键单击“我的电脑”选择“属性”。选择“硬件”选项卡,点击“设备管理器”,如果在硬件列表中查看到 Lego Devices => Lego Mindstorms NXT ,这说明 LEGO USB 驱动已经成功的安装在你的计算机上。