Test de moteurs et actionneurs avec TofuPilot
Chaque moteur qui sort de votre ligne doit tourner à la bonne vitesse, consommer le bon courant, et ne pas se désintégrer par vibration. Les contrôles manuels ponctuels ne passent pas à l'échelle. Vous avez besoin de tests automatisés qui capturent les courbes de couple, les profils de vitesse et les signatures vibratoires pour chaque unité.
TofuPilot et OpenHTF vous permettent de construire ces tests en Python et de suivre chaque résultat à travers la production.
Ce que couvrent les tests moteur
Les tests de production moteur incluent généralement :
| Type de test | Ce qu'il mesure | Pourquoi c'est important |
|---|---|---|
| Vitesse à vide | RPM à tension nominale, sans couple | Intégrité du bobinage et des aimants |
| Couple de blocage | Couple maximal à RPM zéro | Résistance mécanique |
| Consommation de courant | Ampères à vide, charge nominale, blocage | Rendement, courts-circuits de bobinage |
| Force contre-électromotrice | Tension générée lors d'un entraînement externe | Qualité des aimants et du bobinage |
| Vibration | Spectre d'accélération à vitesse de fonctionnement | Santé des roulements, équilibrage |
| Résistance d'isolement | Lecture en mégaohms bobinage-carter | Sécurité, intégrité diélectrique |
Prérequis
- Python 3.8+ avec
openhtfettofupilotinstallés - Un dynamomètre ou capteur de couple avec interface série/GPIB/USB
- Une alimentation programmable pour l'entraînement du moteur
- Optionnel : accéléromètre ou capteur de vibration
Étape 1 : Configurer le test à vide
Le test à vide est votre première porte de contrôle. Un moteur qui ne peut pas atteindre la vitesse nominale sans charge a un problème fondamental.
import openhtf as htf
from openhtf.util import units
import time
@htf.measures(
htf.Measurement("no_load_speed_rpm")
.with_units(units.HERTZ) # RPM stocké comme valeur
.in_range(2850, 3150)
.doc("Vitesse à vide à tension nominale"),
htf.Measurement("no_load_current_a")
.with_units(units.AMPERE)
.at_most(0.5)
.doc("Consommation de courant à vide"),
htf.Measurement("startup_time_ms")
.with_units(units.MILLISECOND)
.at_most(200)
.doc("Temps pour atteindre 90% de la vitesse nominale"),
)
def no_load_test(test, psu, tachometer):
"""Faire tourner le moteur à tension nominale sans charge."""
psu.set_voltage(24.0)
psu.output_on()
start = time.time()
# Attendre que le moteur atteigne le régime permanent
time.sleep(2.0)
speed = tachometer.read_rpm()
current = psu.measure_current()
startup = tachometer.get_startup_time_ms()
test.measurements.no_load_speed_rpm = speed
test.measurements.no_load_current_a = current
test.measurements.startup_time_ms = startup
psu.output_off()Étape 2 : Capturer les courbes couple-vitesse
La courbe couple-vitesse caractérise les performances du moteur sur toute sa plage de fonctionnement. Capturez-la comme une mesure multidimensionnelle.
import openhtf as htf
from openhtf.util import units
import numpy as np
@htf.measures(
htf.Measurement("torque_speed_curve")
.with_dimensions(units.HERTZ) # RPM comme dimension
.doc("Courbe caractéristique couple vs vitesse"),
htf.Measurement("rated_torque_nm")
.in_range(0.45, 0.55)
.doc("Couple au point de fonctionnement nominal"),
htf.Measurement("efficiency_at_rated")
.in_range(0.80, 1.0)
.doc("Rendement au point de fonctionnement nominal"),
)
def torque_curve_test(test, psu, dyno):
"""Balayer la charge de vide à blocage, capturer le couple à chaque point."""
psu.set_voltage(24.0)
psu.output_on()
time.sleep(1.0)
torque_points = []
speed_points = []
for load_pct in range(0, 105, 5):
dyno.set_load_percent(load_pct)
time.sleep(0.5) # Temps de stabilisation
torque = dyno.read_torque_nm()
speed = dyno.read_rpm()
torque_points.append(torque)
speed_points.append(speed)
test.measurements.torque_speed_curve[speed] = torque
# Trouver le point de fonctionnement nominal (le plus proche de la vitesse nominale)
rated_idx = np.argmin(np.abs(np.array(speed_points) - 3000))
rated_torque = torque_points[rated_idx]
rated_speed = speed_points[rated_idx]
test.measurements.rated_torque_nm = rated_torque
# Calculer le rendement : P_meca / P_elec
p_mech = rated_torque * rated_speed * 2 * np.pi / 60
p_elec = 24.0 * psu.measure_current()
test.measurements.efficiency_at_rated = p_mech / p_elec
dyno.set_load_percent(0)
psu.output_off()Étape 3 : Ajouter l'analyse vibratoire
Le test de vibration détecte les défauts de roulement, le déséquilibre du rotor et les désalignements avant qu'ils ne deviennent des défaillances terrain.
import openhtf as htf
from openhtf.util import units
import numpy as np
@htf.measures(
htf.Measurement("vibration_rms_g")
.at_most(0.5)
.doc("Vibration RMS globale en g"),
htf.Measurement("vibration_spectrum")
.with_dimensions(units.HERTZ)
.doc("Spectre fréquentiel de vibration"),
htf.Measurement("dominant_frequency_hz")
.with_units(units.HERTZ)
.doc("Composante fréquentielle d'amplitude maximale"),
)
def vibration_test(test, psu, accelerometer):
"""Mesurer la vibration à vitesse nominale."""
psu.set_voltage(24.0)
psu.output_on()
time.sleep(3.0) # Attendre le régime permanent
# Capturer 1 seconde de données d'accélération à 10 kHz
raw_data = accelerometer.capture(duration_s=1.0, sample_rate=10000)
# Vibration RMS
rms = np.sqrt(np.mean(raw_data ** 2))
test.measurements.vibration_rms_g = rms
# FFT pour le spectre
fft_vals = np.abs(np.fft.rfft(raw_data))
freqs = np.fft.rfftfreq(len(raw_data), d=1/10000)
for freq, amplitude in zip(freqs[1:500], fft_vals[1:500]):
test.measurements.vibration_spectrum[freq] = amplitude
# Fréquence dominante
peak_idx = np.argmax(fft_vals[1:]) + 1
test.measurements.dominant_frequency_hz = freqs[peak_idx]
psu.output_off()Étape 4 : Construire la séquence de test complète
Combinez tous les tests moteur en une seule séquence de production :
import openhtf as htf
from tofupilot import TofuPilotClient
def main():
test = htf.Test(
no_load_test,
torque_curve_test,
vibration_test,
)
test.add_output_callbacks(
TofuPilotClient().as_openhtf_callback(
procedure_id="motor-fct",
procedure_name="Test FCT moteur en production",
)
)
test.execute(test_start=htf.PhaseDescriptor.wrap(
lambda test: setattr(
test, "dut_id", input("Scanner le numéro de série du moteur : ")
)
))
if __name__ == "__main__":
main()Étape 5 : Surveiller les tendances de production
Une fois les tests en fonctionnement, utilisez TofuPilot pour détecter les dérives avant qu'elles ne causent des défaillances :
- Vitesse à vide en baisse : Possible démagnétisation ou friction accrue
- Consommation de courant en hausse : Dégradation de l'isolation du bobinage ou usure des roulements
- Vibration RMS en augmentation : Progression de la défaillance des roulements
- Rendement en baisse : Examiner les sous-systèmes électrique et mécanique
Définissez les limites de mesure avec de la marge. Si votre spécification est de 2850 à 3150 RPM, envisagez des limites de production plus serrées de 2900 à 3100 pour détecter les dérives tôt.
Les cartes de contrôle de TofuPilot affichent ces tendances automatiquement. Un décalage de la moyenne ou un écart-type croissant apparaît avant que les pièces ne commencent à échouer.
Considérations spécifiques aux actionneurs
Les actionneurs linéaires et les servomoteurs nécessitent des tests supplémentaires :
| Type d'actionneur | Tests supplémentaires |
|---|---|
| Actionneur linéaire | Longueur de course, force d'extension, vitesse de rétraction |
| Servomoteur | Précision de position, temps de stabilisation, réponse indicielle |
| Moteur pas à pas | Couple de maintien, précision de pas, points de résonance |
| Solénoïde | Tension d'attraction, tension de relâchement, temps de réponse |
La structure de test est la même. Définissez des mesures avec des limites, capturez les données, laissez TofuPilot tout suivre.