|
|
#usage "<qt><nobr>This ULP calculates and place a coil.<p>"
|
|
|
"Depending from where you are starting the ULP, places pads (library) or vias (board).<p>"
|
|
|
"The calculation of coils or inductivities depends on a lot of "
|
|
|
"different factors, like<br>"
|
|
|
" -- basic material of the board<br>"
|
|
|
" -- thickness of the board<br>"
|
|
|
" -- number of layers<br>"
|
|
|
" -- thickness of the layers<br>"
|
|
|
" -- distances between elements<br>"
|
|
|
" -- tracks<br>"
|
|
|
" -- copper areas / ground plains<br>"
|
|
|
" -- thickness of the copper layers<br>"
|
|
|
" -- track width<br>"
|
|
|
" -- distances between tracks<br>"
|
|
|
" -- surface of tracks (tin?)<br>"
|
|
|
" -- the signal's frequency<br>"
|
|
|
" -- ...<br>"
|
|
|
"All these factors should be taken into consideration for the formula !<br>"
|
|
|
"used below to calculate an exact value for a coil. Nevertheless it !<br>"
|
|
|
"is necessary to check the result by a practical measurement. It is !<br>"
|
|
|
"very difficult to generate coils with exact values this way.<br>"
|
|
|
"Generally one can say that printed coils can be used in the MHz range only.<br>"
|
|
|
"<author>Author: support@cadsoft.de, </author></nobr></qt>";
|
|
|
|
|
|
// 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 =
|
|
|
"<qt><nobr>Dieses ULP berechnet eine Spiralspule.<p>" +
|
|
|
"Dieses ULP kann in der Libary ebenso wie im Board benutzt werden.<br>" +
|
|
|
"Je nachdem ob Sie es von einer Library oder von einem Borad aus "
|
|
|
"starten, werden Pads bzw. Vias plaziert.<br>" +
|
|
|
"<br>" +
|
|
|
"Die Berechnung der Windungen bzw. der Induktivitaet haengt von vielen Faktoren ab, wie z.B.:<br>" +
|
|
|
" - Basismaterial<br>" +
|
|
|
" - Staerke der Leiterplatte<br>" +
|
|
|
" - Anzahl der Lagen<br>" +
|
|
|
" - Dicke der Lagen<br>" +
|
|
|
" - Abstand zu benachbarten Bauteilen, Leitungen, Kupferflaechen, Masseflaechen etc.<br>" +
|
|
|
" - Dicke der Kupferbeschichtung<br>" +
|
|
|
" - Breite der Leiterbahn (unteraetzen)<br>" +
|
|
|
" - Abstand zwischen den Leiterbahnen (Spiralkreise / Ätzgenauigkeit)<br>" +
|
|
|
" - Oberflaeche der Leiterbahn (Verzinnt)<br>" +
|
|
|
" - Signal-Frequenz<br>" +
|
|
|
" - ...<br>" +
|
|
|
"Um daraus einen einigermassen genauen Wert zu berechnen, muessten alle oben genannten Faktoren<br>" +
|
|
|
"als Korrekturwerte in die Formael einfliessen.<br>" +
|
|
|
"Was aber in jedem Fall durch entspechende Messungen nachgeprueft werden muesste.<br>" +
|
|
|
"In der Praxis sind Printspulen mit genau definierten Werten und in engen Toleranzen " +
|
|
|
"nur sehr schwer herzustellen.<br>" +
|
|
|
"Im Allgemeinen kann man davon ausgehen, dass Printspulen nur im MHz Bereich " +
|
|
|
"einigermassen Nutzbar sind.<br>" +
|
|
|
"<author>Author: support@cadsoft.de, </author></nobr></qt>";
|
|
|
|
|
|
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<39> */
|
|
|
NewArc = (Xalt - Xorigin + 90) + UserArc;
|
|
|
real rad = PI / 180 * NewArc;
|
|
|
return (RADIUS * cos(rad));
|
|
|
}
|
|
|
if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270<37> */
|
|
|
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<39> */
|
|
|
NewArc = (Xalt - Xorigin + 90) + UserArc;
|
|
|
real rad = PI / 180 * NewArc;
|
|
|
return (RADIUS * sin(rad));
|
|
|
}
|
|
|
if ((Xalt == Xorigin) && (Yalt < Yorigin)) { /* 270<37> */
|
|
|
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<37> - 359<35>
|
|
|
// 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<38> - 270<37>
|
|
|
// 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<39> - 180<38>
|
|
|
// 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<39>
|
|
|
// 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 = "<img src=spiral-coil-ulp.bmp>";
|
|
|
|
|
|
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("<hr>");
|
|
|
dlgCell(6, 2) dlgLabel("<hr>");
|
|
|
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("<qt>All measures in <b>mm</b></qt>");
|
|
|
dlgHBoxLayout {
|
|
|
dlgPushButton("+&OK") { dlgAccept(); doit(); }
|
|
|
dlgPushButton("-&Cancel") { dlgReject(); exit(0); }
|
|
|
dlgStretch(1);
|
|
|
dlgPushButton("&Help") dlgMessageBox(Help, "Ok");
|
|
|
}
|
|
|
};
|
|
|
|
|
|
|