Lesson 9 - Modulo

Modulo Operator - The Basics


If division is the peanut butter, modulo is the jelly of… um… math?


Modulo, often represented by %, divides two numbers and returns the absolute value of the remainder. For example:


Operation

Computation / Remainder

Result

4 % 2

4 / 2 = 2 

Remainder = 0

4 % 2 = 0

3 % 2

3 / 2 = 1

Remainder = 1

3 % 2 = 1

3 % -2

3 / -2 = 1

Remainder = 1

3 % -2 = 1

3 % 4

3 / 4 = 0

Remainder = 3

3 % 4 = 3


To test out more values use this link, or just use the code below!


Modulo Operator - VEX Usages


The modulo operator is commonly used for toggles during driver control. For example, let’s say I wanted my intakes to spin indefinitely when I tapped and released the front left bumper (L1). To stop the intakes, I want to simply press button L1 again. The code would look like this:


pros::Controller controller(CONTROLLER_MASTER);
pros::Motor intake(PORT_NUMBER);

void opcontrol() {
    int count = 0;
   
    while (true) {
        if(controller.get_digital_new_press(DIGITAL_L1)){
            count = count + 1;
        }

        if(count % 2 == 1){
            intake.move(127);
        }
        else if (count % 2 == 0){
            intake.move(0);
        }
       
    }
}


NOTE: “get_digital_new_press” is only a PROS method. It differs from the normal “get_digital” because “get_digital_new_press” only returns true on a new press. That is to say, if I use “get_digital_new_press” and hold down the button, it’ll only return true once. It would only return true again if I released the button and then pressed it again. However, if I were to use “get_digital” it would constantly return true. “get_digital_new_press” uses a concept called rising edge which will be explained later.


This toggle works because any odd numbers divided by 2 returns a remainder of 1 and any even numbers divided by 2 returns a remainder of 0. Because the code increases the integer count by 1 with every press of L1, it switches the count integer from even to odd or vice versa, thereby switching the toggle.


Rising Edge



Whenever a button is pressed on the VEX V5 Controller, a digital signal event occurs. The signal rises (the rising edge) when the button is pressed and stays up for as long as the button is held. Once released, the signal falls (the falling edge). “get_digital_new_press” above only turns true when the signal is rising, meaning even if the signal is at its peak, it returns false. In other words, “get_digital_new_press” only returns true once per button press.


On the other hand, “get_digital” returns true the whole time the signal is at its peak. That means if you hold the button down, you get a lot of “true’s”. For toggles, it is important to use a rising edge counter like “get_digital_new_press” instead of “get_digital” because if you were to use “get_digital” the toggle would flip back and forth multiple times per button press.


If your programming software doesn’t have a rising edge counter method like “get_digital_new_press” you can write your own like this:


bool risingL1(){
    if(controller.get_digital(DIGITAL_L1) && pressed == false){
        pressed = true;
        return true;
    }
    else if(!controller.get_digital(DIGITAL_L1)){
        pressed = false;
        return false;
    }
    else{
        return false;
    }
}


NOTE: You could replace the button (replace all the L1) and it would work for any button!


With our “home-style” rising edge counter, you could write what we previously wrote as:

if(controller.get_digital_new_press(DIGITAL_L1)){
            count = count + 1;
}

And now write it as:

if(risingL1()){
            count = count + 1;
}


NOTE: Make sure to declare the risingL1 function outside of the while loop and before driver control.