purduesigbots / pros

Source code for PROS kernel: open source C/C++ development for the VEX V5 microcontroller
https://pros.cs.purdue.edu
Other
256 stars 76 forks source link

Optical Sensor's "set_integration_time" causes unpredictable behavior with "set_led_pwm" #579

Open Iogician opened 1 year ago

Iogician commented 1 year ago

Expected Behavior:

The Optical Sensor's LED should light up when I set the LED's PWM to 100, and should turn off when I set the LED's PWM to 0, regardless of whether or not I have used the function "set_integration_time".

Actual Behavior:

The Optical Sensor's LED does not light up at all if I use set_integration_time with a parameter other than 100 while using set_led_pwm afterwards. Even if I use the parameter 100 with set_integration_time, the Optical Sensor's LED will be stuck permanently at 100% power after the first time I use set_led_pwm. Avoiding set_integration_time altogether allows set_led_pwm to work as expected.

Steps to reproduce:

Use set_integration_time with any valid parameter (3 ms - 712 ms). Then, try to dynamically change set_led_pwm. For example, you could have the PWM change from 0 to 100 at the press of a button, which was my use case.

System information:

Platform: V5 PROS Kernel Version: 3.8.0

aberiggs commented 11 months ago

Haven't been able to reproduce. Not closing yet, but leaving a note.

aberiggs commented 11 months ago

How I attempted to reproduce the issue:

#include "main.h"

/**
 * A callback function for LLEMU's center button.
 *
 * When this callback is fired, it will toggle line 2 of the LCD text between
 * "I was pressed!" and nothing.
 */
void on_center_button() {
    pros::Optical optical(1);

    static bool pressed = false;
    pressed = !pressed;
    if (pressed) {
        optical.set_led_pwm(100);
    } else {
        optical.set_led_pwm(0);
    }
}

void on_left_button() {
    pros::Optical optical(1);

    static bool pressed = false;
    pressed = !pressed;
    if (pressed) {
        optical.set_integration_time(100);
    }
}

/**
 * Runs initialization code. This occurs as soon as the program is started.
 *
 * All other competition modes are blocked by initialize; it is recommended
 * to keep execution time for this mode under a few seconds.
 */
void initialize() {
    pros::lcd::initialize();
    pros::lcd::set_text(1, "Hello PROS User!");

    //pros::lcd::register_btn1_cb(on_center_button);
    //pros::lcd::register_btn0_cb(on_left_button);
}

/**
 * Runs while the robot is in the disabled state of Field Management System or
 * the VEX Competition Switch, following either autonomous or opcontrol. When
 * the robot is enabled, this task will exit.
 */
void disabled() {}

/**
 * Runs after initialize(), and before autonomous when connected to the Field
 * Management System or the VEX Competition Switch. This is intended for
 * competition-specific initialization routines, such as an autonomous selector
 * on the LCD.
 *
 * This task will exit when the robot is enabled and autonomous or opcontrol
 * starts.
 */
void competition_initialize() {}

/**
 * Runs the user autonomous code. This function will be started in its own task
 * with the default priority and stack size whenever the robot is enabled via
 * the Field Management System or the VEX Competition Switch in the autonomous
 * mode. Alternatively, this function may be called in initialize or opcontrol
 * for non-competition testing purposes.
 *
 * If the robot is disabled or communications is lost, the autonomous task
 * will be stopped. Re-enabling the robot will restart the task, not re-start it
 * from where it left off.
 */
void autonomous() {}

/**
 * Runs the operator control code. This function will be started in its own task
 * with the default priority and stack size whenever the robot is enabled via
 * the Field Management System or the VEX Competition Switch in the operator
 * control mode.
 *
 * If no competition control is connected, this function will run immediately
 * following initialize().
 *
 * If the robot is disabled or communications is lost, the
 * operator control task will be stopped. Re-enabling the robot will restart the
 * task, not resume it from where it left off.
 */
void opcontrol() {
    pros::Controller master(pros::E_CONTROLLER_MASTER);
    //pros::Motor left_mtr(1);
    //pros::Motor right_mtr(2);
    pros::Optical optical(6);

    while (true) {
        pros::lcd::print(0, "%d %d %d", (pros::lcd::read_buttons() & LCD_BTN_LEFT) >> 2,
                         (pros::lcd::read_buttons() & LCD_BTN_CENTER) >> 1,
                         (pros::lcd::read_buttons() & LCD_BTN_RIGHT) >> 0);
        // int left = master.get_analog(ANALOG_LEFT_Y);
        // int right = master.get_analog(ANALOG_RIGHT_Y);

        // left_mtr = left;
        // right_mtr = right;

    /*
    int leftbtn = (pros::lcd::read_buttons() & LCD_BTN_LEFT) >> 2;
        if (leftbtn == 1) {
            printf("Left btn pressed\n");
            optical.set_integration_time(3);
            optical.set_led_pwm(100);
            optical.set_integration_time(10);
        } else {
            optical.set_led_pwm(0);
        }
    */
        optical.set_integration_time(50);
        bool R1 = master.get_digital(pros::E_CONTROLLER_DIGITAL_R1);
        if (R1) {
            optical.set_led_pwm(100);
        } else {
            optical.set_led_pwm(0);
        }

        pros::delay(20);
    }
}