Getting accurate motor performance specs using, kv, and kt

I am trying to figure out the required voltage to send to a motor to stall it at a certain current. Seems simple enough, but I have conflicting data.

My mathematics reasoning is below: has been my primary source of motor specifications, but it only has measured specs at 4V, 6V, 8V, 10V, and 12V. This shouldn't be an issue, though, because also says the following:

Note: VEX Robotics motor curves were made at 12 V. The four key characteristics (free speed / current, stall torque / current) approximately scale proportionally with system voltage. If Motor A was running at 6 V, its stall current would drop from 130 A to 65 A, and its stall torque would drop from 0.7 N · m to 0.35 N · m.

This implies that if I scale specs proportionally with voltage, I should get a “close enough” approximation for how the motor will perform at said voltage.

These are the specs I pulled from the Falcon 500 page of I determined internal resistance by taking 12V / Stall Current (257 amps). kV is determined by Free Speed (6380 rpm) / 12V. kT is determined by Stall Torque (4.69 N-m) / (Stall Current (257 amps) - Free Current (1.5 amps)).

So if I wanted to figure out the motor specs at 4V, for example, I could take the 4 main specs (free speed, stall torque, stall current, and free current) at 12V and divide them by 3 (12/4 = 3) and get the right specifications.

For the Falcon 500, this gives me the following specs:

  • Free Speed: 2126.67 rpm
  • Stall Torque: 1.56 N-m
  • Stall Current: 85.67 Amps
  • Free Current: 0.5 Amps

Now this is fine and dandy, except shows that their dyno testing provides the following specs for a Falcon 500 at 4V:

  • Free Speed: 2110 rpm (very close to the 2126.67 rpm estimate)
  • Stall Torque: 2.15 N-m (Almost 38% higher than the 1.56 N-m estimate)
  • Stall Current: 39 Amps (Only ~45% of the 85.67 Amp estimate)
  • Free Current: 0.6 Amps (Very close to the 0.5 Amps estimate)

Free Speed and Free Current seem pretty much correct, but the difference in Stall Torque and Stall Current are enough to give me a bit of confusion. I asked around to some good friends and was told to use the motor torque constant kT, as that would be a better reflection of how the motor will perform at a given voltage.

I determined kT for the Falcon 500 at 12V by taking the Stall Torque and dividing it by the quantity of Stall Current minus Free Current , which gave me a kT value of ~0.01836. Based on my understanding, for a motor at stall at a given voltage, the output torque of the motor is equal to Voltage * kT / R, where R is the internal resistance of the motor. If I plug in 4V for the voltage and use my kT of 0.01836 and my internal resistance of ~0.047 Ohm, I get and output torque of ~1.56 N-m, which is the same as the estimate from dividing by 3.

My findings lead me to wonder why the VEX test had the stall torque so much higher and the stall current so much lower than the mathematical estimates. I trust VEX’s test results are correct, but they also don’t cover the full range of values that I need, so I need to find a way to formulaically represent the motor specs at given voltages (and vice versa). Normally I would use the mathematical estimates, but these don’t seem to be matching up with VEX’s test results, so I look at one of two options:

  1. I create a best fit line using the test results for each motor spec at 4V, 6V, 8V, 10V, and 12V and determine my approximate performance from a given voltage based on what follows the trend.
  2. I use the mathematical models and assume that they are a safer representation of performance at data points that were not tested by VEX.

Which should I use?


Your numbers line up with what I’ve published on ReCalc. I’ve also run into this issue. I decided to just use the 12v numbers as the single source of truth for the calculators. If anyone cares, the motor model is on Github. I ran into this issue attempting to validate the model, but I hadn’t gotten around to posting about it just yet.

I attempted doing the best fit line option you outline in option 1. The results weren’t very good (subjectively speaking, but what do I know?).


What makes you say the results weren’t very good?

Truthfully I don’t remember the details off the top of my head, and they didn’t have any scientific or mathematical backing besides me getting a little worried about running a linear best fit in order to find “kT at a proprietary voltage”, which should be constant (according to my understanding). I think the majority of why I wound up not doing it is because I don’t understand the problem.

If kT isn’t constant, it introduces a host of other problems.

1 Like

Gotcha. I also found that the kV and kT values were not constant for some reason, with kT on the Falcon 500 having a huge spread. These numbers all come from VEX’s testing at different voltages.

My best fit lines were based off the graphs of the data for the Stall Torque and Stall Current of the brushless motors from

The stall current seemed to closely follow a 2nd degree polynomial while the stall torque was better reflected by a 3rd degree polynomial. I’m not sure if it’s bad practice to just line up what fits best, but since it is a best fit line I thought that would make the most sense. These give me numbers that make sense given the testing results from VEX, but don’t jive well with the theoretical models (because they’re based off the VEX numbers).

1 Like

There is some vaguely related discussion here:

1 Like

That’s some good stuff, thanks for the link! I’ve been contemplating whether it would be worth creating a best fit curve for kV and kT or if that’s going overboard for a simple design calculation. At the end of the day I just wanna have a calculator that gives me numbers that I know will work without being too conservative, but don’t we all? :upside_down_face:

1 Like

@Richard_Wallace is an actual motor subject matter expert…

I don’t think brushless motors follow all the same rules of thumb that brushed motors do, for kT?

1% (Falcon) or 2% (775pro) variation in tested kV seems shockingly good from a lab test results perspective.
I would consider trading all six of my middle toes for my real-world test results to always be that clean.

Are your other calculator inputs (such as loading and friction) accurate to 2%?


I agree that the kV variation is really good. It’s the kT that worries me, primarily for the Falcon.

1 Like

They don’t exactly, but brushless vs brushed alone isn’t enough to account for the discrepancy seen here.

Kt ~ 8.3/Kv, where Kt is in units of [N-m]/[A] and Kv is units of [RPM]/[Volt].

If you instead assume Kt is just ~ 1/(Kv*.1047) with the same units as above, you’ll still end up in right ballpark. (Multiply by ~.1047 converts rotational speed to metric).

For example if you assume the Falcon’s Kv is 520, then Kt calculated from the first and 2nd formula respectively are ~.016 [N-m]/[A] vs ~.018 [N-m]/[A].

Source: Things in Motion: How to estimate the torque of a BLDC (PMSM) electric motor using only its Kv and current draw

Perhaps the differences in Kt at difference voltages is due to using trapezoidal commutation vs sinusoidal/Field Oriented Control. Here’s an excerpt from the link above:

Limitations of this approach

Using KV and a motors current draw to estimate its torque output only works provided that:

  • A motor does not produce any useful reluctance torque (i.e. its a non-salient machine**). This is true for essentially all ‘hobby grade’ electric motors.
  • A motors torque increase linearly with current. This is not true if your motor is close to saturation. However, most ‘hobby grade’ electric motors are designed to operate with a current limit well below that needed to saturate them and so this is generally a safe assumption for stead state use.
  • A motor is operated below its base speed. Operating a motor above its base speed by field weakening effectively lowers a motors KV in that region and so unless you know by how much KV is reduced you can not calculate the torque output. However, since no ‘hobby grade’ motor controllers (ESC’s) that I know of utilise field weakening this is also not an issue.
  • The current waveform supplied by a motor controller exactly matches a motors back EMF waveform (i.e. the current is not exactly on the q-axis at all times). This is generally true when using field oriented control (FOC) on a PMSM motor that has inbuilt position sensors (hall effect, encoder etc.). Operating a motor with ‘six step 120 degree’ commutation at low speed without a position sensor will result in less torque being produced than that predicted using the ‘conversion constant’ while high speed operation should be pretty close.

I posted about very early Neo brushless motor model parameter identification tests back in Nov. '18 when the FRC brushless revolution was just getting under way. Look here.

A couple of posts later in the same thread I took a crack at explaining why brushless motor curves differ from those of brush-type dc motors.

One important challenge when testing to obtain motor performance comparisons is the motor’s internal temperature. As windings get hotter, their electrical resistance increases, thereby limiting the maximum mechanical power they can develop at a given voltage. Heat from the windings is also transported (mostly by convection) to the magnets, which weakens them, limiting the torque that the motor will develop at a given current. These temperature rises, both on the windings and on the magnets, are difficult to account for because they are not easily measured directly – either the coils or the magnets will be spinning, depending on whether the motor is brushless. Stationary coils on a brushless motor are the easier of the two situations to deal with analytically.

Aside from the weight savings, brushless motors have the advantage that the heating effects described above are less significant during a typical FRC match, compared with heating effects in brush type motors. Coils on a brush-type motor’s rotor heat up faster, and cool down more slowly, compared to stationary coils of a brushless motor. The effect is, in rough terms, about 30% less power available from brush motors near the end of a hard-driven FRC match compared to the same motor at the start of the match. Brushless motors lose power due to heating also, but the % change is much smaller.


Richard, what are your thoughts on my problem? Ultimately my goal is to be able to take a voltage and turn that into a decently realistic stall current and stall torque, and be able to take a stall current and turn that into a decently realistic voltage and stall torque.

I’m pretty far out of my depth here trying to get something that matches pretty closely with reality without proper testing equipment, and I’m not sure what the “good enough” point is where extra effort stops being worth the marginal gain in accuracy.

1 Like

Reviving this thread because it came up again in my projects. I’m pretty convinced, on a small data set, that it’s a BLDC issue, if that wasn’t clear already:

It’s pronounced, but not as pronounced, on the NEO 550 as well, but largely not present on any of the 3 brushed motors here.

I also looked at kV, but they were a bit more consistent:

I know the basics of brushed vs brushless, but I’m no EE. I honestly have no idea what’s going on that makes BLDCs inherently more torque-y at lower voltages, as I can’t really find what I’m looking for online (as I’m not entirely sure what to search for…).

On a side note, @Andrew_L I’ve written some code that can iteratively estimate the state of any motor at any current limit given at least 2 pieces of information (out of current, torque, rpm, voltage, or power) and it will auto-complete the rest. I can explain it if you’d like, it’s rather straightforward and isn’t too complicated. I don’t think its portable to a spreadsheet-type environment without some custom scripts though, if that’s what you’re using.


This sounds pretty mfd, Justin. I’m no pro when it comes to code stuff but I’m kinda interested in figuring out how to run it and play around with some subsystem models.

So the way to do it most easily is via a data structure/algorithm (??? its a bit of both) called a rules engine.

I’ve never used one of these before and they’re not super common, but they can be great in niche scenarios like this.

Suppose you have 5 variables, and they can all be calculated based on the others, and you want to calculate whichever of the 5 you don’t provide. In our case, we need two of our 5 (voltage, current, torque, RPM, power). Note that “current” here isn’t current limit, but current draw.

Effectively, we provide the rules engine a set of rules. For example, some rules of our system (but not all):

  1. power = rpm * torque
  2. torque = motor.kT * (current - motor.freeCurrent)

You just basically provide a list of equations that each variable uses to be calculated. Notably, we only have to do this once per equation.

Now, lets say we have an object that represents our motor state. It stores our motor (which has all our constants - kT, kV, stallTorque, etc), our current limit, and 5 optional variables. The optional variables have a ? next to their names. (This is all in Typescript, but the exact language doesn’t matter). By optional, I mean that if they aren’t present, they are undefined (other languages may use null, None, nil, etc). Here, Measurement is just a class I’ve written to help manage units and stuff, it’s nothing super fancy.

type MotorRulesState = {
  motor: Motor;
  currentLimit: Measurement;
  rpm?: Measurement;
  current?: Measurement;
  torque?: Measurement;
  power?: Measurement;
  voltage?: Measurement;

So we have our rules and our incomplete state. We want to effectively feed our state into the engine until no more variables are undefined. So we need to check which variables are defined and which aren’t - so we use something that you could call a condition function.

Each rule has it’s own corresponding condition function. Basically, we are just checking that the variables on the right side of the equation are defined. So for example, the condition function for the rule state.power = state.rpm * state.torque would be

state.rpm !== undefined && state.torque !== undefined

But we also don’t need to double-solve any equations, so we can modify the condition to make sure the left side is undefined:

(state.rpm !== undefined && state.torque !== undefined) && state.power === undefined

So the gist of how it goes is:

  1. Take in an incomplete state
  2. Loop through each condition function
  3. If a condition function is true (eg state.rpm and state.torque are not undefined, and state.power is undefined), go to step 4. Else, go to the next condition function.
  4. Get the corresponding rule, and execute it
  5. Repeat from step 2 until the state is complete

And… that’s it. There are some edge cases you have to do with current limiting and making sure voltages stay in the range of 0-12V, but that’s really it.

For current limiting, you basically check if the current draw went above the limit, and if it did, start over with the given incomplete state but also throw in that the current draw is the current limit. So for example if you gave a state of a Falcon 500 at 12V and 0RPM, you and I both know that’s stall, so the current draw will be high. Say you set a limit of 60A. The code would maybe calculate some other fields but it would realize it would need a current draw of like 250A before any current limiting. So it starts over with a state of 12V, 0RPM, 60A, and calculates the rest from there.

You can also give each rule a priority, and some other stuff to make it run a bit faster and smoother.

Here is the code I use on my site at the moment, in TypeScript, but you won’t be able to run on their own. You could port it to Python or Java or what have you without too much issue, I think. The meat of the code is in Rules.ts. Main.ts is just an example of how I use it in the rest of the project.

Hopefully that all made sense. Happy to do it from a different angle if it didn’t.

Me not understanding something until I thought about it by typing out this post that I'm going to leave up for posterity or something

This is tangentially related to the main topic, but as long as we’re learning about motors I have a question for those more knowledgeable: why does lowering the voltage lower the stall current?

From what little I know about motor modelling, torque is dependent on the force experienced by a current carrying wire in a magnetic field - F=IBL. Using number of active coils and air gap radius to get torque gives T=NIBLR.

Voltage is not present in this equation, so is there something that this simple model does not take into account?

Typing that out made me actually think about it, and I think I realized what I was forgetting - power dissipated by resistance cannot be more than electrical power input. P = I^2 * R cannot exceed P = I * V, and substitution gives V = I * R. Makes sense. Inputting 4V and 0.047 ohms says that stall torque at 4V should be 85.67 amps - the same as calculated in the first post.


Another issue that could be contributing (if not creating) the difference is an implicit assumption that voltage is proportional to throttle setting. For a brushed motor, this is a fair approximation, because in brushed controllers, throttle setting is usually linearly converted to duty cycle [perhaps with a deadband or current limiting], and that becomes an effective voltage because the motor is an inductive load and smooths the voltage. I doubt that brushless controllers generate a voltage proportional to throttle. I guess I could actually measure that A/C voltage easily enough with a Spark Max + NEO*, but not a Falcon.

1 Like

Assuming FRC brushless motors have a trapezoidal back-emf (based off their designation as brushless dc instead of brushless ac, permanent magnet synchronous motor, etc.), voltage across any phase should either be proportional to throttle voltage or 0 (2/3 coils active at a time).

However, even if they generate a sinusoidal back-emf, you may not be able to accurately read it with a typical multimeter. To my knowledge, brushless motor controllers that have a sinusoidal drive shape don’t actually output a sine wave - instead, they use a PWM with varying duty cycle, relying on the inductance of the coils to smooth the signal out to close enough to a true sine wave.

I’ve done some more learning and math and come to conclude that I think VEX has made a typo on non-12V motor dyno curves.

On the Falcon curve:

At 12V, you will see that they are supplying 3085W and 257A. This seems valid, as 12V * 257A ~= 3085W. No issue there.

At 10V, you will see that they are supplying 2215W and 184A. Well we seem to have a problem here, because 10V * 184A is not close to 2215W. But 12V * 184A is 2215W.

At 8V, you will see they are supplying 1515W and 126A. Again, 8V * 126A is not close to 1515W. But 12V * 126A is 1515W.

This continues on for the Falcon, NEO, NEO 550, CIM, Mini CIM, BAG, and presumably other motors that I don’t feel like clicking through.

Presumably, VEX has either measured power and divided by 12 (not voltage) to get current draw, or measured current and multiplied by 12 (not voltage) to get power.

Going back to this, I went in and changed the stall current draw to match “expected” values, rather than VEX’s values. And the problem seems to go away, to some extent:

I’m hoping that someone more knowledgeable in motors than I am can chime in here.


Jumping in here way late and possibly ill informed, but my guess is the recorded currents in the tests are power supply current which isn’t the same as motor (Stator) current. If you are finding the currents seem too low, let’s say 50% lower than expected at 6V, or 2X at 6V depending on where things are measured, then this is probably the culprit.

To add to the confusion, things used to measure current tend to filter and average the readings differently, which is frustrating on its own.

1 Like