Instrument Control

Mesurer précisément le courant d'un moteur

Apprenez à mesurer le courant d'un moteur brushless avec un shunt et un INA228, à dimensionner le shunt et à valider courant moyen et crête.

JJulien Buteau
intermediate10 min de lecture27 octobre 2026

Le courant moteur est la mesure qui révèle un roulement qui frotte, un bobinage en court-circuit ou une voie d'ESC défaillante sur un banc de moteurs brushless, à condition que la valeur soit juste. Apprenez à choisir une méthode de mesure du courant, dimensionner un shunt pour un moniteur INA228, régler l'échantillonnage pour que la moyenne et les crêtes aient un sens, et enregistrer les deux avec des limites dans une procédure TofuPilot.

Quatre façons de mesurer le courant d'un moteur

Un banc de moteurs de drone dispose en général de quatre lectures de courant. Elles ne se valent pas.

MéthodeRésolution typiqueBande passanteÉtalonnéePar moteurUsage
Shunt + INA228 (I2C, 20 bits)0,3 à 0,7 mA avec un shunt de 0,5 à 1 mOhmFixée par le temps de conversion (50 µs à 4,12 ms)Oui, par la tolérance du shunt et l'erreur de gain de l'INA228Oui, un shunt par entrée DCLimites pass/fail
Capteur de courant à effet HallDizaines de mA, limitée par l'offset et le bruitDizaines à centaines de kHzOffset qui dérive avec la température et la rémanenceOuiIsolation galvanique, transitoires rapides
Courant de télémétrie de l'ESCChamp de 0,01 A, précision réelle inconnueUne trame par moteur et par cycle d'interrogationNonOuiRecoupement, diagnostic terrain
Relecture de l'alimentation de bancAffichage de 1 à 10 mAQuelques lectures par secondeOui, mais moyennéeNon, total de toutes les chargesContrôle de cohérence du total

Un shunt lu par un moniteur de précision est la seule option à la fois étalonnée, assez rapide et attribuable à un moteur. Un capteur à effet Hall l'emporte quand il faut une isolation ou la forme d'onde d'un transitoire inférieur à la milliseconde, au prix d'un offset à remettre à zéro avant chaque run. La télémétrie de l'ESC et la relecture de l'alimentation donnent du contexte, pas des mesures sur lesquelles poser des limites.

Sur un ESC 4-en-1, il y a une seule entrée DC pour quatre moteurs. Un shunt sur cette entrée mesure la somme. Pour attribuer le courant à un moteur, faites tourner un moteur à la fois, ou placez le shunt entre l'alimentation et un ESC à une seule voie. Les courants de phase entre ESC et moteur sont des formes d'onde de commutation alternatives, et ce n'est pas là que se place un shunt DC.

Connaître la plage de courant avant de choisir les composants

La plage fixe la valeur du shunt, sa puissance nominale et la gamme du moniteur. Valeurs d'exemple mesurées sur un moteur de taille 3115, 1250 KV (12N14P), sur un bus 6S avec un ESC BLHeli_32 :

GazVitesseCourant sans hélice
3 %ralentienviron 0,1 A
25 %8 350 tr/min0,65 A
70 %22 600 tr/min2,65 A
100 %31 000 tr/min3,5 à 4,5 A

Avec une hélice, le même moteur consomme des dizaines d'ampères. Pour une hélice typique en 6S, 60 à 80 A plein gaz est une estimation raisonnable, pas une valeur mesurée. Dimensionnez pour le cas avec hélice si le banc doit un jour en recevoir une, et vérifiez que la résolution couvre toujours les 0,1 A du ralenti.

Dimensionner le shunt

Trois grandeurs décident du shunt : la tension pleine échelle du moniteur, la puissance dissipée dans le shunt et la résolution à faible courant.

L'INA228 mesure la tension différentielle du shunt avec un ADC delta-sigma 20 bits. Dans sa gamme par défaut (ADCRANGE = 0), la pleine échelle est de ±163,84 mV et le LSB de 312,5 nV. L'entrée de tension de bus accepte jusqu'à 85 V, donc une batterie 6S (25,2 V pleine charge) est largement couverte, côté haut comme côté bas.

shunt-sizing.txt
V_shunt = I x R                 must stay below 163.84 mV at I_maxP_shunt = I^2 x R               shunt power rating >= 2 x P_shuntI_lsb   = 312.5 nV / R          current resolutionV_burden = I x R                voltage the motor no longer sees

Appliqué à une crête de 80 A et à un ESC de 100 A :

ShuntV à 80 AP à 80 AP à 100 ARésolutionCourant max avant saturation
0,5 mOhm40 mV3,2 W5 W0,625 mA327 A
1 mOhm80 mV6,4 W10 W0,3125 mA163 A
2 mOhm160 mV12,8 W20 W0,156 mA81,9 A

Le shunt de 2 mOhm sature au premier transitoire au-dessus de 82 A et dissipe plus de chaleur qu'un petit shunt ne peut en évacuer. Le shunt de 0,5 mOhm garde une dissipation faible, résout encore le courant de ralenti de 0,1 A à mieux que 1 %, et coûte 40 mV de chute à 80 A, soit 0,18 % d'un bus nominal de 22,2 V. Pour un banc qui ne reçoit jamais d'hélice, un shunt de 5 mOhm donne 25 mV à 5 A pour 0,125 W.

Trois détails décident si la valeur inscrite sur le shunt est celle que vous obtenez :

  • Utilisez un shunt quatre fils et des lignes de mesure Kelvin. À 0,5 mOhm, 0,1 mOhm de résistance de soudure ou de contact vissé dans le chemin de mesure fait 20 % d'erreur. Les lignes de mesure vont aux bornes de mesure dédiées, jamais aux cosses de puissance.
  • Tenez compte du coefficient de température. Un shunt qui chauffe de 25 °C à 85 °C avec un TCR de 50 ppm/°C varie de 0,3 %. Choisissez un alliage à faible TCR et montez le shunt là où il peut évacuer sa chaleur.
  • Faites cheminer la paire de mesure ensemble. Torsadez-la et éloignez-la des fils de phase du moteur, qui portent les fronts de commutation de l'ESC.

Choisir la cadence, le moyennage et ce que signifie une crête

Le courant absorbé par un ESC n'est pas une valeur continue. Il porte une ondulation à la fréquence PWM de l'ESC (des dizaines de kHz), et des transitoires à chaque changement de gaz, parce que le moteur a besoin d'un couple supplémentaire pour accélérer son rotor et son hélice. Trois réglages de l'INA228 décident de ce que vous voyez :

  • Temps de conversion (VSHCT, 50 µs à 4,12 ms par conversion). L'ADC delta-sigma intègre sur cette fenêtre, donc l'ondulation PWM se moyenne à l'intérieur d'une conversion.
  • Nombre de moyennes (AVG, 1 à 1024 conversions). Le circuit moyenne en interne avant de mettre à jour le registre de résultat.
  • Cadence de lecture. L'interrogation I2C depuis Python atteint au mieux quelques centaines de lectures par seconde, avec la gigue du système d'exploitation.
ObjectifVSHCTAVGPériode de mise à jour (shunt et bus)Résultat
Courant moyen à gaz constant540 µs16environ 17 msBruit faible, ondulation et pics courts moyennés
Transitoires d'accélération visibles150 µs1environ 0,3 ms, limitée par la cadence de lectureÉchantillons plus bruités, crêtes de quelques dizaines de ms capturées
Événements inférieurs à la millisecondePas l'INA228Sonde à effet Hall sur oscilloscope

La période de mise à jour est VSHCT x AVG pour chaque voie activée, additionnées : 2 x 540 µs x 16 = 17,3 ms avec shunt et bus convertis. Une crête enregistrée avec ce réglage est la plus haute moyenne sur 17 ms, pas la crête instantanée. C'est la bonne grandeur pour une limite thermique ou de dimensionnement d'alimentation, et la mauvaise pour une limite de contrainte des MOSFET. Indiquez laquelle dans la description de la mesure.

N'interrogez pas plus vite que la mise à jour du registre. Relire la même valeur n'apporte aucune information, et interroger plus lentement que la mise à jour sans moyennage saute des données entre deux lectures, ce qui peut faire passer une ondulation pour un pic ou masquer un vrai pic.

Étape 1 : écrire le plug INA228

Le plug possède le bus I2C et renvoie des nombres et des listes simples. Cet exemple utilise smbus2 sur un hôte Linux doté d'un bus I2C (un ordinateur monocarte, ou un adaptateur USB-I2C exposé en /dev/i2c-N) :

requirements.txt
smbus2>=0.4
plugs/ina228.py
60 lines
import timefrom smbus2 import SMBusREG_CONFIG = 0x00REG_ADC_CONFIG = 0x01REG_VSHUNT = 0x04REG_VBUS = 0x05VSHUNT_LSB = 312.5e-9  # V, ADCRANGE = 0 (+/-163,84 mV)VBUS_LSB = 195.3125e-6  # V# Codes de temps de conversion pour VBUSCT / VSHCT / VTCTCT_CODES = {50: 0, 84: 1, 150: 2, 280: 3, 540: 4, 1052: 5, 2074: 6, 4120: 7}AVG_CODES = {1: 0, 4: 1, 16: 2, 64: 3, 128: 4, 256: 5, 512: 6, 1024: 7}MODE_CONT_SHUNT_BUS = 0xBclass INA228:    def __init__(self, bus, address, shunt_ohm):        self.address = address        self.shunt_ohm = shunt_ohm        self.i2c = SMBus(bus)        self.i2c.write_i2c_block_data(self.address, REG_CONFIG, [0x80, 0x00])  # reset        time.sleep(0.01)        self.configure(540, 16)    def __del__(self):        if hasattr(self, "i2c"):            self.i2c.close()    def configure(self, conversion_us, averages):        ct = CT_CODES[conversion_us]        value = (MODE_CONT_SHUNT_BUS << 12) | (ct << 9) | (ct << 6) | (ct << 3) | AVG_CODES[averages]        self.i2c.write_i2c_block_data(self.address, REG_ADC_CONFIG, [value >> 8, value & 0xFF])        # Période de mise à jour d'un résultat shunt + bus, sert à cadencer l'échantillonnage        self.period_s = 2 * conversion_us * 1e-6 * averages    def _read20(self, register, signed):        b = self.i2c.read_i2c_block_data(self.address, register, 3)        raw = ((b[0] << 16) | (b[1] << 8) | b[2]) >> 4        if signed and raw & 0x80000:            raw -= 1 << 20        return raw    def read_current(self):        return self._read20(REG_VSHUNT, True) * VSHUNT_LSB / self.shunt_ohm    def read_bus_voltage(self):        return self._read20(REG_VBUS, False) * VBUS_LSB    def sample_current(self, duration_s):        """Renvoie [times_s, currents_a] échantillonnés au rythme du registre."""        times, currents = [], []        t0 = time.monotonic()        while (now := time.monotonic() - t0) < duration_s:            times.append(round(now, 4))            currents.append(self.read_current())            time.sleep(self.period_s)        return [times, currents]

Le courant est calculé à partir du registre de tension shunt et de la valeur du shunt, ce qui garde l'étalonnage dans un seul nombre visible. L'INA228 peut aussi calculer le courant en interne avec son registre SHUNT_CAL. Les deux donnent le même résultat ; la forme directe est plus facile à auditer.

Déclarez-le avec son bus, son adresse et la valeur du shunt dans with:, pour qu'un autre poste ou un shunt remplacé soit un changement de configuration, pas de code :

procedure.yaml
21 lines
name: Motor Current Checkversion: 0.1.0execution:  workers: 1plugs:  - name: Current Monitor    key: current_monitor    python: plugs.ina228:INA228    scope: station    with:      bus: 1      address: 0x40      shunt_ohm: 0.0005  - name: Motor Driver    key: motor    python: plugs.motor:MotorDriver    scope: station    with:      port: /dev/ttyACM0

workers: 1 compte sur un banc moteur. TofuPilot exécute par défaut les phases indépendantes en parallèle, et deux phases qui pilotent le même moteur ou lisent le même bus I2C en même temps donnent des résultats sans valeur. Le plug motor est ce qui règle les gaz sur votre banc, par exemple un microcontrôleur qui génère du DShot via un port série USB.

Étape 2 : enregistrer courant moyen et crête avec des limites

Enregistrez les échantillons comme une mesure multidimensionnelle, pour que le dashboard affiche la courbe, et posez les limites sur des agrégations de cette courbe :

procedure.yaml
43 lines
main:  - name: Current at 25 % Throttle    key: current_25    python: phases.current:hold_and_measure    timeout: 30s    with:      throttle_pct: 25      settle_s: 2.0      measure_s: 3.0    measurements:      - name: Motor Current 25 %        key: motor_current        description: INA228, VSHCT 540 us, AVG 16. Peak is the highest 17 ms average.        x_axis:          legend: Time          unit: s        y_axis:          - legend: Current            key: current            unit: A            aggregations:              - type: mean                validators:                  - operator: ">="                    expected_value: 0.5                  - operator: "<="                    expected_value: 0.8              - type: max                validators:                  - operator: "<="                    expected_value: 1.2      - name: Bus Voltage        key: bus_voltage        unit: V        validators:          - operator: ">="            expected_value: 21.0          - operator: "<="            expected_value: 25.5teardown:  - name: Stop Motor    python: phases.current:stop_motor

La fenêtre de 0,5 à 0,8 A encadre les 0,65 A mesurés sur un moteur sans hélice. Ce sont des valeurs d'exemple : fixez les vôtres à partir d'un lot de moteurs connus bons, puis resserrez-les avec le Cpk que le dashboard calcule pour la mesure.

phases/current.py
22 lines
import timedef hold_and_measure(motor, current_monitor, measurements, log, throttle_pct, settle_s, measure_s):    motor.ramp_to(throttle_pct)    # Laisser passer le transitoire d'accélération avant de mesurer le courant établi    time.sleep(settle_s)    times, currents = current_monitor.sample_current(measure_s)    measurements.motor_current.x_axis = times    measurements.motor_current.y_axis.current = currents    aggs = measurements.motor_current.y_axis.current.aggregations    aggs.mean = sum(currents) / len(currents)    aggs.max = max(currents)    measurements.bus_voltage = current_monitor.read_bus_voltage()    log.info(f"{len(currents)} samples, mean {aggs.mean:.3f} A, max {aggs.max:.3f} A")def stop_motor(motor):    motor.ramp_to(0)

La phase de teardown s'exécute même quand une limite échoue ou que la phase dépasse son timeout, donc le moteur revient toujours à zéro. C'est une commodité, pas une fonction de sécurité : le banc a toujours besoin d'un arrêt d'urgence câblé qui coupe la puissance.

Chaque run enregistre alors la courbe, la moyenne, le maximum et la tension de bus avec le numéro de série du moteur. Sur le dashboard, un courant moyen qui monte lentement sur un lot de production désigne les roulements ou les aimants avant que la limite ne soit franchie.

Pourquoi le courant de télémétrie de l'ESC n'est pas une mesure

Les ESC BLHeli_32 renvoient le courant dans leur trame de télémétrie avec un champ de 0,01 A. La résolution du champ ne dit rien de la précision :

  • La mesure de l'ESC n'est pas étalonnée unité par unité. Un ESC 4-en-1 mesure le courant avec son propre shunt de faible valeur ou la chute dans les MOSFET, mise à l'échelle par une constante du firmware. Deux ESC du même modèle ne lisent pas la même valeur.
  • L'offset domine à faible courant. Sans hélice, le moteur consomme 0,1 à 4,5 A, soit le bas d'une gamme de capteur de 100 A. Des lectures de 0,00 A au ralenti sont courantes.
  • La cadence est faible. La télémétrie est demandée un moteur à la fois, donc chaque moteur ne reçoit une trame fraîche qu'une fois par cycle d'interrogation.

Enregistrez le courant de l'ESC comme une mesure distincte sans limites serrées, à côté de la valeur de l'INA228. Un écart important entre les deux signale un problème de câblage ou d'ESC ; il ne décide pas du pass ou du fail.

Pièges courants

Brancher les lignes de mesure sur les cosses de puissance. La résistance de contact entre dans le shunt. Utilisez les bornes Kelvin.

Dimensionner le shunt pour le banc sans hélice, puis monter une hélice. Un shunt de 10 mOhm qui lisait proprement 5 A sature à 16 A et dissipe 64 W à 80 A.

Laisser les phases en parallèle. Deux phases qui commandent le moteur en même temps ruinent les deux lectures. Réglez workers: 1 ou chaînez les phases avec depends_on.

Mesurer pendant le transitoire d'accélération. Une moyenne qui inclut la montée en vitesse n'est pas un courant établi. Attendez la stabilisation.

Appeler crête une moyenne sur 17 ms sans le dire. Écrivez la fenêtre de moyennage dans la description de la mesure.

Poser des limites sur le courant de télémétrie de l'ESC. Il n'est pas étalonné et reste grossier à faible courant. Servez-vous-en pour recouper.

Points clés

  • Un shunt câblé en Kelvin et lu par un INA228 est la référence pour le courant moteur ; capteurs Hall, télémétrie d'ESC et relecture d'alimentation sont secondaires.
  • Dimensionnez le shunt avec V = I x R sous 163,84 mV, P = I^2 x R avec une marge de puissance de 2x, et une résolution de 312,5 nV / R.
  • Le temps de conversion et le moyennage décident si vous enregistrez une moyenne ou une crête, et ce que « crête » veut dire.
  • Enregistrez la courbe comme mesure multidimensionnelle, avec des agrégations mean et max qui portent les limites.
  • Exécutez les phases moteur une à la fois et arrêtez le moteur en teardown.

Pour une vue d'ensemble des bancs de test de moteurs et d'actionneurs, consultez Motor and Actuator Testing with TofuPilot.

Plus de guides

Mettez ce guide en pratique