Posts Tagged ‘调试’

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

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

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