找回密码
 马上注册

QQ登录

只需一步,快速开始

查看: 11708|回复: 6

NXC实现的NXT 8547 Color Sorter和Color Catapult通用程序

[复制链接]
发表于 2009-9-5 23:45:22 | 显示全部楼层 |阅读模式
本帖最后由 Programus 于 2009-9-6 10:00 编辑

Color Sorter是NXT 8547软件里面自带的一个机器人。图纸在软件中。
Color Catapult是Color Sorter的改造,也是8547自带的。
8547自带的软件中,对如上两种机器人分别做了编程。
我将程序用下面的代码重写了一次。
在实现了基本功能和一些简单优化之外,提供了自动识别是Color sorter还是Color catapult的功能。

这个是我的第二个NXC程序,如果有写得拙劣的地方,还希望大家指出。

机器人实际效果请看如下视频(没有权限直接发嵌入视频,只有给出链接了):
Color catapult,我翻译为颜色投石车——
http://www.tudou.com/programs/view/7ntn7GxLAyI/
Color sorter,我翻译为颜色甄选器——
http://www.tudou.com/programs/view/gIqjNcqD_Z8/
  1. /*
  2. Author: Programus
  3. Wire setup:
  4.   Port 1 - Touch Sensor for dispenser
  5.   Port 2 - Touch Sensor for tray or catapult
  6.   Port 3 - Color sensor
  7.   Port 4 - UltraSonic Sensor
  8.   Output A - Catapult engine or nothing
  9.   Output B - dispenser engine
  10.   Output C - rotate engine
  11. Function:
  12.   Robot can identify color balls and put same color into same tray or
  13.   throw to same direction
  14.   * Robot can detect whether there is a catapult
  15.   * Robot can dispense color balls automatically
  16.   * Robot can identify the color
  17.   * Robot can do the same thing for the same color
  18. */

  19. #define DISPENSER_ENGINE  OUT_B
  20. #define ROTATION_ENGINE   OUT_C
  21. #define CATAPULT_ENGINE   OUT_A
  22. #define DISPENSER_SENSOR  IN_1
  23. #define ROTATION_SENSOR   IN_2
  24. #define COLOR_SENSOR      IN_3
  25. #define SONAR             IN_4

  26. #define CATAPULT_NEAR     15   // use to judge whether catapult is face to left
  27. #define CATAPULT_2NEAR    9    // use to judge whether catapult is too near
  28. #define TESTING_POWER     20   // power for testing
  29. #define INIT_DISP_ANGLE   -168 // rotate angle for initializing dispenser
  30. #define TURN_DISP_PREANGLE 360 // rotate angle to release ball
  31. #define TURN_DISP_ANGLE   288  // rotate angle to let a ball be under sensor
  32. #define INIT_TRAY_ANGLE   80   // rotate angle for initializing color tray
  33. #define INIT_CATA_ANGLE   -13  // rotate angle for initializing catapult
  34. #define THROW_TIME        500  // wait time when throw a ball
  35. #define BALL_ROLL_TIME    500  // time to wait the ball roll out
  36. #define DISPENSER_POWER   50
  37. #define ROTATION_POWER    50
  38. #define CATAPULT_POWER    100

  39. #define COLOR_NUM         4    // how many colors the robot can identify
  40. #define ERROR_FILE        "Try Again.rso"
  41. #define START_FILE        "! Startup.rso"

  42. /*************** Global Variable **********************************************/
  43. int initCompletedCount = 0;    // record how many init jobs done
  44. int colors[] = {       // all the colors, pay attention to the order
  45.     INPUT_REDCOLOR,
  46.     INPUT_YELLOWCOLOR,
  47.     INPUT_GREENCOLOR,
  48.     INPUT_BLUECOLOR};
  49. int sortColorAngles[] = {0, 90, 180, -90};   // tray turn angles for each color
  50. int cataColorAngles[] = {-50, -15, 15, 50};  // catapult angles for each color
  51. string colorFiles[] = {       // sound file for each color
  52.     "Red.rso",
  53.     "Yellow.rso",
  54.     "Green.rso",
  55.     "Blue.rso"};
  56. int rotationAngle = 0;  // the current angle of color tray
  57. int cataIndex = -1;     // record color index of last time
  58. bool firstTime = true;  // indicate whether this is the first time

  59. // initiliazing work
  60. sub init()
  61. {
  62.     initCompletedCount = 0;
  63.     // set all sensors
  64.     SetSensorTouch(DISPENSER_SENSOR);
  65.     SetSensorTouch(ROTATION_SENSOR);
  66.     SetSensorColorFull(COLOR_SENSOR);
  67.     SetSensorLowspeed(SONAR);
  68. }

  69. // Detect whether there is an engine connected on the specified port.
  70. bool isEnginePlugged(int port)
  71. {
  72.     // rotate the motor a little
  73.     OnFwd(port, TESTING_POWER);
  74.     Wait(100);
  75.     // get the rotation angle
  76.     long angle = MotorRotationCount(port);
  77.     // set the return value
  78.     // if the angle is not 0, that means there is an engine
  79.     bool ret = !(angle == 0);
  80.     if (ret)
  81.     {
  82.         // if there is an engine,
  83.         // rotate it back because we rotate it before to do the test
  84.         RotateMotor(port, TESTING_POWER, -angle);
  85.     }
  86.     return ret;
  87. }

  88. // Tell robot whether it is a catapult.
  89. bool isCatapult()
  90. {
  91.     return isEnginePlugged(CATAPULT_ENGINE);
  92. }

  93. // initialize the dispenser
  94. task initDispenser()
  95. {
  96.     // rotate the dispenser engine until it pushed the touch sensor
  97.     OnFwd(DISPENSER_ENGINE, DISPENSER_POWER);
  98.     until(Sensor(DISPENSER_SENSOR));
  99.     // but if the engine pushed the touch sensor at the beginning,
  100.     // robot can not ensure the engine position after rotate a particular angle
  101.     // so we rotate the engine back,
  102.     // to find the position the sensor just be touched
  103.     OnRev(DISPENSER_ENGINE, DISPENSER_POWER);
  104.     until(!Sensor(DISPENSER_SENSOR));
  105.     // stop the engine, this might not necessary, do this just in case
  106.     Off(DISPENSER_ENGINE);
  107.     // rotate motor to ensure the dispenser is ready
  108.     RotateMotor(DISPENSER_ENGINE, DISPENSER_POWER, INIT_DISP_ANGLE);
  109.     initCompletedCount++;
  110. }

  111. // initialize the color tray
  112. sub initColorTray()
  113. {
  114.     // logic are very similar to the dispenser initialization
  115.     OnFwd(ROTATION_ENGINE, ROTATION_POWER);
  116.     until(Sensor(ROTATION_SENSOR));
  117.     until(!Sensor(ROTATION_SENSOR));
  118.     Off(ROTATION_ENGINE);
  119.     RotateMotor(ROTATION_ENGINE, TESTING_POWER, INIT_TRAY_ANGLE);
  120.     rotationAngle = 0;
  121. }

  122. // initialize the catapult
  123. sub initCatapult()
  124. {
  125.     OnRev(ROTATION_ENGINE, ROTATION_POWER);
  126.     int dist = SensorUS(SONAR);
  127.     while (true)
  128.     {
  129.         int currentDist = SensorUS(SONAR);
  130.         if ((currentDist < CATAPULT_NEAR && currentDist < dist)
  131.             || currentDist < CATAPULT_2NEAR)
  132.         {
  133.             break;
  134.         }
  135.     }
  136.     Off(ROTATION_ENGINE);
  137.     long angle = MotorRotationCount(ROTATION_ENGINE);
  138.     OnFwd(ROTATION_ENGINE, ROTATION_POWER);
  139.     until(Sensor(ROTATION_SENSOR) ||
  140.         abs(MotorRotationCount(ROTATION_ENGINE) - angle) > 135);
  141.     if (abs(MotorRotationCount(ROTATION_ENGINE) - angle) > 135)
  142.     {
  143.         // This case means you installed catapult to a wrong angle,
  144.         // warning and stop program.
  145.         Off(ROTATION_ENGINE);
  146.         PlayFile("! Attention.rso");
  147.         Wait(500);
  148.         PlayFile("Error.rso");
  149.         Wait(1000);
  150.         StopAllTasks();
  151.     }
  152.     until(!Sensor(ROTATION_SENSOR));
  153.     Off(ROTATION_ENGINE);
  154.     RotateMotor(ROTATION_ENGINE, TESTING_POWER, INIT_CATA_ANGLE);
  155.     rotationAngle = 0;
  156. }

  157. // initialize rotation motor
  158. task initRotation()
  159. {
  160.     if (isCatapult())
  161.     {
  162.         PlayTone(440, 100);
  163.         initCatapult();
  164.     }
  165.     else
  166.     {
  167.         initColorTray();
  168.     }
  169.     initCompletedCount++;
  170. }

  171. // subrotine to release ball
  172. sub releaseBall()
  173. {
  174.     if (!firstTime)
  175.     {
  176.         RotateMotor(DISPENSER_ENGINE, DISPENSER_POWER, TURN_DISP_PREANGLE);
  177.         Wait(BALL_ROLL_TIME);
  178.     }
  179.     OnFwd(DISPENSER_ENGINE, DISPENSER_POWER);
  180.     until(Sensor(DISPENSER_SENSOR));
  181.     until(!Sensor(DISPENSER_SENSOR));
  182.     RotateMotor(DISPENSER_ENGINE, DISPENSER_POWER, TURN_DISP_ANGLE);
  183.     Wait(300);
  184. }

  185. // throw ball by catapult
  186. sub throwBall()
  187. {
  188.     OnFwd(CATAPULT_ENGINE, CATAPULT_POWER);
  189.     Wait(THROW_TIME);
  190.     int angle = MotorRotationCount(CATAPULT_ENGINE);
  191.     RotateMotor(CATAPULT_ENGINE, CATAPULT_POWER, -angle);
  192. }

  193. // robot works as a color sorter
  194. sub colorSorter()
  195. {
  196.     bool success = false;
  197.     int angle = rotationAngle;
  198.     for (int i = 0; i < COLOR_NUM; i++)
  199.     {
  200.         int color = Sensor(COLOR_SENSOR);
  201.         if (color == colors[i])
  202.         {
  203.             string sound = colorFiles[i];
  204.             PlayFile(sound);
  205.             int angle = sortColorAngles[i];
  206.             rotationAngle = angle;
  207.             success = true;
  208.             break;
  209.         }
  210.     }
  211.     if (!success)
  212.     {
  213.         PlayFile(ERROR_FILE);
  214.     }
  215.     int rotate = angle - rotationAngle;
  216.     if (rotate > 180)
  217.     {
  218.         rotate = (rotate % 360) - 360;
  219.     }
  220.     else if (rotate < -180)
  221.     {
  222.         rotate = 360 + (rotate % 360);
  223.     }
  224.     RotateMotor(ROTATION_ENGINE, ROTATION_POWER, rotate);
  225.     releaseBall();
  226. }

  227. // robot works as color catapult
  228. sub colorCatapult()
  229. {
  230.     releaseBall();
  231.     int angle = 0;
  232.     if (cataIndex >= 0)
  233.     {
  234.         string sound = colorFiles[cataIndex];
  235.         PlayFile(sound);
  236.         angle = cataColorAngles[cataIndex];
  237.     }
  238.     cataIndex = -1;
  239.     for (int i = 0; i < COLOR_NUM; i++)
  240.     {
  241.         int color = Sensor(COLOR_SENSOR);
  242.         if (color == colors[i])
  243.         {
  244.             cataIndex = i;
  245.             break;
  246.         }
  247.     }
  248.     if (angle != 0)
  249.     {
  250.         RotateMotor(ROTATION_ENGINE, ROTATION_POWER, angle);
  251.         Wait(1000);
  252.         throwBall();
  253.         RotateMotor(ROTATION_ENGINE, ROTATION_POWER, -angle);
  254.     }
  255.     else if (!firstTime)
  256.     {
  257.         PlayFile(ERROR_FILE);
  258.     }
  259. }

  260. task mainProcess()
  261. {
  262.     until (initCompletedCount >= 2)
  263.     {
  264.         Wait(500);
  265.     }
  266.     PlayFile(START_FILE);
  267.     Wait(1000);
  268.     if (isCatapult())
  269.     {
  270.         while (true)
  271.         {
  272.             colorCatapult();
  273.             firstTime = false;
  274.         }
  275.     }
  276.     else
  277.     {
  278.         while (true)
  279.         {
  280.             colorSorter();
  281.             firstTime = false;
  282.         }
  283.     }
  284. }

  285. task main()
  286. {
  287.     init();
  288.     Precedes(initDispenser, initRotation, mainProcess);
  289. }
复制代码
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
发表于 2009-9-6 00:27:12 | 显示全部楼层
看楼主的程序还是蛮难受的,楼主好象没有用tab的习惯嘛?
还用了很多define,虽然修改容易了,可看的人其实蛮辛苦的,猛往上翻定义,
不过很佩服楼主啦,很厉害的程序
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2009-9-6 09:46:49 | 显示全部楼层
本帖最后由 Programus 于 2009-9-6 10:05 编辑
看楼主的程序还是蛮难受的,楼主好象没有用tab的习惯嘛?
还用了很多define,虽然修改容易了,可看的人其实蛮辛苦的,猛往上翻定义,
不过很佩服楼主啦,很厉害的程序
糖伯虎 发表于 2009-9-6 00:27


用很多define是为了可升级性以及端口的可变性。另外,写的时候因为数字拿捏不准,总是要改,用define要方便很多。
而且,我倒觉得全是数字的程序看起来会比较累,因为不知道那个数字是什么意义。用define,就可以知道数字的意义,至于数字是多少,不同人的机器可能还会有一些微小的不同,反正也不重要。呵呵……

至于tab……其实用了,但是bricx默认把tab变成了一个空格,贴到这里竟然就消失了……

等我想想办法。呵呵……
没有tab的程序,我自己看着也会抓狂的。呵呵……
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

 楼主| 发表于 2009-9-6 10:02:38 | 显示全部楼层
本帖最后由 Programus 于 2009-9-6 10:12 编辑

已经调整了,顺便问一下,在bricx里面怎么才能让大括号后的tab不是一个空格呢?
只要前一行有一个大括号,下一行顶头的tab总是默认一个空格。


补充:自己找到答案了,把设置里面的Quick Tab前面的勾去掉就行了。呵呵……
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2009-9-6 10:31:46 | 显示全部楼层
我之前写过篇如果设置bricxcc的小东西,有写过怎么设置tab的
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2009-10-21 19:34:20 | 显示全部楼层
不错!!
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

发表于 2011-9-1 13:30:52 | 显示全部楼层
本帖最后由 安步当车 于 2011-9-1 13:32 编辑

实现了基本功能和一些简单优化之外,提供了自动识别是Color sorter还是Color catapult的功能???

请问是通过检测A电机有没有插么?
看出来了,是用超声波检测的。
如果您觉得我的帖子对您有用,请不吝给我一个“赞”!
回复

使用道具 举报

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

本版积分规则

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

GMT+8, 2025-8-2 03:17 , Processed in 0.212266 second(s), 19 queries .

Powered by Discuz! X3.5

Copyright © 2001-2020, Tencent Cloud.

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