2020-10-17 04:04:13 +00:00
<!DOCTYPE html>
2020-10-08 07:21:58 +00:00
< html lang = "en" >
2020-10-17 04:04:13 +00:00
< head >
< meta charset = "UTF-8" >
< meta name = "viewport" content = "width=device-width, initial-scale=1.0" >
2021-09-24 04:12:36 +00:00
< title > VK3CPU Magnetic Loop Antenna Calculator< / title >
2020-10-17 04:04:13 +00:00
< link rel = "stylesheet" href = "magloop.css" >
< / head >
< body >
2021-09-22 13:45:46 +00:00
< header > Miguel < a href = "mailto:vk3cpu@gmail.com" > VK3CPU< / a > - Magloop Antenna Calculator V6< / header >
2020-10-21 03:39:46 +00:00
< section class = "gridLayoutClass" >
2020-10-21 04:20:10 +00:00
< div class = "chart-container" style = "position: relative;" >
2020-10-21 03:39:46 +00:00
< canvas id = "chartCanvas" class = "chartCanvasClass" >
2D Chart Canvas
< / canvas >
< / div >
< div class = "slider_container" >
< div class = "sliders" >
2020-11-19 08:57:03 +00:00
< label for = "conductor_diameter_slider" > & #8960a:< / label >
2021-09-19 04:44:00 +00:00
< input type = "range" id = "conductor_diameter_slider" min = "5" max = "80" value = "19" step = "0.2" >
2020-10-20 01:19:12 +00:00
< / div >
2020-10-21 03:39:46 +00:00
< div class = "sliders" >
2020-11-19 08:57:03 +00:00
< label for = "loop_diameter_slider" > & #8960b:< / label >
2021-08-31 11:23:56 +00:00
< input type = "range" id = "loop_diameter_slider" min = "0.2" max = "5.0" value = "1.0" step = "0.01" >
2020-10-21 03:39:46 +00:00
< / div >
< div class = "sliders" >
2020-10-21 04:10:02 +00:00
< label for = "loop_turns_slider" > N:< / label >
2020-10-21 03:39:46 +00:00
< input type = "range" id = "loop_turns_slider" min = "1" max = "8" value = "1.0" step = "1.0" >
< / div >
< div class = "sliders" >
2020-11-19 08:57:03 +00:00
< label for = "loop_spacing_slider" > c/a:< / label >
2021-09-22 10:51:31 +00:00
< input type = "range" id = "loop_spacing_slider" min = "1.1" max = "10.0" value = "2.0" step = "0.01" >
2020-10-21 03:39:46 +00:00
< / div >
< div class = "sliders" >
2020-10-21 04:10:02 +00:00
< label for = "transmit_power_slider" > Tx:< / label >
2021-08-31 11:23:56 +00:00
< input type = "range" id = "transmit_power_slider" min = "5" max = "1500" value = "100" step = "5" >
2020-10-21 03:39:46 +00:00
< / div >
2021-09-22 13:12:41 +00:00
< div class = "sliders" >
< label for = "external_losses_slider" > Re:< / label >
< input type = "range" id = "external_losses_slider" min = "0" max = "1000" value = "0" step = "1" >
< / div >
2021-08-28 03:06:12 +00:00
< div class = "radios" >
2021-09-18 07:08:52 +00:00
< label > Met< / label >
2021-08-28 04:06:36 +00:00
< input type = "radio" name = "unit_radio" id = "metric_radio" value = "metric" checked / >
2021-09-18 07:08:52 +00:00
< label > Imp< / label >
2021-08-28 04:06:36 +00:00
< input type = "radio" name = "unit_radio" id = "imperial_radio" value = "imperial" / >
< label > Cu< / label >
< input type = "radio" name = "metal_radio" id = "copper_radio" value = "copper" checked / >
< label > Al< / label >
< input type = "radio" name = "metal_radio" id = "aluminium_radio" value = "aluminium" / >
2021-09-16 02:50:54 +00:00
< label > Circ< / label >
< input type = "radio" name = "shape_radio" id = "circle_radio" value = "circle" checked / >
< label > Oct< / label >
2021-09-18 07:08:52 +00:00
< input type = "radio" name = "shape_radio" id = "oct_radio" value = "octagon" / >
2021-09-16 02:50:54 +00:00
< label > Hex< / label >
2021-09-18 07:08:52 +00:00
< input type = "radio" name = "shape_radio" id = "hex_radio" value = "hexagon" / >
2021-09-16 02:50:54 +00:00
< label > Sqr< / label >
< input type = "radio" name = "shape_radio" id = "square_radio" value = "square" / >
2021-08-28 03:06:12 +00:00
< / div >
2020-10-21 03:39:46 +00:00
< / div >
< div id = "antenna-front-container" class = "antennaFront-container" style = "position: relative;" >
2020-10-23 05:55:31 +00:00
< canvas id = "antennaFront2D" class = "antennaFrontClass" width = "150" height = "150" >
2020-10-20 01:19:12 +00:00
< / canvas >
2020-10-21 03:39:46 +00:00
< / div >
< div id = "antenna-side-container" class = "antennaSide-container" style = "position: relative;" >
2020-10-23 05:55:31 +00:00
< canvas id = "antennaSide2D" class = "antennaSideClass" width = "150" height = "150" >
2020-10-21 03:39:46 +00:00
< / canvas >
< / div >
2020-11-19 08:57:03 +00:00
< div class = "notes" >
2021-09-18 07:08:52 +00:00
< p style = "text-align:center" > < b > < u > < a href = "./magloop_equations.html" > EQUATIONS USED < / a > < / u > < / b > < / p >
< b > < u > Notes:< / u > < / b > < br >
The Magloop Antenna Calculator was developed to predict the characteristics of a small-loop (aka "magnetic loop" or "magloop")
2021-09-18 08:37:03 +00:00
antenna, given physical dimensions entered via slider widgets. < br >
It supports:
< ul >
< li > circular, octagonal, hexagonal and square-shaped loops< / li >
< li > main loops made from either hollow round anodised-copper or aluminium conductors< / li >
< li > metric and imperial units< / li >
< / ul >
I developed this multi-turn capable magloop calculator to take advantage of the
2020-11-19 08:57:03 +00:00
touch-screens and high-speed of modern mobile phones, to allow users to get realtime feedback of the predicted
2021-09-09 13:39:43 +00:00
behaviour of a magloop antenna. This would help a radio amateur to decide on the characteristics for the build. < br > -- 73 de VK3CPU< br > < br >
2021-09-12 04:58:07 +00:00
< u > < b > Inputs via the slider and radio widgets:< / b > < / u >
2020-11-19 08:57:03 +00:00
< ul >
2021-09-19 04:23:58 +00:00
< li > & #8960a : Conductor diameter in millimeters (mm) or inches ("). (Measured between opposing conductor outer surfaces.)< / li >
< li > & #8960b : Loop diameter in meters (m) or feet ('). (Measured between the conductor centers.)< / li >
2020-11-19 08:57:03 +00:00
< li > N : Number of turns or loops.< / li >
2021-07-27 04:47:29 +00:00
< li > c/a : is the spacing ratio; based on 'c' being the inter-winding spacing for multi-turn loops measured between conductor centers, and 'a' is the conductor diameter. (Must be >= 1.1)
2021-09-18 22:18:51 +00:00
A low-value will increase the resistance due to the proximity effect. (Ignore for single-turn loops.)< / li >
2021-09-12 04:55:58 +00:00
< li > Tx : The transmit power in Watts. This affects the predicted voltage across the capacitor (Vcap), and the RMS loop current (Ia).< / li >
2021-09-24 05:12:29 +00:00
< li > Re : Additional resistance due to external losses, due mainly from capacitor contact resistance and proximity-to-ground effects.
Use Re=0.0 to assume the loop is in free-space with no capacitor losses (i.e. ideal conditions, with loop-related losses only).
Adding Re will reduce antenna efficiency, Q, Vcap and Ia, while increasing antenna BW.
According to [1] and [2], a 1 m diameter loop of 22 mm copper tubing at a height of 1.5 m above the ground operating at 7 MHz had a calculated capacitor contact resistance of ~190 mΩ
and an additional ground proximity loss resistance of ~30 mΩ . Note that true ground losses are dependent on both frequency and height-above-ground.< / li >
2021-08-28 04:44:16 +00:00
< li > Metric or Imperial : selects the measuring system.< / li >
2021-09-02 12:47:21 +00:00
< li > Cu or Al : selects the type of metal conductor (annealed copper or aluminum).< / li >
2021-09-18 07:27:34 +00:00
< li > Circ, Oct, Hex or Sqr : selects the shape of the magloop.< / li >
2020-11-19 08:57:03 +00:00
< / ul >
2021-09-12 04:58:07 +00:00
< u > < b > Calculated parameters:< / b > < / u >
2021-09-01 13:29:19 +00:00
< ul >
< li > L : Inductance in microhenries.< / li >
< li > A : Loop area in square meters or square feet.< / li >
2021-09-20 14:03:03 +00:00
< li > C : Effective capacitance of the loop in picofarads.< / li >
2021-09-18 07:08:52 +00:00
< li > peri : Perimeter of the main loop in meters or feet.< / li >
2021-09-01 13:29:19 +00:00
< li > c : Distance between windings, measured from the conductor centers in mm or inches.< / li >
2021-09-18 07:08:52 +00:00
< li > cond : Total required conductor length in meters or feet.< / li >
2021-09-01 13:29:19 +00:00
< li > Tuning Cap (pF): The capacitance required to bring the loop into resonance at the given frequency. Value in picofarads.< / li >
< li > Vcap (kV): The predicted voltage across the capacitance given the desired transmit power.< / li >
2021-09-19 01:04:13 +00:00
< li > BW (kHz): The predicted 3dB bandwidth of the magloop antenna. < / li >
< li > Efficiency (%): The percentage of input energy that is actually radiated and not lost as heat.< / li >
2021-09-01 13:29:19 +00:00
< li > R-radiation (& #937): The calculated radiation resistance of the loop in ohms.< / li >
2021-09-22 13:29:00 +00:00
< li > R-loop (& #937): The calculated resistance of the loop in ohms, due to the combination of material conductance, conductor length, skin-effect and proximity effects.< / li >
2021-09-01 13:29:19 +00:00
< li > Reactance (j& #937): The inductive reactance of the loop in ohms.< / li >
2021-09-19 01:04:13 +00:00
< li > Q : The antenna Q (quality) factor.< / li >
2021-09-01 13:29:19 +00:00
< li > Ia (A): The RMS loop current in amps.< / li >
2021-09-22 11:09:02 +00:00
< li > Perimeter (& #955): Antenna perimeter size relative to the wavelength.< / li >
2021-09-01 13:29:19 +00:00
< / ul >
< br >
2021-09-22 13:12:41 +00:00
< b > < u > References:< / u > < / b > < br >
2021-09-22 13:18:33 +00:00
[1]: B. Austin, A. Boswell and M. Perks, < b > "Loss Mechanisms in the Electrically Small Loop Antenna"< / b > < i > , IEEE Antennas and Propagation Magazine, 56, 4, August 2014, pp. 143.< / i > < br >
[2]: A. Boswell, A. J. Tyler and A. White, < b > "Performance of a Small Loop Antenna in the 3 - 10 MHz Band"< / b > < i > , IEEE Antennas and Propagation Magazine, 47, 2, April 2005, pp. 5 1 -56.< / i > < br >
2021-09-22 13:12:41 +00:00
< br >
2021-09-12 09:27:28 +00:00
< b > < u > Change history:< / u > < / b > < br >
2021-09-22 13:12:41 +00:00
< b > [23-Sep-21]< / b > < br >
2021-09-23 10:23:39 +00:00
* Changed Q equation back to the original Xl/Rtot. Changed max Q to 4000.< br >
2021-09-22 13:29:00 +00:00
* Introduced a new slider "Re" to inject external losses to account for the combined losses due to capacitor contact resistance and ground losses.< br >
* Renamed R-loss to R-loop to avoid confusion, as loop resistance is no longer the only resistance that contributes to losses. The other being Re.< br >
2021-09-24 05:13:31 +00:00
* Changed to V6 to capture the significant changes.< br >
2021-09-21 13:22:39 +00:00
< b > [22-Sep-21]< / b > < br >
2021-09-22 10:45:31 +00:00
* Added antenna perimeter size in wavelength to the chart display as a new item.< br >
2021-09-22 10:51:31 +00:00
* Changed maximum spacing ratio c/a from 4.0 to 10.0. Values higher than 4 have no further effect on proximity resistance, but does reduce coil inductance which drives up the SRF.< br >
2021-09-20 14:03:03 +00:00
< b > [21-Sep-21]< / b > < br >
* Added distributed capacitance calculation and display for the single turn loop.< br >
2021-09-19 09:18:57 +00:00
< b > [19-Sep-21]< / b > < br >
* Increased supported conductor diameter to 80 mm. (3.15 inches)< br >
2021-09-18 07:08:52 +00:00
< b > [18-Sep-21]< / b > < br >
* Updated to V5; Added support for octagon, hexagon and square shaped loops. Moved and hyperlinked equations-used to a separate page for clarity.< br >
< b > [16-Sep-21]< / b > < br >
2021-09-22 13:12:41 +00:00
* Updated to V4; Updated equation used for Q to match the one use in the ARRL Antenna Book. This will affect predictions for V_cap, I_loop and BW. (Based on Q equation D.1 used in
2021-09-18 07:08:52 +00:00
< i > "Impedance, Bandwidth, and Q of Antennas"< / i > by A D Yaghjian, IEEE Transactions on Antennas and Propagation, April 2005.)< br >
* Added equation graphics for V_cap, I_loop and BW formulas.< br >
* Flipped the main-loop graphic to have the capacitor above the coupling loop.< br >
< b > [12-Sep-21]< / b > < br >
* Set maximum values to Q, Vcap and I axes to stop autoscaling. Max Q set to 2000, Vcap to 20 kV and I to 100 A.< br >
* Added formula/equation graphics in Notes section. A few more complex ones, such as effective capacitance and SRF, are still needed.< br >
* Fixed minor error in calculation of resistive loss due to proximity effect.< br >
< b > [11-Sep-21]< / b > < br >
* Added visual cues for all slider-controlled parameters to highlight which parameter is being modified in the graphic representation.< br >
< b > [10-Sep-21]< / b > < br >
* Added c/a display to graphic representation. Moved N from center to left.< br >
< b > [30-Aug-21]< / b > < br >
* Added SRF calculation and display for multi-loop antennas.< br >
< b > [28-Aug-21]< / b > < br >
* Added support for imperial units and for aluminum metal.< br >
< b > [27-Jul-21]< / b > < br >
* Added total conductor length display.< br >
< b > [24-Jul-21]< / b > < br >
* Added loop circumference display.< br >
2021-09-12 09:27:28 +00:00
< br >
2020-11-19 08:57:03 +00:00
< / div >
2020-10-23 07:16:48 +00:00
< / section >
2020-11-17 04:46:57 +00:00
< script src = "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.9.3/Chart.min.js" > < / script >
< script src = "https://cdn.jsdelivr.net/npm/chartjs-plugin-crosshair@1.1.2" > < / script >
< script >
2021-09-18 07:08:52 +00:00
// GUI control widgets:
2020-11-17 04:46:57 +00:00
var loop_diameter_slider = document.getElementById("loop_diameter_slider");
var conductor_diameter_slider = document.getElementById("conductor_diameter_slider");
var loop_turns_slider = document.getElementById("loop_turns_slider");
var loop_spacing_slider = document.getElementById("loop_spacing_slider");
var transmit_power_slider = document.getElementById("transmit_power_slider");
2021-08-28 03:06:12 +00:00
var metric_radio = document.getElementById("metric_radio");
var imperial_radio = document.getElementById("imperial_radio");
2021-09-18 07:08:52 +00:00
var shape_radio = document.getElementById("shape_radio");
2021-09-22 13:12:41 +00:00
var external_losses_slider = document.getElementById("external_losses_slider");
2021-08-28 03:06:12 +00:00
2021-09-18 07:08:52 +00:00
// Global variables:
2021-08-28 03:06:12 +00:00
var units = "metric";
2021-09-18 07:08:52 +00:00
var conductivity = 58e6; // Default is annealed copper
var shape = "circle"; // Shape of the main loop
var inductance = 0.0;
var area = 0.0; // Loop area in square meters.
var perimeter = 0.0; // Perimeter of a single turn of the main loop
2021-09-20 14:03:03 +00:00
var loop_capacitance = 0.0; // Effective capacitance of a single or multi-turn loop
var srf = 0.0; // Self-resonant frequency SRF
2021-09-18 07:08:52 +00:00
var conductor_length = 0.0; // Total conductor length
2021-09-22 13:12:41 +00:00
var R_ext = 0.0; // External losses due to capacitor resistance and ground effects, in ohms
2021-09-26 11:49:37 +00:00
var metal = "Cu"; // Default metal is copper
2021-09-18 07:08:52 +00:00
var frequencies = [];
2020-11-17 04:46:57 +00:00
function updateFrequencies() {
const hamFrequencies = [
2021-08-30 10:27:47 +00:00
0.1365, 0.475, 1.8, 3.5, 5.0, 7.0, 10.1, 14.0, 18.068, 21.0, 24.89, 28.0, 29.7, 35.0, 40.0, 45.0, 50.0, 52.0, 54.0
2020-11-17 04:46:57 +00:00
];
2021-08-30 04:33:36 +00:00
2020-11-17 04:46:57 +00:00
frequencies = [];
hamFrequencies.forEach(freq => {
const wavelength = 3e8 / (freq * 1e6);
const l = (Math.PI * loop_diameter_slider.value) / wavelength;
2021-09-20 14:03:03 +00:00
if ((l < = 0.30) & & ((freq * 1e6) < srf ) ) {
2020-11-17 04:46:57 +00:00
frequencies.push(freq);
}
});
}
2021-09-18 07:08:52 +00:00
function setGlobals() {
inductance = getInductance();
area = getArea();
perimeter = getPerimeter();
2021-09-20 14:03:03 +00:00
loop_capacitance = (loop_turns_slider.value > 1) ? multiloopCapacitance() : (2.69e-12 * perimeter);
srf = calculateSRF();
2021-09-18 07:08:52 +00:00
conductor_length = ((((perimeter* loop_turns_slider.value) ** 2.0) + ((loop_spacing_slider.value * conductor_diameter_slider.value * 1e-3 * loop_turns_slider.value) ** 2.0)) ** 0.5);
2021-09-22 13:12:41 +00:00
R_ext = external_losses_slider.value * 0.001;
2021-09-18 07:08:52 +00:00
}
// Returns the loop area in square meters:
function getArea() {
var l_area = 0.0;
const width = loop_diameter_slider.value;
if(shape == "circle") {
l_area = 3.141592 * (0.5 * width)**2;
} else
if(shape == "octagon") {
const r = 0.4142135 * width;
l_area = 4.8284 * r**2.0;
} else
if(shape == "hexagon") {
const r = 0.5 * width;
l_area = 3.4641 * r**2.0;
} else
if(shape == "square") {
l_area = width **2.0;
}
return l_area;
}
// Returns the loop area in square meters:
function getPerimeter() {
var l_perimeter = 0.0;
const width = loop_diameter_slider.value;
if(shape == "circle") {
l_perimeter = 3.141592 * width;
} else
if(shape == "octagon") {
const r = 0.4142135 * width;
l_perimeter = 8 * r;
} else
if(shape == "hexagon") {
const r = 0.5 * width;
const t = 2.0 * r * 0.57735;
l_perimeter = 6 * t;
} else
if(shape == "square") {
l_perimeter = 4 * width;
}
return l_perimeter;
}
2021-09-01 13:29:19 +00:00
// Calculate the inductance of the coil. For single turn loops, use standard inductance equation. For multi-turn, use Nagaoka correction.
2021-08-31 11:23:56 +00:00
function getInductance() {
const mu0 = Math.PI * 4e-7;
const loop_diameter_meters = loop_diameter_slider.value;
const cond_diameter_meters = conductor_diameter_slider.value * 1e-3;
const spacing_ratio = loop_spacing_slider.value;
const loop_turns = loop_turns_slider.value;
const a_coil_radius = loop_diameter_meters * 0.5;
const coil_length = cond_diameter_meters * spacing_ratio * loop_turns;
var retval = 0.0;
2021-09-18 07:08:52 +00:00
if(shape == "circle") {
if(loop_turns > 1) {
retval = (loop_turns**2.0) * mu0 * Math.PI * (a_coil_radius**2.0) * nagaokaCoefficient() / coil_length;
} else {
const b_conductor_radius = cond_diameter_meters * 0.5;
retval = mu0 * a_coil_radius * (Math.log(8.0 * a_coil_radius / b_conductor_radius) - 2.0);
}
} else
if(shape == "octagon") {
const N = loop_turns;
const s = (100.0 * loop_diameter_meters) * 0.414213; // side length in cm
const l = (N>1) ? (coil_length * 100.0) : (cond_diameter_meters * 100.0); // coil length in cm
const bOn2r = l / (1.09868411*s);
//retval = 1e-6 * 0.016 * (N**2) * s * ( Math.log((2.613*s*N)/((N+1)*l)) + 0.75143 + ((0.07153*(N+1)*l) / (s*N)));
retval = 1e-6 * 0.016 * (N**2) * s * ( Math.log(1.0/bOn2r) + 0.75143 + 0.18693*bOn2r + 0.11969*bOn2r**2 - 0.08234*bOn2r**4);
} else
if(shape == "hexagon") {
const N = loop_turns;
const s = (100.0 * loop_diameter_meters) * 0.57735; // side length in cm
const l = (N>1) ? (coil_length * 100.0) : (cond_diameter_meters * 100.0); // coil length in cm
const bOn2r = l / (loop_diameter_meters * 115.470);
//retval = 1e-6 * 0.012 * (N**2) * s * ( Math.log((2.0*s*N)/((N+1)*l)) + 0.65533 + ((0.1348*(N+1)*l) / (s*N)));
retval = 1e-6 * 0.012 * (N**2) * s * ( Math.log(1.0/bOn2r) + 0.65533 + 0.26960*bOn2r + 0.07736*bOn2r**2 - 0.05504*bOn2r**4);
} else
if(shape == "square") {
const N = loop_turns;
const s = (100.0 * loop_diameter_meters); // side length in cm
const l = (N>1) ? (coil_length * 100.0) : (cond_diameter_meters * 100.0); // coil length in cm
const bOn2r = l / (loop_diameter_meters * 141.4214);
//retval = 1e-6 * 0.008 * (N**2) * s * ( Math.log((1.4142*s*N)/((N+1)*l)) + 0.37942 + ((0.3333*(N+1)*l)/(s*N)));
retval = 1e-6 * 0.008 * (N**2) * s * ( Math.log(1.0/bOn2r) + 0.37942 + 0.47140*bOn2r - 0.014298*bOn2r**2 - 0.02904*bOn2r**4);
2021-08-31 11:23:56 +00:00
}
return retval; // In Henries
}
2020-11-17 04:46:57 +00:00
function radiationResistance(frequency) {
const n_turns = loop_turns_slider.value;
const wavelength = 3e8 / frequency;
2021-09-18 07:08:52 +00:00
var retval = 0.0;
if(shape == "circle") {
const k = 20.0 * (Math.PI ** 2.0);
const l = (Math.PI * loop_diameter_slider.value) / wavelength;
retval = (n_turns ** 2.0) * k * (l ** 4.0);
} else {
retval = (31171.0 * n_turns**2.0 * area**2.0) / (wavelength**4.0);
}
return retval;
2020-11-17 04:46:57 +00:00
}
function calculateRadiationResistance() {
var retval = [];
frequencies.forEach(freq => {
const rr = radiationResistance(freq * 1e6);
retval.push({x:freq, y:rr});
});
return retval;
}
function inductiveReactance(frequency) {
2021-09-18 07:08:52 +00:00
//const inductance = getInductance();
2020-11-17 04:46:57 +00:00
const reactance = 2.0 * Math.PI * frequency * inductance;
return reactance;
}
function calculateInductiveReactance() {
var retval = [];
frequencies.forEach(freq => {
const reactance = inductiveReactance(freq * 1e6);
retval.push({x:freq, y:reactance});
});
return retval;
}
function nagaokaCoefficient() {
// From Knight's 2016 paper on coil self-resonance, attributed to Wheeler's 1982 eqn as modified by Bob Weaver
var retval;
const c_spacing = 1e-3 * loop_spacing_slider.value * conductor_diameter_slider.value;
const x = loop_diameter_slider.value / (c_spacing * loop_turns_slider.value);
const zk = 2.0 / (Math.PI * x);
const k0 = 1.0 / (Math.log(8.0 / Math.PI) - 0.5);
const k2 = 24.0 / (3.0 * Math.PI**2 - 16.0);
const w = -0.47 / (0.755 + x)**1.44;
const p = k0 + 3.437/x + k2/x**2 + w;
retval = zk * (Math.log(1 + 1/zk) + 1/p);
2021-09-18 07:08:52 +00:00
//console.log(retval);
2020-11-17 04:46:57 +00:00
return retval;
}
function ctdw(ff, ei, ex) {
// From Knight's 2016 paper
const kL = nagaokaCoefficient();
const kct = 1.0/kL - 1.0;
return 11.27350207 * ex * ff * (1.0 + kct * (1.0 + ei/ex) / 2.0);
}
function ciae(ff, ei, ex) {
// From Knight's 2016 paper
return 17.70837564 * (ei+ex) / Math.log(1.0 + Math.PI**2 * ff);
}
2021-09-01 13:29:19 +00:00
// Calculates the effective capacitance of a multi-turn loop based on the work of Knight from his 2016 paper:
2020-11-17 04:46:57 +00:00
function multiloopCapacitance() {
const e0 = 8.854187e-12;
const h = 1e-3 * loop_spacing_slider.value * conductor_diameter_slider.value;
const ei = 1.0; // Assume internal epsilon is air (or free-space)
const ex = 1.0; // Assume external epsilon is air (or free-space)
const solenoid_length = loop_turns_slider.value * h;
const ff = solenoid_length / loop_diameter_slider.value;
2021-09-18 07:08:52 +00:00
// How much longer is the perimeter compared to the circumference if it were circular:
const shape_factor = perimeter / (Math.PI * loop_diameter_slider.value);
var l_multiloop_capacitance = 1e-12 * shape_factor * (ctdw(ff, ei, ex) / Math.sqrt(1 - h**2 / loop_diameter_slider.value**2) + ciae(ff, ei, ex)) * loop_diameter_slider.value;
return l_multiloop_capacitance; // in Farads
2020-11-17 04:46:57 +00:00
}
2021-09-20 14:03:03 +00:00
/*
function singleloopCapacitance() {
var retval = 2.69 * perimeter;
return (retval*1e-12); // in Farads
}
*/
2020-11-17 04:46:57 +00:00
function tuningCapacitance(frequency) {
// frequency is in Hertz
const reactance = inductiveReactance(frequency);
2021-09-20 14:03:03 +00:00
const capacitance = 1e12 * ((1.0 / (2.0 * Math.PI * frequency * reactance)) - loop_capacitance);
2020-11-17 04:46:57 +00:00
return capacitance; // in picofarads
2020-10-17 13:00:08 +00:00
}
2020-10-29 08:11:50 +00:00
2020-11-17 04:46:57 +00:00
function calculateTuningCapacitor() {
var retval = [];
frequencies.forEach(freq => {
const capacitor = tuningCapacitance(freq * 1e6);
retval.push({x:freq, y:capacitor});
});
return retval;
}
2020-10-20 01:19:12 +00:00
2020-11-17 04:46:57 +00:00
const proximityResistance = {
// From G. S. Smith, "Radiation Efficiency of Electrically Small Multiturn Loop Antennas", IEEE Trans Antennas Propagation, September 1972
// 0 - this is the corresponding x-axis value. 1 - single loop adds zero to proximity resistance. Others measured empirically.
0:[ 1.1, 1.15, 1.20, 1.25, 1.30, 1.40, 1.50, 1.60, 1.70, 1.80, 1.90, 2.00, 2.20, 2.40, 2.50, 2.60, 2.80, 3.00, 3.50, 4.00],
1:[0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000, 0.000],
2:[0.299, 0.284, 0.268, 0.254, 0.240, 0.214, 0.191, 0.173, 0.155, 0.141, 0.128, 0.116, 0.098, 0.032, 0.077, 0.071, 0.061, 0.054, 0.040, 0.031],
3:[0.643, 0.580, 0.531, 0.491, 0.455, 0.395, 0.346, 0.305, 0.270, 0.241, 0.216, 0.195, 0.161, 0.135, 0.124, 0.114, 0.098, 0.085, 0.062, 0.048],
4:[0.996, 0.868, 0.777, 0.704, 0.644, 0.564, 0.470, 0.408, 0.353, 0.316, 0.281, 0.252, 0.205, 0.170, 0.156, 0.144, 0.123, 0.106, 0.077, 0.058],
5:[1.347, 1.142, 1.002, 0.896, 0.809, 0.674, 0.572, 0.492, 0.428, 0.375, 0.332, 0.295, 0.239, 0.197, 0.180, 0.165, 0.141, 0.121, 0.087, 0.066],
6:[1.689, 1.400, 1.210, 1.068, 0.956, 0.784, 0.658, 0.561, 0.485, 0.423, 0.372, 0.330, 0.265, 0.217, 0.198, 0.182, 0.154, 0.133, 0.095, 0.072],
7:[2.020, 1.693, 1.401, 1.224, 1.086, 0.880, 0.732, 0.620, 0.532, 0.462, 0.405, 0.358, 0.286, 0.234, 0.213, 0.195, 0.165, 0.142, 0.101, 0.076],
8:[2.340, 1.872, 1.577, 1.365, 1.203, 0.965, 0.796, 0.670, 0.573, 0.495, 0.433, 0.392, 0.304, 0.247, 0.225, 0.206, 0.174, 0.150, 0.106, 0.080]
};
function getProximityResFromSpacing(spacing_ratio) {
// Use the proximityResistance look-up table and interpolate values depending on the spacing ratio and the number of turns.
var retval = 0.0;
var n_turns = loop_turns_slider.value;
var i = 0;
for (i = 0; i < (proximityResistance[0].length-1); i++) {
if(spacing_ratio < = proximityResistance[0][i+1]) {
// Linear interpolation between empirical proximity resistance values:
2021-08-30 02:28:09 +00:00
retval = (((spacing_ratio - proximityResistance[0][i]) / (proximityResistance[0][i+1] - proximityResistance[0][i])
* (proximityResistance[n_turns][i+1] - proximityResistance[n_turns][i])) + proximityResistance[n_turns][i]);
2020-11-17 04:46:57 +00:00
break;
}
}
return retval;
}
2020-10-21 04:48:16 +00:00
2020-11-17 04:46:57 +00:00
function lossResistance(frequency) {
// Frequency in Hertz
const a_coil_radius = loop_diameter_slider.value * 0.5;
const b_conductor_radius = conductor_diameter_slider.value * 0.0005;
const n_turns = loop_turns_slider.value;
const loop_spacing_ratio = loop_spacing_slider.value;
const mu0 = 4.0 * Math.PI * 1e-7;
2021-09-18 07:08:52 +00:00
// How much longer is the perimeter compared to the circumference if it were circular:
const shape_factor = perimeter / (Math.PI * loop_diameter_slider.value);
2020-11-17 04:46:57 +00:00
const k = (n_turns * a_coil_radius / b_conductor_radius);
const Rp = getProximityResFromSpacing(loop_spacing_ratio);
2021-08-28 03:06:12 +00:00
const Rs = Math.sqrt(Math.PI * frequency * mu0 / conductivity);
2021-09-12 04:55:58 +00:00
//const R0 = (n_turns * Rs) / (2.0 * Math.PI * b_conductor_radius);
2021-09-18 07:08:52 +00:00
const R_ohmic = shape_factor * k * Rs * (Rp + 1.0);
2021-09-12 04:55:58 +00:00
//const R_ohmic = k * Rs * (Rp / R0 + 1.0);
2020-11-17 04:46:57 +00:00
return R_ohmic;
}
function calculateLossResistance() {
var retval = [];
frequencies.forEach(freq => {
const R_ohmic = lossResistance(freq * 1e6);
retval.push({x:freq, y:R_ohmic});
});
return retval;
}
2020-10-19 12:33:01 +00:00
2020-11-17 04:46:57 +00:00
function calculateEfficiencyFactor() {
var retval = [];
frequencies.forEach(freq => {
const R_ohmic = lossResistance(freq * 1e6);
const R_rad = radiationResistance(freq * 1e6);
2021-09-22 13:12:41 +00:00
const efficiency = 100.0 * R_rad / (R_rad + R_ohmic + R_ext);
//const efficiency = 100.0 / (1.0 + (R_ohmic / R_rad));
2020-11-17 04:46:57 +00:00
//const efficiency = 10.0 * Math.log10(1.0 / (1.0 + (R_ohmic / R_rad))); // for Efficiency in dB
retval.push({x:freq, y:efficiency});
});
return retval;
}
function qualityFactor(frequency) {
const Xl = inductiveReactance(frequency);
const Rl = lossResistance(frequency);
const Rr = radiationResistance(frequency);
2021-09-22 13:12:41 +00:00
const Q = Xl / (Rl + Rr + R_ext);
2020-11-17 04:46:57 +00:00
return Q;
}
function calculateQualityFactor() {
var retval = [];
frequencies.forEach(freq => {
const Q = qualityFactor(freq * 1e6);
retval.push({x:freq, y:Q});
});
return retval;
}
function bandwidth(frequency) {
const Q = qualityFactor(frequency);
const bw = frequency * 1e-3 / Q; // in kiloHertz, remember that frequency comes in as Hz. Conversion between Hz and kHz is why the 1e-3 exists.
return bw;
}
function calculateBandwidth() {
var retval = [];
frequencies.forEach(freq => {
const bw = bandwidth(freq * 1e6);
retval.push({x:freq, y:bw});
});
return retval;
}
function capacitorVoltage(frequency) {
const Vcap = Math.sqrt(transmit_power_slider.value * inductiveReactance(frequency) * qualityFactor(frequency));
return Vcap;
}
function calculateCapacitorVoltage() {
var retval = [];
frequencies.forEach(freq => {
const Vcap = 0.001 * capacitorVoltage(freq * 1e6);
retval.push({x:freq, y:Vcap});
});
return retval;
}
function circulatingCurrent(frequency) {
const cc = Math.sqrt(transmit_power_slider.value * qualityFactor(frequency) / inductiveReactance(frequency));
return cc;
}
function calculateCirculatingCurrent() {
var retval = [];
frequencies.forEach(freq => {
const cc = circulatingCurrent(freq * 1e6);
retval.push({x:freq, y:cc});
});
return retval;
}
2021-08-30 02:28:09 +00:00
2021-09-21 12:45:41 +00:00
function calculateAntennaSize() {
var retval = [];
frequencies.forEach(freq => {
const lambda = 3e8 / (freq*1e6);
2021-09-22 10:45:31 +00:00
const size = perimeter / lambda; // size along the perimeter
// const size = conductor_length / lambda;
2021-09-21 12:45:41 +00:00
retval.push({x:freq, y:size});
});
return retval;
}
2021-08-30 02:28:09 +00:00
function calculateSRF() {
2021-09-01 13:29:19 +00:00
// According to Knight (2016), SRF for a single coil is equivalent to the circumference being equivalent to a half-wave dipole.
2021-08-30 02:28:09 +00:00
const inductance = getInductance();
2021-09-20 14:03:03 +00:00
return (1.0 / (2.0 * Math.PI * ((inductance * loop_capacitance) ** 0.5)));
2021-08-30 02:28:09 +00:00
}
2020-11-17 04:46:57 +00:00
2021-08-28 03:06:12 +00:00
metric_radio.oninput = function() {
units = metric_radio.value;
//console.log(units);
2021-09-18 07:08:52 +00:00
setGlobals();
2021-08-28 03:06:12 +00:00
drawFrontDesign();
drawSideDesign();
}
imperial_radio.oninput = function() {
units = imperial_radio.value;
//console.log(units);
drawFrontDesign();
drawSideDesign();
}
copper_radio.oninput = function() {
conductivity = 58e6;
2021-09-26 11:49:37 +00:00
metal = "Cu";
2021-09-18 07:08:52 +00:00
setGlobals();
2021-08-28 03:06:12 +00:00
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-08-28 03:06:12 +00:00
myChart.update();
}
aluminium_radio.oninput = function() {
conductivity = 35e6;
2021-09-26 11:49:37 +00:00
metal = "Al";
2021-09-18 07:08:52 +00:00
setGlobals();
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-09-18 07:08:52 +00:00
myChart.update();
}
circle_radio.oninput = function() {
shape = "circle";
setGlobals();
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-09-18 07:08:52 +00:00
myChart.update();
}
oct_radio.oninput = function() {
shape = "octagon";
setGlobals();
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-09-18 07:08:52 +00:00
myChart.update();
}
hex_radio.oninput = function() {
shape = "hexagon";
setGlobals();
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-09-18 07:08:52 +00:00
myChart.update();
}
square_radio.oninput = function() {
shape = "square";
setGlobals();
2021-08-28 03:06:12 +00:00
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2021-08-28 03:06:12 +00:00
myChart.update();
}
2021-09-11 07:29:38 +00:00
// Specify fonts for changing parameters controlled by the sliders:
2021-09-16 08:51:58 +00:00
const normal_font = "12px arial";
const emphasis_font = "bold 14px arial";
2021-09-11 07:29:38 +00:00
const emphasis_delay = 1200;
2021-09-16 08:51:58 +00:00
const normal_width = 1;
const emphasis_width = 3;
2021-09-11 07:29:38 +00:00
var loop_dia_timer_handler = 0;
var loop_dia_font = normal_font;
2021-09-16 08:51:58 +00:00
var loop_dia_thickness = normal_width;
2021-09-11 07:29:38 +00:00
2020-11-17 04:46:57 +00:00
loop_diameter_slider.oninput = function() {
2021-09-11 07:29:38 +00:00
if(loop_dia_timer_handler == 0) {
loop_dia_font = emphasis_font;
2021-09-16 08:51:58 +00:00
loop_dia_thickness = emphasis_width;
2021-09-11 07:29:38 +00:00
loop_dia_timer_handler = setTimeout(function(){
loop_dia_font = normal_font;
drawFrontDesign();
loop_dia_timer_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(loop_dia_timer_handler);
loop_dia_timer_handler = setTimeout(function(){
loop_dia_font = normal_font;
2021-09-16 08:51:58 +00:00
loop_dia_thickness = normal_width;
2021-09-11 07:29:38 +00:00
drawFrontDesign();
loop_dia_timer_handler = 0;
}, emphasis_delay);
}
2021-09-18 07:08:52 +00:00
setGlobals();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
drawSideDesign();
updateFrequencies();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2020-11-17 04:46:57 +00:00
myChart.update();
}
2021-09-11 07:29:38 +00:00
var cond_dia_timer_handler = 0;
var cond_dia_font = normal_font;
2021-09-16 08:51:58 +00:00
var cond_dia_thickness = normal_width;
2021-09-11 07:29:38 +00:00
2020-11-17 04:46:57 +00:00
conductor_diameter_slider.oninput = function() {
2021-09-11 07:29:38 +00:00
if(cond_dia_timer_handler == 0) {
cond_dia_font = emphasis_font;
2021-09-16 08:51:58 +00:00
cond_dia_thickness = emphasis_width;
2021-09-11 07:29:38 +00:00
cond_dia_timer_handler = setTimeout(function(){
cond_dia_font = normal_font;
drawFrontDesign();
cond_dia_timer_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(cond_dia_timer_handler);
cond_dia_timer_handler = setTimeout(function(){
cond_dia_font = normal_font;
2021-09-16 08:51:58 +00:00
cond_dia_thickness = normal_width;
2021-09-11 07:29:38 +00:00
drawFrontDesign();
cond_dia_timer_handler = 0;
}, emphasis_delay);
}
2021-09-18 07:08:52 +00:00
setGlobals();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
drawSideDesign();
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2020-11-17 04:46:57 +00:00
myChart.update();
}
2021-09-11 07:29:38 +00:00
var turns_timer_handler = 0;
var turns_font = normal_font;
2020-11-17 04:46:57 +00:00
loop_turns_slider.oninput = function() {
2021-09-11 07:29:38 +00:00
if(turns_timer_handler == 0) {
turns_font = emphasis_font;
turns_timer_handler = setTimeout(function(){
turns_font = normal_font;
drawSideDesign();
turns_timer_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(turns_timer_handler);
turns_timer_handler = setTimeout(function(){
turns_font = normal_font;
drawSideDesign();
turns_timer_handler = 0;
}, emphasis_delay);
}
2021-09-18 07:08:52 +00:00
setGlobals();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
drawSideDesign();
2021-08-30 04:33:36 +00:00
updateFrequencies();
2020-11-17 04:46:57 +00:00
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2020-11-17 04:46:57 +00:00
myChart.update();
}
2021-09-11 07:29:38 +00:00
var spacing_timer_handler = 0;
var spacing_font = normal_font;
2020-11-17 04:46:57 +00:00
loop_spacing_slider.oninput = function() {
2021-09-11 07:29:38 +00:00
if(spacing_timer_handler == 0) {
spacing_font = emphasis_font;
spacing_timer_handler = setTimeout(function(){
spacing_font = normal_font;
drawSideDesign();
spacing_timer_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(spacing_timer_handler);
spacing_timer_handler = setTimeout(function(){
spacing_font = normal_font;
drawSideDesign();
spacing_timer_handler = 0;
}, emphasis_delay);
}
2021-09-18 07:08:52 +00:00
setGlobals();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
drawSideDesign();
2021-09-01 13:29:19 +00:00
if(loop_turns_slider.value > 1) {
updateFrequencies();
}
2020-11-17 04:46:57 +00:00
myChart.data.datasets[0].data = calculateTuningCapacitor();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[4].data = calculateRadiationResistance();
myChart.data.datasets[5].data = calculateLossResistance();
myChart.data.datasets[6].data = calculateInductiveReactance();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
2021-09-21 12:45:41 +00:00
myChart.data.datasets[9].data = calculateAntennaSize();
2020-11-17 04:46:57 +00:00
myChart.update();
}
2021-09-11 07:33:47 +00:00
var tx_timer_handler = 0;
var tx_font = normal_font;
2020-11-17 04:46:57 +00:00
transmit_power_slider.oninput = function() {
2021-09-11 07:33:47 +00:00
if(tx_timer_handler == 0) {
tx_font = emphasis_font;
tx_timer_handler = setTimeout(function(){
tx_font = normal_font;
drawFrontDesign();
tx_timer_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(tx_timer_handler);
tx_timer_handler = setTimeout(function(){
tx_font = normal_font;
drawFrontDesign();
tx_timer_handler = 0;
}, emphasis_delay);
}
2021-09-18 07:08:52 +00:00
setGlobals();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
myChart.update();
}
2021-09-22 13:12:41 +00:00
var external_losses_handler = 0;
var external_losses_font = normal_font;
external_losses_slider.oninput = function() {
if(external_losses_handler == 0) {
external_losses_font = emphasis_font;
external_losses_handler = setTimeout(function(){
external_losses_font = normal_font;
drawFrontDesign();
external_losses_handler = 0;
}, emphasis_delay);
} else {
clearTimeout(external_losses_handler);
external_losses_handler = setTimeout(function(){
external_losses_font = normal_font;
drawFrontDesign();
external_losses_handler = 0;
}, emphasis_delay);
}
setGlobals();
drawFrontDesign();
myChart.data.datasets[1].data = calculateCapacitorVoltage();
myChart.data.datasets[2].data = calculateBandwidth();
myChart.data.datasets[3].data = calculateEfficiencyFactor();
myChart.data.datasets[7].data = calculateQualityFactor();
myChart.data.datasets[8].data = calculateCirculatingCurrent();
myChart.update();
}
2020-11-17 04:46:57 +00:00
window.onresize = function() {
myChart.resize();
//myChart.update();
drawFrontDesign();
drawSideDesign();
// console.log("resize!");
}
window.onorientationchange = function() {
//myChart.resize();
//myChart.update();
drawFrontDesign();
drawSideDesign();
}
window.onbeforeprint = function() {
console.log("onbeforeprint");
//myChart.resize();
drawFrontDesign();
drawSideDesign();
}
const afront_canvas = document.getElementById("antennaFront2D");
const fctx = afront_canvas.getContext('2d');
function drawFrontDesign() {
const win_width = document.getElementById("antenna-front-container").offsetWidth;
const win_height = document.getElementById("antenna-front-container").offsetHeight;
afront_canvas.width = win_width-2;
afront_canvas.height = win_height-2;
fctx.clearRect(0, 0, win_width, win_height);
2021-09-12 04:55:58 +00:00
const loop_radius = win_width < win_height ? 0 . 32 * win_width : 0 . 32 * win_height ;
2021-09-19 04:44:00 +00:00
const cond_radius = conductor_diameter_slider.value / 12;
2020-11-17 04:46:57 +00:00
const loopx = win_width/2;
const loopy = win_height/2;
2021-09-18 07:08:52 +00:00
if(shape == "circle") {
// Draw loop:
fctx.beginPath();
fctx.arc(loopx, loopy, loop_radius + cond_radius, -0.5 * Math.PI + 0.025, -0.5 * Math.PI - 0.025, false);
fctx.arc(loopx, loopy, loop_radius - cond_radius, -0.5 * Math.PI - 0.025, -0.5 * Math.PI + 0.025, true);
fctx.closePath();
fctx.fill();
// Draw variable capacitor:
fctx.lineWidth = 3;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx - 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx + 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx + 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx - 12, loopy - loop_radius + 3*cond_radius);
fctx.lineTo(loopx + 12, loopy - loop_radius - 3*cond_radius);
/*
fctx.moveTo(loopx + 8, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx + 14, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx + 14, loopy - loop_radius - 3*cond_radius + 6);
*/
fctx.stroke();
2020-11-17 04:46:57 +00:00
2021-09-18 07:08:52 +00:00
// Draw coupling loop:
fctx.lineWidth = 2;
fctx.beginPath();
fctx.arc(loopx, loopy + (loop_radius - loop_radius/5) - cond_radius , loop_radius/5, 0, 2*Math.PI, true);
fctx.stroke();
// Draw conductor diameter arrow:
fctx.lineWidth = cond_dia_thickness;
fctx.beginPath();
var p1x = loopx + 0.45 * (loop_radius - cond_radius);
var p1y = loopy + 0.45 * (loop_radius - cond_radius);
var p2x = loopx + 0.707 * (loop_radius - cond_radius);
var p2y = loopy + 0.707 * (loop_radius - cond_radius);
var p3x = loopx + 0.707 * (loop_radius - cond_radius) - 3*cond_radius;
var p3y = loopy + 0.707 * (loop_radius - cond_radius);
var p4x = loopx + 0.707 * (loop_radius - cond_radius);
var p4y = loopy + 0.707 * (loop_radius - cond_radius) - 3*cond_radius;
fctx.moveTo(win_width-p1x, p1y);
fctx.lineTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
2021-09-26 11:49:37 +00:00
p1x = loopx + 0.9 * (loop_radius + cond_radius);
p1y = loopy + 0.9 * (loop_radius + cond_radius);
2021-09-18 07:08:52 +00:00
p2x = loopx + 0.707 * (loop_radius + cond_radius);
p2y = loopy + 0.707 * (loop_radius + cond_radius);
p3x = loopx + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
p3y = loopy + 0.707 * (loop_radius + cond_radius);
p4x = loopx + 0.707 * (loop_radius + cond_radius);
p4y = loopy + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
fctx.moveTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
fctx.stroke();
fctx.lineWidth = normal_width;
2021-09-26 11:49:37 +00:00
fctx.font = normal_font;
fctx.textAlign = "left";
fctx.fillText(metal, loopx + 0.9 * (loop_radius + cond_radius) + 3, loopy + 0.9 * (loop_radius + cond_radius));
2021-09-18 07:08:52 +00:00
} else
if(shape == "octagon") {
// Draw octagon:
//const width = loop_diameter_slider.value;
const a = 0.4142135 * loop_radius * 2.0;
const circumradius = 1.30656296 * a;
fctx.lineWidth = 2 * cond_radius;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - loop_radius);
for(var i=0; i< 8 ; i + + ) {
fctx.lineTo(loopx - circumradius * Math.sin(Math.PI * (i/4.0 + 1.0/8)), loopy - circumradius * Math.cos(Math.PI * (i/4.0 + 1.0/8)));
}
fctx.lineTo(loopx + 3, loopy - loop_radius);
fctx.stroke();
// Draw variable capacitor:
fctx.lineWidth = 3;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx - 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx + 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx + 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx - 12, loopy - loop_radius + 3*cond_radius);
fctx.lineTo(loopx + 12, loopy - loop_radius - 3*cond_radius);
fctx.stroke();
// Draw coupling loop:
fctx.lineWidth = 2;
fctx.beginPath();
fctx.arc(loopx, loopy + (loop_radius - loop_radius/5) - cond_radius , loop_radius/5, 0, 2*Math.PI, true);
fctx.stroke();
fctx.font = normal_font;
fctx.save();
fctx.translate(loopx - loop_radius - cond_radius - 8, loopy);
fctx.rotate(-Math.PI * 0.5);
fctx.textAlign = "center";
const s = (100.0 * loop_diameter_slider.value) * 0.414213; // side length in cm
if(units == "metric") {
fctx.fillText(s.toPrecision(3).toString() + " cm", 0, 0);
} else {
fctx.fillText((s*0.03281).toPrecision(3).toString() + "\'", 0, 0);
}
fctx.restore();
// Draw conductor diameter arrow:
fctx.lineWidth = cond_dia_thickness;
fctx.beginPath();
var p1x = loopx + 0.45 * (loop_radius - cond_radius);
var p1y = loopy + 0.45 * (loop_radius - cond_radius);
var p2x = loopx + 0.707 * (loop_radius - cond_radius);
var p2y = loopy + 0.707 * (loop_radius - cond_radius);
var p3x = loopx + 0.707 * (loop_radius - cond_radius) - 3*cond_radius;
var p3y = loopy + 0.707 * (loop_radius - cond_radius);
var p4x = loopx + 0.707 * (loop_radius - cond_radius);
var p4y = loopy + 0.707 * (loop_radius - cond_radius) - 3*cond_radius;
fctx.moveTo(win_width-p1x, p1y);
fctx.lineTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
2021-09-26 11:49:37 +00:00
p1x = loopx + 0.9 * (loop_radius + cond_radius);
p1y = loopy + 0.9 * (loop_radius + cond_radius);
2021-09-18 07:08:52 +00:00
p2x = loopx + 0.707 * (loop_radius + cond_radius);
p2y = loopy + 0.707 * (loop_radius + cond_radius);
p3x = loopx + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
p3y = loopy + 0.707 * (loop_radius + cond_radius);
p4x = loopx + 0.707 * (loop_radius + cond_radius);
p4y = loopy + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
fctx.moveTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
fctx.stroke();
fctx.lineWidth = normal_width;
2021-09-26 11:49:37 +00:00
fctx.font = normal_font;
fctx.textAlign = "left";
fctx.fillText(metal, p1x + 3, p1y);
2021-09-18 07:08:52 +00:00
} else
if(shape == "hexagon") {
// Draw hexagon:
const radius = 2.0 * loop_radius * 0.57735;
fctx.lineWidth = 2 * cond_radius;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - radius);
for(var i=1; i< 6 ; i + + ) {
fctx.lineTo(loopx - radius * Math.sin(Math.PI * (i/3.0)), loopy - radius * Math.cos(Math.PI * (i/3.0)));
}
fctx.lineTo(loopx + 3, loopy - radius);
fctx.stroke();
// Draw variable capacitor:
fctx.lineWidth = 3;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - radius - 3*cond_radius);
fctx.lineTo(loopx - 3, loopy - radius + 3*cond_radius);
fctx.moveTo(loopx + 3, loopy - radius - 3*cond_radius);
fctx.lineTo(loopx + 3, loopy - radius + 3*cond_radius);
fctx.moveTo(loopx - 12, loopy - radius + 3*cond_radius);
fctx.lineTo(loopx + 12, loopy - radius - 3*cond_radius);
fctx.stroke();
// Draw coupling loop:
fctx.lineWidth = 2;
fctx.beginPath();
fctx.arc(loopx, loopy + (radius - radius/4) - cond_radius , radius/5, 0, 2*Math.PI, true);
fctx.stroke();
fctx.font = normal_font;
fctx.save();
fctx.translate(loopx - loop_radius - cond_radius - 8, loopy);
fctx.rotate(-Math.PI * 0.5);
fctx.textAlign = "center";
const s = (100.0 * loop_diameter_slider.value) * 0.57735; // side length in cm
if(units == "metric") {
fctx.fillText(s.toPrecision(3).toString() + " cm", 0, 0);
} else {
fctx.fillText((s*0.03281).toPrecision(3).toString() + "\'", 0, 0);
}
fctx.restore();
// Draw conductor diameter arrow:
fctx.lineWidth = cond_dia_thickness;
fctx.beginPath();
var p0x = loopx + 0.45 * loop_radius;
var p0y = loopy + 0.45 * loop_radius;
var p1x = loopx + loop_radius - cond_radius - 4*cond_radius;
var p1y = loopy + 0.45 * loop_radius;
var p2x = loopx + loop_radius - cond_radius;
var p2y = loopy + 0.45 * loop_radius;
var p3x = loopx + loop_radius - cond_radius - 2*cond_radius;
var p3y = loopy + 0.45 * loop_radius - 2*cond_radius;
var p4x = loopx + loop_radius - cond_radius - 2*cond_radius;
var p4y = loopy + 0.45 * loop_radius + 2*cond_radius;
fctx.moveTo(win_width-p0x, p0y);
fctx.lineTo(p0x, p0y);
//fctx.lineTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
p1x = loopx + loop_radius + cond_radius + 4*cond_radius;
//p1y = loopy + 1.0 * (loop_radius + cond_radius);
p2x = loopx + loop_radius + cond_radius;
//p2y = loopy + 0.707 * (loop_radius + cond_radius);
p3x = loopx + loop_radius + cond_radius + 2*cond_radius;
//p3y = loopy + 0.707 * (loop_radius + cond_radius);
p4x = loopx + loop_radius + cond_radius + 2*cond_radius;
//p4y = loopy + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
fctx.moveTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
fctx.stroke();
fctx.lineWidth = normal_width;
2021-09-26 11:49:37 +00:00
fctx.font = normal_font;
fctx.textAlign = "left";
fctx.fillText(metal, p1x + 3, p1y);
2021-09-18 07:08:52 +00:00
} else {
// Draw square:
const radius = 1.414 * loop_radius;
fctx.lineWidth = 2 * cond_radius;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - loop_radius);
for(var i=0; i< 4 ; i + + ) {
fctx.lineTo(loopx - radius * Math.sin(Math.PI * (i/2.0 + 0.25)), loopy - radius * Math.cos(Math.PI * (i/2.0 + 0.25)));
}
fctx.lineTo(loopx + 3, loopy - loop_radius);
fctx.stroke();
// Draw variable capacitor:
fctx.lineWidth = 3;
fctx.beginPath();
fctx.moveTo(loopx - 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx - 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx + 3, loopy - loop_radius - 3*cond_radius);
fctx.lineTo(loopx + 3, loopy - loop_radius + 3*cond_radius);
fctx.moveTo(loopx - 12, loopy - loop_radius + 3*cond_radius);
fctx.lineTo(loopx + 12, loopy - loop_radius - 3*cond_radius);
fctx.stroke();
// Draw coupling loop:
fctx.lineWidth = 2;
fctx.beginPath();
fctx.arc(loopx, loopy + (loop_radius - loop_radius/5) - cond_radius , loop_radius/5, 0, 2*Math.PI, true);
fctx.stroke();
fctx.font = normal_font;
fctx.save();
fctx.translate(loopx - loop_radius - cond_radius - 8, loopy);
fctx.rotate(-Math.PI * 0.5);
fctx.textAlign = "center";
const s = (100.0 * loop_diameter_slider.value); // side length in cm
if(units == "metric") {
fctx.fillText(s.toPrecision(3).toString() + " cm", 0, 0);
} else {
fctx.fillText((s*0.03281).toPrecision(3).toString() + "\'", 0, 0);
}
fctx.restore();
// Draw conductor diameter arrow:
fctx.lineWidth = cond_dia_thickness;
fctx.beginPath();
var p0x = loopx + 0.45 * (loop_radius - cond_radius);
var p0y = loopy + 0.45 * (loop_radius - cond_radius);
var p1x = loopx + loop_radius - cond_radius - 4*cond_radius;
var p1y = loopy + 0.7 * loop_radius;
var p2x = loopx + loop_radius - cond_radius;
var p2y = loopy + 0.7 * loop_radius;
var p3x = loopx + loop_radius - cond_radius - 2*cond_radius;
var p3y = loopy + 0.7 * loop_radius - 2*cond_radius;
var p4x = loopx + loop_radius - cond_radius - 2*cond_radius;
var p4y = loopy + 0.7 * loop_radius + 2*cond_radius;
fctx.moveTo(win_width-p0x, p0y);
fctx.lineTo(p0x, p0y);
fctx.lineTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
p1x = loopx + loop_radius + cond_radius + 4*cond_radius;
//p1y = loopy + 1.0 * (loop_radius + cond_radius);
p2x = loopx + loop_radius + cond_radius;
//p2y = loopy + 0.707 * (loop_radius + cond_radius);
p3x = loopx + loop_radius + cond_radius + 2*cond_radius;
//p3y = loopy + 0.707 * (loop_radius + cond_radius);
p4x = loopx + loop_radius + cond_radius + 2*cond_radius;
//p4y = loopy + 0.707 * (loop_radius + cond_radius) + 3*cond_radius;
fctx.moveTo(p1x, p1y);
fctx.lineTo(p2x, p2y);
fctx.lineTo(p3x, p3y);
fctx.lineTo(p4x, p4y);
fctx.lineTo(p2x, p2y);
fctx.stroke();
fctx.lineWidth = normal_width;
2021-09-26 11:49:37 +00:00
fctx.font = normal_font;
fctx.textAlign = "left";
fctx.fillText(metal, p1x + 3, p1y);
2021-09-18 07:08:52 +00:00
}
2020-11-17 04:46:57 +00:00
// Draw loop diameter arrow:
2021-09-16 08:51:58 +00:00
fctx.lineWidth = loop_dia_thickness;
2020-11-17 04:46:57 +00:00
fctx.beginPath();
fctx.moveTo(loopx - loop_radius, loopy);
fctx.lineTo(loopx - loop_radius + 2*cond_radius, loopy - 2*cond_radius);
fctx.lineTo(loopx - loop_radius + 2*cond_radius, loopy + 2*cond_radius);
fctx.lineTo(loopx - loop_radius, loopy);
fctx.lineTo(loopx + loop_radius, loopy);
fctx.lineTo(loopx + loop_radius - 2*cond_radius, loopy + 2*cond_radius);
fctx.lineTo(loopx + loop_radius - 2*cond_radius, loopy - 2*cond_radius);
fctx.lineTo(loopx + loop_radius, loopy);
fctx.stroke();
2021-09-16 08:51:58 +00:00
fctx.lineWidth = normal_width;
2020-11-17 04:46:57 +00:00
// Write loop inductance:
2021-09-11 07:33:47 +00:00
fctx.font = normal_font;
2021-09-18 07:08:52 +00:00
const L = inductance * 1.0e+6;
//const L = getInductance() * 1.0e+6;
2020-11-17 04:46:57 +00:00
fctx.fillText("L = " + L.toPrecision(3).toString() + " \u03bcH", 8, 18);
// Write Tx power text:
2021-09-11 07:33:47 +00:00
fctx.font = tx_font;
2021-09-22 13:12:41 +00:00
fctx.fillText("Tx = " + transmit_power_slider.value + " W", 8, win_height * 0.8 + 10);
fctx.font = external_losses_font;
fctx.fillText("Re = " + R_ext.toFixed(3).toString() + " \u03A9", 8, win_height * 0.8 + 24);
2020-11-17 04:46:57 +00:00
// Write loop diameter symbol:
2021-09-11 07:33:47 +00:00
fctx.font = normal_font;
2020-11-17 04:46:57 +00:00
fctx.textAlign = "center";
const dia = 1.0 * loop_diameter_slider.value;
2021-09-11 07:29:38 +00:00
fctx.font = loop_dia_font;
2021-08-28 03:06:12 +00:00
if(units == "metric") {
fctx.fillText("\u2300b = " + dia.toPrecision(3).toString() + " m", loopx, loopy - 6);
} else {
fctx.fillText("\u2300b = " + (dia*3.28084).toPrecision(3).toString() + "\'", loopx, loopy - 6);
}
2021-09-11 07:29:38 +00:00
fctx.font = normal_font;
2020-11-17 04:46:57 +00:00
2021-09-18 07:08:52 +00:00
p1x = loopx + 0.45 * (loop_radius - cond_radius);
p1y = loopy + 0.45 * (loop_radius - cond_radius) - 5;
2020-11-17 04:46:57 +00:00
//fctx.textAlign = "right";
const cond_dia = 1.0 * conductor_diameter_slider.value;
2021-08-28 03:06:12 +00:00
fctx.textAlign = "center";
if(units == "metric") {
2021-09-11 07:29:38 +00:00
fctx.font = cond_dia_font;
2021-09-16 08:51:58 +00:00
fctx.fillText("\u2300a = " + cond_dia.toPrecision(3).toString() + " mm", loopx, p1y+1);
2021-09-11 07:29:38 +00:00
fctx.font = normal_font;
2021-08-28 03:06:12 +00:00
// Write loop area:
fctx.textAlign = "right";
2021-09-18 07:08:52 +00:00
fctx.fillText("A = " + area.toPrecision(3).toString() + " m\u00B2", win_width-8, 18);
2021-07-24 13:26:11 +00:00
2021-08-28 03:06:12 +00:00
// Write Tx power text:
2021-09-22 13:12:41 +00:00
fctx.fillText("peri = " + perimeter.toPrecision(3).toString() + " m", win_width-8, win_height * 0.8 + 24);
2021-08-28 03:06:12 +00:00
} else {
2021-09-11 07:29:38 +00:00
fctx.font = cond_dia_font;
2021-09-16 08:51:58 +00:00
fctx.fillText("\u2300a = " + (cond_dia/25.4).toPrecision(3).toString() + "\"", loopx, p1y+1);
2021-09-11 07:29:38 +00:00
fctx.font = normal_font;
2021-08-28 03:06:12 +00:00
// Write loop area:
fctx.textAlign = "right";
2021-09-18 07:08:52 +00:00
fctx.fillText("A = " + (area * 10.76391).toPrecision(3).toString() + " ft\u00B2", win_width-8, 18);
2021-08-28 03:06:12 +00:00
// Write Tx power text:
2021-09-22 13:12:41 +00:00
fctx.fillText("peri = " + (perimeter*3.28084).toPrecision(3).toString() + " ft", win_width-8, win_height * 0.8 + 24);
2021-08-28 03:06:12 +00:00
}
2020-11-17 04:46:57 +00:00
}
2020-10-19 12:00:47 +00:00
2020-11-17 04:46:57 +00:00
const aside_canvas = document.getElementById("antennaSide2D");
const sctx = aside_canvas.getContext('2d');
function drawSideDesign() {
const win_width = document.getElementById("antenna-side-container").offsetWidth;
const win_height = document.getElementById("antenna-side-container").offsetHeight;
aside_canvas.width = win_width-2;
aside_canvas.height = win_height-2;
sctx.clearRect(0, 0, win_width, win_height);
2021-09-19 04:44:00 +00:00
const cond_radius = conductor_diameter_slider.value / 12;
2020-11-17 04:46:57 +00:00
const cond_spacing = 2 * cond_radius * loop_spacing_slider.value;
const start_x = win_width/2 - loop_turns_slider.value * cond_spacing * 0.5;
const top_y = win_height * 0.2;
const bot_y = win_height * 0.7;
for (let i = 0; i < loop_turns_slider.value ; i + + ) {
sctx.beginPath();
sctx.arc(start_x + i * cond_spacing, bot_y, cond_radius, 0, Math.PI);
sctx.arc(start_x + cond_spacing * 0.5 + i * cond_spacing, top_y, cond_radius, Math.PI, 0);
sctx.lineTo(start_x + i * cond_spacing + cond_radius, bot_y);
sctx.fill();
sctx.beginPath();
sctx.moveTo(start_x + cond_spacing * 0.5 + i * cond_spacing + cond_radius, top_y);
sctx.lineTo(start_x + (i+1) * cond_spacing + cond_radius, bot_y);
sctx.arc(start_x + (i+1) * cond_spacing, bot_y, cond_radius, 0, Math.PI, false);
sctx.lineTo(start_x + cond_spacing * 0.5 + i * cond_spacing - cond_radius, top_y);
sctx.stroke();
}
// Draw left spacing arrow:
const dim_y = win_height * 0.8;
2020-10-21 03:39:46 +00:00
sctx.beginPath();
2020-11-17 04:46:57 +00:00
sctx.moveTo(start_x - 20, dim_y);
sctx.lineTo(start_x, dim_y);
sctx.lineTo(start_x - 7, dim_y + 7)
sctx.lineTo(start_x - 7, dim_y - 7)
sctx.lineTo(start_x, dim_y);
sctx.moveTo(start_x, dim_y - 7);
sctx.lineTo(start_x, dim_y + 7);
sctx.stroke();
// Draw right spacing arrow:
2020-10-21 03:39:46 +00:00
sctx.beginPath();
2020-11-17 04:46:57 +00:00
sctx.moveTo(start_x + cond_spacing + 20, dim_y);
sctx.lineTo(start_x + cond_spacing, dim_y);
sctx.lineTo(start_x + cond_spacing + 7, dim_y + 7)
sctx.lineTo(start_x + cond_spacing + 7, dim_y - 7)
sctx.lineTo(start_x + cond_spacing, dim_y);
sctx.moveTo(start_x + cond_spacing, dim_y - 7);
sctx.lineTo(start_x + cond_spacing, dim_y + 7);
2020-10-21 03:39:46 +00:00
sctx.stroke();
2020-11-17 04:46:57 +00:00
2021-09-11 07:06:02 +00:00
sctx.textAlign = "left";
2021-09-11 07:29:38 +00:00
sctx.font = turns_font;
2021-09-11 07:06:02 +00:00
sctx.fillText("N = " + loop_turns_slider.value.toString(), 8, win_height * 0.1 + 3);
2021-09-11 07:29:38 +00:00
sctx.font = spacing_font;
2021-09-11 07:06:02 +00:00
sctx.fillText("c/a = ", 8, win_height * 0.1 + 18);
sctx.fillText((loop_spacing_slider.value*1.0).toPrecision(3).toString(), 8, win_height * 0.1 + 33);
2021-09-11 07:29:38 +00:00
sctx.font = normal_font;
2021-09-11 07:06:02 +00:00
// Multi-turn loop, so calculate C and SRF:
2021-09-20 14:03:03 +00:00
const L = loop_capacitance * 1e+12;
sctx.textAlign = "right";
sctx.fillText("C = " + L.toFixed(0).toString() + " pF", win_width-8, 18);
sctx.fillText("SRF = ", win_width-8, win_height * 0.1 + 18);
sctx.fillText((srf*1e-6).toPrecision(3).toString() + " MHz", win_width-8, win_height * 0.1 + 33);
2021-09-11 07:06:02 +00:00
2021-07-27 03:17:56 +00:00
sctx.textAlign = "right";
2021-09-22 13:12:41 +00:00
sctx.fillText("cond = " , win_width-8, dim_y + 10);
2021-08-28 03:06:12 +00:00
if(units == "metric") {
2021-09-22 13:12:41 +00:00
sctx.fillText(conductor_length.toPrecision(4).toString() + " m", win_width-8, dim_y + 24);
2021-08-28 03:06:12 +00:00
} else {
2021-09-22 13:12:41 +00:00
sctx.fillText((conductor_length * 3.28084).toPrecision(4).toString() + " ft", win_width-8, dim_y + 24);
2021-08-28 03:06:12 +00:00
}
2021-07-27 03:17:56 +00:00
2020-11-17 04:46:57 +00:00
// Draw spacing text:
2020-10-25 07:55:54 +00:00
sctx.textAlign = "center";
2021-08-28 04:54:17 +00:00
const spc = (loop_turns_slider.value > 1) ? loop_spacing_slider.value * conductor_diameter_slider.value : 0.0;
2021-08-28 03:06:12 +00:00
if(units == "metric") {
sctx.fillText("c = " + spc.toPrecision(3).toString() + " mm", start_x + cond_spacing, dim_y + 20);
} else {
sctx.fillText("c = " + (spc/25.4).toPrecision(3).toString() + " in", start_x + cond_spacing, dim_y + 20);
}
2020-10-25 07:55:54 +00:00
}
2021-09-18 07:08:52 +00:00
2021-09-20 14:03:03 +00:00
// Set the global variables, which are all determined by physical dimensions, and are thus frequency-independent:
setGlobals();
2021-09-18 07:08:52 +00:00
// Update the frequencies, now that we have the sliders available:
updateFrequencies();
2020-11-17 04:46:57 +00:00
drawFrontDesign();
drawSideDesign();
const chartCanvas = document.getElementById("chartCanvas");
const chartCanvasContext = chartCanvas.getContext('2d');
var myChart = new Chart(chartCanvasContext, {
type: 'line',
data: {
datasets: [
{
label: 'Tuning Cap (pF)',
fill: false,
borderColor: 'green',
backgroundColor: 'green',
data: calculateTuningCapacitor(),
borderWidth: 1,
yAxisID: 'pfID'
},
{
label: 'Vcap (kV)',
fill: false,
borderColor: 'rgb(150, 150, 0)',
backgroundColor: 'rgb(200, 200, 0)',
data: calculateCapacitorVoltage(),
borderWidth: 1,
yAxisID: 'vID'
},
{
label: 'BW (kHz)',
fill: false,
borderColor: 'brown',
backgroundColor: 'brown',
data: calculateBandwidth(),
borderWidth: 1,
yAxisID: 'bwID'
},
{
label: 'Efficiency (%)',
fill: false,
borderColor: 'black',
backgroundColor: 'black',
data: calculateEfficiencyFactor(),
borderWidth: 1,
yAxisID: 'effID'
},
{
label: 'R-radiation (\u03A9)',
fill: false,
borderColor: 'red',
backgroundColor: 'red',
data: calculateRadiationResistance(),
borderWidth: 1,
yAxisID: 'mohmsID'
},
{
2021-09-22 13:29:00 +00:00
label: 'R-loop (\u03A9)',
2020-11-17 04:46:57 +00:00
fill: false,
borderColor: 'orange',
backgroundColor: 'orange',
data: calculateLossResistance(),
borderWidth: 1,
yAxisID: 'mohmsID'
},
{
label: 'Reactance (j\u03A9)',
fill: false,
borderColor: 'blue',
backgroundColor: 'blue',
data: calculateInductiveReactance(),
borderWidth: 1,
yAxisID: 'ohmsID'
},
{
label: 'Q',
fill: false,
borderColor: 'purple',
backgroundColor: 'purple',
data: calculateQualityFactor(),
borderWidth: 1,
yAxisID: 'qID'
},
{
label: 'I\u2092 (A)',
fill: false,
borderColor: 'rgb(0,255,255)',
backgroundColor: 'rgb(0,128,128)',
data: calculateCirculatingCurrent(),
borderWidth: 1,
yAxisID: 'ccID'
2021-09-21 12:45:41 +00:00
},
{
2021-09-22 11:09:02 +00:00
label: 'Perimeter (\u03BB)',
2021-09-21 12:45:41 +00:00
fill: false,
2021-09-24 04:12:36 +00:00
borderColor: 'rgb(130,130,130)',
backgroundColor: 'rgb(130,130,130)',
2021-09-21 12:45:41 +00:00
data: calculateAntennaSize(),
borderWidth: 1,
yAxisID: 'sizeID'
2020-10-17 04:04:13 +00:00
}]
},
2020-11-17 04:46:57 +00:00
options: {
responsive: true,
maintainAspectRatio: false,
scales: {
xAxes: [{
type: 'linear',
position: 'bottom',
display: true,
scaleLabel: {
display: true,
labelString: 'Frequency (MHz)'
2020-10-27 09:30:29 +00:00
}
2020-11-17 04:46:57 +00:00
}],
yAxes: [{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'Efficiency %',
fontColor: 'black',
fontStyle: 'bold'
},
ticks: {
min: 0,
max: 100,
},
position: 'left',
id: 'effID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'BW kHz',
fontColor: 'brown',
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
},
position: 'left',
id: 'bwID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'kV',
fontColor: 'rgb(150, 150, 0)',
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
2021-09-16 04:22:41 +00:00
max: 10.0,
2020-11-17 04:46:57 +00:00
},
min: 0.0,
position: 'left',
id: 'vID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: '\u03A9',
fontColor: 'red',
fontStyle: 'bold'
},
position: 'right',
id: 'mohmsID',
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'pF',
fontColor: 'green',
fontStyle: 'bold'
},
ticks: {
2021-09-26 12:46:46 +00:00
max: 1000.0,
2020-11-17 04:46:57 +00:00
},
position: 'left',
id: 'pfID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'j\u03A9',
fontColor: 'blue',
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
},
position: 'right',
id: 'ohmsID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'Q',
fontColor: 'purple',
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
2021-09-23 10:23:39 +00:00
max: 4000.0,
2020-11-17 04:46:57 +00:00
},
position: 'right',
id: 'qID'
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: 'A',
fontColor: 'rgb(0,128,128)',
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
2021-09-12 09:06:31 +00:00
max: 100.0,
2020-11-17 04:46:57 +00:00
},
min: 0.0,
position: 'right',
id: 'ccID'
2021-09-21 12:45:41 +00:00
},{
type: 'linear',
display: 'auto',
scaleLabel: {
display: true,
labelString: '\u03BB',
2021-09-24 04:12:36 +00:00
fontColor: 'rgb(90,90,90)',
2021-09-21 12:45:41 +00:00
fontStyle: 'bold'
},
ticks: {
beginAtZero: true,
max: 0.3,
},
min: 0.0,
position: 'right',
id: 'sizeID'
2020-11-17 04:46:57 +00:00
}]
},
showLines: true,
tooltips: {
mode: 'interpolate',
intersect: false,
position: 'nearest',
2020-10-27 09:30:29 +00:00
callbacks: {
2020-11-17 04:46:57 +00:00
title: function(tooltipItem, data) {
var label = '' + tooltipItem[0].xLabel.toFixed(3).toString();
label += ' MHz ';
return label;
2020-10-27 09:30:29 +00:00
},
2020-11-17 04:46:57 +00:00
label: function(tooltipItem, data) {
var label = data.datasets[tooltipItem.datasetIndex].label || '';
if (label) {
label += ': ';
}
2021-09-26 12:46:46 +00:00
if(data.datasets[tooltipItem.datasetIndex].label == "Tuning Cap (pF)" || data.datasets[tooltipItem.datasetIndex].label == "Q") {
label += Math.round(tooltipItem.yLabel);
} else {
label += tooltipItem.yLabel.toFixed(3).toString();
//label += Math.round(tooltipItem.yLabel * 1000) / 1000;
}
2020-11-17 04:46:57 +00:00
return label;
}
}
2021-09-26 11:49:37 +00:00
} ,
2020-11-17 04:46:57 +00:00
plugins: {
crosshair: {
line: {
2021-09-26 11:49:37 +00:00
color: 'grey', // crosshair line color
2020-11-17 04:46:57 +00:00
width: 1, // crosshair line width
dashPattern: [100, 100]
},
sync: {
enabled: false, // enable trace line syncing with other charts
group: 1, // chart group
suppressTooltips: true // suppress tooltips when showing a synced tracer
},
zoom: {
enabled: false, // enable zooming
zoomboxBackgroundColor: 'rgba(66,133,244,0.2)', // background color of zoom box
zoomboxBorderColor: '#48F', // border color of zoom box
zoomButtonText: 'Reset Zoom', // reset zoom button text
zoomButtonClass: 'reset-zoom', // reset zoom button class
},
callbacks: {
beforeZoom: function(start, end) { // called before zoom, return false to prevent zoom
return false; // return true to enable zooming
},
afterZoom: function(start, end) { // called after zoom
}
2020-10-27 09:30:29 +00:00
}
}
}
}
2020-11-17 04:46:57 +00:00
});
< / script >
< / body >
2020-10-08 07:21:58 +00:00
< / html >