Change Motor Port Mid-Program?

Hi everyone,

I was wondering if there was any way to change motor ports in the middle of running a program, or a way to redefine motors after they have already been defined. I know this is a very dumb thing to do under normal circumstances, but it would really help me with my program.

It would help to understand what you are trying to accomplish.

So basically, I’m trying to create a motor config menu on the V5 brain using LVGL. I want to set it up so that you can adjust values on the V5 brain in order to reverse motors and change what port they are assigned to rather than editing the source code, compiling, and uploading it again. Once again, I know this is rather unorthodox, but it’s something that I’ve been wanting to experiment with.

Currently, my solution is to have the motor ports and reverse variables stored in a .ini file on the microSD card. I have already worked out reversing the motors, but not changing ports. I would also like to set it up so that if a microSD card isn’t found, the program would fall back on built-in variables that would be the port numbers. Typing this all out makes me realize how ridiculous this all sounds, but it’s something that I’d really like to achieve.

2 Likes

Since you’ve said LVGL I assume you are using PROS. I know you can say

<motorname>.setreversed(true/false);

To reverse a motor

Maybe ask @hotel for some help. He’s the main PROS person.

The simplest way would be to use the PROS C API.
That way you don’t need to create motor objects, and you can specify the port for each motor move command.

However, if you really want to use the C++ API, this is valid syntax:

Motor motor(3);
motor = Motor(2);
4 Likes

Okay. so I tried this by entering the following:

pros::Motor motor(3);
motor = pros::Motor(4);

However, when trying to compile, I got the following error message:

Compiled src/main.cpp [WARNINGS]
src/main.cpp: In function 'void initialize()':
src/main.cpp:26:24: error: use of deleted function 'pros::Motor& 
pros::Motor::operator=(pros::Motor&&)'
   motor = pros::Motor(4);
   ^
In file included from ./include/api.h:66:0,
             from ./include/main.h:37,
             from src/main.cpp:1:
./include/pros/motors.hpp:26:7: note: 'pros::Motor& pros::Motor::operator=(pros::Motor&&)' is implicitly deleted because the default definition would be ill-formed:
 class Motor {
 ^~~~~
./include/pros/motors.hpp:26:7: error: non-static const member 'const uint8_t pros::Motor::_port', can't use default assignment operator

You should really use the C API.

I believe the above command actually only works with an okapi::Motor, using the latest, unreleased, version of okapilib (v4).

You can try with okapi::Motor in v3, which is the current version.

Okay, thank you for your help!

To expand on using the C++ API, you cannot just “redefine” motors with the syntax @theol0403 mentioned. In both cases, you are calling the constructor for the pros::Motor class, which can only be used to create a new instance of pros::Motor.

What I think would work, however, is predefining a pros::Motor for each port and using pointers to represent each physical motor:

pros::Motor port1(1);
pros::Motor port2(2);
pros::Motor port3(3);
// etc.

pros::Motor* driveMotor;
pros::Motor* clawMotor;
// etc.

void changeMotorPort(pros::Motor* &motor, int newPort) {
  if (newPort == 1)
    motor = &port1;
  else if (newPort == 2)
    motor = &port2;
  else if (newPort == 3)
    motor = &port3;
  // etc.
}

Then you could call, for example, changeMotorPort(driveMotor, 2); and any of your normal motor commands like *driveMotor.move(127); or driveMotor->move(127);.

(I think I got all the syntax correct, but some of it may be wrong)

Note that this is a fairly kludgy solution and I also recommend just using the C API.

If you are seriously going to do this, then, to make it slightly less kludgy, consider using a lookup array in void changeMotorPort() instead of a long series of if statements.


Edit: See @theol0403’s post below

2 Likes

The syntax I mentioned is usually valid. However, pros::Motor has the copy constructor implicitly deleted, whereas okapi::Motor does not. The new instance of the Motor is formed in = Motor(2);, and then it is copied to the target motor so that the previous motor is replaced.

If you really want to use the C++ API, you can also do as @Barin suggests and use pointers.
However, I would do some changes to reduce code bloat.
Warning that using pointers like this can become messy really fast, especially when using dynamic initialization which is what is probably best for this situation:

pros::Motor* driveMotor = nullptr; // always initialize pointers to be NULL
pros::Motor* clawMotor = nullptr;
// etc.

void changeMotorPort(pros::Motor* &motor, int newPort) {
  if(motor) delete motor; // delete previous motor assigned to pointer
  motor = new Motor(newPort);
}

This is the only wrong syntax I spotted. You should always use driveMotor->move(127);, but if you wanted to use the dereference operator, you need to have it in parenthesis

(*driveMotor).move(127);
4 Likes

Once you change what port the motor is in physically you will still need to restart the program to prevent the constant error messages from it detecting that there was once a motor in port # but then it didn’t

I disagree, I don’t think that is a problem.
The warnings come from VEXos detecting that a motor is physically unplugged, it has nothing to do with what the code thinks is plugged in. Changing a motor port in the code does not cause VEXos warnings iirc.

2 Likes

Thank you all for taking the time to come up with solutions for me. However, I believe that using the C API is going to be the best option. You all are clearly better programmers than I am, and if I’m being completely honest, I don’t entirely understand some of these solutions. I’d feel bad for using a solution that someone gave to me without fully understanding it. Thank you all for your help.

2 Likes

I agree it won’t affect the program itself but since he is using PROS LVGL gives constant reoccurring alerts once it has detected a device that was there. With the alerts it would be very challenging to use a GUI or other screen related functions and unfortunately there is no way to turn them off. Luckily a quick program restart would remove the constant alerts.

I didn’t say it wouldn’t affect the program, I said it would not show alerts in the first place.

Only one way to find out, but I don’t think any warnings will show up if a motor port is changed in the code. Again, the alerts are caused by physical unplugging, not changing the port in the code.

Yup, you are right, I successfully set everything up and I only get an error when a motor is physically unplugged.

@theol0403 I agree with you. However the point I am trying to say is that once you change the motor port via the screen and physically the constant LVGL alerts make make the screen unusable. An example would be that you need to change multiple motors. You change it via the screen for all three ports and then you unplug the old motors and replug them into their new ports the screen would be flooded with alerts. Then if you need to change something or choose an Auto program on the screen it will be extremely frustrating with all the alerts.
I hope that helped clarify what I have been trying to convey.