【问题标题】:RobotC - Programming an ElevatorRobotC - 为电梯编程
【发布时间】:2013-11-09 21:18:41
【问题描述】:

我正在为一个高中项目设计和编程一个类似电梯的机器人。我可以做些什么来让这更简单吗?或更好?我附上了一张我在 AutoCAD Inventor 中制作的带有标签的设计图片。

对于那些不熟悉 RobotC 或 VEX(它与 C 和 C++ 非常相似)的人:限位开关(limit1、limit2、...)和碰撞开关(floor1、floor2、...)是模拟按钮和如果未按下则返回值 0,如果按下则返回 1。电机(mainMotor)旋转齿轮,使机构在滑块上向上移动。当伸出电动机构的轴上下移动时,它按下限位开关并使其返回值1。

int callup [3];
int calldown [3];
int floorat[3];

    int main ()
    {

        if (SensorValue[limit1] == 1)
        {
            floorat[0] = 1;
        }
        else
        {
            floorat[0] = 0;
        }

        if (SensorValue[limit2] == 1)
        {
            floorat[1] = 1;
        }
        else
        {
            floorat[1] = 0;
        }

        if (SensorValue[limit3] == 1)
        {
            floorat[2] = 1;
        }
        else
        {
            floorat[2] = 0;
        }

        if (SensorValue[floor1] == 1)
        {
            calldown[0] = 1;
            SensorValue[LED1] = 1;
        }

        if (SensorValue[floor2] == 1 && floorat[2] == 1)
        {
            calldown[1] = 1;
            SensorValue[LED2] = 1;
        }

        if (SensorValue[floor2] == 1 && floorat[0] == 1)
        {
            callup[1] = 1;
            SensorValue[LED2] = 1;
        }

        if (SensorValue[floor3])
        {
            callup[2] = 1;
            SensorValue[LED3] = 1;
        }

        motors ();

    }


    void motors ()
    {

        if (callup[2] == 1 && floorat[2] == 1)
        {
            int x = 1;
            while (x < 3)
            {
                SensorValue[LED3] = 1;
                wait(0.5);
                SensorValue[LED3] = 0;
                wait(0.5);
            }
            callup[2] = 0;
            main ();
        }
        else if (callup[1] == 1 && floorat[1] == 1)
        {
            int x = 1;
            while (x < 3)
            {
                SensorValue[LED2] = 1;
                wait(0.5);
                SensorValue[LED2] = 0;
                wait(0.5);
            }
            callup[1] = 0;
            main ();
        }
        else if (callup[0] == 1 && floorat[0] == 1)
        {
            int x = 1;
            while (x < 3)
            {
                SensorValue[LED1] = 1;
                wait(0.5);
                SensorValue[LED1] = 0;
                wait(0.5);
            }
            callup[0] = 0;
            main ();
        }

        if (callup[2] == 1 && floorat[1] == 1 && calldown[0] == 0 || callup[2] == 1 && floorat[0] == 1 && callup[1] == 0)
        {
            startMotor(mainMotor, 60);
            untilTouch(limit3);
            stopMotor(mainMotor);
            callup[2] = 0;
            wait(1);
            main ();
        }

        if (callup[1] == 1 && floorat[0] == 1)
        {
            startMotor(mainMotor, 60);
            untilTouch(limit2);
            stopMotor(mainMotor);
            callup[1] = 0;
            wait(1);
            main();
        }

        if (calldown[1] == 1 && floorat[2] == 1)
        {
            startMotor(mainMotor, -60);
            untilTouch(limit2);
            stopMotor(mainMotor);
            calldown[1] = 0;
            wait(1);
            main();
        }

        if (calldown[0] == 1 && floorat[2] == 1 && calldown[1] == 0 || calldown[0] == 1 && floorat[1] == 1)
        {
            startMotor(mainMotor, -60);
            untilTouch(limit1);
            stopMotor(mainMotor);
            calldown[0] = 0;
            wait(1);
            main();
        }
    }

虽然这个问题不应该关心,但startMotor命令中的60是电机的速度,只是为了更清楚。

如有任何问题,请随时提出。

【问题讨论】:

  • 如果语言允许,您可以考虑如何用表格来表示您的电梯系统。考虑一下 100 层而不是 3 层的代码可能是什么样子。您将如何编写这样的代码,以便仅几行代码就可以查询更大的表/数据结构集以知道该怎么做?
  • 您可能还需要考虑使用while 循环。真的,除了main() 的无底递归和调用之外的任何东西都会更好。别介意调用main() 是一个禁忌,递归最终会毁掉你的堆栈。
  • 我可以使用 while 循环和/或 for 循环。但我没有在这里使用它们,因为真正需要循环的唯一楼层是 floor2,而且手动输入代码更容易。
  • 这样做可能更容易,但除非 VEX 与普通 C 非常不同,否则您的实现最终会崩溃。我更喜欢我的电梯可靠。 :)
  • 我该怎么做才能不必一遍又一遍地引用 main() ?它基本上是带有特殊变量的 C,因此 C 用户的建议也会有所帮助。

标签: c++ c robotics robot


【解决方案1】:

让我们定义电梯在给定时刻的状态:

电梯可以向上向下空闲

电梯位于给定的楼层,并在触发开关时从一层到另一层:

现在,如果我们把它翻译成一些伪代码(应该很容易翻译成RobotC):

enum elevator_status = { idle, down, up };
int currentfloor; //1, 2, 3 


switch(elevator_status)
{
    case idle:    
        //we check if a button is pressed and possibly go up or down           
        if(SensorValue(floor1))
        {         
             if(currentfloor > 1)
                elevator_status = down;               
        }
        else if(SensorValue(floor2))
        {
              if(currentfloor > 2)
                  elevator_status = down;
              else if(currentfloor < 2)
                  elevator_status = up;               
        }
        else if(SensorValue(floor3))
        {
              if(currentfloor < 3)
                  elevator_status = up;   
        }
        break;

    case up:
    case down:    
        //we check if we trigger a floor switch and stop the elevator
        if(SensorValue(limit1))
        {      
           currentfloor = 1;
           elevator_status = idle;
        }
        else if(SensorValue(limit2))
        {
           currentfloor = 2;
           elevator_status = idle;
        }
        else if(SensorValue(limit3))
        {
           currentfloor = 3;
           elevator_status = idle;
        }
        break;
}


//we set the speed of the motor
if(elevator_status == up)
{
   set_motorstate(cw);
)
else if(elevator_status == down)
{
   set_motorstate(ccw);   
}
else if(elevator_status == idle)
{
   set_motorstate(idle);   
}

注意:在此代码中,电梯只会在电梯空闲时处理新的上下楼层呼叫。它在移动时不存储上下呼叫,稍后再去那里。不知道是不是你的要求。

【讨论】:

    【解决方案2】:

    我对 RobotC 或 VEX 不熟悉,但我注意到一定数量的复制操作可以制作成它们自己的函数。

    下面的代码 sn-ps 我会做成单独的函数。因此,在名为 motor 的大型函数中,您有以下一组操作:

        int x = 1;
        while (x < 3)
        {
            SensorValue[LED3] = 1;
            wait(0.5);
            SensorValue[LED3] = 0;
            wait(0.5);
        }
        callup[2] = 0;
        main ();
    

    这是重复的,但值略有不同。

    这里我会写一个类似下面的函数:

    void adjust_sensors( size_t led, size_t level )
    {
        int x = 1;
        while (x < 3)
        {
            SensorValue[led] = 1;
            wait(0.5);
            SensorValue[led] = 0;
            wait(0.5);
        }
        callup[level] = 0;
        main ();
    }
    

    您也可以对以下代码执行相同操作:

    startMotor(mainMotor, 60);
    untilTouch(limit3);
    stopMotor(mainMotor);
    callup[2] = 0;
    wait(1);
    main ();
    

    另外,while 循环似乎永远不会结束,因为 x 的值永远不会改变。

    您在声明时顶部还有一个错字:

    int callown [2];
    

    我猜你的意思是:

    int calldown [2];
    

    为了清晰起见,最好在您的代码中添加一些 cmets。

    希望这会有所帮助。

    【讨论】:

    • 那是一种类型,我现在已经修好了。是的,这很有帮助,谢谢。
    【解决方案3】:

    我可能会走得更远,因为我只是一个有自己问题的学生,但看起来你可能在数组大小方面犯了错误。例如,当您声明:

    int floorat[2];
    

    这使数组大小为 2。然后您引用此数组中的 3 个元素位置 [0, 1, 2]。另外,你不能只使用一个常规整数,然后给它赋值 1、2 或 3?

    我建议将这些变量重新定义为:

    int callup;
    int calldown;
    int floorat;
    

    那么您可以避免额外的代码行并将 if/else 子句简化为:

    if (SensorValue[limit1] == 1)
    {
        floorat = 1;
    }
    
    if (SensorValue[limit2] == 1)
    {
        floorat = 2;
    }
    
    
    if (SensorValue[limit3] == 1)
    {
        floorat = 3;
    }
    

    【讨论】:

    • 当您声明一个数组 (floorat[2]) 时,它会创建三个变量: floorat[0]、floorat[1] 和 floorat[2]。这就是我稍后在代码中访问的内容。正如我刚才所说,这些不仅仅是单个变量,它们是数组,所以我无法重命名它们。而且我还需要稍后在代码中检查每一层,因此将其简化为一个变量根本没有帮助。
    • 在 C 中声明 int f[2]; 为索引为 0 和 1 的两个整数提供了空间。可能您的语言不同,但您应该检查并确定。
    • @user2974881 在 C 中声明数组时,括号中的值是数组中位置的数量。要引用它们,请使用 0 来表示值,因为第一个位置是 0,而不是 1。我的意思是,您似乎只使用 floorat 数组来确定电梯所在的楼层(基于限制),而不是执行复杂的 if else 系统来检查它是否在 1 楼,然后是 2 楼,然后是 3 楼,并为每个部分分配 0 或 1,您可以只使用一个 int 并为其分配楼层值,然后在三个不同的数组位置检查 1、2 或 3,而不是 0 或 1。
    • 是的,我注意到了。我将它与 Visual Basic 混合在一起。我无法想象在我学习更多语言之后会有多混乱。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-05
    • 2017-11-20
    • 2015-12-24
    • 2012-09-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多