KiCad PCB EDA Suite
Loading...
Searching...
No Matches
microstrip.cpp
Go to the documentation of this file.
1/*
2 * microstrip.cpp - microstrip class implementation
3 *
4 * Copyright (C) 2001 Gopal Narayanan <[email protected]>
5 * Copyright (C) 2002 Claudio Girardi <[email protected]>
6 * Copyright (C) 2005, 2006 Stefan Jahn <[email protected]>
7 * Modified for Kicad: 2018 Jean-Pierre Charras <jp.charras at wanadoo.fr>
8 * Copyright (C) 1992-2023 Kicad Developers, see AUTHORS.txt for contributors.
9 *
10 * This program is free software; you can redistribute it and/or modify
11 * it under the terms of the GNU General Public License as published by
12 * the Free Software Foundation; either version 2 of the License, or (at
13 * your option) any later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this package; see the file COPYING. If not, write to
22 * the Free Software Foundation, Inc., 51 Franklin Street - Fifth Floor,
23 * Boston, MA 02110-1301, USA.
24 *
25 */
26
27
28/* microstrip.c - Puts up window for microstrip and
29 * performs the associated calculations
30 * Based on the original microstrip.c by Gopal Narayanan
31 */
32
33#include <cmath>
34#include <cstdio>
35#include <cstdlib>
36#include <cstring>
37
38#include "microstrip.h"
39#include "transline.h"
40
41#include "units.h"
42
44 h( 0.0 ), // height of substrate
45 ht( 0.0 ), // height to the top of box
46 t( 0.0 ), // thickness of top metal
47 rough( 0.0 ), // Roughness of top metal
48 mur( 0.0 ), // magnetic permeability of substrate
49 w( 0.0 ), // width of line
50 l( 0.0 ), // length of line
51 Z0_0( 0.0 ), // static characteristic impedance
52 Z0( 0.0 ), // characteristic impedance
53 er_eff_0( 0.0 ), // Static effective dielectric constant
54 mur_eff( 0.0 ), // Effective mag. permeability
55 w_eff( 0.0 ), // Effective width of line
56 atten_dielectric( 0.0 ), // Loss in dielectric (dB)
57 atten_cond( 0.0 ), // Loss in conductors (dB)
58 Z0_h_1( 0.0 ) // homogeneous stripline impedance
59{
60 m_Name = "MicroStrip";
61 Init();
62}
63
64
65/*
66 * Z0_homogeneous() - compute the impedance for a stripline in a
67 * homogeneous medium, without cover effects
68 */
70{
71 double freq, Z0_value;
72
73 freq = 6.0 + ( 2.0 * M_PI - 6.0 ) * exp( -pow( 30.666 / u, 0.7528 ) );
74 Z0_value = ( ZF0 / ( 2.0 * M_PI ) ) * log( freq / u + sqrt( 1.0 + 4.0 / ( u * u ) ) );
75 return Z0_value;
76}
77
78
79/*
80 * delta_Z0_cover() - compute the cover effect on impedance for a
81 * stripline in a homogeneous medium
82 */
83double MICROSTRIP::delta_Z0_cover( double u, double h2h )
84{
85 double P, Q;
86 double h2hp1;
87
88 h2hp1 = 1.0 + h2h;
89 P = 270.0 * ( 1.0 - tanh( 1.192 + 0.706 * sqrt( h2hp1 ) - 1.389 / h2hp1 ) );
90 Q = 1.0109 - atanh( ( 0.012 * u + 0.177 * u * u - 0.027 * u * u * u ) / ( h2hp1 * h2hp1 ) );
91 return P * Q;
92}
93
94
95/*
96 * filling_factor() - compute the filling factor for a microstrip
97 * without cover and zero conductor thickness
98 */
99double MICROSTRIP::filling_factor( double u, double e_r )
100{
101 double a, b, q_inf;
102 double u2, u3, u4;
103
104 u2 = u * u;
105 u3 = u2 * u;
106 u4 = u3 * u;
107 a = 1.0 + log( ( u4 + u2 / 2704 ) / ( u4 + 0.432 ) ) / 49.0 + log( 1.0 + u3 / 5929.741 ) / 18.7;
108 b = 0.564 * pow( ( e_r - 0.9 ) / ( e_r + 3.0 ), 0.053 );
109 q_inf = pow( 1.0 + 10.0 / u, -a * b );
110 return q_inf;
111}
112
113
114/*
115 * delta_q_cover() - compute the cover effect on filling factor
116 */
117double MICROSTRIP::delta_q_cover( double h2h )
118{
119 double q_c;
120
121 q_c = tanh( 1.043 + 0.121 * h2h - 1.164 / h2h );
122 return q_c;
123}
124
125
126/*
127 * delta_q_thickness() - compute the thickness effect on filling factor
128 */
129double MICROSTRIP::delta_q_thickness( double u, double t_h )
130{
131 double q_t;
132
133 q_t = ( 2.0 * log( 2.0 ) / M_PI ) * ( t_h / sqrt( u ) );
134 return q_t;
135}
136
137
138/*
139 * e_r_effective() - compute effective dielectric constant from
140 * material e_r and filling factor
141 */
142double MICROSTRIP::e_r_effective( double e_r, double q )
143{
144 double e_r_eff;
145
146 e_r_eff = 0.5 * ( e_r + 1.0 ) + 0.5 * q * ( e_r - 1.0 );
147 return e_r_eff;
148}
149
150
151/*
152 * delta_u_thickness - compute the thickness effect on normalized width
153 */
154double MICROSTRIP::delta_u_thickness( double u, double t_h, double e_r )
155{
156 double delta_u;
157
158 if( t_h > 0.0 )
159 {
160 /* correction for thickness for a homogeneous microstrip */
161 delta_u = ( t_h / M_PI )
162 * log( 1.0 + ( 4.0 * M_E ) * pow( tanh( sqrt( 6.517 * u ) ), 2.0 ) / t_h );
163 /* correction for strip on a substrate with relative permettivity e_r */
164 delta_u = 0.5 * delta_u * ( 1.0 + 1.0 / cosh( sqrt( e_r - 1.0 ) ) );
165 }
166 else
167 {
168 delta_u = 0.0;
169 }
170 return delta_u;
171}
172
173
174/*
175 * microstrip_Z0() - compute microstrip static impedance
176 */
178{
179 double e_r, h2, h2h, u, t_h;
180 double Z0_h_r;
181 double delta_u_1, delta_u_r, q_inf, q_c, q_t, e_r_eff, e_r_eff_t, q;
182
184 h2 = m_parameters[H_T_PRM];
185 h2h = h2 / m_parameters[H_PRM];
188
189 /* compute normalized width correction for e_r = 1.0 */
190 delta_u_1 = delta_u_thickness( u, t_h, 1.0 );
191 /* compute homogeneous stripline impedance */
192 Z0_h_1 = Z0_homogeneous( u + delta_u_1 );
193 /* compute normalized width correction */
194 delta_u_r = delta_u_thickness( u, t_h, e_r );
195 u += delta_u_r;
196 /* compute homogeneous stripline impedance */
197 Z0_h_r = Z0_homogeneous( u );
198
199 /* filling factor, with width corrected for thickness */
200 q_inf = filling_factor( u, e_r );
201 /* cover effect */
202 q_c = delta_q_cover( h2h );
203 /* thickness effect */
204 q_t = delta_q_thickness( u, t_h );
205 /* resultant filling factor */
206 q = ( q_inf - q_t ) * q_c;
207
208 /* e_r corrected for thickness and non homogeneous material */
209 e_r_eff_t = e_r_effective( e_r, q );
210
211 /* effective dielectric constant */
212 e_r_eff = e_r_eff_t * pow( Z0_h_1 / Z0_h_r, 2.0 );
213
214 /* characteristic impedance, corrected for thickness, cover */
215 /* and non homogeneous material */
216 m_parameters[Z0_PRM] = Z0_h_r / sqrt( e_r_eff_t );
217
218 w_eff = u * m_parameters[H_PRM];
219 er_eff_0 = e_r_eff;
221}
222
223
224/*
225 * e_r_dispersion() - computes the dispersion correction factor for
226 * the effective permeability
227 */
228double MICROSTRIP::e_r_dispersion( double u, double e_r, double f_n )
229{
230 double P_1, P_2, P_3, P_4, P;
231
232 P_1 = 0.27488 + u * ( 0.6315 + 0.525 / pow( 1.0 + 0.0157 * f_n, 20.0 ) )
233 - 0.065683 * exp( -8.7513 * u );
234 P_2 = 0.33622 * ( 1.0 - exp( -0.03442 * e_r ) );
235 P_3 = 0.0363 * exp( -4.6 * u ) * ( 1.0 - exp( -pow( f_n / 38.7, 4.97 ) ) );
236 P_4 = 1.0 + 2.751 * ( 1.0 - exp( -pow( e_r / 15.916, 8.0 ) ) );
237
238 P = P_1 * P_2 * pow( ( P_3 * P_4 + 0.1844 ) * f_n, 1.5763 );
239
240 return P;
241}
242
243
244/*
245 * Z0_dispersion() - computes the dispersion correction factor for the
246 * characteristic impedance
247 */
249 double u, double e_r, double e_r_eff_0, double e_r_eff_f, double f_n )
250{
251 double R_1, R_2, R_3, R_4, R_5, R_6, R_7, R_8, R_9, R_10, R_11, R_12, R_13, R_14, R_15, R_16,
252 R_17, D, tmpf;
253
254 R_1 = 0.03891 * pow( e_r, 1.4 );
255 R_2 = 0.267 * pow( u, 7.0 );
256 R_3 = 4.766 * exp( -3.228 * pow( u, 0.641 ) );
257 R_4 = 0.016 + pow( 0.0514 * e_r, 4.524 );
258 R_5 = pow( f_n / 28.843, 12.0 );
259 R_6 = 22.2 * pow( u, 1.92 );
260 R_7 = 1.206 - 0.3144 * exp( -R_1 ) * ( 1.0 - exp( -R_2 ) );
261 R_8 = 1.0
262 + 1.275
263 * ( 1.0
264 - exp( -0.004625 * R_3 * pow( e_r, 1.674 )
265 * pow( f_n / 18.365, 2.745 ) ) );
266 tmpf = pow( e_r - 1.0, 6.0 );
267 R_9 = 5.086 * R_4 * ( R_5 / ( 0.3838 + 0.386 * R_4 ) )
268 * ( exp( -R_6 ) / ( 1.0 + 1.2992 * R_5 ) ) * ( tmpf / ( 1.0 + 10.0 * tmpf ) );
269 R_10 = 0.00044 * pow( e_r, 2.136 ) + 0.0184;
270 tmpf = pow( f_n / 19.47, 6.0 );
271 R_11 = tmpf / ( 1.0 + 0.0962 * tmpf );
272 R_12 = 1.0 / ( 1.0 + 0.00245 * u * u );
273 R_13 = 0.9408 * pow( e_r_eff_f, R_8 ) - 0.9603;
274 R_14 = ( 0.9408 - R_9 ) * pow( e_r_eff_0, R_8 ) - 0.9603;
275 R_15 = 0.707 * R_10 * pow( f_n / 12.3, 1.097 );
276 R_16 = 1.0 + 0.0503 * e_r * e_r * R_11 * ( 1.0 - exp( -pow( u / 15.0, 6.0 ) ) );
277 R_17 = R_7 * ( 1.0 - 1.1241 * ( R_12 / R_16 ) * exp( -0.026 * pow( f_n, 1.15656 ) - R_15 ) );
278
279 D = pow( R_13 / R_14, R_17 );
280
281 return D;
282}
283
284
285/*
286 * dispersion() - compute frequency dependent parameters of
287 * microstrip
288 */
290{
291 double e_r, e_r_eff_0;
292 double u, f_n, P, e_r_eff_f, D, Z0_f;
293
295 e_r_eff_0 = er_eff_0;
297
298 /* normalized frequency [GHz * mm] */
300
301 P = e_r_dispersion( u, e_r, f_n );
302 /* effective dielectric constant corrected for dispersion */
303 e_r_eff_f = e_r - ( e_r - e_r_eff_0 ) / ( 1.0 + P );
304
305 D = Z0_dispersion( u, e_r, e_r_eff_0, e_r_eff_f, f_n );
306 Z0_f = Z0_0 * D;
307
308 m_parameters[EPSILON_EFF_PRM] = e_r_eff_f;
309 m_parameters[Z0_PRM] = Z0_f;
310}
311
312
313/*
314 * conductor_losses() - compute microstrip conductor losses per unit
315 * length
316 */
318{
319 double e_r_eff_0, delta;
320 double K, R_s, Q_c, alpha_c;
321
322 e_r_eff_0 = er_eff_0;
324
325 if( m_parameters[FREQUENCY_PRM] > 0.0 )
326 {
327 /* current distribution factor */
328 K = exp( -1.2 * pow( Z0_h_1 / ZF0, 0.7 ) );
329 /* skin resistance */
330 R_s = 1.0 / ( m_parameters[SIGMA_PRM] * delta );
331
332 /* correction for surface roughness */
333 R_s *= 1.0
334 + ( ( 2.0 / M_PI )
335 * atan( 1.40 * pow( ( m_parameters[ROUGH_PRM] / delta ), 2.0 ) ) );
336 /* strip inductive quality factor */
338 / ( R_s * C0 * K );
339 alpha_c = ( 20.0 * M_PI / log( 10.0 ) ) * m_parameters[FREQUENCY_PRM] * sqrt( e_r_eff_0 )
340 / ( C0 * Q_c );
341 }
342 else
343 {
344 alpha_c = 0.0;
345 }
346
347 return alpha_c;
348}
349
350
351/*
352 * dielectric_losses() - compute microstrip dielectric losses per unit
353 * length
354 */
356{
357 double e_r, e_r_eff_0;
358 double alpha_d;
359
361 e_r_eff_0 = er_eff_0;
362
363 alpha_d = ( 20.0 * M_PI / log( 10.0 ) ) * ( m_parameters[FREQUENCY_PRM] / C0 )
364 * ( e_r / sqrt( e_r_eff_0 ) ) * ( ( e_r_eff_0 - 1.0 ) / ( e_r - 1.0 ) )
366
367 return alpha_d;
368}
369
370
371/*
372 * attenuation() - compute attenuation of microstrip
373 */
375{
377
380}
381
382
383/*
384 * mur_eff_ms() - returns effective magnetic permeability
385 */
387{
388 double* mur = &m_parameters[MUR_PRM];
389 double* h = &m_parameters[H_PRM];
390 double* w = &m_parameters[PHYS_WIDTH_PRM];
391 mur_eff = ( 2.0 * *mur )
392 / ( ( 1.0 + *mur ) + ( ( 1.0 - *mur ) * pow( ( 1.0 + ( 10.0 * *h / *w ) ), -0.5 ) ) );
393}
394
395
396// synth_width - calculate width given Z0 and e_r
398{
399 double e_r, a, b;
400 double w_h, width;
401
403
404 a = ( ( m_parameters[Z0_PRM] / ZF0 / 2 / M_PI ) * sqrt( ( e_r + 1 ) / 2. ) )
405 + ( ( e_r - 1 ) / ( e_r + 1 ) * ( 0.23 + ( 0.11 / e_r ) ) );
406 b = ZF0 / 2 * M_PI / ( m_parameters[Z0_PRM] * sqrt( e_r ) );
407
408 if( a > 1.52 )
409 {
410 w_h = 8 * exp( a ) / ( exp( 2. * a ) - 2 );
411 }
412 else
413 {
414 w_h = ( 2. / M_PI )
415 * ( b - 1. - log( ( 2 * b ) - 1. )
416 + ( ( e_r - 1 ) / ( 2 * e_r ) ) * ( log( b - 1. ) + 0.39 - 0.61 / e_r ) );
417 }
418
419 if( m_parameters[H_PRM] > 0.0 )
420 width = w_h * m_parameters[H_PRM];
421 else
422 width = 0;
423
424 return width;
425}
426
427
428/*
429 * line_angle() - calculate microstrip length in radians
430 */
432{
433 double e_r_eff;
434 double v, lambda_g;
435
436 e_r_eff = m_parameters[EPSILON_EFF_PRM];
437
438 /* velocity */
439 v = C0 / sqrt( e_r_eff * mur_eff );
440 /* wavelength */
441 lambda_g = v / m_parameters[FREQUENCY_PRM];
442 /* electrical angles */
443 m_parameters[ANG_L_PRM] = 2.0 * M_PI * m_parameters[PHYS_LEN_PRM] / lambda_g; /* in radians */
444}
445
446
448{
449 /* effective permeability */
450 mur_eff_ms();
451 /* static impedance */
453 /* calculate freq dependence of er and Z0 */
454 dispersion();
455 /* calculate electrical lengths */
456 line_angle();
457 /* calculate losses */
458 attenuation();
459}
460
461
463{
466
468 setResult( 1, atten_cond, "dB" );
469 setResult( 2, atten_dielectric, "dB" );
470
472}
473
474
476{
479
480 // Check for errors
481 if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
483
484 if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
486
487 // Check for warnings
488 if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
490
491 if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
493}
494
496{
499
500 // Check for errors
501 if( !std::isfinite( m_parameters[Z0_PRM] ) || ( m_parameters[Z0_PRM] < 0 ) )
503
504 if( !std::isfinite( m_parameters[ANG_L_PRM] ) || ( m_parameters[ANG_L_PRM] < 0 ) )
506
507 // Check for warnings
508 if( !std::isfinite( m_parameters[PHYS_LEN_PRM] ) || ( m_parameters[PHYS_LEN_PRM] < 0 ) )
510
511 if( !std::isfinite( m_parameters[PHYS_WIDTH_PRM] ) || ( m_parameters[PHYS_WIDTH_PRM] <= 0 ) )
513}
514
515/*
516 * synthesis function
517 */
519{
520 double z0_dest = m_parameters[Z0_PRM];
521 double angl_dest = m_parameters[ANG_L_PRM];
522 /* calculate width and use for initial value in Newton's method */
525
526 m_parameters[Z0_PRM] = z0_dest;
527 m_parameters[ANG_L_PRM] = angl_dest;
528 double const er_eff = m_parameters[EPSILON_EFF_PRM];
530 * m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
531 calcAnalyze();
532
533 m_parameters[Z0_PRM] = z0_dest;
534 m_parameters[ANG_L_PRM] = angl_dest;
536 * m_parameters[ANG_L_PRM] / 2.0 / M_PI; /* in m */
537}
double w_eff
Definition: microstrip.h:49
void microstrip_Z0()
Definition: microstrip.cpp:177
double e_r_effective(double, double)
Definition: microstrip.cpp:142
void calcSynthesize() override
Computation for synthesis.
Definition: microstrip.cpp:518
double Z0_0
Definition: microstrip.h:45
double dielectric_losses()
Definition: microstrip.cpp:355
void line_angle()
Definition: microstrip.cpp:431
double w
Definition: microstrip.h:43
double atten_cond
Definition: microstrip.h:51
void dispersion()
Definition: microstrip.cpp:289
double filling_factor(double, double)
Definition: microstrip.cpp:99
double Z0_dispersion()
double e_r_dispersion(double, double, double)
Definition: microstrip.cpp:228
double delta_u_thickness(double, double, double)
Definition: microstrip.cpp:154
double delta_q_thickness(double, double)
Definition: microstrip.cpp:129
double delta_q_cover(double)
Definition: microstrip.cpp:117
void calcAnalyze() override
Computation for analysis.
Definition: microstrip.cpp:447
double synth_width()
Definition: microstrip.cpp:397
double mur_eff
Definition: microstrip.h:48
double atten_dielectric
Definition: microstrip.h:50
double alpha_c()
double er_eff_0
Definition: microstrip.h:47
void mur_eff_ms()
Definition: microstrip.cpp:386
void show_results() override
Shows results.
Definition: microstrip.cpp:462
double h
Definition: microstrip.h:38
double conductor_losses()
Definition: microstrip.cpp:317
double Z0_homogeneous(double)
Definition: microstrip.cpp:69
void showAnalyze() override
Shows synthesis results and checks for errors / warnings.
Definition: microstrip.cpp:495
void showSynthesize() override
Shows analysis results and checks for errors / warnings.
Definition: microstrip.cpp:475
double mur
Definition: microstrip.h:42
double Z0_h_1
Definition: microstrip.h:54
void attenuation()
Definition: microstrip.cpp:374
double delta_Z0_cover(double, double)
Definition: microstrip.cpp:83
void Init()
Definition: transline.cpp:87
void setResult(int, double, const char *)
Definition: transline.cpp:130
bool minimizeZ0Error1D(double *)
@function minimizeZ0Error1D
Definition: transline.cpp:346
double m_parameters[EXTRA_PRMS_COUNT]
Definition: transline.h:131
const char * m_Name
Definition: transline.h:84
void setProperty(enum PRMS_ID aPrmId, double aValue)
Definition: transline.cpp:106
double skin_depth()
@function skin_depth calculate skin depth
Definition: transline.cpp:234
void setErrorLevel(PRMS_ID, char)
@function setErrorLevel
Definition: transline.cpp:432
#define D(x)
Definition: ptree.cpp:41
constexpr int delta
@ EPSILON_EFF_PRM
Definition: transline.h:74
@ SIGMA_PRM
Definition: transline.h:69
@ SKIN_DEPTH_PRM
Definition: transline.h:70
@ FREQUENCY_PRM
Definition: transline.h:51
@ T_PRM
Definition: transline.h:46
@ MUR_PRM
Definition: transline.h:48
@ Z0_PRM
Definition: transline.h:52
@ TAND_PRM
Definition: transline.h:40
@ PHYS_LEN_PRM
Definition: transline.h:60
@ ANG_L_PRM
Definition: transline.h:55
@ H_T_PRM
Definition: transline.h:44
@ ROUGH_PRM
Definition: transline.h:47
@ EPSILONR_PRM
Definition: transline.h:39
@ H_PRM
Definition: transline.h:42
@ PHYS_WIDTH_PRM
Definition: transline.h:56
#define TRANSLINE_WARNING
Definition: transline.h:30
#define TRANSLINE_ERROR
Definition: transline.h:31
#define ZF0
Definition: units.h:62
double atanh(double x)
Definition: units.h:51
#define C0
Definition: units.h:61
#define UNIT_MICRON
Definition: units_scales.h:35