RoboCatz.com

My Blocks


What are MyBlocks?

MyBlocks are small blocks of code to help make your program more "modular" which, in turn, may make it easier to read and understand--providing that the MyBlocks are simple and appropriately labeled.

When do you use MyBlocks?

MyBlocks should be created and used whenever you have a set of robot actions that may be repeated within a program or repeated across different programs. For example, to drive straight for a specified distance. The move blocks in NXT-G require you to specify the number of rotations or the motor. Or, to drive until the rotation sensor has achieved a certain limit. If you wish to write a program specifying distance in inches, it is often necessary to convert distance into rotations. This conversion can be done within the MyBlock.

What about RobotC and why is RobotC shown on this page?

Both RobotC and NXT-G are programming languages. Both languages have similar constructs and capabilities. There are a few differences with regard to the development environment for each program. However, the two languages do have suprising similiarities. Examples for each MyBlock are shown in RobotC code for illustrative purposes.

In RobotC the MyBlocks are defined as "functions" -- usually of the type "void". So, for example, the "Drive Forward" MyBlock would have a corresponding RobotC function called: "DriveForward".

MyBlocks

Subroutines used to perform small specific functions such as moving forward, turning, stopping.

Principle: MyBlocks can help make your program easier to understand by creating unique blocks to perform very specific functions.

MyBlock: Stop Moving


Download this program

The main Options used in this block are to set the Direction to "Stop" and the Next Action to "Brake"


Example in RobotC


void Stop() {
  bFloatDuringInactiveMotorPWM = false; // brake
  nSyncedMotors = synchNone;   // De-sync the motors.
  motor[motorB] = 0;  // turn the motor off.
  motor[motorC] = 0;  // turn the motor off.
}

MyBlock: Forward

This MyBlock is used to drive the robot forward at a specified power level for a specified distance in inches.



Parameters

This block has three input parameters:
  1. "Keep Going" - Checkbox - If checked, the robot will continue moving the motors even after the specified distance has been reached.
  2. If Un-checked, the robot will put on the brakes as soon as the specified distance has been reached.
  3. "Move __ Inches" - Numeric - Allows you to specify the distance in inches for the robot to travel.
  4. "Power" - Numeric - Level of Power to apply to the motors. Values from 0 to +100.

Program


Download this program

How it works.

The robot is driven forward with the Move block which is set to an unlimited duration. The Power level used in the Move block is passed from the input. The formula used inside the loop is as follows: the distance to be traveled is divided by the circumference of the wheel and then multiplied by 360 Degrees to get the total number of degrees. Once the criteria is met, the program exits the main loop and proceeds to the "Keep Going" check. If "Keep Going" is checked, the robot will continue driving forward, otherwise it will stop.

Inputs Into this Block

This MyBlock uses two main inputs: distance and power level. The Power level input is sent directly to the Move Block and gets the robot moving. The Distance input is the distance you want the robot to travel in inches. For example, if you want the robot to travel 24 inches, then you would enter 24 as the input value. The circumference of the wheel is stored internally in the MyBlock.

Troubleshooting

Did you specify a power level?
Did you enter a distance to travel?

Example in RobotC


void DriveForward(int inches, int power, bool KeepGoing) {
  long rotationSensor = 0;
  float targetDegrees;
  rotationSensor = nMotorEncoder[motorB];

  //   WheelCircumference is in millimeters, so, multiply inches by 25.4 to convert to mm.
  targetDegrees = rotationSensor + 360 * inches * 25.4 / wheelCircumference * gearRatio;

  nSyncedMotors = synchBC;
  if(KeepGoing) {
    bFloatDuringInactiveMotorPWM = true;  // coast or float
  } else {
    bFloatDuringInactiveMotorPWM = false; // brake
    nMotorEncoderTarget[motorB] = targetDegrees;
  }
  motor[motorB] = power;
  while(
    nMotorRunState[motorB] != runStateIdle && 
    nMotorRunState[motorB] != runStateHoldPosition && 
    nMotorEncoder[motorB] <= targetDegrees) {
    // Basically nothing gets done inside this loop.  We are just waiting for
    //  one of the exit conditions to become false so that we can stop the loop.
    //  The program stays in the loop only while all of the conditions are met.
  }
  if(!KeepGoing) motor[motorB] = 0;  // turn the motor off.
  bFloatDuringInactiveMotorPWM = false; // brake
}

MyBlock: Stop On Line

This MyBlock is used in navigation to stop the robot if it crosses a line. It is used, for example, to drive to a line and stop.


Parameters

None. Just make sure the robot is already moving before you use this block. This block will not start the robot moving--it only stops it moving.

Program: Version 1


Download this program

Program: Version 2


Download this program

In Version 1 of this program, The primary block is the Light Sensor. The main Options used for the Light Sensor include setting the Criteria to Less than 30 ( "<" 30). If there is a pattern in the background or if the background is not white, you may want to change the criteria to a lower value.


In version 2 of this program, The primary block is the Wait (hourglass). Set the type of wait to Sensor and choose the Light Sensor. The main Options used for the Light Sensor include setting the Criteria to Less than 30 ( "<" 30). If there is a pattern in the background or if the background is not white, you may want to change the criteria to a lower value.


Troubleshooting
  1. Are you using Calibrated light sensors?
  2. Is the robot already moving when you get to this block in the program?
  3. If you are using the Green Move block before the this "Stop On Line" MyBlock, make sure you have specified the duration to be "Unlimited".
  4. If you are using a Forward MyBlock, make sure you checked the "Keep Going" box and also specified a distance that is less than the expected line. The Forward MyBlock will get the robot moving with the distance set to just an inch or two. The checked "Keep Going" option will force the robot to continue going forward into the "Stop On Line" MyBlock which will allow the robot to continue until it sees the line.

Usage Method 1

Move Block with duration set to Unlimited.


Usage Method 2

Forward MyBlock with "Keep Going" Checked, Distance less than the actual line, and Power set to a certain value.


Example in RobotC


void StopOnLine() {
  SensorType[S3] = sensorLightActive;  // Make sure you turn the light 'on'

  // Enter a loop and stay there as long as the light value is greater than 40%
  while(getLightPercent() > 40) {  }

  // Stop moving now
  bFloatDuringInactiveMotorPWM = false; // brake
  nSyncedMotors = synchNone;   // De-sync the motors.
  motor[motorB] = 0;  // turn the motor off.
  motor[motorC] = 0;  // turn the motor off.
  SensorType[S3] = sensorLightInactive;  // Turn light 'off'
}

MyBlock: Point Turn (Left / Right)

This block will make the robot turn a certain number of degrees,


Parameters

This block has three input parameters:
  1. "Number of Degrees" - Numeric - Allows you to specify the number of degrees for the robot to turn.
  2. "Power" - Numeric - Level of Power to apply to the motors. Values from 0 to +100.

Program


Download this program


Notice how in this block one motor is turning forward while the other motor is turning backward. Both motors turn for a specified number of degrees at a specified power level.

The value to be used for the multiplier is up to you. It depends on the size of the wheels and how far apart they are from each other. So, for example, to get the robot to turn 90 degrees, it may be necessary to get the wheels to turn 400 degrees. This can be figured out using algebra and trigonometry. The "multiplier" is simply a number that represents how many rotations the wheels have to make in order to get the robot to make 1 complete circle.

MyBlock: Turn Left / Turn Right

This MyBlock is used in navigation to make the robot turn.


Parameters

This block has three input parameters:
  1. "Keep Going" - Checkbox - If checked, the robot will not stop abruptly after turning the specified number of degrees.
  2. "Number of Degrees" - Numeric - Allows you to specify the number of degrees for the robot to turn.
  3. "Power" - Numeric - Level of Power to apply to the motors. Values from 0 to +100.

Program


Download

Troubleshooting

  1. If the robot turns in the opposite direction, reverse the sign of the tSteering variable. Please note that if you change the direction of the steering, you may also need to change the direction of the Rotation Sensor.
  2. IF the robot turns too much or too little, adjust the "Multiplier" variable. Increasing the variable will make the robot turn more. Decreasing this variable will make the robot turn less.

Example in RobotC


void TurnRight(int turnDegrees, int power, bool KeepGoing) {
  float targetDegrees = (2 * centerOfWheelToCenterOfRobotMM * PI) /
    wheelCircumference * gearRatio * turnDegrees;
  targetDegrees = targetDegrees + nMotorEncoder[motorB];
  nSyncedMotors = synchBC; //motor B is the master, motor C is the slave
  if(KeepGoing) {
    bFloatDuringInactiveMotorPWM = true;  // coast or float
  } else {
    bFloatDuringInactiveMotorPWM = false; // brake
    nMotorEncoderTarget[motorB] = targetDegrees; // sets a target
  }
  nSyncedTurnRatio = -100; //motors move in opposite directions of one another
  motor[motorB] = power; //turns the motor on at specified power
  while(nMotorRunState[motorB] != runStateIdle &&
    nMotorRunState[motorB] != runStateHoldPosition &&
    nMotorEncoder[motorB] <= targetDegrees) {
    //continue to power motorB until the motor nMotorEncoderTarget position is reached
  }
  if(!KeepGoing) motor[motorB] = 0;  // turn the motor off.
  bFloatDuringInactiveMotorPWM = false; // brake
}

void TurnLeft(int turnDegrees, int power, bool KeepGoing) {
  float targetDegrees = (2 * centerOfWheelToCenterOfRobotMM * PI) /
    wheelCircumference * gearRatio * turnDegrees;
  targetDegrees = targetDegrees + nMotorEncoder[motorC];
  nSyncedMotors = synchCB; //motor C is the master, motor B is the slave
  if(KeepGoing) {
    bFloatDuringInactiveMotorPWM = true;  // coast or float
  } else {
    bFloatDuringInactiveMotorPWM = false; // brake
    nMotorEncoderTarget[motorC] = targetDegrees; // sets a target
  }
  nSyncedTurnRatio = -100; //motors move in opposite directions of one another
  motor[motorC] = power; //turns the motor on at specified power
  while(nMotorRunState[motorC] != runStateIdle && 
    nMotorRunState[motorC] != runStateHoldPosition && 
    nMotorEncoder[motorC] <= targetDegrees) {
    //while motorB is not in an idle state

    //continue to power motorB until the motor nMotorEncoderTarget position is reached
  }
  if(!KeepGoing) motor[motorC] = 0;  // turn the motor off.
  bFloatDuringInactiveMotorPWM = false; // brake
}
If you examine the code above, you may notice that the nSyncedTurnRatio is set to -100 for both Left Turn and Right Turn. You may be wondering how the turning ratio can be the same for turns that seem to turn in opposite directions. The answer, is that the syncronization of the two motors between the Left Turn and Right Turn sets a different motor as the Master for each turn. For example, the Right Turn uses the syncronization: synchBC while the Left turn uses: synchCB. The first motor specified in the synch paramteter is the Master and the other motor turns in the opposite direction based on the turn ratio.

MyBlock: Stop If Close 2

This MyBlock is used in navigation to stop the robot if it gets within a certain number of inches to an object. It is used, for example, to drive to an object and stop.


Parameters

One--the distance to stop before hitting the object. Make sure the robot is already moving before you use this block. This block will not start the robot moving--it only stops it moving.

Program


Download this program

The primary block in this program is the Ultrasonic Sensor. The main Options used for the Ultrasonic Sensor include setting the Criteria to a value passed as an input parameter.

Troubleshooting

  1. Is the robot already moving when you get to this block in the program?
  2. If you are using the Green Move block before the this "Stop If Close 2" MyBlock, make sure you have specified the duration to be "Unlimited".
  3. If you are using a Forward MyBlock, make sure you checked the "Keep Going" box and also specified a distance that is less than the expected object. The Forward MyBlock will get the robot moving with the distance set to just an inch or two. The checked "Keep Going" option will force the robot to continue going forward into the "Stop If Close 2" MyBlock which will allow the robot to continue until it is within the specified number of inches of the Object.

Usage Method 1

Move Block with duration set to Unlimited.


Usage Method 2

Forward MyBlock with "Keep Going" Checked, Distance less than the actual object, and Power set to a certain value.


Example in RobotC


void StopIfCloseTo(float distance_in_inches) {
  float distance_in_cm;  distance_in_cm = distance_in_inches * 2.54;
  while(SensorValue(sonarSensor) > distance_in_cm) {  }
  bFloatDuringInactiveMotorPWM = false; // brake
  nSyncedMotors = synchNone;   // De-sync the motors.
  motor[motorB] = 0;  // turn the motor off.
  motor[motorC] = 0;  // turn the motor off.
}

MyBlock: Accessory

This MyBlock is used to operate and Accessory motor. Please note that the range of motion must be restricted because this block detects a motor stall condition. If the Accessory motor stalls, then the robot will stop applying power to that motor. This block is useful for controlling arms, grabbers, lifters, pinchers, etc.


Parameters

One. Check box allows you to specify whether the motor should move in one direction (if checked) or the other (if un-checked).

Program


Download this program

MyBlock: Follow Line

Line Following is a great task to study programming concepts. There are dozens of different forms of line following programs. A variety of them are shown here. If you have to create a line following MyBlock, make absolutely sure you have looked at the examples on our line following page.

The example shown below is not a pretty or a simple example. It is just an example of how a Line Following program could be contained within a MyBlock function. In the example below, a MyBlock is used to help the robot follow a line. The program is based on the Proportional Line Follower with Constant program.


Parameters

Program


Download this program

Usage
The Power Level is the only required parameter. If no Distance is entered, then the robot will follow the line forever, or, until one of the other criteria is met. If the robot is told to stop within ___ inches of an object, then make sure the Ultrasonic Sensor is used on port four (4). The robot will follow the left side of the line by default. However, if you want the robot to follow the right side of the line, check that option.

Troubleshooting
If the Robot follows the wrong side of the line, try checking (or un-checking) the option to follow the right side of the line.

Tuning
You can adjust the variable in the program for the circumference of the wheel. You can adjust the level of constant power. A level of constant power to the motors helps the robot to move fast around curves and bends. However, if the robot loses the line at curves, then you may need to reduce this parameter.

Example in RobotC


void FollowLine(int power, int distance_to_drive_in_inches,
                int inches_to_stop_before_collision, bool right_side) {
  SensorType[S3] = sensorLightActive;  // Make sure you Turn the light 'on'

  long rotationSensor = 0;
  float targetDegrees;
  rotationSensor = nMotorEncoder[motorB];

  //   WheelCircumference is in millimeters, so, multiply inches by 25.4 to convert to mm.
  targetDegrees = rotationSensor + 
    360 * distance_to_drive_in_inches * 25.4 / wheelCircumference * gearRatio;
  if(distance_to_drive_in_inches>0) {
    // Though not absolutely necessary since the Break action in the main loop
    // will force the robot to stop, it is good to include this target here so 
    // that the robot will slow down to a complete stop at the target distance 
    // and will be less likely to overshoot the target.
    nMotorEncoderTarget[motorB] = targetDegrees;
  }
  // Increase the power by multiplying it by a factor because 1/2 of the power is needed for each motor
  int defaultPower = power * 1.6;
  float currPower = 0;

  // Begin the main loop
  // If no distance_to_drive_in_inches or inches_to_stop_before_collision are specified,
  //   the robot will follow the line forever
  while(true) {
    currPower = getLightPortion() * defaultPower;
    motor[motorB] = currPower;
    motor[motorC] = defaultPower - currPower;

    if(distance_to_drive_in_inches>0) {     // The User specified some distance.  Now check it.
      if(nMotorEncoder[motorC] >= targetDegrees) { break; }
    }
    if(inches_to_stop_before_collision>0) { // 
      float distance_in_cm;  distance_in_cm = inches_to_stop_before_collision * 2.54;
      if(SensorValue(sonarSensor) < distance_in_cm) { break; }
    }
  }
  bFloatDuringInactiveMotorPWM = false; // brake
  // De-sync the motors.  Otherwise they will start moving again even though power is removed.
  nSyncedMotors = synchNone;
  motor[motorB] = 0;  // turn the motors off.
  motor[motorC] = 0;  // turn the motors off.
  SensorType[S3] = sensorLightInactive;  // Turn light 'off'
}