Robot C Graphical (Multi-Task)

  1. 4 months ago

    Robot C Graphical: How do we get a program to display a sensor value and at the same time many other things would be happening (motors starting and stopping, waiting etc.) I am currently only able to get it to display after it runes each series of code. this make take a few seconds. Basically I am trying to do multi tasking with RobotC Graphical.

    First, as with callen, I have to admit I'm not 100% certain what the objectives are, so let me state what I think they are and you correct me where I'm wrong.

    repeating forever
        Display sonar and color values
    
       if sonar reports distances over 51 US units
               {    spin at speed 50 ** but more on this later ** }
       else { drive forward at 75
    
                  if color is reflected over 50 units
                       { 
                         drive backwards at -75 for 1 second and stop
                       }
               } 

    What I expect this to do is spin in 1/10th second intervals, stopping at each interval - which means the bot will be very jerky, starting and stopping 10 times a second, until the sonar reports a distance over 51. I doubt this is your intention, but I could be wrong. In other words, I don't believe you want to stop all motors every 10th of a second. I think you intend to CHECK the sonar at 1/10th second intervals while the motor CONTINUES to spin at 50/-50.

    I'll leave the "else" alone for the moment.

    Ok, given that some of that might be misinterpretation of your intentions, let me deal with the timing issue. Callen has a point at his closing. Let me expand on it.

    Consider what's happening during a phase where getUSdistance is not reporting over 51, but ALSO the reflected color is below 50.

    That means the loop is running full out, eating up CPU power, while displaying sensor values (which itself is actually a bit of a delay because it's work). Notice that my point is that when getUSdistance doesn't return >=51, this means the wait( .1, seconds ) isn't called, and since getColorReflected(color) isn't greater than 50, the wait(1,seconds) isn't getting called - therefore nothing keeps that phase of operation from repeating as fast as the CPU can run - DRAINING BATTERY POWER (for nothing).

    To fix THAT situation, rethink timing.

    Start out, BEFORE the repeat( forever), by initializing a timing variable[ Number ]...say, t = 0.0;

    Now, at the "top of the loop", which is to say the very first thing AFTER the repeat(forever), wait ( .1, seconds ).

    When that returns, increment the time.

    t = t + .1;

    This is counting the passage of time, AND it is keeping the loop from running any faster than 10 times per second. You can control this rate. If, for example, you choose to wait ( .05, seconds ) - and also change to t = t + .05, you'll keep the loop running at 20 times per second. You can almost maintain a rate of up to 100 times per second, but that might be a bit impractical depending on the rest of the code.

    Further, because you want to do multiple things, and the language is limiting you to "if" or "if/else", you may need to adopt a "command" messaging concept. This means a new variable, say "c", represents a command.

    The construction would be like this now:

    delay_time = 0.1;
    t = 0.0;
    c = 0;
    cmd_time = 0.0;
    
    repeat (forever) 
    {
     wait( delay_time, seconds );
     t = t + delay_time;
    
     displaySensorValues( line8, sonar );
     displaySensorValues( line5, color );
    
     if ( c == 0 )
        {
          if ( getUSDistance( sonar ) >= 51 )
              { 
               setMotor( MotorB, 50 );
               setMotor( MotorC, -50 );
               c = 1; // NOTE THAT THIS SETS THE 'COMMAND' TO 1
               cmd_time = t;
               continue;
              }
    
          setMultipleMotors( 75, MotorB, MotorC, noMotor );
           
          if ( getColorReflected( color ) > 50 )
              {
               setMultipleMotors( -75, MotorB, MotorC, noMotor );
               c = 2; // NOTE THAT THIS SETS THE 'COMMAND' TO 2
               cmd_time = t;
               continue;
              }
        } // this is the end of "if ( c== 0 )"
    
     if ( c == 1)
      {
        if ( t - cmd_time >= 0.1 )
          {
           stopAllMotors();
           c = 0;
           continue;
          }
     }
    
     if ( c == 2 )
      {
        if ( t - cmd_time >= 1.0 )
         {
          stopAllMotors();
          c = 0;
          continue; // this wouldn't be necessary unless you add other commands after this
         } 
      }
    
    
    }

    Note: I HAVE NOT TESTED THIS CODE, nor did I write it with RobotC, I'm just typing "notes" here.

    However, the idea is to separate the operations so that the loop is never locked up waiting on something. The loop continues to run at roughly the rate defined by "delay_time".

    "t" accumulates the time (which is approximate).

    Notice that "c" is a command or "state" of operation. When it is zero, your tests are written fairly similar to the way they were. In this way, "c at zero" means nothing is waiting to turn off a motor. Note, too, that there are no wait( ) calls after the motors are set.

    Notice there is no "else" either. I've used continue to do something similar, but now I'm not bound to just two cases, there can be many more.

    The "cmd_time" is a notation of when the command "c" changed. It so happens that ( t - cmd_time ) equals how long SINCE the command changed.

    This means, especially for c == 2, that even though c becomes 2 ONLY when getColorReflected return > 50 and the motors were set to -75, the LOOP can repeat MANY times without waiting, until INSIDE the command "responder" for c==2 we see that all of the time we wanted to wait ( 1 second ) has expired before stopping all the motors.

    This is the basic theory I'm trying to show you.

    You can continue operating the loop, control the rate at which that loop repeats, and still be able to track the timing of events that take longer than the loop.

  2. callen

    Jun 7 Braintree, MA, USA

    With RobotC Graphical I don't think you can create new tasks. However, frequently those asking for tasks don't really need tasks, just a different way of thinking through their code. For example, instead of starting some motors followed by wait1MSec() and preventing yourself from doing more things, you could start a timer and keep checking it in a loop that does other things. Could you post the commands you have? It's hard to help much without seeing more.

  3. Jason63

    Jun 7 Florida NA

    Your username suggests you are a teacher, not a student - is that right?

    I'm a tutor, or mentor, volunteer at the local high school's robotics club teaching programming. I've been a programming for decades. I'm not convinced you're a teacher, so correct me if I'm wrong.

    Let me be frank about this.

    The graphical mode of RobotC is not going to give access to the full capabilities of the micro controller. I never investigated the graphical mode much, but I have seen several of your posts here on the subject, so I decided to investigate it for a while.

    I believe there is a dual purpose for the graphical mode of RobotC. It is intended as an "easy" invitation for younger participants. In my opinion that is also the same "danger" as training wheels on a bicycle, where students may become all too dependent upon it for functionality.

    As a parent (and a grandparent), I've observed that training wheels actually don't teach anything. In reality, they're used to get the kid on the bike, moving, enjoying - but there's never a moment when they actually help a kid to learn how to balance. The wheels have to come off for that.

    The concepts you're considering require the non-graphical mode of RobotC. Since a great deal of what the micro controller can do is locked away from you because of the graphical mode, you really must consider transitioning.

    The concept of tasks you're asking about makes this particularly clear, to me, on this point. Tasks (as they're called in RobotC - in most other operating systems and language contexts they're called threads) are an advanced concept compared to what the graphical RobotC environment can support, and the mere fact you're asking this question makes it clear beyond all doubt you're heading for the non-graphical mode, and ready for it.

    What you describe tells me you have a complexity of working code that is beyond graphical, and NOW the graphical mode is no longer a helper, it is an obstacle.

    So, if you can post screen shots that show your entire graphical code, I could help translate that into a standard RobotC version, which would give you 90% of what you need to know to move into non-graphical mode, and then I can show you how to launch tasks.

    Interested?

  4. tabor473

    Jun 7 V5 Beta Tester OYES, WPI

    @Jason63 Your username suggests you are a teacher, not a student - is that right?

    I'm a tutor, or mentor, volunteer at the local high school's robotics club teaching programming. I've been a programming for decades. I'm not convinced you're a teacher, so correct me if I'm wrong.

    Let me be frank about this.

    The graphical mode of RobotC is not going to give access to the full capabilities of the micro controller. I never investigated the graphical mode much, but I have seen several of your posts here on the subject, so I decided to investigate it for a while.

    I believe there is a dual purpose for the graphical mode of RobotC. It is intended as an "easy" invitation for younger participants. In my opinion that is also the same "danger" as training wheels on a bicycle, where students may become all too dependent upon it for functionality.

    As a parent (and a grandparent), I've observed that training wheels actually don't teach anything. In reality, they're used to get the kid on the bike, moving, enjoying - but there's never a moment when they actually help a kid to learn how to balance. The wheels have to come off for that.

    The concepts you're considering require the non-graphical mode of RobotC. Since a great deal of what the micro controller can do is locked away from you because of the graphical mode, you really must consider transitioning.

    The concept of tasks you're asking about makes this particularly clear, to me, on this point. Tasks (as they're called in RobotC - in most other operating systems and language contexts they're called threads) are an advanced concept compared to what the graphical RobotC environment can support, and the mere fact you're asking this question makes it clear beyond all doubt you're heading for the non-graphical mode, and ready for it.

    What you describe tells me you have a complexity of working code that is beyond graphical, and NOW the graphical mode is no longer a helper, it is an obstacle.

    So, if you can post screen shots that show your entire graphical code, I could help translate that into a standard RobotC version, which would give you 90% of what you need to know to move into non-graphical mode, and then I can show you how to launch tasks.

    Interested?

    ROBOTC will actually do a graphical to text conversion. The blocks are all quite obviously functions so its a trivial thing for them to implement.

  5. I have attached a copy of the section of code that we are having a problem with. I understand that there are many other features in the non graphical versions of RobotC, but in this particular case-class we are using graphical and were just trying to get this small code to run a little more fluidly.

  6. callen

    Jun 8 Braintree, MA, USA

    The first part of the blue if statement really isn't an issue since it's so quick. It's the second part (the else) where things can get hung up.

    But first, on the second part of the blue if statement (the else), I'm confused why you always set motors to 75 when you want -75 sometimes. I would think the setMultipleMotors to 75 would be within an else section of the purple. But at the same time, what is setting to 75 ever doing? If you don't immediately switch to -75, you exit right away without delay and go to the display and check for 50/-50. So you only ever have the 75 setting for an incredibly small time, though that could repeat many times.

    The basic idea of avoiding the tasks is this, inside the purple if statement.

    1. set the motors
    2. clear/reset the timer
    3. while(the timer is less than 1 second) {display your sensor values and waiting 10 ms or so}.
  7. Jason63

    Jun 10 Answer Florida NA
    Edited 4 months ago by Jason63

    First, as with callen, I have to admit I'm not 100% certain what the objectives are, so let me state what I think they are and you correct me where I'm wrong.

    repeating forever
        Display sonar and color values
    
       if sonar reports distances over 51 US units
               {    spin at speed 50 ** but more on this later ** }
       else { drive forward at 75
    
                  if color is reflected over 50 units
                       { 
                         drive backwards at -75 for 1 second and stop
                       }
               } 

    What I expect this to do is spin in 1/10th second intervals, stopping at each interval - which means the bot will be very jerky, starting and stopping 10 times a second, until the sonar reports a distance over 51. I doubt this is your intention, but I could be wrong. In other words, I don't believe you want to stop all motors every 10th of a second. I think you intend to CHECK the sonar at 1/10th second intervals while the motor CONTINUES to spin at 50/-50.

    I'll leave the "else" alone for the moment.

    Ok, given that some of that might be misinterpretation of your intentions, let me deal with the timing issue. Callen has a point at his closing. Let me expand on it.

    Consider what's happening during a phase where getUSdistance is not reporting over 51, but ALSO the reflected color is below 50.

    That means the loop is running full out, eating up CPU power, while displaying sensor values (which itself is actually a bit of a delay because it's work). Notice that my point is that when getUSdistance doesn't return >=51, this means the wait( .1, seconds ) isn't called, and since getColorReflected(color) isn't greater than 50, the wait(1,seconds) isn't getting called - therefore nothing keeps that phase of operation from repeating as fast as the CPU can run - DRAINING BATTERY POWER (for nothing).

    To fix THAT situation, rethink timing.

    Start out, BEFORE the repeat( forever), by initializing a timing variable[ Number ]...say, t = 0.0;

    Now, at the "top of the loop", which is to say the very first thing AFTER the repeat(forever), wait ( .1, seconds ).

    When that returns, increment the time.

    t = t + .1;

    This is counting the passage of time, AND it is keeping the loop from running any faster than 10 times per second. You can control this rate. If, for example, you choose to wait ( .05, seconds ) - and also change to t = t + .05, you'll keep the loop running at 20 times per second. You can almost maintain a rate of up to 100 times per second, but that might be a bit impractical depending on the rest of the code.

    Further, because you want to do multiple things, and the language is limiting you to "if" or "if/else", you may need to adopt a "command" messaging concept. This means a new variable, say "c", represents a command.

    The construction would be like this now:

    delay_time = 0.1;
    t = 0.0;
    c = 0;
    cmd_time = 0.0;
    
    repeat (forever) 
    {
     wait( delay_time, seconds );
     t = t + delay_time;
    
     displaySensorValues( line8, sonar );
     displaySensorValues( line5, color );
    
     if ( c == 0 )
        {
          if ( getUSDistance( sonar ) >= 51 )
              { 
               setMotor( MotorB, 50 );
               setMotor( MotorC, -50 );
               c = 1; // NOTE THAT THIS SETS THE 'COMMAND' TO 1
               cmd_time = t;
               continue;
              }
    
          setMultipleMotors( 75, MotorB, MotorC, noMotor );
           
          if ( getColorReflected( color ) > 50 )
              {
               setMultipleMotors( -75, MotorB, MotorC, noMotor );
               c = 2; // NOTE THAT THIS SETS THE 'COMMAND' TO 2
               cmd_time = t;
               continue;
              }
        } // this is the end of "if ( c== 0 )"
    
     if ( c == 1)
      {
        if ( t - cmd_time >= 0.1 )
          {
           stopAllMotors();
           c = 0;
           continue;
          }
     }
    
     if ( c == 2 )
      {
        if ( t - cmd_time >= 1.0 )
         {
          stopAllMotors();
          c = 0;
          continue; // this wouldn't be necessary unless you add other commands after this
         } 
      }
    
    
    }

    Note: I HAVE NOT TESTED THIS CODE, nor did I write it with RobotC, I'm just typing "notes" here.

    However, the idea is to separate the operations so that the loop is never locked up waiting on something. The loop continues to run at roughly the rate defined by "delay_time".

    "t" accumulates the time (which is approximate).

    Notice that "c" is a command or "state" of operation. When it is zero, your tests are written fairly similar to the way they were. In this way, "c at zero" means nothing is waiting to turn off a motor. Note, too, that there are no wait( ) calls after the motors are set.

    Notice there is no "else" either. I've used continue to do something similar, but now I'm not bound to just two cases, there can be many more.

    The "cmd_time" is a notation of when the command "c" changed. It so happens that ( t - cmd_time ) equals how long SINCE the command changed.

    This means, especially for c == 2, that even though c becomes 2 ONLY when getColorReflected return > 50 and the motors were set to -75, the LOOP can repeat MANY times without waiting, until INSIDE the command "responder" for c==2 we see that all of the time we wanted to wait ( 1 second ) has expired before stopping all the motors.

    This is the basic theory I'm trying to show you.

    You can continue operating the loop, control the rate at which that loop repeats, and still be able to track the timing of events that take longer than the loop.

 

or Sign Up to reply!