# -*- coding: utf-8 -*- """ Macro FreeCAD : génération paramétrique d'un frame de quadcopter en configuration X. UTILISATION : 1. Ouvrir FreeCAD 2. Menu Macro > Macros... > Créer (ou coller directement dans la console Python, View > Panels > Python console) 3. Coller ce script, l'exécuter 4. Ajuster les paramètres ci-dessous et relancer pour itérer 5. Une fois satisfait : Fichier > Exporter > STEP (.step) ou pour impression 3D : STL (.stl) C'est un point de départ volontairement simple (plaque + bras droits + plaque moteur). Prochaines évolutions possibles : bras effilés, plaque du bas + standoffs, découpe pour câblage, congés (fillets) pour la résistance aux chocs, arrondi des angles. """ import FreeCAD as App import Part import math doc = App.newDocument("DroneFrame") # --------------------------------------------------------------------------- # PARAMETRES (en mm) - à adapter à votre choix de moteurs / taille d'hélices # --------------------------------------------------------------------------- WHEELBASE = 220.0 # distance diagonale moteur-à-moteur (standard "5 pouces" ~210-230mm) PLATE_THICKNESS = 4.0 # épaisseur de la plaque centrale et des bras (carbone typique : 3-5mm) ARM_WIDTH = 10.0 # largeur des bras CENTER_SIZE = 40.0 # côté de la plaque centrale carrée FC_MOUNT_PATTERN = 30.5 # pattern standard "mini" pour flight controller (30.5x30.5mm) FC_HOLE_DIA = 3.2 # diamètre de perçage pour vis M3 (jeu inclus) MOTOR_MOUNT_PATTERN = 12.0 # ATTENTION : varie selon le moteur (12x12, 16x16, 19x16...) # -> vérifiez la fiche technique du moteur choisi et ajustez ici MOTOR_HOLE_DIA = 3.2 MOTOR_PLATE_SIZE = 20.0 # taille de la plaque support moteur en bout de bras arm_length = WHEELBASE / 2.0 # distance centre -> axe moteur # --------------------------------------------------------------------------- # Fonctions utilitaires # --------------------------------------------------------------------------- def make_hole(x, y, dia, height): cyl = Part.makeCylinder(dia / 2, height) cyl.translate(App.Vector(x, y, -1)) # dépasse un peu de chaque côté pour une coupe propre return cyl # --------------------------------------------------------------------------- # Plaque centrale # --------------------------------------------------------------------------- center_plate = Part.makeBox(CENTER_SIZE, CENTER_SIZE, PLATE_THICKNESS) center_plate.translate(App.Vector(-CENTER_SIZE / 2, -CENTER_SIZE / 2, 0)) half_fc = FC_MOUNT_PATTERN / 2 for sx in (-1, 1): for sy in (-1, 1): h = make_hole(sx * half_fc, sy * half_fc, FC_HOLE_DIA, PLATE_THICKNESS + 2) center_plate = center_plate.cut(h) # --------------------------------------------------------------------------- # Bras + plaques moteur (config X : 45°, 135°, 225°, 315°) # --------------------------------------------------------------------------- frame = center_plate for angle_deg in (45, 135, 225, 315): # bras arm = Part.makeBox(arm_length, ARM_WIDTH, PLATE_THICKNESS) arm.translate(App.Vector(0, -ARM_WIDTH / 2, 0)) arm.rotate(App.Vector(0, 0, 0), App.Vector(0, 0, 1), angle_deg) frame = frame.fuse(arm) # plaque moteur en bout de bras motor_plate = Part.makeBox(MOTOR_PLATE_SIZE, MOTOR_PLATE_SIZE, PLATE_THICKNESS) motor_plate.translate(App.Vector(-MOTOR_PLATE_SIZE / 2, -MOTOR_PLATE_SIZE / 2, 0)) half_motor = MOTOR_MOUNT_PATTERN / 2 for sx in (-1, 1): for sy in (-1, 1): h = make_hole(sx * half_motor, sy * half_motor, MOTOR_HOLE_DIA, PLATE_THICKNESS + 2) motor_plate = motor_plate.cut(h) motor_plate.translate(App.Vector(arm_length, 0, 0)) motor_plate.rotate(App.Vector(0, 0, 0), App.Vector(0, 0, 1), angle_deg) frame = frame.fuse(motor_plate) # --------------------------------------------------------------------------- # Affichage dans le document FreeCAD # --------------------------------------------------------------------------- Part.show(frame, "DroneFrame") doc.recompute() print("Frame généré : wheelbase = %.1fmm, épaisseur = %.1fmm" % (WHEELBASE, PLATE_THICKNESS))