matthuszagh / pyems

High-level python interface to OpenEMS with automatic mesh generation

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

PCB Properties

clemc98 opened this issue · comments

Hi, i would know if is it possible to use different pcb properties than oshpark4 like rf4 for example ?

I don't know anything about EM simulations but I think I can answer this question.


For simulation with your own PCB. you need to define two pieces of information - dielectric material and PCB parameters.

Create a PCB definition

Before we begin, create an empty file named project.py for the purpose of this tutorial, and import the following definitions.

from pyems.pcb import PCBProperties
from pyems.material import Dielectric

First, we need to define the dielectric material of the PCB using its dielectric constants and loss tangents at different frequencies. By default, two materials are pre-defined - FR408 and PTFE. You can see their definitions in pyems/material.py.

common_dielectrics = {
    "FR408": Dielectric(
        epsr=[
            (100e6, 3.72),
            (1e9, 3.69),
            (2e9, 3.68),
            (5e9, 3.64),
            (10e9, 3.65),
        ],
        loss=[
            (100e6, 0.0072),
            (1e9, 0.0091),
            (2e9, 0.0092),
            (5e9, 0.0098),
            (10e9, 0.0095),
        ],
    ),
    "PTFE": Dielectric(epsr=[(1, 2.06)], loss=[(1, 0.0002)]),
}

As you can see, FR408 and PTFE are both high-performance materials with low dielectric constants and loss tangents. Now let's define our generic FR-4 material, with a dielectric constant εr = 4.6 and a loss tangent of 0.03. For simplicity, we assume εr is not a function of frequency (in fact, εr drops slightly as frequency increases) and define them at 1 Hz, pyems, has nothing better to select, will always return this value for all frequencies).

project_dielectrics = {
    "Generic-FR-4": Dielectric(epsr=[(1, 4.6)], loss=[(1, 0.03)]),
}

Then write that into project.py (don't attempt to change the library file pyems/material.py itself, otherwise everyone needs to install your custom copy of pyems).

Next, we need to define our PCB parameters. By default, pyems/pcb.py defines oshpark4.

common_pcbs = {
    "oshpark4": PCBProperties(
        substrate=common_dielectrics["FR408"],
        copper_thickness=[0.0356e-3, 0.0178e-3, 0.0178e-3, 0.0356e-3],
        substrate_thickness=[0.1702e-3, 1.1938e-3, 0.1702e-3],
        metal_conductivity=5.8e7,
        via_plating_thickness=0.0254e-3,
    )
}

As we see, these are the parameters that we need to define.

  • substrate - dielectric material of the PCB. We use "Generic-FR-4" as we defined previously.
  • copper_thickness - layer by layer, defined in a list, unit is meter.
  • substrate_thickness - layer by layer, defined in a list, unit is meter.
  • metal_conductivity - copper conductivity, no change needed.
  • via_plating_thickness - the metalization thickness of the plated through-hole vias. According to this post, typical value is around 16 to 23 microns, ask your manufacturer if you need an accurate value. But I think it does not matter here.

Assume we're making a 1-oz (copper thickness 0.0356 mm), 1.6 mm, two-layer board. We define:

project_pcbs = {
    "custom-2layer": PCBProperties(
        substrate=project_dielectrics["Generic-FR-4"],
        copper_thickness=[0.0356e-3, 0.0356e-3],
        substrate_thickness=[1.6e-3],
        metal_conductivity=5.8e7,
        via_plating_thickness=0.020e-3,
    )
}

Then write that into project.py.

Running a Simulation

Finally let's try using the PCB we just defined for a real simulation, say examples/microstrip.py.

Copy the project.py we just written into examples/. Then we need to modify microstrip.py for our simulation needs.

Import PCB Definitions

In the beginning of the file...

  1 #!/usr/bin/env python3
  2 
  3 import numpy as np
  4 from pyems.structure import PCB, Microstrip
  5 from pyems.simulation import Simulation
  6 from pyems.mesh import Mesh
  7 from pyems.pcb import common_pcbs
  8 from pyems.coordinate import Coordinate2, Axis, Box3, Coordinate3
  9 from pyems.field_dump import FieldDump, DumpType
 10 from pyems.utilities import print_table

Add

from project import project_pcbs

Below line 10.

Change PCB Materials

 21 pcb_prop = common_pcbs["oshpark4"]

Change this to

#pcb_prop = common_pcbs["oshpark4"]  (commented out)
pcb_prop = project_pcbs["custom-2layer"]

Change Line Width

The original file defines...

 15 unit = 1e-3
 16 sim = Simulation(freq=freq, unit=unit, reference_frequency=ref_freq)
 17 pcb_len = 10
 18 pcb_width = 5
 19 trace_width = 0.38

Note that unit = 1e-3, so all units here are in millimeters.

Since we're simulating a 50-ohm microstrip on a 1.6 mm PCB, we need to adjust the line width to produce the characteristic impedance. ProTip: For a thick 2-layer board, a 50-ohm microstrip's line width is approximately 2x the board thickness, trace_width = 3.2.

After the trace is significantly widened, the entire board should also be enlarged so they are not out of proportions. Here, we increase PCB length and width by 4x.

pcb_len = 40
pcb_width = 20
trace_width = 3.2

Simulate

Running python3 microstrip.py, after a few seconds of auto-meshing, we should be able to see our PCB model in CSXCAD.

2-layer PCB under Simulation is CSXCAD

Close the window and start the simulation, and we get the following results after a minute.

freq      z0          s11         
0.00      48.8447     -33.7377    
0.01      48.1392     -33.7345    
0.02      48.0268     -33.7247    
0.03      47.9999     -33.7089    
0.04      47.9876     -33.6873    
0.05      47.9793     -33.6607    

The characteristic impedance of the microstrip line is around 50 ohms, as expected. This is a successful simulation.

Limitations

I also noticed some limitations when writing this answer.

  1. Currently, pyems assumes each layer is separated by the same dielectric material. But in practice, in a 4-layer board, the prepreg layer between layer 1/2 & 3/4, and the core layer between 2/3 are different materials with different dielectric constants.

  2. Currently, pyems colors the substrate as the "green" solder mask color. But in fact solder mask modeling, which is yet another dielectric material, is not even supported, thus this color, while familiar to look at, is somewhat misleading.

The effects of extra dielectrics are mostly negligible, so these simplifications don't affect simulation accuracy by too much.

This is correct, thanks for chiming in @biergaizi! You're also right about the limitations. Different dielectrics for different layers has been on the todo list for a while, but I haven't gotten around to it yet (though it's probably a simple fix). I also agree that green is a poor default substrate color. I opened an issue for that.

I'm closing this as I feel it's been adequately answered. I've opened separate issues for each of the mentioned limitations.