#usage "This ULP calculates and place a coil.

" "Depending from where you are starting the ULP, places pads (library) or vias (board).

" "The calculation of coils or inductivities depends on a lot of " "different factors, like
" " -- basic material of the board
" " -- thickness of the board
" " -- number of layers
" " -- thickness of the layers
" " -- distances between elements
" " -- tracks
" " -- copper areas / ground plains
" " -- thickness of the copper layers
" " -- track width
" " -- distances between tracks
" " -- surface of tracks (tin?)
" " -- the signal's frequency
" " -- ...
" "All these factors should be taken into consideration for the formula !
" "used below to calculate an exact value for a coil. Nevertheless it !
" "is necessary to check the result by a practical measurement. It is !
" "very difficult to generate coils with exact values this way.
" "Generally one can say that printed coils can be used in the MHz range only.
" "Author: support@cadsoft.de,
"; // THIS PROGRAM IS PROVIDED AS IS AND WITHOUT WARRANTY OF ANY KIND, // EXPRESSED OR IMPLIED. #require 4.1106 string Help = usage; // **************----- german description -------------*************** // ---------------------------------------------------------------- string deHelp = "Dieses ULP berechnet eine Spiralspule.

" + "Dieses ULP kann in der Libary ebenso wie im Board benutzt werden.
" + "Je nachdem ob Sie es von einer Library oder von einem Borad aus " "starten, werden Pads bzw. Vias plaziert.
" + "
" + "Die Berechnung der Windungen bzw. der Induktivitaet haengt von vielen Faktoren ab, wie z.B.:
" + " - Basismaterial
" + " - Staerke der Leiterplatte
" + " - Anzahl der Lagen
" + " - Dicke der Lagen
" + " - Abstand zu benachbarten Bauteilen, Leitungen, Kupferflaechen, Masseflaechen etc.
" + " - Dicke der Kupferbeschichtung
" + " - Breite der Leiterbahn (unteraetzen)
" + " - Abstand zwischen den Leiterbahnen (Spiralkreise / Ätzgenauigkeit)
" + " - Oberflaeche der Leiterbahn (Verzinnt)
" + " - Signal-Frequenz
" + " - ...
" + "Um daraus einen einigermassen genauen Wert zu berechnen, muessten alle oben genannten Faktoren
" + "als Korrekturwerte in die Formael einfliessen.
" + "Was aber in jedem Fall durch entspechende Messungen nachgeprueft werden muesste.
" + "In der Praxis sind Printspulen mit genau definierten Werten und in engen Toleranzen " + "nur sehr schwer herzustellen.
" + "Im Allgemeinen kann man davon ausgehen, dass Printspulen nur im MHz Bereich " + "einigermassen Nutzbar sind.
" + "Author: support@cadsoft.de,
"; if (language() == "de") Help = deHelp; // 05.06.2002 alf@cadsoft.de // 24.01.2005 alf@cadsoft.de // ****************************************************************** // Parameterliste -- parameter section real n = 4.0; // number of turns real Wirewidth_mm = 0.2; // track width real Wiredistance_mm = 0.2; // min. distance between tracks real Diameter = 0.6; // pad/via diameter real Drill = 0.4; // drill diameter real offx = 0.0; real offy = 0.0; real UserArc; int windn; int wind1; // count of total turns real windlast; // reminder Turn real Ndist; // distance between turns string Shape = "ROUND"; // Pad/Via-Form nicht veraendern string direction = "CCW"; // *** Drehrichtung der Spirale nicht veraendern *** // *** Direction do not change *** string solderpoint; string cmd = ""; string s; int Layer = 1; /* calculate X coordinate by Radius */ real Xneu(real Xalt, real Yalt, real Xorigin, real Yorigin, real UserArc) { real RADIUS = sqrt(((Xalt - Xorigin) * (Xalt - Xorigin)) + ((Yalt - Yorigin) * (Yalt - Yorigin))); real NewArc; /* alter Cosinus Winkel = (Xalt - Xorigin) / RADIUS; */ { if ((Xalt > Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 1 */ NewArc = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt < Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 2 */ NewArc = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt < Xorigin) && (Yalt < Yorigin)) { /* Quadrant 3 */ NewArc = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt > Xorigin) && (Yalt < Yorigin)) { /* Quadrant 4 */ NewArc = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt == Yorigin)) { /* Ursprung */ NewArc = (Xalt - Xorigin) + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt > Yorigin)) { /* 90° */ NewArc = (Xalt - Xorigin + 90) + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270° */ NewArc = (Xalt - Xorigin + 270)+ UserArc; real rad = PI / 180 * NewArc; return (RADIUS * cos(rad)); } } } /* calculate Y coordinate by Radius */ real Yneu(real Xalt, real Yalt, real Xorigin, real Yorigin, real UserArc) { real RADIUS = sqrt(((Xalt - Xorigin) * (Xalt - Xorigin)) + ((Yalt - Yorigin) * (Yalt - Yorigin))); real NewArc; /* alter Cosinus Winkel = (Xalt - Xorigin) / RADIUS; */ { if ((Xalt > Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 1 */ NewArc = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt < Xorigin) && (Yalt >= Yorigin)) { /* Quadrant 2 */ NewArc = acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt < Xorigin) && (Yalt < Yorigin)) { /* Quadrant 3 */ NewArc = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt > Xorigin) && (Yalt < Yorigin)) { /* Quadrant 4 */ NewArc = 360 - acos((Xalt - Xorigin) / RADIUS) * 57.29578 + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt == Yorigin)) { /* Ursprung */ NewArc = (Xalt - Xorigin) + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt > Yorigin)) { /* 90° */ NewArc = (Xalt - Xorigin + 90) + UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270° */ NewArc = (Xalt - Xorigin + 270)+ UserArc; real rad = PI / 180 * NewArc; return (RADIUS * sin(rad)); } } } /* place a Pad (Via) on startpoint */ void PadViaS(real x1, real x2, real w, real g) { real p = x1 + (Wirewidth_mm / 2) - (Diameter / 2); // sprintf( s, "%s (%4.2f %4.2f);\n", solderpoint , p + offx , 0.0 + offy); cmd += s; } /* place a Pad (Via) on endpoint */ void PadViaE(real x1, real x2, real w, real g) { real pRadius = x2 + ((x1 - x2) / 180 * g) + (Diameter / 2) - (Wirewidth_mm / 2) ; real px = Xneu(pRadius, 0, 0, 0, w); real py = Yneu(pRadius, 0, 0, 0, w); sprintf( s, "%s (%4.2f %4.2f);\n", solderpoint, px + offx, py + offy); cmd += s; } void doit(void) { Ndist = (Wiredistance_mm + Wirewidth_mm ) ; // distance ARC to ARC windn = round(n); // liefert x gerundet auf den nächsten Integer-Wert. wind1 = trunc(n); // liefert den ganzzahligen Teil von n. windlast = n - wind1; // rest der letzten Windung UserArc = 360 * windlast; real startarc = 0; real endarc = 0; real end2arc = 0; real Y = 0; int x = 0; real ewx ; real ewy ; sprintf( s, "GRID mm;\n"); cmd += s; sprintf( s, "Change dia %4.2f;\n", Diameter); cmd += s; sprintf( s, "Change shape %s;\n", Shape); cmd += s; sprintf( s, "Change drill %4.2f;\n", Drill); cmd += s; PadViaS( Ndist, Ndist, 0, 0); sprintf( s, "change width %4.3f;\n", Wirewidth_mm); cmd += s; sprintf( s, "Change layer %d;\n", Layer); cmd += s; // full turns for (x = 1; x <= wind1; x++) { // first ARC -|- erster Halbbogen startarc = x * Ndist; endarc = -(x * Ndist + (Ndist / 2)); sprintf( s, "ARC '%s' (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", direction, startarc + offx, Y + offy, endarc + offx, Y + offy, endarc + offx, Y + offy); cmd += s; // second ARC -|- zweiter Halbbogen end2arc = (x + 1) * Ndist; sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", endarc + offx, Y + offy, end2arc + offx, Y + offy, end2arc + offx, Y + offy); cmd += s; } // last turn if (UserArc >= 270) { // ***** 270° - 359° // first ARC -|- erster Halbbogen startarc = (x ) * Ndist; endarc = -((x * Ndist) + (Ndist / 2)); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", startarc + offx, Y + offy, endarc + offx, Y + offy, endarc + offx, Y + offy); cmd += s; // finish ARC -|- letzter Halbbogen end2arc = (x + 1) * Ndist + (Ndist / 8); ewx = Xneu(end2arc, 0, 0, 0, UserArc); ewy = Yneu(end2arc, 0, 0, 0, UserArc); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", endarc + offx, Y + offy, end2arc + offx, Y + offy, ewx + offx, ewy + offy); cmd += s; PadViaE( end2arc, -endarc, UserArc, UserArc - 180); UserArc = 0; } else if (UserArc >= 180) { // ***** 180° - 270° // finish ARC -|- letzter Halbbogen startarc = (x ) * Ndist; endarc = -((x * Ndist) + (Ndist / 2)); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", startarc + offx, Y + offy, endarc + offx, Y + offy, endarc + offx, Y + offy); cmd += s; // finish ARC -|- letzter Halbbogen end2arc = (x + 1) * Ndist + (Ndist / 2); ewx = Xneu(end2arc, 0, 0, 0, UserArc); ewy = Yneu(end2arc, 0, 0, 0, UserArc); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", endarc + offx, Y + offy, end2arc + offx, Y + offy, ewx + offx, ewy + offy); cmd += s; PadViaE(end2arc, -endarc, UserArc, UserArc - 180); UserArc = 0; } else if (UserArc >= 90) { // ***** 90° - 180° // finish ARC -|- letzter Halbbogen startarc = (x ) * Ndist; endarc = -((x * Ndist) + (Ndist / 2)); ewx = Xneu(startarc, 0, 0, 0, UserArc); ewy = Yneu(startarc, 0, 0, 0, UserArc); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", startarc + offx, Y + offy, endarc + offx, Y + offy, ewx + offx, ewy + offy); cmd += s; PadViaE(-endarc, startarc , UserArc, UserArc); UserArc = 0; } else if (UserArc > 0) { // ***** 0° - 90° // finish ARC -|- letzter Halbbogen startarc = (x ) * Ndist; endarc = -((x * Ndist) + (Ndist / 2)); ewx = Xneu(startarc, 0, 0, 0, UserArc); ewy = Yneu(startarc, 0, 0, 0, UserArc); sprintf( s, "ARC (%6.3f %6.3f) (%6.3f %6.3f) (%6.3f %6.3f);\n", startarc + offx, Y + offy, endarc + offx, Y + offy, ewx + offx, ewy + offy); cmd += s; PadViaE(-endarc, startarc ,UserArc, UserArc ); } else if (UserArc == 0) { startarc = (x ) * Ndist; endarc = -((x * Ndist) + (Ndist / 2)); PadViaE(-endarc, startarc ,UserArc, UserArc ); } sprintf( s, "Change Layer tPlace;\n"); sprintf( s, "window (%6.3f %6.3f);\n", offx, offy); cmd += s; exit (cmd); } // *** main *** if (board) board(B) { solderpoint = "VIA"; }; if (library) library(L) {solderpoint = "PAD"; }; string ulp_path = filedir(argv[0]); string Spiral_H = ""; dlgDialog("Copper Spiral") { dlgHBoxLayout { dlgVBoxLayout { dlgHBoxLayout { dlgLabel("&Turns"); // number of turns (Windungen) dlgRealEdit( n, 1.0, 100.0); dlgStretch(1); } dlgLabel(Spiral_H); dlgHBoxLayout { } } dlgVBoxLayout { dlgGridLayout { dlgCell(1, 1) dlgLabel("wire &width 'w'"); // track width dlgCell(1, 2) dlgRealEdit(Wirewidth_mm, 0.01, 25.0); dlgCell(2, 1) dlgLabel("wire &distance 'd'"); // min. distance between tracks dlgCell(2, 2) dlgRealEdit(Wiredistance_mm, .01, 25.0); dlgCell(3, 1) dlgLabel("Via/Pad di&ameter"); // pad/via diameter dlgCell(3, 2) dlgRealEdit(Diameter, 0.1, 10.0); dlgCell(4, 1) dlgLabel("Via/Pad d&rill"); // drill diameter dlgCell(4, 2) dlgRealEdit(Drill, .1, 10.0); dlgCell(5, 1) dlgLabel("&Layer"); // Layer number dlgCell(5, 2) dlgIntEdit(Layer, 1, 255); dlgCell(6, 1) dlgLabel("


"); dlgCell(6, 2) dlgLabel("
"); dlgCell(7, 1) dlgLabel("offset &X"); // place with offset X dlgCell(7, 2) dlgRealEdit( offx ); dlgCell(8, 1) dlgLabel("offset &Y"); // place with offset Y dlgCell(8, 2) dlgRealEdit( offy ); } dlgStretch(1); } } dlgLabel("All measures in mm"); dlgHBoxLayout { dlgPushButton("+&OK") { dlgAccept(); doit(); } dlgPushButton("-&Cancel") { dlgReject(); exit(0); } dlgStretch(1); dlgPushButton("&Help") dlgMessageBox(Help, "Ok"); } };