Unexpected Motor Current Increments
-
While troubleshooting my extruder motor (NEMA 14, 1A), I noticed that M906 E# does not necessarily provide the desired motor current. In general, I noticed the actual motor current (measured using a Fluke i30s AC/DC current clamp) increased at ~100mA intervals with a minimal motor current of ~85mA. Here's a list of measured values I got with its given M906 to better explain the dilemma.
@ E1000, Readings: 985 mA ± 3mA
@ E950, Readings: 873 mA ± 2mA
@ E900, Readings: 873 mA ± 2mA
@ E850, Readings: 782 mA ± 2mA
@ E800, Readings: 782 mA ± 2mA
@ E750, Readings: 698 mA ± 3mA
@ E700, Readings: 698 mA ± 3mA
@ E650, Readings: 600 mA ± 2mA
@ E600, Readings: 600 mA ± 2mA
@ E550, Readings: 492 mA ± 2mA
@ E500, Readings: 492 mA ± 2mA
@ E450, Readings: 390 mA ± 2mA
@ E400, Readings: 390 mA ± 2mA
@ E350, Readings: 284 mA ± 1mA
@ E300, Readings: 284 mA ± 1mA
@ E250, Readings: 190 mA ± 2mA
@ E200, Readings: 190 mA ± 2mA
@ E150, Readings: 84 mA ± 1mA
@ E100, Readings: 84 mA ± 1mA
@ E50, Readings: 84 mA ± 1mA
@ E25, Readings: 84 mA ± 1mA
@ E20, Readings: 84 mA ± 1mA
@ E15, Readings: 84 mA ± 1mA
@ E10, Readings: 84 mA ± 1mA
@ E5, Readings: 84 mA ± 1mA
@ E1, Readings: 84 mA ± 1mA
@ E0, Readings: 84 mA ± 1mAIs this expected? (I was assuming a linear increase.)
Hardware Info: DuetWifi v1.02 with an DuetEthernet connection.
Software Info: DuetEthernet 1.18.1
Other Info: The idle current was set to 100% to avoid misreadings. This occurs on the XY axis motors too. The motor MOTs do not seem visibly damaged.Image of extruder MOTS: https://imgur.com/a/uIy17
-
Sounds reasonable to me, I would surmise the TMC2660 and the i30s are measuring the current differently.
Another possibility after a quick check of the datasheet: the current control looks to be 5 bits, so 32 steps between 0 and ~3A. Works out to about 90mA per setting. This explains why there are some areas of the scale where increasing by 50mA doesn't trigger the next current interval.
I'm not sure how this would matter in practice? A 50mA difference is not going to be detectable in any practical sense.
-
The motor current is adjustable in increments of 100mA. The firmware rounds the requested current down to the nearest multiple of 100mA, except for values just under a multiple of 100mA which are rounded up. The minimal possible current when the driver is enabled is 100mA.
-
Thanks. What's the highest difference ( E[ 100-[delta] ] ) that the firmware accepts to round up?
-
I remembered incorrectly. 50mA gets rounded down to zero, but 55mA gets rounded up to 100.
-
Thanks for clarification. I want to remove this rounding. Where in the source code would I find the rounding being implemented? Or is there an easier method to remove this feature?
-
Perhaps my previous comment was unclear, apologies if that was the case. There are two issues at play here:
1.) Measurement error:
500mA is requested, but 492mA is measured. This difference is likely due to the measurement error of the i30s meter, and the measurement error of the TMC2660. Note that the i30s is not as accurate as you state - the stated accuracy of the i30s alone is 2mA+/- 1%, which would mean +/-3mA at 100mA, +/-7mA at 500mA, and so on. Also note that this does not include the measurement error of whatever you're using to read the i30s.
The measurement error of the TMC2660 is probably around 10-20mA.
2.) Desired current resolution:
You set 550mA, but only see 492mA still.
There are only 5 bits available in the TMC2660 for defining the target current. 2^5 = 32, so there's only 32 steps available. Each step is ~100mA.
Thus, it is not physically possible to remove the rounding. Or I guess you could remove the rounding, but you're still left with the same result (100mA resolution, and therefore a ~50mA error).
The rounding it not a feature, it is necessary because the TMC2660 only represents desired current with 5 bits, and this is because there's no practical reason for better resolution than that.
For reference the relevant code is in TMC2660.cpp:
// Set the motor current void TmcDriverState::SetCurrent(float current) { // The current sense resistor on the production Duet WiFi is 0.051 ohms. // This gives us a range of 101mA to 3.236A in 101mA steps in the high sensitivity range (VSENSE = 1) const uint32_t iCurrent = static_cast<uint32_t>(constrain<float>(current, 100.0, MaximumMotorCurrent)); const uint32_t csBits = (32 * iCurrent - 1600)/3236; // formula checked by simulation on a spreadsheet registers[StallGuardConfig] &= ~TMC_SGCSCONF_CS_MASK; registers[StallGuardConfig] |= TMC_SGCSCONF_CS(csBits); registersToUpdate |= 1u << StallGuardConfig; }</float></uint32_t>
-
Oh .. I see. Thanks for help.