Sylib LED's break field driver control

Apologies for the repost but I realised this should be in the pros section, not the vexcode section. Also added some more details.

I am new to pros and have been using Sylib to control some RGB strips but encountered a problem where driver control wouldn’t run if using field control.
Works perfectly when running the code without the field control.

I did a lot of debugging with a completely fresh pros project and found it stops working when you add the code to create the LED object in driver control.
“auto right_strip = sylib::Addrled(PexpandR, PlightR, length);”

Def’s at top of the code cause I try to be tidy.
#define PexpandL 22 // 22 for built-in
#define PlightL 8 // A = 1 H = 8
int length = 58;

I have tested out every solution I could think of but nothing worked.

For now, I can use my robot without lights in matches but any help to resolve this issue would be greatly appreciated.

1 Like

Can you please send your entire code project?

I should probably add some comments be here it is.
It ain’t the best or the tidiest code out there but this is my first go with the pros.

#include "main.h"
#include <cstdint>
#include <vector>

// Ports
#define Pimu 5
#define Pdrive_left_1 10
#define Pdrive_left_2 9
#define Pdrive_right_1 4
#define Pdrive_right_2 3
#define Pcatta_left 2
#define Pcatta_right 8
#define Pintake 1
#define Pwings 1 // A = 1 H = 8

// Light Strip Left
#define PexpandR 22 // 22 for built in
#define PlightR 7   // A = 1 H = 8
int length = 58;    // Must be int to compaire with. Length of both strips because symetrical

// Light Strip Right
#define PexpandL 22 // 22 for built in
#define PlightL 8   // A = 1 H = 8

void PID(int target, bool left) // true if you want to go left
{
    pros::Imu imu(Pimu);
    pros::Motor drive_left1(Pdrive_left_1);
    pros::Motor drive_left2(Pdrive_left_2);
    pros::Motor drive_right1(Pdrive_right_1, true);
    pros::Motor drive_right2(Pdrive_right_2, true);
    imu.tare_rotation();
    int kp = 2;
    int ki = 8;
    int kd = 27;
    int max = 70;
    int exit_ = 1;
    int exit_time = 5; // times by time step

    int travled = 0;
    int output = 0;
    int cycles = 0;
    int error = 0;
    int p = 0;
    int i = 0;
    int d = 0;
    int error_ = 0; // Last error

    while (true)
    {
        travled = abs(imu.get_rotation());

        // Exit if exit condititons met
        if (travled > (target - exit_) && travled < (target + exit_))
        {
            cycles++;
            if (cycles == exit_time)
            {
                drive_left1 = 0;
                drive_left2 = 0;
                drive_right1 = 0;
                drive_right2 = 0;
                return; // exit pid
            }
        }
        else
        {
            cycles = 0;
        }

        error = target - travled;

        p = kp * error;

        i = i + (ki * (error + error_));

        // Intergral anti windup
        if (i > max)
        {
            i = max;
        }
        else if (i < -max)
        {
            i = -max;
        }

        d = kd * (error - error_);

        output = p + (i / 4) + d;

        // limit max speed
        if (output > max)
        {
            output = max;
        }
        else if (output < -max)
        {
            output = -max;
        }

        error_ = error; // store last error

        if (left)
        {
            drive_left1 = -output;
            drive_left2 = -output;
            drive_right1 = output;
            drive_right2 = output;
        }
        else
        {
            drive_left1 = output;
            drive_left2 = output;
            drive_right1 = -output;
            drive_right2 = -output;
        }

        // printf("T:%d  O:%d\n", travled, output); //Debug code

        pros::delay(10);
    }
}

void move(int distace, int speed)
{
    pros::Motor drive_left1(Pdrive_left_1);
    pros::Motor drive_left2(Pdrive_left_2);
    pros::Motor drive_right1(Pdrive_right_1, true);
    pros::Motor drive_right2(Pdrive_right_2, true);

    drive_left1.move_relative(distace, speed);
    drive_left2.move_relative(distace, speed);
    drive_right1.move_relative(distace, speed);
    drive_right2.move_relative(distace, speed);

    pros::delay(100);

    while (drive_left1.get_actual_velocity() != 0)
    {
        pros::delay(10);
    }

    drive_left1 = 0;
    drive_left2 = 0;
    drive_right1 = 0;
    drive_right2 = 0;
}
/**
 * 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()
{
    // Reset IMU.
    pros::Imu imu(Pimu);
    imu.reset();
    // Initialize sylib background processes
    sylib::initialize();
}

/**
 * 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()
{
    pros::Motor drive_left1(Pdrive_left_1);
    pros::Motor drive_left2(Pdrive_left_2);
    pros::Motor drive_right1(Pdrive_right_1, true);
    pros::Motor drive_right2(Pdrive_right_2, true);
    pros::Motor intake(Pintake, true);

    int speed = 170;

    move(-3100, speed);

    PID(90, true);

    intake = -100;

    pros::delay(900);

    intake = 0;

    drive_left1 = 100;
    drive_left2 = 100;
    drive_right1 = 100;
    drive_right2 = 100;

    pros::delay(700);

    drive_left1 = 0;
    drive_left2 = 0;
    drive_right1 = 0;
    drive_right2 = 0;

    move(-800, speed);

    PID(90, false);

    move(1100, speed);

    PID(90, false);

    move(1500, speed);

    intake = 100;

    pros::delay(500);

    intake = 0;

    move(-300, 70);

    PID(100, false);

    move(1000, speed);

    PID(70, false);

    move(1100, speed);

    intake = -100;

    pros::delay(900);

    intake = 0;

    drive_left1 = 100;
    drive_left2 = 100;
    drive_right1 = 100;
    drive_right2 = 100;

    pros::delay(700);

    drive_left1 = 0;
    drive_left2 = 0;
    drive_right1 = 0;
    drive_right2 = 0;

    move(-800, speed);
}

/**
 * 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()
{
    // Set up devices
    pros::Imu imu(Pimu);
    pros::Motor drive_left1(Pdrive_left_1);
    pros::Motor drive_left2(Pdrive_left_2);
    pros::Motor drive_right1(Pdrive_right_1, true);
    pros::Motor drive_right2(Pdrive_right_2, true);
    pros::Controller master(CONTROLLER_MASTER);
    pros::Motor catta_left(Pcatta_left);
    pros::Motor catta_right(Pcatta_right, true);
    pros::Motor intake(Pintake, true);
    pros::ADIDigitalOut wings(Pwings);

    catta_left.set_brake_mode(MOTOR_BRAKE_COAST);
    catta_right.set_brake_mode(MOTOR_BRAKE_COAST);

    // Create addrled objects for light strips
    auto right_strip = sylib::Addrled(PexpandR, PlightR, length);
    auto left_strip = sylib::Addrled(PexpandL, PlightL, length);

    // Set strips to green to signal forward Drive and ready
    right_strip.set_all(0x008000);
    left_strip.set_all(0x008000);
    // Caliber colour #f47a20 || Version that works on strip #ff6a00

    // Store the time at the start of the loop
    std::uint32_t clock = pros::millis();

    // Vars to keep tract of differnt states
    bool reverse = false;
    bool shoot = false;
    bool wing = false;
    bool rotate = false;
    int rot = 0;
    int left = 0;
    int right = 0;

    while (true)
    {
        if (reverse)
        {
            left = -master.get_analog(ANALOG_RIGHT_Y);
            right = -master.get_analog(ANALOG_LEFT_Y);
        }
        else
        {
            left = master.get_analog(ANALOG_LEFT_Y);
            right = master.get_analog(ANALOG_RIGHT_Y);
        }

        if (left > 100)
        {
            left = round((2.85185185 * left) - 235);
        }
        else if (left < -100)
        {
            left = round((2.85185185 * left) + 235);
        }
        else
        {
            left = round(0.5 * left);
        }

        if (right > 100)
        {
            right = round((2.85185185 * right) - 235);
        }
        else if (right < -100)
        {
            right = round((2.85185185 * right) + 235);
        }
        else
        {
            right = round(0.5 * right);
        }

        drive_left1 = left;
        drive_left2 = left;
        drive_right1 = right;
        drive_right2 = right;

        if (master.get_digital(DIGITAL_R1))
        {
            intake = 100;
        }
        else if (master.get_digital(DIGITAL_R2))
        {
            intake = -100;
        }
        else
        {
            intake = 0;
        }

        if (master.get_digital_new_press(DIGITAL_A))
        {
            wing = !wing;
            wings.set_value(wing);
        }

        if (master.get_digital_new_press(DIGITAL_L1))
        {
            catta_left.move_relative(255, 120);
            catta_right.move_relative(255, 200);
            shoot = true;
        }
        else if (master.get_digital_new_press(DIGITAL_L2))
        {
            catta_left.move_relative(255, 100);
            catta_right.move_relative(255, 100);
            shoot = true;
        }
        else if (master.get_digital_new_press(DIGITAL_DOWN))
        {
            catta_left.brake();
            catta_right.brake();
            catta_left = -40;
            catta_right = -40;
            pros::delay(200);
            catta_left.brake();
            catta_right.brake();
        }

        if (shoot)
        {
            if (catta_left.get_position() > (catta_left.get_target_position() - 10))
            {
                catta_left.brake();
                catta_right.brake();
                catta_left = -50;
                catta_right = -50;
                pros::delay(200);
                catta_left.brake();
                catta_right.brake();
                shoot = false;
            }
        }

        if (master.get_digital_new_press(DIGITAL_B))
        {
            reverse = !reverse;
            if (reverse)
            {
                master.rumble("...");
                right_strip.set_all(0xff6a00); // 0x800000);
                left_strip.set_all(0xff6a00);  // 0x800000);
            }
            else
            {
                master.rumble("-");
                right_strip.set_all(0x008000);
                left_strip.set_all(0x008000);
            }
        }

        if (master.get_digital_new_press(DIGITAL_X))
        {
            right_strip.gradient(0xFF0000, 0xFF0005, 0, 0, false, true);
            left_strip.gradient(0xFF0000, 0xFF0005, 0, 0, false, true);
            rot = 0;
            rotate = true;
            /*catta_left = 100;
            catta_right = 100;
            pros::delay(40);
            catta_left = 0;
            catta_right = 0;
            catta_left.brake();
            catta_right.brake();*/
            // Catta jugle celebration code
        }

        if (rotate)
        {
            if (rot < (2 * length))
            {
                right_strip.rotate(1, false);
                left_strip.rotate(1, false);
                rot++;
            }
            else
            {
                rotate = false;
                if (reverse)
                {
                    right_strip.set_all(0xff6a00); // 0x800000);
                    left_strip.set_all(0xff6a00);  // 0x800000);
                }
                else
                {
                    right_strip.set_all(0x008000);
                    left_strip.set_all(0x008000);
                }
            }
        }

        // 10ms delay to allow other tasks to run
        sylib::delay_until(&clock, 10);
    }

}

Thanks for the help

Hey there quick follow-up.
Just wonder if you have any idea what causing the issue.

No worries if you are busy or can’t help at the moment just wondering if you had any thought :slight_smile:

it may not be your issue, but I had almost the same issue. I use sylib with vexcode so some things may be different. The cause of the issue for me (most likely) was the initialization of the LEDs in driver control and the fact that driver control may be called more than once by the field controller. I solved this by creating a separate thread and initializing it in the beginning but I’m pretty sure there’s a better way in PROS.

here’s Sylvie’s spin up code: GitHub - sy1vi3/5090x-spin-up . In the code they only declare the LEDs once inside of robot.cpp and put it in the header file config.hpp.

Thanks. I think this worked but I only got to test a little before the robot went flat.
I forgot to bring the charger home so I will update you when the robot is recharged.

If I get it to work it may be a good idea for Sylvie to change the example LED project on the site to fix this issue.

Thanks for the help. :slight_smile:
This is gonna make my team’s match’s %Infinite Cooler.

For anyone else with this issue, I fixed the problem by moving the LED creation code outside the main loops instead instead near the top of main.cpp like this.

// Create addrled objects for light strips
// Outside main loops to prevent op control not running
sylib::Addrled right_strip(22, 7, 58);
sylib::Addrled left_strip(22, 8, 58);

If you have multiple files that want to use the light you could make shared functions in main.cpp or have right_strip and left_strip in a .hpp file.

Thanks for the help EcstaticPilot :slight_smile:

This topic was automatically closed 365 days after the last reply. New replies are no longer allowed.