【问题标题】:RobotC VEX / Lego Programming: How to make a robot run multiple reactions in parallel?RobotC VEX / Lego Programming:如何让机器人并行运行多个反应?
【发布时间】:2014-03-21 00:11:29
【问题描述】:

我需要让我的机器人能够使用碰撞开关,以便可以按下任一开关,并且只要按下碰撞开关,对应于该碰撞开关的电机就会运行。我遇到的问题是让 LED 正确点亮。在碰撞开关代码块运行时,每次光传感器值高于 400 时,我需要 LED 点亮和熄灭七次,持续一秒钟。我该怎么做?请帮忙! 我的代码发布在下面:

#pragma config(Sensor, in2,    lightSensor,    sensorReflection)
#pragma config(Sensor, dgtl3,  bumpSwitch,     sensorTouch)
#pragma config(Sensor, dgtl4,  bumpSwitch2,    sensorTouch)
#pragma config(Sensor, dgtl10, ledGreen,       sensorLEDtoVCC)
#pragma config(Sensor, dgtl11, ledRed,         sensorLEDtoVCC)
#pragma config(Motor,  port1,           leftMotor,     tmotorVex269, openLoop)
#pragma config(Motor,  port10,          rightMotor,    tmotorVex269, openLoop)

task main() {

while(true) {

    if (SensorValue(lightSensor) > 400) {
        int count = 0;
        while (count < 7) {
            turnLEDOn(ledGreen);
            turnLEDOn(ledRed);
            wait(1);
            turnLEDOff(ledGreen);
            turnLEDOff(ledRed);
            count++;
        }
    }

    while (SensorValue(bumpSwitch) == 0 && SensorValue(bumpSwitch2) == 0) {
        stopMotor(rightMotor);
        stopMotor(leftMotor);
    }

    while (SensorValue(bumpSwitch2) == 1) {
        startMotor(rightMotor, 55);
        startMotor(leftMotor, 55);
    }

    while (SensorValue(bumpSwitch) == 1){
        startMotor(rightMotor, -55);
        startMotor(leftMotor, -55);
    }
}
}

【问题讨论】:

    标签: java robot nxt mindstorms


    【解决方案1】:

    机器人编程经验(虽然我没有使用过机器人 C)表明,要让机器人并行运行两个或多个传感器反应,您必须以非常不同的方式构建程序,而不是只使用一个反应。 Robot C 教程没有涵盖这一点,甚至没有介绍执行此操作所需的语言和库功能。

    在这种情况下,您希望光传感器触发持续 1 秒的 LED 开/关序列,而碰撞传感器触发电机动作,直到这些传感器不再碰撞为止。

    这里的问题是您的电机控制的内部while 循环阻塞了线程,主要是使其无法运行 LED 控制循环。 LED 控制循环同样会阻塞线程 7 秒,延迟它运行电机控制循环。

    一般来说,机器人控制循环的每次迭代都应该读取传感器,发送输出命令,记住以后需要处理的任何状态,然后再次循环,以便控制循环的所有部分在每个循环中运行(频率为可能或以受控的速率)。不要通过停留在内部 while 循环中来阻塞控制流,直到传感器发生变化。

    第一步是疏通电机控制回路:

    while (true) {
    
      // Light sensor LED control code ...
    
      // Bumper/motor control
      if (SensorValue(bumpSwitch) == 1) {
        startMotor(rightMotor, -55);
        startMotor(leftMotor, -55);
      } else if (SensorValue(bumpSwitch2) == 1){
        startMotor(rightMotor, 55);
        startMotor(leftMotor, 55);
      } else {
        stopMotor(rightMotor);
        stopMotor(leftMotor);
      }
    }
    

    现在您当前的 LED 控制代码仍会调用 wait(1) 7 次。根据http://www.robotc.net/support/nxt/ROBOTC-for-Beginners/wait(1)等待1.0秒,所以这部分代码目前需要7秒才能运行。检查碰撞开关之间的时间很长。

    此外,您的代码在关闭和重新打开 LED 之间没有明显延迟,因此直到该序列结束时您才会真正注意到 LED 关闭。

    所以第二步是修复LED控制代码阻塞控制回路。基本上有两种方式(不知道Robot C是否支持第一选择,但比较简单):

    1. 当光传感器高于阈值并且它在上一次迭代中低于阈值,即它刚刚转换,然后启动 [或“fork”] 一个线程(或任务)运行LED 开/关循环。该线程应该循环 7 次:{打开 LED,wait(1.0/14.0) 秒,关闭 LED,然后 wait(1.0/14.0) 秒}。这样,循环的 7 个循环将花费 7 * (1/14 + 1/14) = 1.0 秒。我将其写为1.0/14.0 而不是1/14,因为许多编程语言在整数数学中计算1/14,产生0,而1.0/14.0 使用浮点数学。我不知道机器人 C。或者,您可以使用 wait1Msec(71) 等待 71 毫秒,也就是大约 1/14 秒。
    2. 使用变量通过闪光灯 LED 循环跟踪排序。围绕主循环的每个循环,使用if 语句检查这些变量,如果时间到了,则执行闪光灯循环中的下一步,并更新这些变量。步骤为:在初始状态且光传感器超过阈值时打开LED,1/14秒后关闭LED,1/14秒后打开LED稍后,... 在 14 个这些步骤之后,关闭并将跟踪变量设置回初始状态。最简单的跟踪变量将是一个从 0(初始状态)到 14(执行最后一个 LED“关闭”阶段)的计数器以及最后一次更改的系统时钟值,以便您检测时钟何时晚于 71 毫秒那。完成第 14 步后,返回 0。跟踪变量有其他选择,例如 3 个单独的变量,用于表示当前是否正在闪烁、当前正在执行的 7 个闪烁周期中的哪一个、是否处于开启或关闭阶段周期和时钟读数。

    方法 #2 比较棘手,因为同时做两件事比较棘手。 (认为​​开车时发短信可以同时处理多项任务的人大错特错。)

    如果机器人在 LED 闪烁时不需要运行保险杠/电机控制回路,也就是说,如果它不介意在 LED 闪烁 1 秒时对保险杠无响应,则可以采用更简单的方法。如果这些保险杠传感器阻止机器人从桌子的末端跑出,那么 1 秒钟无响应是个坏消息。但是如果机器人在闪灯的同时按压保险杠 1 秒是可以的,那么代码的光传感器 LED 部分可能会变成这样:

    while (true) {
      // Light sensor LED control code
      if (SensorValue(lightSensor) > 400) {
        for (int i = 0; i < 7; ++i) {
          turnLEDOn(ledGreen);
          turnLEDOn(ledRed);
          wait1Msec(71); // 1/14 second
          turnLEDOff(ledGreen);
          turnLEDOff(ledRed);
          wait1Msec(71);
        }
      }
    
      // Bumper/motor control code ...
    }
    

    这又做了一个简化的假设:如果光传感器在完成 1 秒 LED 闪烁循环后仍然亮,则可以在下一次围绕主控制循环进行另一个 1 秒闪烁循环,这很快就会发生。因此,只要光传感器亮,LED 就会一直闪烁,电机每秒只会检查一次保险杠。要解决此问题,请使用变量来确定光传感器何时从暗变为亮。

    【讨论】:

    • @user3376956 很高兴为您提供帮助。如果它回答了问题,请记住接受答案。
    • 顺便说一句,我浏览了 Robot C 教程,它从未提到任何可以让机器人一次做多项事情的功能!主控制循环可以在循环结束时使用一个wait() 来设置每次迭代所需时间的下限,但读取时钟会更好。有没有办法分叉一个线程?我没有找到它的参考文档。
    【解决方案2】:

    你应该放入一个子程序。

    //*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
    
    task blink()
    {
    // Light sensor LED control code
    if (SensorValue(lightSensor) > 400) 
        {
        for (int i = 0; i < 7; ++i) {
            turnLEDOn(ledGreen);
            turnLEDOn(ledRed);
            wait1Msec(71); // 1/14 second
            turnLEDOff(ledGreen);
            turnLEDOff(ledRed);
            wait1Msec(71);
        }
    
    }
    
    
        task main()
        {
            startTask(blink);
            while (true)
                {
    
                // Light sensor LED control code ...
    
                // Bumper/motor control
                if (SensorValue(bumpSwitch) == 1) {
                    startMotor(rightMotor, -55);
                    startMotor(leftMotor, -55);
                    } else if (SensorValue(bumpSwitch2) == 1){
                    startMotor(rightMotor, 55);
                    startMotor(leftMotor, 55);
                    } else {
                    stopMotor(rightMotor);
                    stopMotor(leftMotor);
                }
            }
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-27
      • 1970-01-01
      • 2023-04-10
      • 1970-01-01
      • 2022-01-23
      • 2023-03-04
      • 1970-01-01
      • 2019-08-26
      相关资源
      最近更新 更多