tracespace icon indicating copy to clipboard operation
tracespace copied to clipboard

Collect board stats when processing gerber collection

Open kasbah opened this issue 6 years ago • 15 comments

(@mcous has taken over this post to elevate comment below):

New package proposal: @tracespace/stats. It think it could have the same signature as pcb-stackup or be included in pcb-stackup by default.

As a user rendering boards, I often to collect other information about the board for manufacturing / quoting purposes. The following pieces of information should be "easy" to collect:

  • Number of layers of a given type
  • Minimum trace width
  • Number of drill hits
  • Drill sizes
  • Board size
  • Number of pads
    • At the moment, hard to distinguish between TH and SM pads

Both @kasbah and myself have received emails about this sort of functionality. Also see #139

kasbah avatar Mar 21 '18 14:03 kasbah

This could be a good thing to pair with a what's that gerber update. I've been thinking about a more sane API for wtg, and a return object (rather than a string) of something like:

{
  type: 'copper',
  side: 'top'
}
// and
{
  type: 'drill',
  side: 'all'
}

Would both be way easier to use and make something like this more straightforward

mcous avatar Mar 21 '18 19:03 mcous

Once #77 is merged, this can be accomplished with:

const pcbStackup = require('pcb-stackup')
const wtg = require('wtg')
const layers = getLayersSomehow() 

pcbStackup(layers, (error, stackup) => {
  if (error) return console.error(error)
  console.log(`Number of copper layers: ${
    stackup.layers.filter(ly => ly.type === wtg.TYPE_COPPER).length
  }`)
})

I guess pre-77, you could still do:

const pcbStackup = require('pcb-stackup')
const layers = getLayersSomehow() 

pcbStackup(layers, (error, stackup) => {
  if (error) return console.error(error)
  console.log(`Number of copper layers: ${
    stackup.layers.filter(ly => ly.type.slice(1) === 'cu').length
  }`)
})

@kasbah do you think that's satisfactory to close this issue?

mcous avatar Nov 03 '18 16:11 mcous

Thinking this might be worth a package: @tracespace/stats or something. It think it could have the same signature as pcb-stackup. I've gotten a few emails about various bits of information people are trying to glean, and I think there's at least a naive path forward on most of them.

  • Number of layers of type
  • Minimum trace width
  • Minimum trace spacing
    • Not sure how to do this one; it's getting into DFM checker territory
  • Number of drill hits
  • Drill sizes
  • Board size

mcous avatar Nov 04 '18 18:11 mcous

Yes, I agree. I was going to open an issue about minimum trace width actually as I may be able to get a paid gig to work on that.

kasbah avatar Nov 04 '18 18:11 kasbah

Prior art: https://github.com/bellmann/pcb.js/blob/master/index.js

mcous avatar Mar 21 '19 22:03 mcous

Is there any updates to this? I'm yet another person who would like to glean them juicy statistics (trace width, trace spacing, pad size being the main ones I'm looking for). Even just an idea of how to approach getting this information would be incredibly appreciated.

@mcous You mentioned having a "naive path forward" -- is there any documentation on this? I've been trying to think of an approach and the best I can do is "parse out and interpret values from the SVG markup produced by gerber-to-svg" but my unfortunate lack of PCB manufacturing and vector imaging knowledge really holds me back (that, and budget heh). And I also feel like that approach may be entirely wrong!

Thanks, and kudos on this fantastic set of utilities! Been a pleasure working with all these tools.

dontpanic avatar Jul 31 '20 00:07 dontpanic

@dontpanic there's been some progress in the sense that the next major version of the tracespace project will be much more geared towards producing inspectable trees at various steps rather than streaming directly into an SVG string:

  1. Abstract syntax tree of each Gerber file
  2. Plot trees for each file <- this is what you'd inspect for stuff
  3. SVG syntax tree

You can try out (1): npm i @tracespace/parser@next. The rest are still in progress. It would, however, be a pretty tall order to glean any information from the syntax tree itself (though it's certainly possible! At that point, you're effectively starting work on a plot tree generator...).

For now, you could try to using the existing gerber-to-svg pipeline and hook into the plotter:

const converter = gerberToSvg(copperFileContents)
const plotter = converter.plotter

plotter.on('data', () => {
  // grab tool shapes, pad flashes, and trace strokes here
  // see https://github.com/tracespace/tracespace/blob/main/packages/gerber-plotter/API.md
})

From there, you could "naively" grab:

  • Trace width, by looking at the tool diameter used for stroke plotter objects
    • If your Gerber file uses strokes for copper fills, like Eagle often does, this could be misleading
  • Pad size, by looking at the tool shape + size params for pad plotter objects
    • Sometimes, CAD programs (still looking at Eagle) will use strokes for pads, so again, this is naive

Unfortunately, copper spacing is a much harder problem because it involves building up an actual geometric understanding of the shapes plotted rather than simply recording them

mcous avatar Jul 31 '20 00:07 mcous

Is a there a way I can solve the strokes for pads issue because I'm having trouble counting the pads.

In a single file I get different kinds of output.

 {
        type: 'shape',
        tool: '10',
        shape: [
            { type: 'rect', cx: 0, cy: 0, r: 0, width: 0.35, height: 0.35 },
        ],
    },
    { type: 'pad', tool: '10', x: 43.5164, y: 30.8491 },
    { type: 'pad', tool: '10', x: 44.5164, y: 30.8491 },
    { type: 'pad', tool: '10', x: 47.9505, y: 32.7134 },
    { type: 'pad', tool: '10', x: 46.9505, y: 32.7134 },
    {
        type: 'stroke',
        width: 0.145,
        path: [
            {type: 'line',start: [53.8203, 31.0353],end: [55.0653, 31.0353]},
            {type: 'line',start: [55.0653, 31.0353],end: [55.0653, 30.6003]},
            {type: 'line',start: [55.0653, 30.6003],end: [53.8203, 30.6003]},
            {type: 'line',start: [53.8203, 30.6003],end: [53.8203, 31.0353]},
            {type: 'line',start: [53.8203, 30.738],end: [55.0653, 30.738]},
            {type: 'line',start: [55.0653, 30.8757],end: [53.8203, 30.8757]},
            {type: 'line',start: [53.8203, 31.0134],end: [55.0653, 31.0134]},
            {type: 'line',start: [55.0653, 31.9853],end: [53.8203, 31.9853]},
            {type: 'line',start: [53.8203, 31.9853],end: [53.8203, 31.5503]},
            {type: 'line',start: [53.8203, 31.5503],end: [55.0653, 31.5503]},
            {type: 'line',start: [55.0653, 31.5503],end: [55.0653, 31.9853]},
            {type: 'line',start: [53.8203, 31.688],end: [55.0653, 31.688]},
            {type: 'line',start: [55.0653, 31.8257],end: [53.8203, 31.8257]},
            {type: 'line',start: [53.8203, 31.9634],end: [55.0653, 31.9634]},
            {type: 'line',start: [55.0653, 32.9353],end: [53.8203, 32.9353]},
            {type: 'line',start: [53.8203, 32.9353],end: [53.8203, 32.5003]},
            {type: 'line',start: [53.8203, 32.5003],end: [55.0653, 32.5003]},
            {type: 'line',start: [55.0653, 32.5003],end: [55.0653, 32.9353]},
            {type: 'line',start: [53.8203, 32.638],end: [55.0653, 32.638]},
            {type: 'line',start: [55.0653, 32.7757],end: [53.8203, 32.7757]},
            {type: 'line',start: [53.8203, 32.9134],end: [55.0653, 32.9134]},
            {type: 'line',start: [52.7353, 32.9353],end: [51.4903, 32.9353]},
            {type: 'line',start: [51.4903, 32.9353],end: [51.4903, 32.5003]},
            {type: 'line',start: [51.4903, 32.5003],end: [52.7353, 32.5003]},
            {type: 'line',start: [52.7353, 32.5003],end: [52.7353, 32.9353]},
            {type: 'line',start: [51.4903, 32.638],end: [52.7353, 32.638]},
            {type: 'line',start: [52.7353, 32.7757],end: [51.4903, 32.7757]},
            {type: 'line',start: [51.4903, 32.9134],end: [52.7353, 32.9134]},
            {type: 'line',start: [52.7353, 31.0353],end: [51.4903, 31.0353]},
            {type: 'line',start: [51.4903, 31.0353],end: [51.4903, 30.6003]},
            {type: 'line',start: [51.4903, 30.6003],end: [52.7353, 30.6003]},
            {type: 'line',start: [52.7353, 30.6003],end: [52.7353, 31.0353]},
            {type: 'line',start: [51.4903, 30.738],end: [52.7353, 30.738]},
            {type: 'line',start: [52.7353, 30.8757],end: [51.4903, 30.8757]},
            {type: 'line',start: [51.4903, 31.0134],end: [52.7353, 31.0134]},
        ],
    }

The pads that have strokes instead of tool size have been marked Screenshot (6)

This is the file I used to extract the pads. gerber_paste_layer_example.zip

Please help.

M0hammedImran avatar May 21 '21 09:05 M0hammedImran

The parameters most often required for quoting PCB manufacturing are:

  • Dimensions and UOM (already available)
  • Thickness
  • Layer count (already available)
  • Laminations - to cover blind and buried vias (any drill hole that doesn't pass through all layers requires a lamination. This significantly impacts the cost of manufacturing)
  • Copper weight
  • Material type (e.g. FR4)
  • Finish (e.g. ENIG)
  • SilkScreen color - if specified in the file
  • Solder Mask (top, bottom, both)
  • Solder Mask Color (e.g. green) if specified in the file
  • IPC Class
  • Drill sizes
  • Finish

Other fields are helpful, but these are used by many PCB fab houses in determining the cost.

Sharp92938 avatar Aug 01 '21 15:08 Sharp92938

A lot of those are not available in the RS274-X format though. I believe more are available in Gerber X2 but Tracespace doesn't support that yet.

kasbah avatar Aug 09 '21 11:08 kasbah

I've added a $500 bounty to #372 which is a start on some of this functionality: https://www.bountysource.com/issues/102825979-extract-drill-information

kasbah avatar Oct 10 '21 19:10 kasbah

Feel free to add to that bounty if you have an interest in this functionality.

kasbah avatar Oct 10 '21 19:10 kasbah

@kasbah aren't they available already?

I am happy to back further development of this package (especially when it comes to statistics!) but would prefer somewhat of a scope first, if feasible at all.

ju5t avatar Oct 10 '21 19:10 ju5t

Not sure what you mean @ju5t, #372 has a more reduced scope. Do you mean it's already been implemented?

kasbah avatar Oct 10 '21 20:10 kasbah

@kasbah sorry, you're right that there isn't a great API for this yet.

ju5t avatar Oct 14 '21 08:10 ju5t