Placer des composants en cercle (anneau de LED) avec l'API Python de KiCad

Publié le 18 octobre 2026 par leZ

Placez N footprints en cercle parfait et orientez-les vers l'extérieur par script — anneau de 24 LED WS2812B, avec pcbnew ou l'API IPC de KiCad.

Anneau de 24 LED WS2812B placées en cercle par script Python dans KiCad, chaîne de données DOUT → DIN routée
24 LED WS2812B placées, orientées et routées par script (KiCad 10).

Placer 24 LED à la main sur un cercle, chacune tournée de 15° par rapport à la précédente, c’est long et jamais parfaitement régulier. Par script, c’est une boucle de cinq lignes : un peu de trigonométrie pour la position, un angle proportionnel pour l’orientation. Tout le code de cette page a été exécuté sur une vraie board KiCad 10.

La formule

Pour le composant i parmi n, sur un cercle de centre (cx, cy) et de rayon r, en partant du haut et en tournant dans le sens horaire :

Essayez avec le widget : changez le nombre de composants et le rayon, la boucle se met à jour.

for i, fp in enumerate(parts):          # 24 parts
    a = 2 * math.pi * i / 24
    x = cx + 29.5 * math.sin(a)
    y = cy - 29.5 * math.cos(a)
    fp.SetPosition(pcbnew.VECTOR2I_MM(x, y))
    fp.SetOrientationDegrees(90 - 15 * i)
24
29.5

Placer les footprints

import math
import pcbnew

board = pcbnew.GetBoard()
cx, cy, r, n = 115, 105, 29.5, 24          # mm

for i in range(n):
    fp = board.FindFootprintByReference(f"D{i + 1}")
    a = 2 * math.pi * i / n
    fp.SetPosition(pcbnew.VECTOR2I_MM(cx + r * math.sin(a), cy - r * math.cos(a)))
    fp.SetOrientationDegrees(90 - 360 / n * i)

pcbnew.Refresh()

Dans la console de KiCad, pcbnew.Refresh() redessine la board immédiatement.

import math
from kipy import KiCad
from kipy.geometry import Angle, Vector2

board = KiCad().get_board()
cx, cy, r, n = 115, 105, 25, 24            # mm

by_ref = {f.reference_field.text.value: f for f in board.get_footprints()}
parts = [by_ref[f"D{i + 1}"] for i in range(n)]
for i, fp in enumerate(parts):
    a = 2 * math.pi * i / n
    fp.position = Vector2.from_xy_mm(cx + r * math.sin(a), cy - r * math.cos(a))
    fp.orientation = Angle.from_degrees(90 - 360 / n * i)
board.update_items(parts)

Testé : après exécution, D4 (i = 3, a = 45°) se trouve bien en (132,678 ; 87,322) mm, orienté à 45°. Un seul update_items() pour toute la liste suffit.

Router la chaîne de données

Sur des LED adressables, la sortie DOUT de chaque LED rejoint l’entrée DIN de la suivante. Une fois les LED en place, une piste par paire :

def pad(fp, number):
    return next(p for p in fp.Pads() if p.GetNumber() == number)

leds = [board.FindFootprintByReference(f"D{i + 1}") for i in range(n)]
for i in range(n - 1):
    dout, din = pad(leds[i], "2"), pad(leds[i + 1], "4")   # WS2812B : 2 = DOUT, 4 = DIN
    track = pcbnew.PCB_TRACK(board)
    track.SetStart(dout.GetPosition())
    track.SetEnd(din.GetPosition())
    track.SetWidth(pcbnew.FromMM(0.3))
    track.SetLayer(pcbnew.F_Cu)
    track.SetNet(dout.GetNet())
    board.Add(track)

Dans notre board de démo, l’alimentation est assurée par deux zones (VDD sur F.Cu, GND sur B.Cu reliée par une via près de chaque LED) : DRC à 0 violation et 0 élément non connecté.

Même logique côté IPC : créez des Track() entre les pastilles des LED voisines et ajoutez-les en une fois avec board.create_items(...) — voir le tutoriel sur les pistes.

Le résultat en 3D, avec les vrais modèles des LED fournis par KiCad :

Rendu 3D KiCad d'un anneau de 24 LED WS2812B placées en cercle par script Python
Rendu 3D réel de l'anneau (modèles 3D WS2812B de la bibliothèque KiCad).

Pour aller plus loin

Le même principe s’applique à tout motif circulaire : trous de fixation sur un cercle, pastilles d’un encodeur rotatif, connecteurs autour d’un capteur. Pour tourner un composant déjà placé autour d’un point quelconque, voyez la rotation autour d’un centre.