cortex motor speed testing

  1. 6 years ago

    jpearman

    20 May 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888
    Edited 2 years ago by jpearman

    When testing motors to determine their speed-torque curves in this thread , it has been noticed that motors are reaching their maximum unloaded speed before the maximum possible control value. This can be seen in this post where there is a graph of control values to output speed.

    These tests above were done using port 9 on the cortex and an external motor controller 29. This port (as we know) is different to ports 1 & 10 as the output is a RC style servo control signal that has a nominal pulse width of 1.5mS when a motor speed of 0 is requested. The spec for this type of signal usually has the width of the pulse varying between 1.0mS and 2.0mS to move a servo from one end of it's range to the other.

    Using an oscilloscope the pulse width on the input to the motor controller 29 was measured and the following results found.

    control value		pulse width
    -127			864uS
    -100			1.0mS
       0			1.5mS
     100			2.0mS
     127			2.14mS

    Here are the same pulses on the oscilloscope (a composite image)

    RCpwm_comp.jpg

    I also looked at the output of the motor controller 29 and observed that as the control value passed 84 the output reached maximum duration. This is easiest done with a resistive load rather than a real motor. (ie. replace the motor with a suitable resistor).

    This is illustrated in this scope composite.

    RCpwm_out_comp.jpg

    So from the above we conclude the following.

    1. A control value of 100 corresponds to a pulse width of 1.5mS on the inout to the motor controller, this is nominally the maximum motor speed.

    2. The motor controller 29 has a maximum output with slightly less than the theoretical 1.5mS pulse input, somewhere around 1.42mS or a control value of 84.

    While I was doing this I also wanted to compare the difference between a resistive load and the motor (which is both inductive and resistive) as the load. Here is a scope composite with both shown. The control value here is only 20 but this causes the motor to run at about half speed (no load). The lower trace shows a back emf voltage that could theoretically be measured to determine motor speed.

    RCpwm_bemf_comp.jpg

    One final test was done to compare the speed for a given control value on port 10 to the speed from port 9. A control value of 20 was sent and the rpm of the unloaded motor measured. port 10 was found to be at 44rpm, port9 was at 56rpm, a significant difference.

    So the final conclusion from these tests is that a motor on a 3 wire port will not run at the same speed as a motor on a 2 wire port.

    All of the previous tests were done with master firmware 3.21 and ROBOTC V3.08. EasyC V4.1.0.3 was spot checked and produced the same results. I also reverted back to both 3.16 firmware and 2.81 firmware (not a good idea, what a pain) and everything was the same as far as I could tell.

  2. jgraber

    21 May 2012 Dallas Texas metroplex

    @jpearman
    One final test was done to compare the speed for a given control value on port 10 to the speed from port 9. A control value of 20 was sent and the rpm of the unloaded motor measured. port 10 was found to be at 44rpm, port9 was at 56rpm, a significant difference.

    So the final conclusion from these tests is that a motor on a 3 wire port will not run at the same speed as a motor on a 2 wire port.

    Was this the same motor?
    Did I miss the slide showing the pwm is the same for ports 9,10 with the same control value sent?

    A motor on a #9 3-wire port will run the same speed as
    a motor on a #10 2-wire port if they are mechanically linked.

    Performance under load may be more similar, or may not be.

    I maintain that any two motors (unlinked, openloop) will not run the same speed, even if you run them off a Y cable from the same port.
    This is either trivially true (insignificantly difference), or significantly true.
    Corollary 1: If you want two motors to run at same speed, close the loop or link them.

  3. jpearman

    21 May 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @jgraber Was this the same motor?
    Did I miss the slide showing the pwm is the same for ports 9,10 with the same control value sent?

    Yes, all testing was done with the same motor.

    There was not a slide for the 2 wire port, I only reference the motor speed, although I have looked at it with the scope and verified that it changes up to the maximum control value of 127.

    Performance under load may be more similar, or may not be.

    This may be true, I don't have a suitable setup to be able to test this yet.

  4. jgraber

    21 May 2012 Dallas Texas metroplex

    @jpearman Yes, all testing was done with the same motor.

    There was not a slide for the 2 wire port, I only reference the motor speed, although I have looked at it with the scope and verified that it [the chopped DC PWM of port 10; jg] changes up to the maximum control value of 127.

    So port9+mc#29 vs port10 motor speeds are different primarily because the PWM are different.
    Is it likely that this is an abberation in your example mc#29?
    Probably not, since there was another similar non-linearity report.

  5. Paul Copioli

    21 May 2012 Event Partner Heath, TX

    The MC29 is definitely non-linear in the same way the Victor Speed controller is non-linear. Similar PWM-to-Duty Cycle code was used for both controllers.

  6. jpearman

    21 May 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @jgraber So port9+mc#29 vs port10 motor speeds are different primarily because the PWM are different.

    ports 1 & 10 are driven from the user processor by EasyC or ROBOTC, a value of 64 is converted to a pwm waveform with a 50% duty cycle. They use a hardware timer for this purpose (timer4 if anyone cares).

    ports 2 through 9 have two characteristics that are different. First the scale for neutral RC pwm to full speed pwm is 0 to 100 control values so 64 is mapping to somewhere around 1.82mS instead of a theoretically correct value of 1.75mS (halfway between 1.5 and 2.0). Secondly, the MC29 has a deadband so that full speed motor output occurs with an input pulse width somewhere around 1.92mS rather than 2.0mS. This means that overall a control value of 64 will give a pwm duty cycle nearer to 76%. (all this is theory, I did not actually measure). Looks like I do need to compare speed vs control for port 10 after all.

    Please bear in mind that this is mostly an academic discussion, we have all been mixing motors on different ports with no side effects and controlling speeds without knowledge (except for a select few) that the control to speed mapping is non linear. A lot of student code I see even has digital motor control, either full speed or off :)

    Is it likely that this is an abberation in your example mc#29?
    Probably not, since there was another similar non-linearity report.

    It seems unlikely.

  7. jpearman

    25 May 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888
    Edited 2 years ago by jpearman

    I realized that I did not actually post a graph of the difference between unloaded motor speed for a cortex 2 wire port vs a servo port, so here it is, same motor tested on port 9 using a MC29 and then port 10.

    motor_control_speed_2.jpg

  8. LegoMindstormsmaniac

    3 Jun 2012 Owings Mills, Maryland BNS

    @jpearman I realized that I did not actually post a graph of the difference between unloaded motor speed for a cortex 2 wire port vs a servo port, so here it is, same motor tested on port 9 using a MC29 and then port 10.

    [image snip]

    Are you planning on creating a similar graph for the 2-Wire Motor 393? I was going to create one myself, but yours look very pretty and I was simply wondering what your plan was.

    ~Jordan

  9. jpearman

    3 Jun 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @LegoMindstormsmaniac Are you planning on creating a similar graph for the 2-Wire Motor 393? I was going to create one myself, but yours look very pretty and I was simply wondering what your plan was.

    ~Jordan

    I don't really have a plan, I can repeat the test sometime when I get my hands on a 393 (they are all at the school, I only have 269's at home) but I'm not expecting any significant difference as the speed profile is determined by the MC29 and internal H-Bridge control far more than the motor.

    If you want I can post the test code I used and you can do your own tests. More significant will be repeating with the motor under various loads but that is on the back burner as well.

  10. LegoMindstormsmaniac

    3 Jun 2012 Owings Mills, Maryland BNS

    @jpearman I don't really have a plan, I can repeat the test sometime when I get my hands on a 393 (they are all at the school, I only have 269's at home) but I'm not expecting any significant difference as the speed profile is determined by the MC29 and internal H-Bridge control far more than the motor.

    If you want I can post the test code I used and you can do your own tests. More significant will be repeating with the motor under various loads but that is on the back burner as well.

    Okay, thank you. The code would be great to have and yes, I was planning on trying the test with various loads, as well.

    Thanks!
    ~Jordan

  11. jpearman

    3 Jun 2012 Moderator, ROBOTC Tech Support, V5 Beta Moderator Los Angeles 8888

    @LegoMindstormsmaniac Okay, thank you. The code would be great to have and yes, I was planning on trying the test with various loads, as well.

    Thanks!
    ~Jordan

    Here, to do with as you like.

    #pragma config(UART_Usage, UART1, VEX_2x16_LCD, baudRate19200, IOPins, None, None)
    #pragma config(I2C_Usage, I2C1, i2cSensors)
    #pragma config(Sensor, I2C_1,  ,sensorQuadEncoderOnI2CPort,, AutoAssign)
    #pragma config(Motor,  port9,  ,tmotorVex269, openLoop, encoder, encoderPort, I2C_1, 1000)
    #pragma config(Motor,  port10, ,tmotorVex269, openLoop)
    //*!!Code automatically generated by 'ROBOTC' configuration wizard               !!*//
    
    /*-----------------------------------------------------------------------------*/
    /*  Code to ramp motor values from -128 to 128 while measuring speed with an   */
    /*  IME.                                                                       */
    /*  James Pearman, May 2012                                                    */
    /*-----------------------------------------------------------------------------*/
    
    // global for measured motor rpm
    float   rpm;
    
    // delay between new speeds sent to the motor in units of 50mS
    #define TESTDELAY      40
    
    // encoder counts depending on motor
    #define TICKS_PER_REV_269  240.448
    #define TICKS_PER_REV_393S 392
    #define TICKS_PER_REV_393T 627.2
    
    // uncomment as necessary depending on the motor
    #define TICKS_PER_REV      TICKS_PER_REV_269
    //#define TICKS_PER_REV      TICKS_PER_REV_393S
    //#define TICKS_PER_REV      TICKS_PER_REV_393T
    
    // calculate motor rpm for motor
    task calcSpeed()
    {
        static  int delayTimeMs = 500;
    
        long enc;
        long oldenc;
        float delta;
    
        while(1)
            {
            // Get encoder value
            enc = nMotorEncoder[port9];
    
            // calculate encoder delta
            delta  = enc-oldenc;
            oldenc = enc;
    
            // calculate the rpm for a 269 motor
            rpm = (1000.0/delayTimeMs) * delta * 60.0 / TICKS_PER_REV;
    
            // wait
            wait1Msec(delayTimeMs);
            }
    }
    
    // check a joystick button
    int CheckJoystickButton(TVexJoysticks button)
    {
        if( vexRT[ button ] == 1 )
            {
            // wait for button release
            while( vexRT[ button ] == 1 )
                wait1Msec(10);
            // action
            return(1);
            }
        return(0);
    }
    
    // button check for full speed
    int speedFull()
    {
        return( CheckJoystickButton( Btn8U ));
    }
    // button check for starting the test
    int startTest()
    {
        return( CheckJoystickButton( Btn8D ));
    }
    // Button check for all stop
    int AllStop()
    {
        return( CheckJoystickButton( Btn8R ));
    }
    
    // set speed for motors on port9 and port10
    void SetMotor( int speed )
    {
        motor[port9]  = (abs(speed) > 127) ? sgn(speed) * 127 : speed;
        motor[port10] = (abs(speed) > 127) ? sgn(speed) * 127 : speed;
    }
    
    // main entry point
    task main()
    {
        int    testRunning = 0;
        int    testSpeed   = 0;
        int    testCounter;
        int    speed;
        string str;
        
        // LCD backlight on
        bLCDBacklight = true;
     
        // start motor rpm calculation task
        StartTask( calcSpeed );
        
        clearLCDLine(0);
    
        // run forever.
        while(1)
            {
            // run full speed for testing
            if( speedFull() )
                {
                speed = 128;
                SetMotor( speed );
                }
                
            // stop everything
            if( AllStop() )
                {
                speed = 0;
                SetMotor( speed );
                testRunning = 0;
                }
    
            // start gathering data
            if( startTest() )
                {
                testCounter = TESTDELAY;   // send first value immeadiately
                testSpeed   = -128; // will be truncated to -127 by ROBOTC
                testRunning = 1;    // start test
                }
    
            // Is the test running ?
            if( testRunning )
                {
                // New speed every 2 seconds
                if( testCounter++ >= TESTDELAY )              
                    {      
                    // reset delay counter
                    testCounter = 0;
                    
                    // use test speed
                    speed = testSpeed;               
                    
                    // are we done ?
                    if(testSpeed > 128 )
                        {
                        testRunning = 0;
                        speed = 0;
                        }
                    else
                        // inc test speed
                        testSpeed += 4;
                    }
                }
            else
                {
                // use 128 to override joystick
                if( speed < 128 )
                    speed = vexRT[ Ch1 ];
                }
              
            // update motors
            SetMotor( speed );
    
            // display what's going on
            sprintf(str, "%4d , %6.2f", speed, rpm);
            displayLCDString(0, 0, str);
    
            // display results just before we send a new value
            if( testRunning && testCounter == (TESTDELAY-1) )
                writeDebugStreamLine(str);
              
            // wait 50mS
            wait1Msec(50);
            }
    }
 

or Sign Up to reply!