diff --git a/coil_generator-12.ipynb b/coil_generator-12.ipynb new file mode 100644 index 0000000..5271a70 --- /dev/null +++ b/coil_generator-12.ipynb @@ -0,0 +1,681 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "import numpy as np\n", + "\n", + "# import matplotlib as plt\n", + "import matplotlib.pyplot as plt\n", + "import scipy\n", + "from skspatial.objects import LineSegment, Line, Vector\n", + "from enum import Enum\n", + "\n", + "Layer = Enum(\"Layer\", \"FRONT BACK\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "VIA_DIAM = 0.8\n", + "VIA_DRILL = 0.4\n", + "STATOR_HOLE_RADIUS = 5\n", + "TRACK_WIDTH = 0.127\n", + "TRACK_SPACING = 0.127\n", + "TURNS = 9\n", + "STATOR_RADIUS = 18\n", + "PIN_DIAM = 1.7\n", + "COIL_CENTER_RADIUS = 11.5\n", + "COIL_VIA_RADIUS = 12.5\n", + "# where to place the pins\n", + "CONNECTION_PINS_RADIUS = 16\n", + "USE_SPIRAL = False" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# get the point on an arc at the given angle\n", + "def get_arc_point(angle, radius):\n", + " return (\n", + " radius * np.cos(np.deg2rad(angle)),\n", + " radius * np.sin(np.deg2rad(angle)),\n", + " )\n", + "\n", + "\n", + "# draw an arc\n", + "def draw_arc(start_angle, end_angle, radius, step=10):\n", + " points = []\n", + " for angle in np.arange(start_angle, end_angle + step, step):\n", + " x = radius * np.cos(np.deg2rad(angle))\n", + " y = radius * np.sin(np.deg2rad(angle))\n", + " points.append((x, y))\n", + " return points\n", + "\n", + "\n", + "# roate the points by the required angle\n", + "def rotate(points, angle):\n", + " return [\n", + " [\n", + " x * np.cos(np.deg2rad(angle)) - y * np.sin(np.deg2rad(angle)),\n", + " x * np.sin(np.deg2rad(angle)) + y * np.cos(np.deg2rad(angle)),\n", + " ]\n", + " for x, y in points\n", + " ]\n", + "\n", + "\n", + "# move the points out to the distance at the requited angle\n", + "def translate(points, distance, angle):\n", + " return [\n", + " [\n", + " x + distance * np.cos(np.deg2rad(angle)),\n", + " y + distance * np.sin(np.deg2rad(angle)),\n", + " ]\n", + " for x, y in points\n", + " ]\n", + "\n", + "\n", + "# flip the y coordinate\n", + "def flip_y(points):\n", + " return [[x, -y] for x, y in points]\n", + "\n", + "\n", + "def flip_x(points):\n", + " return [[-x, y] for x, y in points]\n", + "\n", + "\n", + "def create_pad(radius, angle, name):\n", + " return {\n", + " \"x\": radius * np.cos(np.deg2rad(angle)),\n", + " \"y\": radius * np.sin(np.deg2rad(angle)),\n", + " \"name\": name,\n", + " }\n", + "\n", + "\n", + "def create_silk(point, text):\n", + " return {\n", + " \"x\": point[0],\n", + " \"y\": point[1],\n", + " \"text\": text,\n", + " }\n", + "\n", + "\n", + "def create_via(point):\n", + " return {\"x\": point[0], \"y\": point[1]}\n", + "\n", + "\n", + "def create_track(points):\n", + " return [{\"x\": x, \"y\": y} for x, y in points]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Arbitrary Coil Generation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# templates must be simetric around the X axis and must include the center points on both size (e.g. (X1, 0).... (X2, 0) )\n", + "# template must also be convex\n", + "template = [\n", + " (-1.5, 0),\n", + " (-1.5, -0.1),\n", + " (1.9, -0.8),\n", + " (1.9, 0.0),\n", + " (1.9, 0.8),\n", + " (-1.5, 0.1),\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# plot the template shape wrapping around to the first point\n", + "df = pd.DataFrame(template + [template[0]], columns=[\"x\", \"y\"])\n", + "ax = df.plot.line(x=\"x\", y=\"y\", color=\"blue\")\n", + "ax.axis(\"equal\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def calculate_point(point, point1, point2, spacing, turn):\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", + " vector = Vector(point1) - Vector(point2)\n", + " normal = vector / np.linalg.norm(vector)\n", + " # rotate the vector 90 degrees\n", + " normal = np.array([-normal[1], normal[0]])\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_points(template, turns, spacing):\n", + " coil_points = []\n", + " reference_vector = Vector([-100, 0])\n", + " template_index = 0\n", + " template_length = len(template)\n", + " for turn in range(turns * template_length):\n", + " point1 = template[template_index % template_length]\n", + " point2 = template[(template_index + 1) % template_length]\n", + "\n", + " # calculate the new positions of the points\n", + " coil_point1 = calculate_point(\n", + " point1, point1, point2, spacing, template_index // template_length\n", + " )\n", + " coil_point2 = calculate_point(\n", + " point2, point1, point2, spacing, (template_index + 1) // template_length\n", + " )\n", + " # adjust the previous point so that the previous line intersects with this new line\n", + " # this prevents any cutting of corners\n", + " if len(coil_points) >= 2:\n", + " # create a line from the previous two points\n", + " line1 = Line(\n", + " coil_points[len(coil_points) - 2],\n", + " np.array(coil_points[len(coil_points) - 1])\n", + " - np.array(coil_points[len(coil_points) - 2]),\n", + " )\n", + " # create a line from the two new points\n", + " line2 = Line(\n", + " np.array(coil_point1),\n", + " np.array(np.array(coil_point1) - np.array(coil_point2)),\n", + " )\n", + " # find the intersection of the two lines\n", + " try:\n", + " intersection = line1.intersect_line(line2)\n", + " # replace the previous point with the intersection\n", + " coil_points[len(coil_points) - 1] = intersection\n", + " # add the new point\n", + " coil_points.append(coil_point2)\n", + " except:\n", + " # the lines did not intersect so just add the points\n", + " coil_points.append(coil_point1)\n", + " coil_points.append(coil_point2)\n", + " else:\n", + " coil_points.append(coil_point1)\n", + " coil_points.append(coil_point2)\n", + "\n", + " template_index = template_index + 1\n", + " return coil_points\n", + "\n", + "\n", + "def optimize_points(points):\n", + " # follow the line and remove points that are in the same direction as the previous poin\n", + " # keep doing this until the direction changes significantly\n", + " # this is a very simple optimization that removes a lot of points\n", + " # it's not perfect but it's a good start\n", + " optimized_points = []\n", + " for i in range(len(points)):\n", + " if i == 0:\n", + " optimized_points.append(points[i])\n", + " else:\n", + " vector1 = np.array(points[i]) - np.array(points[i - 1])\n", + " vector2 = np.array(points[(i + 1) % len(points)]) - np.array(points[i])\n", + " length1 = np.linalg.norm(vector1)\n", + " length2 = np.linalg.norm(vector2)\n", + " if length1 > 0 and length2 > 0:\n", + " dot = np.dot(vector1, vector2) / (length1 * length2)\n", + " # clamp dot between -1 and 1\n", + " dot = max(-1, min(1, dot))\n", + " angle = np.arccos(dot)\n", + " if angle > np.deg2rad(5):\n", + " optimized_points.append(points[i])\n", + " print(\"Optimised from {} to {} points\".format(len(points), len(optimized_points)))\n", + " return optimized_points\n", + "\n", + "\n", + "def chaikin(points, iterations):\n", + " if iterations == 0:\n", + " return points\n", + " l = len(points)\n", + " smoothed = []\n", + " for i in range(l - 1):\n", + " x1, y1 = points[i]\n", + " x2, y2 = points[i + 1]\n", + " smoothed.append([0.95 * x1 + 0.05 * x2, 0.95 * y1 + 0.05 * y2])\n", + " smoothed.append([0.05 * x1 + 0.95 * x2, 0.05 * y1 + 0.95 * y2])\n", + " smoothed.append(points[l - 1])\n", + " return chaikin(smoothed, iterations - 1)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if not USE_SPIRAL:\n", + " template_f = []\n", + " for i in range(len(template)):\n", + " template_f.append(template[len(template) - i - len(template) // 2])\n", + " template_f = flip_x(template_f)\n", + " points_f = chaikin(\n", + " optimize_points(\n", + " flip_x(get_points(template_f, TURNS, TRACK_SPACING + TRACK_WIDTH))\n", + " ),\n", + " 2,\n", + " )\n", + " points_b = chaikin(\n", + " optimize_points(get_points(template, TURNS, TRACK_SPACING + TRACK_WIDTH)), 2\n", + " )\n", + "\n", + " points_f = [(COIL_VIA_RADIUS - COIL_CENTER_RADIUS, 0)] + points_f\n", + " points_b = [(COIL_VIA_RADIUS - COIL_CENTER_RADIUS, 0)] + points_b\n", + "\n", + " df = pd.DataFrame(points_f, columns=[\"x\", \"y\"])\n", + " ax = df.plot.line(x=\"x\", y=\"y\", color=\"blue\")\n", + " ax.axis(\"equal\")\n", + " df = pd.DataFrame(points_b, columns=[\"x\", \"y\"])\n", + " ax = df.plot.line(x=\"x\", y=\"y\", color=\"red\", ax=ax)\n", + "\n", + " print(\"Track points\", len(points_f), len(points_b))\n", + "else:\n", + " print(\"Using spiral\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Basic Spiral Coil Generation" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "def get_spiral(turns, start_radius, thickness, layer=Layer.FRONT):\n", + " points = []\n", + " # create a starting point in the center\n", + " for angle in np.arange(0, turns * 360, 1):\n", + " radius = start_radius + thickness * angle / 360\n", + " if layer == Layer.BACK:\n", + " x = radius * np.cos(np.deg2rad(angle + 180))\n", + " y = radius * np.sin(np.deg2rad(angle + 180))\n", + " points.append((x, -y))\n", + " else:\n", + " x = radius * np.cos(np.deg2rad(angle))\n", + " y = radius * np.sin(np.deg2rad(angle))\n", + " points.append((x, y))\n", + " return points" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if USE_SPIRAL:\n", + " points_f = get_spiral(\n", + " TURNS, VIA_DIAM / 2 + TRACK_SPACING, TRACK_SPACING + TRACK_WIDTH, Layer.FRONT\n", + " )\n", + " points_b = get_spiral(\n", + " TURNS, VIA_DIAM / 2 + TRACK_SPACING, TRACK_SPACING + TRACK_WIDTH, Layer.BACK\n", + " )\n", + "\n", + " points_f = [(COIL_VIA_RADIUS - COIL_CENTER_RADIUS, 0)] + points_f\n", + " points_b = [(COIL_VIA_RADIUS - COIL_CENTER_RADIUS, 0)] + points_b\n", + " print(\"Track points\", len(points_f), len(points_b))\n", + "else:\n", + " print(\"Using template\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Generate PCB Layout" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# calculat the total length of the track to compute the resistance\n", + "total_length_front = 0\n", + "for i in range(len(points_f) - 1):\n", + " total_length_front += np.linalg.norm(\n", + " np.array(points_f[i + 1]) - np.array(points_f[i])\n", + " )\n", + "print(\"Total length front\", total_length_front)\n", + "\n", + "total_length_back = 0\n", + "for i in range(len(points_b) - 1):\n", + " total_length_back += np.linalg.norm(\n", + " np.array(points_b[i + 1]) - np.array(points_b[i])\n", + " )\n", + "print(\"Total length back\", total_length_back)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "vias = []\n", + "tracks_f = []\n", + "tracks_b = []\n", + "pads = []\n", + "silk = []\n", + "\n", + "# create the pads at CONNECTION_PINS radius - 2 for each of the coils, A, B and C\n", + "# angle_A = 0\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_A - 30, \"A\"))\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_A + 30, \"A\"))\n", + "\n", + "# angle_B = 120\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_B - 30, \"B\"))\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_B + 30, \"B\"))\n", + "\n", + "# angle_C = 240\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_C - 30, \"C\"))\n", + "# pads.append(create_pad(CONNECTION_PINS_RADIUS, angle_C + 30, \"C\"))\n", + "\n", + "\n", + "# the main coils\n", + "coil_labels = [\"A\", \"B\", \"C\"]\n", + "coils_f = []\n", + "coils_b = []\n", + "for i in range(12):\n", + " angle = i * 360 / 12\n", + " if (i // 3) % 2 == 0:\n", + " coil_A_f = translate(rotate(points_f, angle), COIL_CENTER_RADIUS, angle)\n", + " coil_A_b = translate(rotate(points_b, angle), COIL_CENTER_RADIUS, angle)\n", + " else:\n", + " coil_A_f = translate(rotate(flip_y(points_f), angle), COIL_CENTER_RADIUS, angle)\n", + " coil_A_b = translate(rotate(flip_y(points_b), angle), COIL_CENTER_RADIUS, angle)\n", + " # keep track of the coils\n", + " coils_f.append(coil_A_f)\n", + " coils_b.append(coil_A_b)\n", + "\n", + " tracks_f.append(coil_A_f)\n", + " tracks_b.append(coil_A_b)\n", + " vias.append(create_via(get_arc_point(angle, COIL_VIA_RADIUS)))\n", + " silk.append(\n", + " create_silk(get_arc_point(angle, COIL_CENTER_RADIUS), coil_labels[i % 3])\n", + " )\n", + "\n", + "# raidus for connecting the bottoms of the coils together\n", + "connection_radius1 = STATOR_HOLE_RADIUS + TRACK_SPACING + TRACK_WIDTH\n", + "\n", + "# create tracks to link the A coils around the center\n", + "connection_via_radius_A = connection_radius1 + TRACK_SPACING + VIA_DIAM / 2\n", + "coil_A1_A2_inner = (\n", + " [get_arc_point(0, connection_via_radius_A)]\n", + " + draw_arc(0, 3 * 360 / 12, connection_radius1)\n", + " + [get_arc_point(3 * 360 / 12, connection_via_radius_A)]\n", + ")\n", + "tracks_f.append(coil_A1_A2_inner)\n", + "coil_A3_A4_inner = (\n", + " [get_arc_point(6 * 360 / 12, connection_via_radius_A)]\n", + " + draw_arc(6 * 360 / 12, 9 * 360 / 12, connection_radius1)\n", + " + [get_arc_point(9 * 360 / 12, connection_via_radius_A)]\n", + ")\n", + "tracks_f.append(coil_A3_A4_inner)\n", + "# connect up the bottoms of the A coils\n", + "coils_b[0].append(coil_A1_A2_inner[0])\n", + "coils_b[3].append(coil_A1_A2_inner[-1])\n", + "coils_b[6].append(coil_A3_A4_inner[0])\n", + "coils_b[9].append(coil_A3_A4_inner[-1])\n", + "# add the vias to stitch them together\n", + "vias.append(create_via(coil_A1_A2_inner[0]))\n", + "vias.append(create_via(coil_A1_A2_inner[-1]))\n", + "vias.append(create_via(coil_A3_A4_inner[0]))\n", + "vias.append(create_via(coil_A3_A4_inner[-1]))\n", + "\n", + "# create tracks to link the B coils around the center - this can all be done on the bottom layer\n", + "coil_B1_B2_inner = draw_arc(1 * 360 / 12, 4 * 360 / 12, connection_radius1)\n", + "tracks_b.append(coil_B1_B2_inner)\n", + "coil_B3_B4_inner = draw_arc(7 * 360 / 12, 10 * 360 / 12, connection_radius1)\n", + "tracks_b.append(coil_B3_B4_inner)\n", + "# connect up the bottoms of the A coils\n", + "coils_b[1].append(coil_B1_B2_inner[0])\n", + "coils_b[4].append(coil_B1_B2_inner[-1])\n", + "coils_b[7].append(coil_B3_B4_inner[0])\n", + "coils_b[10].append(coil_B3_B4_inner[-1])\n", + "\n", + "# create tracks to link the C coils around the center\n", + "connection_via_radius_C = connection_via_radius_A + TRACK_SPACING + VIA_DIAM / 2\n", + "coil_C1_C2_inner = draw_arc(2 * 360 / 12, 5 * 360 / 12, connection_via_radius_C)\n", + "tracks_f.append(coil_C1_C2_inner)\n", + "coil_C3_C4_inner = draw_arc(8 * 360 / 12, 11 * 360 / 12, connection_via_radius_C)\n", + "tracks_f.append(coil_C3_C4_inner)\n", + "# connect up the bottoms of the B coils\n", + "coils_b[2].append(coil_C1_C2_inner[0])\n", + "coils_b[5].append(coil_C1_C2_inner[-1])\n", + "coils_b[8].append(coil_C3_C4_inner[0])\n", + "coils_b[11].append(coil_C3_C4_inner[-1])\n", + "# add the vias to stitch them together\n", + "vias.append(create_via(coil_C1_C2_inner[0]))\n", + "vias.append(create_via(coil_C1_C2_inner[-1]))\n", + "vias.append(create_via(coil_C3_C4_inner[0]))\n", + "vias.append(create_via(coil_C3_C4_inner[-1]))\n", + "\n", + "# connect the last three coils together\n", + "common_connection_radius = STATOR_RADIUS - TRACK_SPACING - TRACK_WIDTH\n", + "tracks_f.append(draw_arc(9 * 360 / 12, 11 * 360 / 12, common_connection_radius))\n", + "coils_f[9].append(get_arc_point(9 * 360 / 12, common_connection_radius))\n", + "coils_f[10].append(get_arc_point(10 * 360 / 12, common_connection_radius))\n", + "coils_f[11].append(get_arc_point(11 * 360 / 12, common_connection_radius))\n", + "\n", + "# connect the outer A coils together\n", + "outer_connection_radius_A = STATOR_RADIUS - TRACK_SPACING - TRACK_WIDTH\n", + "tracks_f.append(draw_arc(3 * 360 / 12, 6 * 360 / 12, outer_connection_radius_A))\n", + "coils_f[3].append(get_arc_point(3 * 360 / 12, outer_connection_radius_A))\n", + "coils_f[6].append(get_arc_point(6 * 360 / 12, outer_connection_radius_A))\n", + "\n", + "# connect the outer B coils together\n", + "outer_connection_radius_B = outer_connection_radius_A - TRACK_SPACING - VIA_DIAM / 2\n", + "tracks_b.append(\n", + " [get_arc_point(4 * 360 / 12, outer_connection_radius_B)]\n", + " + draw_arc(4 * 360 / 12, 7 * 360 / 12, outer_connection_radius_A)\n", + " + [get_arc_point(7 * 360 / 12, outer_connection_radius_B)]\n", + ")\n", + "coils_f[4].append(get_arc_point(4 * 360 / 12, outer_connection_radius_B))\n", + "coils_f[7].append(get_arc_point(7 * 360 / 12, outer_connection_radius_B))\n", + "vias.append(create_via(get_arc_point(4 * 360 / 12, outer_connection_radius_B)))\n", + "vias.append(create_via(get_arc_point(7 * 360 / 12, outer_connection_radius_B)))\n", + "\n", + "# connect the outer C coilds together\n", + "outer_connection_radius_C = outer_connection_radius_B - TRACK_SPACING - VIA_DIAM / 2\n", + "tracks_b.append(draw_arc(5 * 360 / 12, 8 * 360 / 12, outer_connection_radius_C))\n", + "coils_f[5].append(get_arc_point(5 * 360 / 12, outer_connection_radius_C))\n", + "coils_f[8].append(get_arc_point(8 * 360 / 12, outer_connection_radius_C))\n", + "vias.append(create_via(get_arc_point(5 * 360 / 12, outer_connection_radius_C)))\n", + "vias.append(create_via(get_arc_point(8 * 360 / 12, outer_connection_radius_C)))\n", + "\n", + "# create pads for the input\n", + "pin_radius = STATOR_RADIUS - TRACK_SPACING - PIN_DIAM / 2\n", + "pads.append(create_pad(pin_radius, 0, \"A\"))\n", + "pads.append(create_pad(pin_radius, 1 * 360 / 12, \"B\"))\n", + "pads.append(create_pad(pin_radius, 2 * 360 / 12, \"C\"))\n", + "\n", + "coils_f[0].append(get_arc_point(0, pin_radius))\n", + "coils_f[1].append(get_arc_point(1 * 360 / 12, pin_radius))\n", + "coils_f[2].append(get_arc_point(2 * 360 / 12, pin_radius))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# dump out the results to json\n", + "json_result = {\n", + " \"parameters\": {\n", + " \"trackWidth\": TRACK_WIDTH,\n", + " \"statorHoleRadius\": STATOR_HOLE_RADIUS,\n", + " \"statorRadius\": STATOR_RADIUS,\n", + " \"viaDiameter\": VIA_DIAM,\n", + " \"viaDrillDiameter\": VIA_DRILL,\n", + " },\n", + " \"vias\": vias,\n", + " \"pads\": pads,\n", + " \"silk\": silk,\n", + " \"tracks\": {\n", + " \"f\": [create_track(points) for points in tracks_f],\n", + " \"b\": [create_track(points) for points in tracks_b],\n", + " },\n", + "}\n", + "\n", + "import json\n", + "\n", + "json.dump(json_result, open(\"coil.json\", \"w\"))\n", + "\n", + "\n", + "# df = pd.DataFrame(coil_A_f, columns=[\"x\", \"y\"])\n", + "# ax = df.plot.line(x=\"x\", y=\"y\", label=\"Coil A\", color=\"blue\")\n", + "# ax.axis(\"equal\")\n", + "# df = pd.DataFrame(coil_A_b, columns=[\"x\", \"y\"])\n", + "# ax = df.plot.line(x=\"x\", y=\"y\", label=\"Coil B\", color=\"green\")\n", + "# ax.axis(\"equal\")\n", + "\n", + "\n", + "# plot the back tracks\n", + "ax = None\n", + "for track in json_result[\"tracks\"][\"b\"]:\n", + " df = pd.DataFrame(track, columns=[\"x\", \"y\"])\n", + " ax = df.plot.line(x=\"x\", y=\"y\", color=\"blue\", ax=ax)\n", + " ax.axis(\"equal\")\n", + "\n", + "# plot the front tracks\n", + "for track in json_result[\"tracks\"][\"f\"]:\n", + " df = pd.DataFrame(track, columns=[\"x\", \"y\"])\n", + " ax = df.plot.line(x=\"x\", y=\"y\", color=\"red\", ax=ax)\n", + " ax.axis(\"equal\")\n", + "\n", + "# hide the legend\n", + "ax.legend().set_visible(False)\n", + "# make the plot bigger\n", + "ax.figure.set_size_inches(10, 10)\n", + "\n", + "# plot the vias\n", + "for via in json_result[\"vias\"]:\n", + " ax.add_patch(\n", + " plt.Circle(\n", + " (via[\"x\"], via[\"y\"]),\n", + " radius=VIA_DIAM / 2,\n", + " fill=True,\n", + " color=\"black\",\n", + " )\n", + " )\n", + " ax.add_patch(\n", + " plt.Circle(\n", + " (via[\"x\"], via[\"y\"]),\n", + " radius=VIA_DRILL / 2,\n", + " fill=True,\n", + " color=\"white\",\n", + " )\n", + " )\n", + "\n", + "# plot the edge cuts\n", + "ax.add_patch(\n", + " plt.Circle(\n", + " (0, 0),\n", + " radius=STATOR_RADIUS,\n", + " fill=False,\n", + " color=\"yellow\",\n", + " )\n", + ")\n", + "ax.add_patch(\n", + " plt.Circle(\n", + " (0, 0),\n", + " radius=STATOR_HOLE_RADIUS,\n", + " fill=False,\n", + " color=\"yellow\",\n", + " )\n", + ")\n", + "\n", + "# plot the pads\n", + "for pad in json_result[\"pads\"]:\n", + " ax.add_patch(\n", + " plt.Circle(\n", + " (pad[\"x\"], pad[\"y\"]),\n", + " radius=1.7 / 2,\n", + " fill=True,\n", + " color=\"yellow\",\n", + " )\n", + " )\n", + " ax.add_patch(\n", + " plt.Circle(\n", + " (pad[\"x\"], pad[\"y\"]),\n", + " radius=1.0 / 2,\n", + " fill=True,\n", + " color=\"white\",\n", + " )\n", + " )\n", + "\n", + "# plot the silk\n", + "for silk in json_result[\"silk\"]:\n", + " ax.text(\n", + " silk[\"x\"],\n", + " silk[\"y\"],\n", + " silk[\"text\"],\n", + " horizontalalignment=\"center\",\n", + " verticalalignment=\"center\",\n", + " color=\"black\",\n", + " fontsize=50,\n", + " )" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3.10.7 ('venv': 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.10.7" + }, + "vscode": { + "interpreter": { + "hash": "fc384f9db26c31784edfba3761ba3d2c7b2f9b8a63e03a9eb0778fc35334efe1" + } + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/coil_generator.ipynb b/coil_generator.ipynb index 2f8aedd..1e8251c 100644 --- a/coil_generator.ipynb +++ b/coil_generator.ipynb @@ -168,7 +168,7 @@ " coil_point2 = calculate_point(\n", " point2, point1, point2, spacing, (template_index + 1) // template_length\n", " )\n", - " # add an intermediate point which is the intersection of this new line with the previous line (if there is one)\n", + " # adjust the previous point so that the previous line intersects with this new line\n", " # this prevents any cutting of corners\n", " if len(coil_points) >= 2:\n", " # create a line from the previous two points\n", @@ -185,11 +185,17 @@ " # find the intersection of the two lines\n", " try:\n", " intersection = line1.intersect_line(line2)\n", - " coil_points.append(intersection)\n", + " # replace the previous point with the intersection\n", + " coil_points[len(coil_points) - 1] = intersection\n", + " # add the new point\n", + " coil_points.append(coil_point2)\n", " except:\n", - " pass\n", - " coil_points.append(coil_point1)\n", - " coil_points.append(coil_point2)\n", + " # the lines did not intersect so just add the points\n", + " coil_points.append(coil_point1)\n", + " coil_points.append(coil_point2)\n", + " else:\n", + " coil_points.append(coil_point1)\n", + " coil_points.append(coil_point2)\n", "\n", " template_index = template_index + 1\n", " return coil_points\n", @@ -479,7 +485,7 @@ "\n", "# wires for connecting to opposite coils\n", "connection_radius1 = STATOR_HOLE_RADIUS + (2 * TRACK_SPACING)\n", - "connection_radius2 = connection_radius1 + (2 * TRACK_SPACING + VIA_DIAM / 2)\n", + "connection_radius2 = connection_radius1 + (TRACK_SPACING + VIA_DIAM / 2)\n", "\n", "# draw a 45 degree line from each coil at connection radius 1\n", "# then connect up to connection radius 2\n",