2010年01月 文档列表

纸糊的瓦力

昨天定制的几根轴还没有送到,周末只好先干点别的。因为小爱的进度太慢,先做个纸糊的,几个小时就能搞定,以此补充一点小小的成就感 :)

从网上找了两张瓦力的纸模:

Wall.E A

Wall.E A

大图

Wall.E B

Wall.E B

大图

这个是拼接说明:

拼接说明

拼接说明

因为没有彩色打印机,只好凑合打印了黑白的。成果如下:
黑白版瓦力

黑白版瓦力

疯狂大采购

最近一直没上来发攻略,主要的时间都在淘宝上逛街了。现在的小爱已经有一个大概的框架图,具体的搭建还需要不断的买材料,调整,再买材料,再调整。

发一些最近买的东西,留个纪念:

无敌风火轮,这是滑板车的轮子,准备做小爱的驱动轮

无敌风火轮,这是滑板车的轮子,准备做小爱的驱动轮

这是万向轮,一般用来做柜子,这个准备做小爱的辅助转向轮

这是万向轮,一般用来做柜子,这个准备做小爱的辅助转向轮

这个是锥齿轮,可以用于轴的转向,其实这是麻将桌的配件,每个5毛钱

这个是锥齿轮,可以用于轴的转向,其实这是麻将桌的配件,每个5毛钱

五金店买的一些金属材料,还没想好怎么用

五金店买的一些金属材料,还没想好怎么用

另外一些舵机专用的支架,和上一个图有些重复

另外一些舵机专用的支架,和上一个图有些重复

各种电机和舵机,一共十多个,刚拆包了几个做了测试

各种电机和舵机,一共十多个,刚拆包了几个做了测试

各种轴承

各种轴承

无数默默无闻的螺丝钉

无数默默无闻的螺丝钉

另外还有一些开发板和传感器还没拍照,等下回做实验的时候发。希望明天几根定制的轴能送到,周末就可以组装点东西了。

解魔方的机器人攻略21 – 读取魔方颜色

之前已经介绍了萝卜头转魔方的各个分解动作,今天介绍如何用颜色传感器读取魔方的颜色。这一部分可以分成三部曲:
1,依次扫描魔方的6*9=54个色块
2,用蓝牙连接把数据发送到电脑
3,通过颜色分组函数,从读数分辨出不同的颜色

这里先说明一下:虽然乐高的颜色传感器以RGB的形式返回颜色值,但是并不是想象中的那样,红色返回(255,0,0),蓝色(0,0,255)这么轻松。事实上这个数值受环境光线强度影响非常大,即使相同的环境下,读数仍然会有跳动。例如下面几个读数:

[0,1,2]=>RGB=(23,0,0),RawRGB={45,1,8}  //红色
[0,2,2]=>RGB=(30,0,0),RawRGB={60,1,5}  //红色
[2,1,2]=>RGB=(28,0,0),RawRGB={55,12,8}  //橙色
[2,2,1]=>RGB=(29,0,0),RawRGB={57,14,14}  //橙色

如果你仅想从RGB来分辨颜色的话,将会“很受伤”。不过今天我只介绍第一步(扫描),在PC端程序部分再介绍如何识别颜色。

因为颜色传感器一次只能读一个点,所以要扫描魔方的话,必须把54个点都扫到。我们以扫描其中一个面为例,看看两个电机怎么配合扫描到所有的9个点。首先,颜色传感器的电机中心位置,应该在2,4两个点的中心延长线上。这样在魔方位置不动的情况下,就可以扫描到中心和四个角了。(相关文章:颜色传感器的安装

扫描魔方中心和魔方的角

扫描魔方中心和魔方的角

然后,让底座旋转一定的角度,同时传感器电机也稍微调整,这样就可以扫到4个棱的颜色。

扫描魔方的棱

扫描魔方的棱

以这种方式扫描一圈,就可以把魔方的一个面读完了。最后使用魔方操作的分解动作,把魔方翻过来倒过去,直到把六个面依次扫描出来。有一件非常麻烦的事情是,在魔方翻来翻去的过程中,数组并不是每次都以0为左上角,它是不停的变换的(相关文章:魔方坐标系)。我用了下面这个map表,用来标记读数的顺序,这可是牺牲了数百个脑细胞换来的,其中idx数组是每个面内的依次读取顺序,idex2数组是不同的面的读取顺序:

int[][] idx={
	{4,6,7,8,5,2,1,0,3},
	{4,0,3,6,7,8,5,2,1},
	{4,2,1,0,3,6,7,8,5},
	{4,8,5,2,1,0,3,6,7},
	{4,2,1,0,3,6,7,8,5},
	{4,2,1,0,3,6,7,8,5}};
int[] idx2={5,1,4,3,2,0};

我们以上一次的程序为基础,添加以下变量和函数:

	//add offset positions for color sensor motor
	static int ColorMotorOffset1 = 33;
	static int ColorMotorOffset2 = 9;
	static int ColorMotorOffset3 = 18;
	static int ColorReadPostion1 = 162;
	static int ColorReadPostion2 = 154;

	//Read each side colors of the cube
	public static void ReadAllSide()
	{ }

	//Read one side by the index
	public static void ReadOneSide(int nSideIndex)
	{ }

最后加一个测试入口,当按下Enter键时,开始扫描魔方。相信看过前面文章的朋友,这里不需要说明了。点此查看具体的代码吧。

补充个小小的说明:我在代码里面统一用英文加了注释,不是在装酷,主要是因为上班的时候是这样强制要求的,以至于自己做东西也养成这种习惯了。

机械结构 – 一次不成功的尝试

据说DIY机器人最麻烦的步骤就是加工零件,主要是因为加工设备太少,巧妇难为无米之炊嘛。我买了一本叫《机器人制作入门篇》的书,作者的家里居然有小型车床和铣床。可是北京的房价这么贵,人都不够住,哪有地方放这么多东西。

前几天我突发奇想,打算试试用废旧的玩具和家具来加工“零件”,因为木头比金属还是容易处理一点,用牙都能啃个豁口出来。所以有了下面的一个小尝试,这次尝试的目标是做一个小车底座。

当然,大家看了标题,已经知道这是一个不成功的案例了。其实我本来想把标题写成“一次失败的….”。后来想起一句老话:没有所谓失败,因为至少排除了一种不可行的方案。正好快过年了,把不开心的事情说出来,让大家开心一下。

首先,盘点一下手头的家伙,看上去还真不少:

家里的工具们

家里的工具们

接下来的工作是忽悠老婆,就说家里的鞋架子已经臭了,该换一个了,然后把它拆成了无数的木条。下面是用小刀抠出来的轴承座:

用小刀抠的轴承座

用小刀抠的轴承座

剪一块罐头铁皮,用钉子在两头打眼,把轴承固定在木头上:

做好的轴承

做好的轴承

一式两份:

两个轴承座

两个轴承座

下面这个是用膨胀螺栓掰成的“联轴器”,外加铁棍和玩具车的轮子:

轮子和轴

轮子和轴

可以变方向的另外两个轮子,木头上的那两个窟窿,废了半天劲用磨轮打出来的:

另外两个轮子

另外两个轮子

用来调节宽度的两个小木块,调节方法是:如果宽了一点,就用小刀把它削平。

宽度调节“装置”

宽度调节“装置”

最后的组装:

小车底座的最终结果

小车底座的最终结果

做到这里就结束了,本来应该还有几个步骤。应该把长出来的轴锯掉,然后接上电机,后面的两个轮也要加上一个控制方向的电机,就变成了一个小车底座。

没有做下去的原因包括:
1,木头+山寨工具=误差,精度实在很差,强度也不够
2,污染很大,满屋子一股奇怪的木头味,另外还有噪声污染
3,粗大的件可以做,复杂的小件做不了

考虑到家里还有孕妇,实在是不能再这么玩了。难怪老外们一说起创业,就是在车库里面,那是一个可以随意折腾的地方。接下来还是打算画点AutoCAD的图,送去工厂加工,不知道要花多少银子啊 :)

最后附上工作照一张,颇有恐怖分子的气质:

工作照

工作照

Arduino开发板实验二:模拟输入和输出(用电位器和开关控制直流电机)

在上一个Arduino小实验里,我们尝试了用开发板来读写数字信号(0和1),貌似非常简单,难度系数跟吃苹果差不多。昨天淘宝的直流电机控制板终于送到了,接下来这个实验准备测试读写模拟信号。这个实验难度系数稍大一点,达到了吃香蕉的程度,搞不定的同学请去动物园请教猴子兄弟(开个玩笑,但是Arduino的确非常好开发)

我计划的实验目标是:
1,使用电位器控制直流电机的转速
2,使用开关控制直流电机的旋转方向

模拟输入

查了下资料,许多单片机的管脚电压都是+5V或0V,分别对应1和0。而机器人面对的自然界却没有这么泾渭分明,例如大气温度,到墙壁的距离,声音的强度等等,这些值就是模拟值。Arduino开发板上,标记了“Analog In”的16个管脚,就是用来测量模拟值输入的。这些输入电压的范围是0~+5V,开发板会把它映射到0~1023的整数。从这个数值范围,我们可以估算出Arduino能识别的电压精度大概是5mV,小于这个范围的变换无法识别。

电位器

这个东西是从邻居小朋友那里骗来的。在我读高中的时候,好像把这个东西叫滑动变阻器,个头很大。现在都是小小的旋转电位器了,原理图应该是一样的:

电位器

电位器

接线方式是两端分别接GND和+5V,中间随意接在一个Analog In的管脚上。我选择了一个大吉大利的6号。

电位器接线

电位器接线

读取模拟电压值的函数为:

int readValue = analogRead(readPin);

用端口监视器做个分解实验,使用Serial.println命令把readValue显示在电脑上,和想象中的结果完全一样。端口读写部分准备做为下一个实验主题,这里就不细说了:

端口监视

端口监视

PWM输出

作为一个外行,我之前曾经想过怎么让单片机输出一个模拟值。觉得必须用10个管脚,对应的二进制从0~1023,然后找一个数模转换的东西变成模拟电压值。结果一看资料发现自己太圭了,原来有一种叫做占空比的东西,只用一个管脚就可以输出0~255的数值。从这里也了解到嵌入式常用的一个叫“时序”的东西,以后应该会经常遇到,这种方式可以用很少的管脚实现非常复杂的功能(估计业内人士又要鄙夷的飘过了)。看下面的图解,从Arduino官网顺来的:

PWM模拟输出

PWM模拟输出

板子上标注了“PWM”的区域就是管脚均可以用于这种输出。使用的函数是:

analogWrite(pin, value);

注意value值的范围是0~255。

直流电机控制板

这个控制板的功能是把PWM的输出,转换成真正的模拟电压值,从而控制直流电机旋转。电机的种类很多,还有舵机,步进电机等等,控制方式都不一样,那些以后再试。先看一下这个板子的介绍,也是一个顺手牵来的图:

直流电机控制板

直流电机控制板

这个图里信息太多了,咱们捞干的讲几个:
1,左右两边是对称的,可以控制两个直流电机,咱们下面只看左边
2,绿色的“直流电机A接口”,用于接电机的两根电源线
3,直流电机A信号输入接口,一共有3个脚,分别是I1,I2和EA。其中I1和I2是数字接口,用于控制开关和方向,EA是模拟接口,用于控制转速
例如:I1=1,I2=0顺时针转,I1=0,I2=1就逆时针转,I1=I2的时候,停止转动。EA是0~255的PWM值,对应从小到大的转速
4,最下面的VMS接电源正极,GND接地,边上还有一个+5V,不用管它,本来是由它给逻辑电路供电的,但是默认情况下,是通过DUAL那个跳线帽由VMS搭车送电。

看看最终的接线图,专业人士一般用面包板之类的东西实验,我就直接把铜丝拧上了,请大家不要效仿:

接线图

接线图

接下来是写代码,一共也没几行,大家看注释吧:
注意:我发现Analog输入区编号是0~15,PWM输出区也有0~13,为了验证这两类管脚编号会不会冲突,我特地把readPin和speedPin都设置成了大吉大利的6号。事实证明两者不冲突。

int readPin = 6;    //用来连接电位器
int buttonPin = 38; //用来连接开关,这次用了个吉利的端口号
int i1Pin = 31;     //连接电机驱动板的I1接口
int i2Pin = 30;     //连接电机驱动板的I2接口
int speedPin = 6;   //连接电机驱动板的EA接口

void setup()
{
  pinMode(buttonPin, INPUT);  //开关用于输入
  pinMode(i1Pin, OUTPUT);     //I1和I2都是数字信号
  pinMode(i2Pin, OUTPUT);     //通过设置I1和I2来控制电机旋转方向
  pinMode(speedPin, OUTPUT);  //按占空比方式输出的模拟信号
  digitalWrite(buttonPin, HIGH);  //设置上拉电阻
}

void loop()
{
  //读取按钮状态
  boolean buttonPressed = digitalRead(buttonPin);
  //设置转动方向,I1和I2值相反时,分别对应两种不同的转向;I1和I2值相同时停止转动
  digitalWrite(i1Pin, buttonPressed);
  digitalWrite(i2Pin, !buttonPressed);
  //读取电位器(传感器)的读数,值范围从0到1023
  int readValue = analogRead(readPin);
  //PMW的值范围是0~255
  readValue/=4;
  //设置转速
  analogWrite(speedPin, readValue);
  delay(500);
}

上传程序以后,旋转电位计,可以看到电机的转速不断变化着;掰一下开关,电机就会反转,实验到此顺利结束。

解魔方的机器人攻略20 – 修正电机误差

在上一篇攻略中,我们使用了一些角度的配置信息,例如:

//the motor angle for paw to hold the cube
static int PawHoldPosition = 56;
//the motor angle for paw to rotate the cube
static int PawTurnOverPosition = 110;

这些用于Motor.rotate(n)的角度,都是相对于电机的原始位置而言的。在我的代码里,初始位置是这样定义的:

颜色传感器和魔方底座的初始位置

颜色传感器和魔方底座的初始位置

爪子的初始位置

爪子的初始位置

在最初的版本里,我是在断电状态下,手动把电机拧到指定的初始位置。(程序一旦开始运行,角度信息就已经开始记录了,而且拧电机会有很大的阻力)
随后问题就来了,如果初始位置不准确的话,那么必然会导致旋转之后的位置不准确。其中最省心的是爪子的初始化位置,因为它是贴在后支架上,这个参照物非常稳定。

颜色传感器的杆很长,目测很难判断是否已经平行。魔方底座更是转十几次以后,误差越来越大。所以我们需要一段程序,把稍有偏差的初始位置纠正回来。

首先看一下如何修正魔方底座的误差。我们曾经介绍过,在魔方底座的下方安装了一个亮度传感器,当底座在某些位置的时候,会挡在亮度传感器的上面,再转过一定角度,就又把它露出来。亮度传感器有一个红色的小灯,可以通过light.setFloodlight(bool);来点亮或者关闭它。通过对比点亮和关闭前后的读数差,就可以判断出底座什么时候被挡住(在底座的下方需要贴一圈白纸,增强反光)。读数的曲线图是这样的:

读数的示意图

读数的示意图

也就是说,随着传感器被慢慢的挡住,这个亮度差值会越来越大,理论上最大值就是被挡住的中心位置。考虑到传感器的读数是有误差的,所以不能只取一个最大值点来计算,需要设置一个阀值,把最大的N个点都找到,那么它的中心位置就比较准确了。

//Fix the position of cube base
public static void FixBasePosition() throws Exception
{
int step = 3;
int tolerance = 4;
light.setFloodlight(false);
bottom.rotate(-50);
int angle = 0, minLight = 10000;
int realtimeLight = ReadLightDifference();
while(realtimeLight < minLight + tolerance)
{
bottom.rotate(step);
realtimeLight = ReadLightDifference();
if(realtimeLight < minLight)
{
minLight = realtimeLight;
angle = 0;
}
else
{
angle += step;
}
}
bottom.rotate(- angle/2 - FixBasePositionOffset);
}

//Read the light difference between light on and light off
private static int ReadLightDifference() throws Exception
{
int l1 = 0, l2 = 0;
l1 = light.readValue();
light.setFloodlight(true);
Thread.sleep(20);
l2 = light.readValue();
light.setFloodlight(false);
return l1-l2;
}

可以测试一下,把魔方底座手动拧歪一个小角度(正负十几度^_^),运行这段代码之后,底座会还原到和爪子平行的位置。

颜色传感器的位置修正比较简单:让它慢慢的靠近魔方,在传感器下方遇到魔方之前,它的读数都是0。所以一旦发现有读数,我们让它返回32度,就回到了爪子平行的位置,这个度数通过几次实验就可以试出来。

//Fix color sensor position
  public static void FixColorSensorPosition() throws Exception
  {
   int tolerance = 5;
   ColorMotorBaseAngle = -25;
   monitor.rotateTo(ColorMotorBaseAngle);
   Thread.sleep(100);
   monitor.setSpeed(50);
   int r = color.getRawRed();
   int g = color.getRawGreen();
   int b = color.getRawBlue();
   int baseColor = r + g + b;
   int TargetExists = 0;
   while(TargetExists < baseColor + tolerance && ColorMotorBaseAngle > -50)
   {
    monitor.rotateTo(ColorMotorBaseAngle--);
    r = color.getRawRed();
    g = color.getRawGreen();
    b = color.getRawBlue();
    TargetExists = r + g + b;
   }
   monitor.rotateTo(ColorMotorBaseAngle + 32);
  }

下面也做一个实验,把颜色传感器的位置拧歪,它也能回复到指定的位置。点此下载这个例子的全部代码。实验方法为:按Left键修正魔方底座位置,按Right键修正颜色传感器位置,按Escape键退出

时间仓促,每次贴的功能都不多,下一次介绍如何把魔方的颜色读取到数组中。

Arduino开发板实验一:补充

感谢 lifanxigalaxy 两位同学对昨天实验一的讨论。经过补充实验,事实证明galaxy的看法是对的。当PinMode是INPUT时,digitalWrite(pin, HIGH)实际上是用来设置上拉电阻,所以只需要在setup中设置一次即可。

代码如下:

int ledPin=13;
int buttonPin=44;

void setup()
{
 pinMode(ledPin, OUTPUT);
 pinMode(buttonPin, INPUT);
 digitalWrite(buttonPin, HIGH);
}

void loop()
{
 //这一行移到上面的setup中
 //digitalWrite(buttonPin, HIGH);
 digitalWrite(ledPin, digitalRead(buttonPin));
 delay(100);
}

因为我的外部电路连接的GND,所以没法测试下拉电阻。
做完实验我又看了一个教程,发现我的这个实验非常粗暴,“是烧毁单片机的最佳途径”。因为44脚置1后的电压是+5V,我直接用一个开关把它接地了。还好单片机已经有内置的上拉电阻,否则的话这个板子可能就废了(软件开发经常提到的一个术语是“冒烟测试”,看来就是用于检查这种低级错误)。下面这个图是专业人士推荐的接线方式:

接线方式

接线方式

这样接线的好处是,任意两个可能存在电压差的管脚之间,都至少存在一个电阻,就不容易烧板子了。我现在手头没有空的电阻,就不重复这个实验了。有兴趣的同学可以点此看原文教程。

Arduino开发板实验一:数字输入输出

最近有很多朋友关心小爱的进展,真是非常感谢。这段时间我主要在研究小爱的制作方案,大致的工作分为几个部分:机械设计,电子电路,嵌入式开发和人工智能几个部分。

为了确定最终的方案,我最近总在淘宝上晃悠,劲头跟美女购物狂们逛商场有一拼。前一段时间无意中看到了一个叫Arduino的东西,貌似还挺好用,暂定以这个板子为基础来开发电子电路和嵌入式的部分。我以前没有接触过嵌入式开发,如果路过的朋友有更好的方案,请一定要吱一声,谢谢 :)

昨天淘宝的Arduino板子终于到了,型号是Arduino MEGA ATmega1280-16AU AVR(完全不清楚不同型号之间有什么区别),秀一下样子:

Arduino 开发板

Arduino 开发板

今天进行了第一个小实验,跟大家分享一下。实验的目的是实现一个简单的功能,外接一个开关,通过打开或者关闭开关,来控制一个小灯的亮和灭
电子专业的老婆冷笑飘过,这个实验太简单了吧,用传统电路甚至更简单,一个开关直接切断电路即可(传说中的手电筒)。不过我通过这个小实验了解了一个重要信息:原来嵌入式开发可以直接对CPU的管脚直接进行读写,0就是低电压,1就是高电压。以前一直使用高级语言,读CPU的某个脚电压貌似非常遥远。

第一步:到Arduino官网下载Arduino开发IDE和相关驱动
下载完一看,这个软件是绿色的,并且绿的相当彻底,里面还包含了板子的驱动,双击打开就可以使用,我在Windows7,Server2008以及Vista下都用的挺好。

第二步:用USB线连接Arduino板子和电脑,发现驱动可以被自动识别,然后添加了一个USB UART的设备。查看一下这个设备的COM端口号,后面需要用到:

查看COM端口号

查看COM端口号

第三步:
双击运行arduino.exe,第一次使用前,需要设置设备端口号和板子的型号,看下面的抓图:

设置主板型号,我这个是Mega

设置主板型号,我这个是Mega

选择刚才看到的端口号

选择刚才看到的端口号

第四步:接线
为了做这个小实验,我还真拆了家里一个手电筒(真是败家)。文档里说开发板有个LED小灯接在13号管脚,据说术语叫做Pin13,所以就不需要外接小灯了。开关的两个脚一个接地(GND),另一个随便接某个管脚。考虑到13这个数字不吉利,我特地选了一个44号管脚避个邪。看下图:

接了个开关,红色灯是13号LED

接了个开关,红色灯是13号LED

第五步:写代码

int ledPin=13;
int buttonPin=44;

void setup()
{
  pinMode(ledPin, OUTPUT);
  pinMode(buttonPin, INPUT);
}

void loop()
{
  digitalWrite(buttonPin, HIGH);
  digitalWrite(ledPin, digitalRead(buttonPin));
  delay(100);
}

经常搞windows软件开发的朋友可能有点迷糊,这个程序入口在哪里,出口在哪里?事实上这个程序是被Arduino的IDE封装了,它的规则就是先定义几个变量,然后在setup里做几个设置,最后就孜孜不倦的反复跑loop里面的程序。我猜想应该有些中断机制来执行一些特殊处理,这个以后再慢慢学。看来单片机的程序通电以后就没打算让它歇着,高级语言的程序员需要适应一下。
接下来的程序就很好解释了:
pinMode 用于设置管脚的用途,输入还是输出
digitalWrite 用于把某个管脚的电压设置成High还是LOW
digitalRead 用于读取某个管脚的电压状态,返回的也是HIGH或LOW

有一句 digitalWrite(buttonPin, HIGH); 需要解释一下。我希望44号管脚当开关打开时是1,开关闭合是是0。但是请注意第一次闭合以后,这个管脚电压降到0,它不会自动升到1。为了让下次开关打开的时候管脚电压置1,我在每次循环前都给它设置初始值1。画了一个非常丑的电路图:

电路图

电路图

第六步,编译并上传代码

用IDE中的Verify来编译代码,然后用Upload上传。选的44号辟邪管脚果然有效,代码直接编译通过上传成功(真相是确实太简单了)。结果就不给大家贴图了,没啥好看的。不过好人做到底,虽然Arduino的IDE按钮都有提示,我还是画了个说明:

Arduino 0017的菜单

Arduino 0017的菜单

总结:这虽然是个很简单的实验,但是对于一个像我这样没有接触过嵌入式的程序员来说,还是有很多的知识点。我相信有很多和我一样的人,想做机器人但是觉得无从下手,希望这些学习经验有所帮助。高手们就请优雅的飘过吧 :)

解魔方的机器人攻略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

翻译后的页面在这里

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

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