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