pcb-stator-coil-generator/coil_generator-generic.ipynb

727 lines
25 KiB
Text
Raw Normal View History

{
"cells": [
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"import matplotlib.pyplot as plt\n",
"from skspatial.objects import LineSegment, Line, Vector\n",
"\n",
"from enum import Enum\n",
"Layer = Enum(\"Layer\", \"FRONT BACK\")\n",
"\n",
"from helpers import *\n",
"from pcb_json import *"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Parameters \n",
"edit those:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Track width and spacing\n",
"TRACK_WIDTH = 0.127\n",
"TRACK_SPACING = 0.127\n",
"\n",
"# via defaults\n",
"VIA_DIAM = 0.8\n",
"VIA_DRILL = 0.4\n",
"\n",
"# this is for a 1.27mm pitch pin\n",
"PIN_DIAM = 1.0\n",
"PIN_DRILL = 0.65\n",
"\n",
"SCREW_HOLE_DRILL_DIAM = 2.3 # 2.3mm drill for a 2mm screw\n",
"\n",
"# this is for the PCB connector - see https://www.farnell.com/datasheets/2003059.pdf\n",
"PAD_WIDTH = 3\n",
"PAD_HEIGHT = 2\n",
"PAD_PITCH = 2.5\n",
"\n",
"# how to connect coils\n",
"PAD_ENABLE = False\n",
"CONNECT_WITH_VIAS = True\n",
"\n",
"# NET Naming\n",
"COIL_NET_NAME = \"coil\" \n",
"USE_INDIVIDUAL_NET_NAMES_PER_COIL = False # appends numbering to COIL_NET_NAME\n",
"USE_ABC_NET_NAMES_FOR_COILS = True # appends A,B,C to COIL_NET_NAME\n",
"\n",
"# draw on edge cuts:\n",
"PCB_EDGE_CUTS = False\n",
"\n",
"LAYERS = 4\n",
"\n",
"# Geometry RADIUS_\n",
"# -------------------------------------------------\n",
"RADIUS_STATOR_HOLE = 20 # 14\n",
"RADIUS_CONNECTIONS_INSIDE = RADIUS_STATOR_HOLE + 3 * TRACK_SPACING # for connecting the bottoms of the coils\n",
"\n",
"RADIUS_COIL_START = 33\n",
"RADIUS_COIL_CENTER = 38\n",
"RADIUS_COIL_CENTER_VIA = RADIUS_COIL_CENTER + 0.5\n",
"RADIUS_COIL_END = 40\n",
"\n",
"RADIUS_CONNECTIONS_OUTSIDE = 53\n",
"RADIUS_CONNECTOR = 53\n",
"\n",
"RADIUS_TOTAL_STATOR = 55\n",
"\n",
"SCREW_HOLE_RADIUS = RADIUS_TOTAL_STATOR # where to put the mounting pins\n",
"\n",
"# many coils (are placed ccw)\n",
"NUM_SEGMENTS = 12\n",
"NUM_COILS = 12\n",
"\n",
"ROTATION = 0\n",
"\n",
"space = RADIUS_COIL_START * np.sin(np.deg2rad(360 / NUM_COILS / 2)) \n",
"TURNS = int(space / (TRACK_SPACING+TRACK_WIDTH))\n",
"\n",
"FILE_NAME = f\"coil_motor_{RADIUS_TOTAL_STATOR}mm.json\"\n",
"\n",
"# meta helper\n",
"coil_windings_width = TURNS * (TRACK_WIDTH+TRACK_SPACING)\n",
"radius_coil_start_effective = round(RADIUS_COIL_START - coil_windings_width, 2)\n",
"radius_coil_end_effective = round(RADIUS_COIL_END + coil_windings_width,2)\n",
"\n",
"print(TURNS)\n",
"print(f\"Effective radius range: {radius_coil_start_effective} - {radius_coil_end_effective}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Arbitrary Coil Generation"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# templates must be convex, simetric around the X axis and must include the center points on both size (e.g. (X1, 0).... (X2, 0) )\n",
"template = [\n",
" (-3.5, 0),\n",
" (-3.5, -0.01),\n",
" (1.9, -1.45),\n",
" (1.9, 0.0),\n",
" (1.9, 1.45),\n",
" (-3.5, 0.01),\n",
"]\n",
"\n",
"def plot_points(template):\n",
" df = pd.DataFrame(template, columns=[\"x\", \"y\"])\n",
" ax = df.plot.line(x=\"x\", y=\"y\", color=\"blue\")\n",
"\n",
" scatter_df = pd.DataFrame(template, columns=[\"x\", \"y\"])\n",
" scatter_df.plot.scatter(x=\"x\", y=\"y\", color=\"red\", ax=ax)\n",
"\n",
" ax.axis(\"equal\")\n",
" plt.grid(True)\n",
" \n",
" ax.text(0.05, 0.95, f\"len= {len(template)}\", transform=ax.transAxes, ha=\"left\")\n",
"\n",
"plot_points(template)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"def calculate_point(point, p_here, p_next, spacing, turn):\n",
" vector = Vector(p_here) - Vector(p_next)\n",
" normal = vector / np.linalg.norm(vector)\n",
" normal = np.array([-normal[1], normal[0]]) # rotate 90 degrees\n",
"\n",
" reference_vector = Vector([-100, 0])\n",
" angle = np.rad2deg(Vector(point).angle_between(reference_vector))\n",
" if point[1] > 0:\n",
" angle = 360 - angle\n",
"\n",
" # move the point along the normal vector by the spacing\n",
" offset = spacing * (turn * 360 + angle) / 360\n",
" coil_point = point + normal * offset\n",
" return (coil_point[0], coil_point[1])\n",
"\n",
"\n",
"def get_coil(template, turns, spacing):\n",
" coil_points = []\n",
" reference_vector = Vector([-100, 0])\n",
"\n",
" for turn in range(turns):\n",
" for index in range(len(template)):\n",
" p_here = template[index]\n",
" turn_here = turn\n",
"\n",
" p_next = template[(index + 1) % len(template)]\n",
"\n",
" turn_here = turn\n",
" turn_next = (turn * len(template) + index + 1) // len(template)\n",
"\n",
" coil_p_here = calculate_point(p_here, p_here, p_next, spacing, turn_here)\n",
" coil_p_next = calculate_point(p_next, p_here, p_next, spacing, turn_next)\n",
"\n",
" if len(coil_points) >= 2:\n",
" \n",
" line1 = Line(\n",
" coil_points[-2],\n",
" np.array(coil_points[-1]) - np.array(coil_points[-2]),\n",
" )\n",
" # create a line from the two new points\n",
" line2 = Line(\n",
" np.array(coil_p_here),\n",
" np.array(np.array(coil_p_here) - np.array(coil_p_next)),\n",
" )\n",
"\n",
" # find the intersection of the two lines\n",
" try: # replace the previous point with the intersection\n",
" intersection = line1.intersect_line(line2)\n",
" coil_points[-1] = intersection\n",
" except: # the lines did not intersect so just add the points\n",
" coil_points.append(coil_p_here)\n",
"\n",
" coil_points.append(coil_p_next)\n",
" else:\n",
" coil_points.append(coil_p_here)\n",
" coil_points.append(coil_p_next)\n",
"\n",
" return coil_points\n",
"\n",
"def coil(template): \n",
" return get_coil(template, TURNS, TRACK_SPACING + TRACK_WIDTH)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Generate a single coil"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"x_from = -3.5\n",
"x_to = 1.9\n",
"y_amp = 1.45\n",
"\n",
"radius_len = RADIUS_COIL_END - RADIUS_COIL_START\n",
"\n",
"angle = round(360/2/NUM_COILS,2)\n",
"y_amp = round(np.sin(np.deg2rad(angle)) * radius_len, 2)\n",
"x_len = round(np.cos(np.deg2rad(angle)) * radius_len, 2)\n",
"\n",
"x_to = RADIUS_COIL_END - RADIUS_COIL_CENTER\n",
"x_from = x_to - x_len\n",
"\n",
"micro = 0.01 #1e-6\n",
"template = [\n",
" (x_from, 0),\n",
" (x_from, -micro),\n",
" (x_to, -y_amp),\n",
" (x_to, 0.0),\n",
" (x_to, y_amp),\n",
" (x_from, +micro)\n",
"]\n",
"shape = [\n",
" (x_from+x_len/2, -y_amp/2),\n",
" (x_to, -y_amp*0.8),\n",
" (x_to, 0),\n",
" (x_from+x_len/2, +y_amp/2),\n",
" (x_to, +y_amp*0.8),\n",
"]\n",
"shape = [\n",
" (x_to, -y_amp),\n",
" (x_to, 0.0),\n",
" (x_to, y_amp),\n",
"]\n",
"# template = shape\n",
"# template.insert(0, (x_from, 0))\n",
"# template.insert(1, (x_from, -micro))\n",
"# # # for i in range(len(shape)):\n",
"# # # j = len(shape)-i-1\n",
"# # # template.append([shape[j][0], -shape[j][1]])\n",
"# template.append((x_from, +micro))\n",
"if 1:\n",
" print(template)\n",
"\n",
" plot_points(template)\n",
" plot_points(optimize_points(coil(template)))\n",
" plot_points(chaikin_(coil(template), 5))\n",
"\n",
" ###############\n",
" template_f = []\n",
" for i in range(len(template)):\n",
" template_f.append(template[len(template) - i - len(template) // 2])\n",
" # print(f\"i = {i}, map = {len(template) - i - len(template) // 2}, template_f = {template_f[i]}\")\n",
"\n",
" template_f = flip_x(template_f)\n",
"\n",
" points_top = chaikin_(flip_x(coil(template_f)), 5)\n",
" points_bot = chaikin_(coil(template), 5)\n",
"\n",
" # add point to middle for via\n",
" points_top = [(RADIUS_COIL_CENTER_VIA - RADIUS_COIL_CENTER, 0)] + points_top\n",
" points_bot = [(RADIUS_COIL_CENTER_VIA - RADIUS_COIL_CENTER, 0)] + points_bot\n",
"\n",
" def plot_tracks_vias(track_points_top, track_points_bot, via_points=0):\n",
"\n",
" df = pd.DataFrame(track_points_top, columns=[\"x\", \"y\"])\n",
" ax = df.plot.line(x=\"x\", y=\"y\", color=\"red\")\n",
" df = pd.DataFrame(track_points_bot, columns=[\"x\", \"y\"])\n",
" ax = df.plot.line(x=\"x\", y=\"y\", color=\"blue\", ax=ax)\n",
"\n",
" if via_points:\n",
" scatter_df = pd.DataFrame(via_points, columns=[\"x\", \"y\"])\n",
" scatter_df.plot.scatter(x=\"x\", y=\"y\", color=\"green\", ax=ax)\n",
"\n",
" ax.axis(\"equal\")\n",
" plt.grid(True)\n",
" ax.text(0.05, 0.95, f\"len= {len(template)}\", transform=ax.transAxes, ha=\"left\")\n",
"\n",
"\n",
" plot_tracks_vias(points_top, points_bot, 0)\n",
"\n",
"\n",
"# Compute Track Length, estimate resistance and print\n",
"def compute_track_length(points):\n",
" track_length = 0\n",
" for i in range(len(points) - 1):\n",
" track_length += np.linalg.norm(np.array(points[i + 1]) - np.array(points[i]))\n",
" return round(track_length,2)\n",
"\n",
"def compute_pcb_track_resistance(length_mm, track_width_mm, copper_thickness_mm=0.035, resistivity=1.68e-8):\n",
" cross_sectional_area_m2 = (track_width_mm / 1000.0) * (copper_thickness_mm / 1000.0)\n",
" resistance_ohms = resistivity * (length_mm / 1000.0) / cross_sectional_area_m2\n",
" return round(resistance_ohms,2)\n",
"\n",
"def print_length_resistance(prepend, points):\n",
" length = compute_track_length(points)\n",
" resistance = compute_pcb_track_resistance(length, TRACK_WIDTH)\n",
" print(f\"{prepend} Track length: {round(length)} mm, resistance: {resistance} \\u03A9\")\n",
"\n",
"print_length_resistance(\"Top \", points_top)\n",
"print_length_resistance(\"Bot \", points_bot)\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Reproduce coils"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"vias = []\n",
"tracks_top = []\n",
"tracks_bot = []\n",
"pads = []\n",
"pins = []\n",
"mounting_holes = []\n",
"silk = []\n",
"components = []\n",
"\n",
"arc_seg = 360 / NUM_COILS\n",
"\n",
"USE_LABELS = False #todo\n",
"\n",
"def angleAt(coil_index):\n",
" return coil_index * arc_seg + ROTATION\n",
"\n",
"def place_coil(coil_points, angle, radius):\n",
" return translate(rotate(coil_points, angle), radius, angle)\n",
"\n",
"# def appendTo(tracks_obj, name, pts):\n",
"# tracks_obj.append({\"net\": name, \"pts\": pts})\n",
" \n",
"# the main coils\n",
"coil_labels = [\"A\", \"B\", \"C\"]\n",
"coils_top = []\n",
"coils_bot = []\n",
"for i in range(NUM_SEGMENTS):\n",
" angle = angleAt(i)\n",
" radius = RADIUS_COIL_CENTER\n",
" if (i // 3) % 2 == 0:\n",
" coil_top = place_coil(points_top, angle, radius)\n",
" coil_bot = place_coil(points_bot, angle, radius)\n",
" else:\n",
" # slightly nudge the coils so that they don't overlap when flipped\n",
" coil_top = place_coil(flip_y(points_top), angle, radius)\n",
" coil_bot = place_coil(flip_y(points_bot), angle, radius)\n",
" \n",
" coils_top.append(coil_top)\n",
" coils_bot.append(coil_bot)\n",
"\n",
" name = COIL_NET_NAME + \"_\"\n",
" if USE_INDIVIDUAL_NET_NAMES_PER_COIL:\n",
" name += str(i).zfill(2)\n",
" if USE_ABC_NET_NAMES_FOR_COILS:\n",
" name += coil_labels[i % 3]\n",
"\n",
" tracks_top.append({\"net\": name, \"pts\": coil_top})\n",
" tracks_bot.append({\"net\": name, \"pts\": coil_bot})\n",
" \n",
" vias.append(create_via(pol2cat(angle, RADIUS_COIL_CENTER_VIA), name))\n",
" silk.append(create_silk(pol2cat(angle, RADIUS_COIL_CENTER), coil_labels[i % 3]))\n",
" # silk.append(create_silk(pol2cat(angle, RADIUS_TOTAL_STATOR), coil_labels[i % 3]))\n",
" silk.append(create_silk(pol2cat(angle+1.5, radius_coil_end_effective+2), coil_labels[i % 3]))\n",
"\n",
"if 1:\n",
" via_points = []\n",
" for via in vias:\n",
" via_points.append([via[\"x\"], via[\"y\"]])\n",
"\n",
" track_points_top = []\n",
" for t in tracks_top:\n",
" for p in t[\"pts\"]:\n",
" track_points_top.append(p)\n",
"\n",
" track_points_bot = []\n",
" for t in tracks_bot:\n",
" for p in t[\"pts\"]:\n",
" track_points_bot.append([p[0], p[1]])\n",
" \n",
" plot_tracks_vias(track_points_top, track_points_bot, via_points)\n",
" \n",
"\n",
"\n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Create coil inner connections"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# all ___At functions are little helpers that take coil_index + sometimes radius\n",
"def pointAt(coil_index, radius):\n",
" return pol2cat(angleAt(coil_index), radius)\n",
"\n",
"def nameAt(coil_index):\n",
" name = COIL_NET_NAME\n",
" if USE_ABC_NET_NAMES_FOR_COILS:\n",
" name += coil_labels[coil_index % 3]\n",
" return name\n",
"\n",
"def appendAt(coils_ref, coil_index, radius):\n",
" coils_ref[coil_index].append(pointAt(coil_index, radius))\n",
"\n",
"def appendVia(coil_index, radius):\n",
" vias.append(create_via(pointAt(coil_index, radius), nameAt(coil_index)))\n",
"\n",
"radius_coni_common = RADIUS_CONNECTIONS_INSIDE\n",
"\n",
"# connects coils with arc and uses last points of coils to connect to the arc\n",
"def connect_coils_auto_arc(c1, c2 , tracks_ref, radius):\n",
" tracks_ref.append({\n",
" \"net\": nameAt(c1),\n",
" \"pts\": (\n",
" [coils_bot[c1][-1]]\n",
" + draw_arc(angleAt(c1), angleAt(c2), radius)\n",
" + [coils_bot[c2][-1]] )}) \n",
" \n",
"def connect_coils_with_arc(c1, c2 , tracks_ref, radius, radius_points):\n",
" pts = draw_arc(angleAt(c1), angleAt(c2), radius)\n",
"\n",
" if radius_points != 0:\n",
" pts = [pointAt(c1, radius_points)] + pts + [pointAt(c2, radius_points)]\n",
"\n",
" tracks_ref.append({\n",
" \"net\": nameAt(c1),\n",
" \"pts\": pts}) \n",
" \n",
" appendAt(coils_top, c1, radius)\n",
" appendAt(coils_top, c2, radius)\n",
"\n",
" # append vias everywhere to connect middle layers properly in parallel.\n",
" appendVia(c1, radius)\n",
" appendVia(c2, radius)\n",
"\n",
"if 1: # create coil ic = inner connections\n",
"\n",
" space = 5 * TRACK_SPACING \n",
"\n",
" radius_coni_A = radius_coni_common + 3 * space + VIA_DIAM / 2\n",
" for c in range(0, 12, 3):\n",
" point = pointAt(c, radius_coni_A)\n",
" coils_bot[c].append(point)\n",
" vias.append(create_via(point, nameAt(c)))\n",
" for con in range(2):\n",
" connect_coils_auto_arc(con*6+0, con*6+3, tracks_top, radius_coni_A)\n",
" \n",
" radius_coni_B = radius_coni_common\n",
" for c in range(1, 12, 3):\n",
" point = pointAt(c, radius_coni_B)\n",
" coils_bot[c].append(point)\n",
" vias.append(create_via(point, nameAt(c)))\n",
" for con in range(2):\n",
" connect_coils_auto_arc(con*6+1, con*6+4, tracks_bot, radius_coni_B)\n",
" \n",
" radius_coni_C = radius_coni_common + 2 * space - VIA_DIAM / 2\n",
" for c in range(2, 12, 3):\n",
" point = pointAt(c, radius_coni_C)\n",
" coils_bot[c].append(point)\n",
" vias.append(create_via(point, nameAt(c)))\n",
" for con in range(2):\n",
" connect_coils_auto_arc(con*6+2, con*6+5, tracks_top, radius_coni_C)\n",
"\n",
"### OUTSIDE CONNECTIONS\n",
"# ------------------------------------------------------------------------------------\n",
"if 1:\n",
" # connects the middle/star point\n",
" r = RADIUS_CONNECTIONS_OUTSIDE\n",
" r_inc = - 5 * TRACK_SPACING \n",
"\n",
" connect_coils_with_arc(9, 11, tracks_top, r, 0)\n",
" appendAt(coils_top, 10, r)\n",
" appendVia(10, r)\n",
"\n",
" r += r_inc\n",
" connect_coils_with_arc(3, 6, tracks_top, r, 0)\n",
"\n",
" r += r_inc\n",
" connect_coils_with_arc(4, 7, tracks_bot, r, 0)\n",
"\n",
" r += r_inc\n",
" connect_coils_with_arc(5, 8, tracks_bot, r, 0,)\n",
"\n",
"# create the pads for connecting the inputs to the coils\n",
"if PAD_ENABLE:\n",
"\n",
" def appendSilk(y, text, size=1, angle=0):\n",
" silk.append(create_silk((RADIUS_CONNECTOR - PAD_HEIGHT - 2.5, y), text, \"f\", 2.5, -900))\n",
"\n",
" appendSilk(+PAD_PITCH, \"C\")\n",
" appendSilk( 0, \"B\")\n",
" appendSilk(-PAD_PITCH, \"A\")\n",
" \n",
" def appendPad(y, name):\n",
" pads.append(create_pad([RADIUS_CONNECTOR, y], PAD_WIDTH, PAD_HEIGHT, \"a\", name))\n",
" \n",
" appendPad(+PAD_PITCH, nameAt(0))\n",
" appendPad(0, nameAt(1))\n",
" appendPad(-PAD_PITCH, nameAt(2))\n",
"\n",
" # connect coil A to the top pad\n",
" pad_connection_point_x = RADIUS_CONNECTOR\n",
" pad_angle = np.rad2deg(np.arcsin(PAD_PITCH / pad_connection_point_x))\n",
" coils_top[0].append(pointAt(0, pad_connection_point_x))\n",
" appendVia(0, pad_connection_point_x)\n",
"\n",
" # connect coil B to the middle pad\n",
" coils_top[1].append((pad_connection_point_x + PAD_WIDTH / 2 + VIA_DIAM / 2, 0))\n",
" vias.append(create_via(\n",
" ((pad_connection_point_x + PAD_WIDTH / 2 + VIA_DIAM / 2, 0)), nameAt(1)))\n",
" \n",
" # connect coil C to the bottom pad\n",
" coils_top[2].append(pointAt(2, pad_connection_point_x))\n",
" appendVia(2, pad_connection_point_x)\n",
"\n",
"elif CONNECT_WITH_VIAS:\n",
" for i in range(3):\n",
" appendAt(coils_top, i, RADIUS_CONNECTOR)\n",
" appendVia(i, RADIUS_CONNECTOR)"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Multi-Layer"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# if we are doing multiple layers then duplicate the front and back layers\n",
"tracks_in = []\n",
"if LAYERS >= 4:\n",
" tracks_in.append(tracks_bot.copy())\n",
" tracks_in.append(tracks_top.copy())\n",
"if LAYERS >= 6:\n",
" tracks_in.append(tracks_bot.copy())\n",
" tracks_in.append(tracks_top.copy())\n",
"if LAYERS == 8:\n",
" tracks_in.append(tracks_bot.copy())\n",
" tracks_in.append(tracks_top.copy())"
]
},
{
"attachments": {},
"cell_type": "markdown",
"metadata": {},
"source": [
"# Generate JSON"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Generate the JSON output file\n",
"if PAD_ENABLE:\n",
" # these final bits of wiring up to the input pads don't need to be duplicated\n",
" tracks_bot.append({\n",
" \"net\": COIL_NET_NAME,\n",
" \"pts\": [\n",
" (pad_connection_point_x + PAD_WIDTH / 2, 0),\n",
" (pad_connection_point_x, 0),\n",
" ],\n",
" })\n",
" tracks_bot.append({\n",
" \"net\": COIL_NET_NAME,\n",
" \"pts\": draw_arc(angleAt(0), -pad_angle, pad_connection_point_x, 1),\n",
" })\n",
" tracks_bot.append({\n",
" \"net\": COIL_NET_NAME,\n",
" \"pts\": draw_arc(angleAt(2), pad_angle, pad_connection_point_x, 1),\n",
" })\n",
"\n",
"nibble_angle_size = 360 * SCREW_HOLE_DRILL_DIAM / (2 * np.pi * RADIUS_TOTAL_STATOR)\n",
"\n",
"if PCB_EDGE_CUTS:\n",
" outer_cuts = (\n",
" draw_arc(\n",
" -45 + nibble_angle_size / 2, 45 - nibble_angle_size / 2, RADIUS_TOTAL_STATOR, 5\n",
" )\n",
" + translate(\n",
" rotate(draw_arc(5, 175, SCREW_HOLE_DRILL_DIAM / 2, 5)[::-1], 135),\n",
" RADIUS_TOTAL_STATOR,\n",
" 45,\n",
" )\n",
" + draw_arc(\n",
" 45 + nibble_angle_size / 2, 135 - nibble_angle_size / 2, RADIUS_TOTAL_STATOR, 5\n",
" )\n",
" + translate(\n",
" rotate(draw_arc(5, 175, SCREW_HOLE_DRILL_DIAM / 2, 5), 225)[::-1],\n",
" RADIUS_TOTAL_STATOR,\n",
" 135,\n",
" )\n",
" + draw_arc(\n",
" 135 + nibble_angle_size / 2, 225 - nibble_angle_size / 2, RADIUS_TOTAL_STATOR, 5\n",
" )\n",
" + translate(\n",
" rotate(draw_arc(5, 175, SCREW_HOLE_DRILL_DIAM / 2, 5), 315)[::-1],\n",
" RADIUS_TOTAL_STATOR,\n",
" 225,\n",
" )\n",
" + draw_arc(\n",
" 225 + nibble_angle_size / 2, 315 - nibble_angle_size / 2, RADIUS_TOTAL_STATOR, 5\n",
" )\n",
" + translate(\n",
" rotate(draw_arc(5, 175, SCREW_HOLE_DRILL_DIAM / 2, 5), 45)[::-1],\n",
" RADIUS_TOTAL_STATOR,\n",
" 315,\n",
" )\n",
" )\n",
"\n",
" edge_cuts = [\n",
" outer_cuts,\n",
" draw_arc(0, 360, RADIUS_STATOR_HOLE, 1),\n",
" ]\n",
"else:\n",
" edge_cuts = []\n",
"\n",
"# dump out the json version\n",
"json_result = dump_json(\n",
" filename=FILE_NAME,\n",
" track_width=TRACK_WIDTH,\n",
" pin_diam=PIN_DIAM,\n",
" pin_drill=PIN_DRILL,\n",
" via_diam=VIA_DIAM,\n",
" via_drill=VIA_DRILL,\n",
" vias=vias,\n",
" pins=pins,\n",
" pads=pads,\n",
" silk=silk,\n",
" tracks_f=tracks_top,\n",
" tracks_in=tracks_in,\n",
" tracks_b=tracks_bot,\n",
" mounting_holes=mounting_holes,\n",
" edge_cuts=edge_cuts,\n",
" components=components,\n",
")"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"plot_json(json_result, 70)\n",
"print(json_result['parameters'])\n",
"\n",
"print(TURNS)\n",
"print(f\"Effective radius range: {radius_coil_start_effective} - {radius_coil_end_effective}\")"
]
}
],
"metadata": {
"kernelspec": {
"display_name": ".venv",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.11.6"
},
"vscode": {
"interpreter": {
"hash": "97df458a008df4bb35f481235dd1a04940c0d868e77540a7386d9922f34deb97"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}