Functions

Functions contain code that can be reused throughout your program, which helps organize complex logic. Think of a function as a program within a program. Parameters specify different input values for your function; they are like a variable but only apply to the function, and they are not global to the rest of the program.

Define

functionEvaluate

Functions can be defined anywhere in a program, but in our examples we prefer to define them above the main loop for consistency. Notice how we actually define them in a separate tab on the block canvas Oval text viewer. This make it extremely simple for novice users to interpret the Oval code without the confusion of functions. You only have a single view in the text canvas so everything will be written in line. See the below very basic blink function example that changes the LED's to red for 2s, then green for 2s:

void blink()
{
    setRgbLed(255, 0, 0);
    delay(2);
    setRgbLed(0, 255, 0);
    delay(2);
}

void startProgram()
{
    blink();
}

Parameters

functionEvaluateParameters Parameters are like variables, but they are local to a function in that they only serve the function; they are not global to the rest of the program. Parameters can be very helpful in quickly changing inputs without modifying the core functionality, or if you want to call a function many times and make changes to the input each time. The below blinkPower example extends blink function by enabling you to quickly control the timeOn, timeOff and loop parameters, so you can call the function with different values each time. If you write this program without parameters it would require 4 times as much code:

float timeOn = 0;
float timeOff = 0;
int loopNum = 0;

void blinkPower (float timeOn, float timeOff, int loopNum)
{
    int _loopCount_1 = 1;
    while (_loopCount_1 < loopNum)
    {
        _loopCount_1 = _loopCount_1 + 1;
        setRgbLed(0, 255, 0);
        delay(timeOn);
		setRgbLed(0, 0, 0);
		delay(timeOff);
    }
	playSound(0, 7);
	delay(0.05);
}

void startProgram()
{
    blinkPower (1.0, 0.5, 3);
    blinkPower (0.25, 0.5, 4);
    blinkPower (0.05, 0.1, 20);
    blinkPower (0.02, 0.05, 40);
}

Notice that after you define a parameter it is added to the predictive fill engine when you call it later:

paramPredict


Example Helper Functions


There are some blocks from the Actions category in the block canvas that are Functions, not pure Oval code. These were used in the block canvas so novice users can easily write fun block programs without worrying about combining complicated commands. Feel free to use these in the text canvas to get started using functions.

Note: These functionsare uniquely recognized with _, but your custom functions do not require that character.

Helper functions, aka libraries, are important because they allow languages to adapt and grow over time, often through the crafty contributions of developers reading documentation like this and imagining cool uses for the technology. Send us your awesome function and maybe we'll add it to the list for others to use!

Roll

actions_roll

_doRoll combines duration, speed and heading to make the robot roll. For example, to have the robot roll for 2s, at 200 speed and 90°, use:

void _doRoll(float duration, float speed, float direction)
{
   if (duration > 0)
   {
     controlSystemTargetYaw = direction;
     controlSystemTargetSpeed = speed;

     float finishTime = currentRobotTime + duration;
     while (currentRobotTime < finishTime)
     {
       wait;
     }
   }
   controlSystemTargetSpeed = 0;
}

void startProgram()
{
  _doRoll(2, 200, 90);
}

Raw Motor

actions_rawMotor

_doRawMotor controls the electrical power sent to the left and right motors independently, on a scale from -4095 to 4095. If you set both motors to full power the robot will jump because stabilization (use of the IMU to keep the robot upright) is disabled when using this command. This is different from Set Speed because Raw Motor sends an "Electromotive force" to the motors, whereas Set Speed is a target speed measured by the encoders. For example, to set the raw motor to full power for 4s, making the robot jump off the ground, use:

void _doRawMotor(float leftMotor, float rightMotor, float duration)
{
   float finishTime = currentRobotTime + duration;
   int controlSystemState = controlSystemIsOn;
   controlSystemIsOn = 0;

   while (currentRobotTime < finishTime)
   {
     leftMotorPwm = leftMotor;
     rightMotorPwm = rightMotor;
     wait;
   }

   controlSystemIsOn = controlSystemState;
   leftMotorPwm = 0;
   rightMotorPwm = 0;
}

void startProgram()
{
    _doRawMotor(4095, 4095, 4)
}

Spin

actions_spin

_doSpin spins the robot for a given number of degrees over time, with 360° being a single revolution. For example, to spin the robot 360° over 1s, use:

void _doSpin(float numDegrees, float duration)
{
   if (duration > 0)
   {
     float speed = numDegrees / duration;
     float currentTime = currentRobotTime;
     float finishTime = currentTime + duration;
     while (currentTime < finishTime)
     {
       float newTime = currentRobotTime;
       float dTime = newTime - currentTime;
       if (dTime > 0)
       {
         float newYaw = controlSystemTargetYaw + (speed * dTime);
         while (newYaw > 360.0)
         {
           newYaw = newYaw - 360.0;
         }
         controlSystemTargetYaw = newYaw;
       }
       currentTime = newTime;
       wait;
     }
   }
}

void startProgram()
{
    _doSpin(360, 1)
}

Fade

actions_fade

_doFade changes from one color to another over a period of seconds. For example, to fade from green to blue over 2s, use:

void _doFade(float startingR, float startingG, float startingB, float fadeTime, float endingR, float endingG, float endingB)
{
   float startTime = currentRobotTime;
   float blend = 0.0;
   int done = false;

   if (fadeTime <= 0.0)
   {
     done = true;
   }

   while (not done)
   {
     blend = ((currentRobotTime - startTime) / fadeTime);
     if (blend > 1.0)
     {
       blend = 1.0;
     }

     redLed = ((startingR * (1.0 - blend)) + (endingR * blend));
     greenLed = ((startingG * (1.0 - blend)) + (endingG * blend));
     blueLed = ((startingB * (1.0 - blend)) + (endingB * blend));

     if (currentRobotTime >= (startTime + fadeTime))
     {
       done = true;
     }

     wait;
   }
   setRgbLed(endingR, endingG, endingB);
}

void startProgram()
{
    _doFade(39, 255, 152, 2, 26, 9, 255)
}

Strobe

actions_strobe

_doStrobe blinks the main LED lights for a period of seconds and repeats for a count of cycles. A short period creates a fast blink whereas a long period creates a slow blink. For example, to strobe green for 2s, for a count of 15 cycles, use:

void _doStrobe(float r, float g, float b, float period, int count)
{
   int strobeCount = 0;
   float lastTime = currentRobotTime;
   int on = false;
   while (strobeCount < count)
   {
     if (currentRobotTime >= (lastTime + period))
     {
       if (on)
       {
         setRgbLed(0, 0, 0);
         on = false;
         strobeCount = strobeCount + 1;
       }
       else
       {
         setRgbLed(r, g, b);
         on = true;
       }

       lastTime = currentRobotTime;
     }
     wait;
   }
}

void startProgram()
{
    _doStrobe(39, 255, 152, 2, 15)
}

Configure Scheduler

configureScheduler(schedulerId, float delay, float startTime, int &callbackFunctionPointer) allows you to set a timer that will regularly call a function based on the below parameters:

int schedulerId is a unique value for the scheduler. If you use more than one schedule, you need to ensure each has a unique value. You can name them 1, 2, 3 etc. for simplicity.

float delay is the time period in seconds between each cycle.

float startTime is the time period in seconds after starting the program when the scheduler begins.

int &callbackFunctionPointer is the name of the function you want to call. You must include the & character and define your function before using the scheduler.

For example, to call the below updateColor function repeatedly for the duration of the program use:

int isWhite = false;

void setWhite() {
    setRgbLed(255, 255, 255);
    isWhite = true;
}

void setBlack() {
    setRgbLed(0, 0, 0);
    isWhite = false;
}

void updateColor() {
    if (isWhite) {
        setBlack();
    }
    else {
        setWhite();
    }
}

void startProgram()
{
    configureScheduler(1, 0.25, 1.0, &updateColor);
}

You can turn a schedule off by using:

configureScheduler(1, 0, 0, -1);