VCS open loop motor control

It may be a couple more weeks before we release an updated SDK for VCS with open loop motor control. So in the meantime I’m going to post some code that the more advanced teams can use who really want to turn off the PID control in the V5 motor and control it more directly. Use at your own risk, I haven’t tested using lots of open loop control along with methods such as rotateTo which will turn PID back on.

To keep some forwards/backwards compatibility the best way to approach this is to use a sub class of vex::motor and add one new method that takes the same parameters as we will have in the next SDK version.

// sub class motor to add new method
namespace vex {
  class motor_special : public motor {
    private:
      uint32_t  _local_index;

    public:
      motor_special( int32_t index ) :  motor( index ), _local_index(index) {};  
      ~motor_special() {};

      // Allow overloading of base class methods
      using motor::spin;
      
      // This is similar, not quite the same, as new a method in the next (Nov ?) SDK release
      // voltage can be +/-12.0 volta or +/-12000 mV
      void spin( directionType dir, double voltage, voltageUnits units ) {
        // convert volts to mV is necessary
        int32_t voltage_mv = (units == voltageUnits::volt ? voltage * 1000.0 : voltage );

        // flip based on direction flag
        voltage_mv = (dir == directionType::fwd ? voltage_mv : -(voltage_mv) );

        if( voltage_mv == 0 ) {
          stop();
        } else {
          // send mV value to control motor open loop
          vexMotorVoltageSet( _local_index, voltage_mv );
        }
      }
  };
}

you would then create an instance of a motor using the new class, for example

motor_special Motor1( vex::PORT1 );

The new method can be called like this.

Motor1.spin( directionType::fwd, 2.0, voltageUnits::volt );

or this


Motor1.spin( directionType::fwd, 2000, voltageUnits::mV );

they are equivalent

to send values directly from the controller, you would need to rescale controller axis values like this.


while(1) {
    double v = (double)Controller1.Axis1.value() * 12.0 / 127;
    Motor1.spin( directionType::fwd, v, voltageUnits::volt );
    this_thread::sleep_for(20);
}

I will attach a VCS demo

To use with VEX C++ you would need to create either additional instances of your motors or abandon using the config screen at all. This cannot be used with blocks programming.
motor_open_loop_control_pro.vex (5.5 KB)

3 Likes

Thank you so much @jpearman !!! I was hoping to better tune a PID for my teams flywheel, I was actually considering switching to PROS just for motor voltage control. Now I don’t have to transfer all my code :slight_smile: . To use an open source PID controller like MiniPID , what’s your best way to impliment the code in VCS? The proper way would be to add the header file and cpp file for MiniPID, and then include the miniPID .h file in my main .cpp file, but that’s not currently possible in VCS. I suspect you have to merge the .h and c++ files into my files, but I’m not quite skilled in c++ to know how to go about doing that.

1 Like

When using the direct voltage control commands, will the motor override this value if it starts to overheat?

Few comments
1.you can tune the pid loop on the motor
https://pros.cs.purdue.edu/v5/api/cpp/motors.html#convert-pid

  1. Any loop you write will run at a slower refresh rate than the loop inside the motor

  2. The ri3d I made worked great with the built in PID for flywheel

1 Like

yes

1 Like

Hello, I was trying to implement this in the Robot Mesh API. I was able to fix all the errors that I got in doing so except for this one. Can anyone help?

C:\V5 Programs\robot_config OS1.h: In member function ‘void vex::motor_special::spin(vex::directionType, double, vex::analogUnits)’:C:\V5 Programs\robot_config OS1.h:38:56: error: ‘vexMotorVoltageSet’ was not declared in this scope
vexMotorVoltageSet( _local_index, voltage_mv );
^

@1320D_Programmer Though RMS’s and VCS’s APIs appear similar on the surface, they are built on two different implementations. What James has posted is a way to get at a method that is a protected method of VCS’s motor class, whereas the method in question does not currently exist at all for RMS’s motor class, even in a protected form.

That being said, look for it in an upcoming release, as we do plan to add support for it. Initially it was a ways down the list on development priorities, but now its turn is nigh.

1 Like

yea, not exactly.
Just add this at the top of your program after #include “vex.h”


extern "C" {
    void vexMotorVoltageSet( uint32_t index, int32_t value );    
}
namespace vex {
  enum class voltageUnits {
    volt,
    mV
  };
}

That should let it build.

1 Like

Well yes, if you extend our API and then forcibly call outside of it the function does exist in the VEXos layer. And now that I take another look, it looks like VCS exposes that layer without documenting it? I had assumed it was a parent class’ method on first glance.

@jpearman If i implement the open loop motor control in VCS, I assume that the built in PID control can no longer be used for that motor? It is one or the other, correct? And also, can the brake, hold and coast be used?

You would be able to in the same program alternate between PID control and open loop motor control. Whatever command you sent most recently is the one that will happen.

@jpearman Does it matter that my Flywheel is running a speed ratio rather than a standard ratio? Would this code still work the same or would I need to add something? If so, what would I need to add?