Trial and Error PID

Yes, that is an important caveat to this discussion. There will be difference in how motor would behave under the load vs being run idle (where the only mechanical load is the friction in their internal components).

See this thread: cortex motor speed testing - Technical Discussion - VEX Forum

Also, using resistor instead of the motor, removes not only back EMF but also the ability of the motor to store additional energy in the inductive component of it windings.

There must be multiple causes for the control-value-vs-resulting-speed curve not being linear but, I believe, a lot of non-lineriarity comes from the interaction between the power capacitor inside the MC29 (C7 in the image below) and the motor’s inductive component.

When there is little or no external load, the supplied energy only needs to go toward overcoming internal motor resistance and friction, which is not much. So, when H-Bridge connects C7 cap to the motor windings it takes very little time to transfer energy from one (cap) to another (windings). Then when H-Bridge disconnects, C7 recharges from Cortex’s battery at a leisurely pace, while energy stored in the motor’s inductive components is being converted into mechanical energy. (Leaving out extra complexities due to triple winding of the brushed DC motor).

I wish I had equipment to test this while varying the value of C7 and/or dynamic load on the motor. NbN would have been a good year to do this test, with everybody having flywheel geartrains with varying degrees of friction as the mechanical load.

The more external load you put on the motor the flatter the curve should become. And it will reach max speed not around 90 but much higher. (Edit: see post below)

If I recall correctly, when we were tuning Flywheel PID for NbN robot, the output speed was changing all the way to the power level ~115 with our setup.