Hadlock

Bearing-mount cylinder calculator

May 2nd, 2026
89
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.40 KB | Source Code | 0 0
  1. #!/usr/bin/env python3
  2. """Bearing-mount cylinder for Feetech STS3215 top adapter plate.
  3. Pygame sliders (0.02mm steps) → CadQuery STEP export."""
  4. import math, time, cadquery as cq, pygame
  5.  
  6. # Top plate ref: OD 19.95, bolt circle ø14 4×M3 (ø3.2), center ø9, thick 4.5mm
  7. P = {  # key: [value, min, max, label]
  8.     "od":      [19.80, 19.0, 20.2, "Outer Dia (6804-0.2)"],
  9.     "bore":    [ 9.00,  3.0, 12.0, "Center Bore"],
  10.     "bolt_cd": [14.00, 12.0, 16.0, "Bolt Circle Dia"],
  11.     "bolt_d":  [ 3.25,  2.8,  3.8, "Bolt Hole (M3+0.25)"],
  12.     "height":  [10.00,  3.0, 25.0, "Height"],
  13. }
  14. STEP = 0.02
  15. KEYS = list(P.keys())
  16. W, H, SX, SW, SH, GAP, TY = 700, 420, 240, 360, 22, 48, 36
  17.  
  18. def snap(v): return round(round(v / STEP) * STEP, 4)
  19.  
  20. def export(p):
  21.     body = cq.Workplane("XY").circle(p["od"]/2).circle(p["bore"]/2).extrude(p["height"])
  22.     pts = [(p["bolt_cd"]/2*math.cos(math.radians(a)),
  23.             p["bolt_cd"]/2*math.sin(math.radians(a))) for a in (0, 90, 180, 270)]
  24.     body = body.faces(">Z").workplane().pushPoints(pts).hole(p["bolt_d"])
  25.     fn = f"STS3215-{int(time.time())}.step"
  26.     cq.exporters.export(body, fn)
  27.     return fn
  28.  
  29. def main():
  30.     pygame.init()
  31.     scr = pygame.display.set_mode((W, H))
  32.     pygame.display.set_caption("STS3215 Bearing Cylinder")
  33.     f = pygame.font.SysFont("menlo,consolas,monospace", 13)
  34.     fb = pygame.font.SysFont("menlo,consolas,monospace", 15, bold=True)
  35.     clk, drag, msg, msg_t = pygame.time.Clock(), None, "", 0
  36.     def vals(): return {k: P[k][0] for k in KEYS}
  37.     def vx(k): return SX + int((P[k][0] - P[k][1]) / (P[k][2] - P[k][1]) * SW)
  38.     def xv(k, x): P[k][0] = snap(P[k][1] + max(0, min(1, (x - SX) / SW)) * (P[k][2] - P[k][1]))
  39.     btn = pygame.Rect(W // 2 - 80, H - 56, 160, 36)
  40.     run = True
  41.     while run:
  42.         mx, my = pygame.mouse.get_pos()
  43.         for ev in pygame.event.get():
  44.             if ev.type == pygame.QUIT or (ev.type == pygame.KEYDOWN and ev.key == pygame.K_ESCAPE):
  45.                 run = False
  46.             elif ev.type == pygame.MOUSEBUTTONDOWN and ev.button == 1:
  47.                 for i in range(len(KEYS)):
  48.                     if pygame.Rect(SX, TY + i * GAP, SW, SH).collidepoint(ev.pos):
  49.                         drag = i; xv(KEYS[i], ev.pos[0])
  50.                 if btn.collidepoint(ev.pos):
  51.                     try: fn = export(vals()); msg, msg_t = f"Saved {fn}", time.time()
  52.                     except Exception as e: msg, msg_t = str(e)[:60], time.time()
  53.             elif ev.type == pygame.MOUSEBUTTONUP: drag = None
  54.             elif ev.type == pygame.MOUSEMOTION and drag is not None: xv(KEYS[drag], ev.pos[0])
  55.         scr.fill((32, 32, 36))
  56.         scr.blit(fb.render("STS3215 Bearing-Mount Cylinder", True, (80, 180, 255)), (16, 8))
  57.         for i, k in enumerate(KEYS):
  58.             y = TY + i * GAP
  59.             scr.blit(f.render(P[k][3], True, (200, 200, 200)), (12, y + 3))
  60.             pygame.draw.rect(scr, (55, 55, 60), pygame.Rect(SX, y, SW, SH), border_radius=3)
  61.             fx = vx(k)
  62.             pygame.draw.rect(scr, (80, 180, 255), pygame.Rect(SX, y, fx - SX, SH), border_radius=3)
  63.             pygame.draw.circle(scr, (255, 255, 255), (fx, y + SH // 2), 7)
  64.             scr.blit(f.render(f"{P[k][0]:7.2f}mm", True, (200, 200, 200)), (SX + SW + 10, y + 3))
  65.         # cross-section preview
  66.         cx, cy, sc = 120, H - 110, 7.5
  67.         p = vals()
  68.         pygame.draw.circle(scr, (55, 55, 60), (cx, cy), int(p["od"] / 2 * sc), 2)
  69.         pygame.draw.circle(scr, (120, 120, 120), (cx, cy), int(p["bore"] / 2 * sc), 1)
  70.         for a in (0, 90, 180, 270):
  71.             bx, by = cx + p["bolt_cd"]/2*sc*math.cos(math.radians(a)), cy + p["bolt_cd"]/2*sc*math.sin(math.radians(a))
  72.             pygame.draw.circle(scr, (80, 180, 255), (int(bx), int(by)), max(2, int(p["bolt_d"] / 2 * sc)), 1)
  73.         scr.blit(f.render("section", True, (100, 100, 100)), (cx - 22, cy + int(p["od"] / 2 * sc) + 6))
  74.         # export button
  75.         hov = btn.collidepoint(mx, my)
  76.         pygame.draw.rect(scr, (70, 200, 110) if hov else (50, 160, 90), btn, border_radius=5)
  77.         bl = fb.render("Export STEP", True, (255, 255, 255))
  78.         scr.blit(bl, (btn.centerx - bl.get_width() // 2, btn.centery - bl.get_height() // 2))
  79.         if msg and time.time() - msg_t < 4:
  80.             scr.blit(f.render(msg, True, (180, 255, 180)), (W // 2 - 100, H - 18))
  81.         pygame.display.flip(); clk.tick(60)
  82.     pygame.quit()
  83.  
  84. if __name__ == "__main__":
  85.     main()
  86.  
Advertisement
Add Comment
Please, Sign In to add comment