3D Gerber Viewer

Reflow ovens, hot plates, pick and place machines, test rigs, solder stencils. Small scale manufacturing and prototyping tool discussion.

Re: 3D Gerber Viewer

Postby TomKeddie » Tue Aug 18, 2015 6:20 pm

Hey Jerome, I'm struggling a little on OSX. I think I have the wrong lua version perhaps. Is that the correct thing to do with LUA_PATH?

The error might be related to http://lua-users.org/lists/lua-l/2013-03/msg00061.html (I really just want to panelise some boards, not learn lua ;-)
Thanks, Tom

Code: Select all
tomk-macbook-pro:201508 tom$ export LUA_PATH=~/hg/hg.piratery.net/aperture-scripting/boards.lua
tomk-macbook-pro:201508 tom$ lua panel.cfg
lua: error loading module 'lfs' from file '/Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua':
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:263: too many C levels (limit is 200) in function at line 201 near ''-''
stack traceback:
   [C]: in ?
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   ...
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   /Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:7: in main chunk
   [C]: in function 'require'
   panel.cfg:1: in main chunk
   [C]: in ?


panel.cfg is

Code: Select all
tomk-macbook-pro:201508 tom$ cat panel.cfg
local boards = require 'boards'
local waterlogger = assert(boards.load('../../kicad/waterlogger/gerber'))

tomk-macbook-pro:201508 tom$
TomKeddie
Full Member
Full Member
 
Posts: 183
Joined: Tue Dec 18, 2012 3:26 pm

Re: 3D Gerber Viewer

Postby doub » Tue Sep 01, 2015 4:59 am

This is not the correct thing to do with LUA_PATH. Use the following instead:

export LUA_PATH="~/hg/hg.piratery.net/aperture-scripting/?.lua;;"
doub
Full Member
Full Member
 
Posts: 131
Joined: Tue Aug 07, 2012 8:59 pm

Re: 3D Gerber Viewer

Postby TomKeddie » Tue Sep 01, 2015 9:43 am

Jerome, many thanks, I had got past that point with symlinks but will add the env var. I'm now stuck with excellon files trying to panelise.

Here is the output I see, I will attach the files. It seems that the excellon data is being scaled or shifted incorrectly perhaps?

Thanks,
Tom

tomk-macbook-pro:tmp tom$ lua panel.lua
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gbo
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gbl
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gtl
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gto
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gtp
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gts
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gbs
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.txt
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gml
warning: typing of macro OC8 is ambiguous
loading AVR-Pocket-Programmer/AVR-Pocket-Programmer.gbp
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gbo
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gbl
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gtl
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gto
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gtp
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gts
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gbs
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.txt
loading pyboard/pyboard.gml
warning: typing of macro OC8 is ambiguous
loading pyboard/pyboard.gbp
warning: typing of macro OC8 is ambiguous
30480000000.0 46990000000.0
39999920000.0 33999932000.0
saving ./final/tkeddie_201508.gbo
saving ./final/tkeddie_201508.gbl
warning: typing of macro OC8 is ambiguous
saving ./final/tkeddie_201508.gtl
warning: typing of macro OC8 is ambiguous
saving ./final/tkeddie_201508.gto
saving ./final/tkeddie_201508.gtp
saving ./final/tkeddie_201508.gts
warning: typing of macro OC8 is ambiguous
saving ./final/tkeddie_201508.gbs
warning: typing of macro OC8 is ambiguous
saving ./final/tkeddie_201508.txt
lua: .../hg/hg.piratery.net/aperture-scripting/gerber/blocks.lua:250: assertion failed!
stack traceback:
[C]: in function 'assert'
.../hg/hg.piratery.net/aperture-scripting/gerber/blocks.lua:250: in function 'gerber.blocks.save_number'
...g/hg.piratery.net/aperture-scripting/excellon/blocks.lua:104: in function <...g/hg.piratery.net/aperture-scripting/excellon/blocks.lua:101>
(...tail calls...)
[C]: in function 'tostring'
...g/hg.piratery.net/aperture-scripting/excellon/blocks.lua:254: in function 'excellon.blocks.save'
...s/tom/hg/hg.piratery.net/aperture-scripting/excellon.lua:406: in function 'excellon.save'
(...tail calls...)
/Users/tom/hg/hg.piratery.net/aperture-scripting/boards.lua:397: in function 'boards.save'
panel.lua:32: in main chunk
[C]: in ?
Attachments
tkeddie.zip
(755.72 KiB) Downloaded 415 times
TomKeddie
Full Member
Full Member
 
Posts: 183
Joined: Tue Dec 18, 2012 3:26 pm

Re: 3D Gerber Viewer

Postby doub » Tue Sep 01, 2015 11:56 am

The input Excellon files are bad. They both have a wrong number format (inconsistent between header and data), but in a different way.

To fix AVR-Pocket-Programmer.txt you need to replace M72 with:
Code: Select all
INCH,TZ
;FILE_FORMAT=2:6


To fix pyboard.txt you need to replace M72 with:
Code: Select all
INCH,TZ
;FILE_FORMAT=2:5


Then to be able to merge these two you need to make their formats match. Just after loading, in the panel file, add the following:
Code: Select all
micropython.images.drill.format.decimal = 6


And the result:

tkeddie-panel.png


Note that you can save some board space by better panelizing the sub-boards (you can rotate boards in your panel script).
doub
Full Member
Full Member
 
Posts: 131
Joined: Tue Aug 07, 2012 8:59 pm

Re: 3D Gerber Viewer

Postby TomKeddie » Thu Sep 03, 2015 12:52 pm

Thanks for helping me with Eagle's crappy excellon generation.

Here is my final panel. I've also attached my script. Is png generation supported in the script? I'm not using your viewer as I'm on a mac.

There is a bug there, I think the rounded corners are going to be milled off the board in the bottom right.

Untitled.png


Untitled 2.png


Code: Select all
local boards = require 'boards'
local extents = require 'boards.extents'
local panelization = require 'boards.panelization'

local makeymusic = assert(boards.load('../../eagle/makeymusic/makeymusic'))
local avrpocket = assert(boards.load('../../../../git/sparkfun/Pocket_AVR_Programmer/Hardware/AVR-Pocket-Programmer'))
local micropython = assert(boards.load('../../../../git/micropython/pyboard/eagle/pyboard'))
local adafruitusbisolator = assert(boards.load('../../../../git/adafruit/Adafruit-USB-Isolator-PCB/Adafruit USB Isolator'))

-- excellon overrides
micropython.images.drill.format.decimal = 6
adafruitusbisolator.images.drill.format.decimal = 6
makeymusic.images.drill.format.decimal = 6

-- size
max_panel_height = 10e9
max_panel_width = 10e9

-- options
local spacing = 1.7e9
local options = {}
options["spacing"] = spacing;

-- extract extents and print them
local makeymusic_extents = extents.compute_board_extents(makeymusic)
local avrpocket_extents = extents.compute_board_extents(avrpocket)
local micropython_extents = extents.compute_board_extents(micropython)
local adafruitusbisolator_extents = extents.compute_board_extents(adafruitusbisolator)

local makeymusic_height=makeymusic_extents["top"]-makeymusic_extents["bottom"]
local makeymusic_width=makeymusic_extents["right"]-makeymusic_extents["left"]
print("makeymusic", makeymusic_height, makeymusic_width)

local avrpocket_height=avrpocket_extents["top"]-avrpocket_extents["bottom"]
local avrpocket_width=avrpocket_extents["right"]-avrpocket_extents["left"]
print("avrpocket", avrpocket_height, avrpocket_width)

local micropython_height=micropython_extents["top"]-micropython_extents["bottom"]
local micropython_width=micropython_extents["right"]-micropython_extents["left"]
print("micropython", micropython_height, micropython_width)

local adafruitusbisolator_height=adafruitusbisolator_extents["top"]-adafruitusbisolator_extents["bottom"]
local adafruitusbisolator_width=adafruitusbisolator_extents["right"]-adafruitusbisolator_extents["left"]
print("adafruitusbisolator", adafruitusbisolator_height, adafruitusbisolator_width)

-- make all the top panels the same height
local tab1 = panelization.empty_board(avrpocket_width, makeymusic_height-avrpocket_height)
local avrpocket_panel = panelization.panelize({tab1, avrpocket}, options, true)

local tab2 = panelization.empty_board(micropython_width, makeymusic_height-micropython_height)
local micropython_panel = panelization.panelize({tab2, micropython}, options, true)

local tab3 = panelization.empty_board(adafruitusbisolator_width, makeymusic_height-adafruitusbisolator_height)
local adafruitusbisolator_panel = panelization.panelize({tab3, adafruitusbisolator}, options, true)

local top_panel = assert(panelization.panelize({avrpocket_panel,  micropython_panel, adafruitusbisolator_panel}, options, false))

-- extract top panel extents
local top_panel_extents = extents.compute_board_extents(top_panel)
local top_panel_height=top_panel_extents["top"]-top_panel_extents["bottom"]
local top_panel_width=top_panel_extents["right"]-top_panel_extents["left"]
print("top_panel", top_panel_height, top_panel_width)

-- pad out bottom panel to same width as top
local tab4 = panelization.empty_board(top_panel_width-makeymusic_width-spacing, makeymusic_height)
local bottom_panel = assert(panelization.panelize({makeymusic, tab4}, options, false))

-- final panel
local panel = assert(panelization.panelize({top_panel,  bottom_panel}, options, true))
boards.merge_apertures(panel)

local panel_extents = extents.compute_board_extents(panel)
local panel_height=panel_extents["top"]-panel_extents["bottom"]
local panel_width=panel_extents["right"]-panel_extents["left"]
print("panel", panel_height, panel_width)

assert(boards.save(panel, './final/tkeddie_201508'))

Attachments
tkeddie.zip
(318.51 KiB) Downloaded 164 times
TomKeddie
Full Member
Full Member
 
Posts: 183
Joined: Tue Dec 18, 2012 3:26 pm

Re: 3D Gerber Viewer

Postby doub » Thu Sep 03, 2015 3:05 pm

I have an utility to make PNGs but it's Windows only just like my viewer.

The rounded corner look fine in both my grbv and gEDA's Gerber Viewer.

However your drill data is still bad. And the copper layers look wrong too, even on your own pictures. Pads and traces are overlapping but that doesn't look to be on purpose.
doub
Full Member
Full Member
 
Posts: 131
Joined: Tue Aug 07, 2012 8:59 pm

Re: 3D Gerber Viewer

Postby TomKeddie » Fri Sep 04, 2015 8:26 am

Thanks for pointing that out, I'm switching back to gerbmerge for now. The drill data is still out, am working on it.

Untitled.png
Attachments
tkeddie_201509.zip
(326.57 KiB) Downloaded 165 times
TomKeddie
Full Member
Full Member
 
Posts: 183
Joined: Tue Dec 18, 2012 3:26 pm

Re: 3D Gerber Viewer

Postby doub » Fri Sep 04, 2015 4:17 pm

If that problem on the big board only appears with my tool, then I'd like to fix the bug. Can you send me the 4 sub-boards and the panel script you used? You can send it directly by email if it's proprietary stuff and you don't want it published.
doub
Full Member
Full Member
 
Posts: 131
Joined: Tue Aug 07, 2012 8:59 pm

Re: 3D Gerber Viewer

Postby TomKeddie » Mon Dec 07, 2015 7:25 am

This is working well for me now. I just wrote two library functions to calculate and add the tabs for me. They don't do any checking so they fall over where boards don't match in size but there isn't enough space to add a tab to make them match. Dirty PCBs should make this just fine, they made the panel above just fine.

pcb_panel.png


Code: Select all
local boards = require 'boards'
local extents = require 'boards.extents'
local panelization = require 'boards.panelization'
local manipulation = require 'boards.manipulation'

local max_panel_lr = 100e9
local max_panel_bt = 100e9
max_panel = panelization.empty_board(max_panel_lr, max_panel_bt)

-- options
spacing = 1.7e9
options = {}
options["spacing"] = spacing
options["routing_mode"] = "stroke"

function merge(name, board1, board2, match_lr)
   local board1_extents = extents.compute_board_extents(board1)
   local size1_bt = board1_extents["top"]-board1_extents["bottom"]
   local size1_lr = board1_extents["right"]-board1_extents["left"]
   local board2_extents = extents.compute_board_extents(board2)
   local size2_bt = board2_extents["top"]-board2_extents["bottom"]
   local size2_lr = board2_extents["right"]-board2_extents["left"]
   local merged_panel = {}

   if match_lr == 1 then
      if size1_lr ~= size2_lr then
         local tab = panelization.empty_board(size1_lr - size2_lr - spacing, size2_bt)
         local panel = panelization.panelize({board2, tab}, options, false)
         merged_panel =  panelization.panelize({board1, panel}, options, true)
      else
         merged_panel =  panelization.panelize({board1, board2}, options, true)
      end
   else
      if size1_bt ~= size2_bt then
         local tab = panelization.empty_board(size2_lr, size1_bt - size2_bt - spacing)
         local panel = panelization.panelize({board2, tab}, options, true)
         merged_panel =  panelization.panelize({board1, panel}, options, false)
      else
         merged_panel =  panelization.panelize({board1, board2}, options, false)
      end
   end

   local merged_panel_extents = extents.compute_board_extents(merged_panel)
   local size_bt = merged_panel_extents["top"]-merged_panel_extents["bottom"]
   local size_lr = merged_panel_extents["right"]-merged_panel_extents["left"]
   print("merge", name, size_lr, size_bt)

   return merged_panel
end

function pcb(filepath, pad_lr_board, pad_bt_board)
   local board = assert(boards.load(filepath))
   board.images.drill.format.zeros = 'L'
   board.images.drill.format.integer = 2
   board.images.drill.format.decimal = 6
   local board_extents = extents.compute_board_extents(board)
   local size_bt = board_extents["top"]-board_extents["bottom"]
   local size_lr = board_extents["right"]-board_extents["left"]
   print(filepath, size_lr, size_bt)

   if pad_lr_board ~= 0 then
      local new_extents = extents.compute_board_extents(pad_lr_board)
      local new_size_lr = new_extents["right"] - new_extents["left"]
      local tab_lr = panelization.empty_board(new_size_lr - size_lr - spacing, size_bt)
      local panel_lr = panelization.panelize({board, tab_lr}, options, false)

      board = panel_lr
      board_extents = extents.compute_board_extents(board)
      size_bt = board_extents["top"]-board_extents["bottom"]
      size_lr = board_extents["right"]-board_extents["left"]
      print("LR Adjusted size", size_lr, size_bt)
   end
   if pad_bt_board ~= 0 then
      local new_extents = extents.compute_board_extents(pad_bt_board)
      local new_size_bt = new_extents["top"] - new_extents["bottom"]
      local tab_bt = panelization.empty_board(size_lr, new_size_bt - size_bt - spacing)
      local panel_bt = panelization.panelize({board, tab_bt}, options, true)

      board = panel_bt
      board_extents = extents.compute_board_extents(board)
      size_bt = board_extents["top"]-board_extents["bottom"]
      size_lr = board_extents["right"]-board_extents["left"]
      print("BT Adjusted size", size_lr, size_bt)
   end

   return board
end

local elseq = pcb('../../../../git/sparkfun/EL_Sequencer/Hardware/EL_Sequencer', 0, 0)
local ft231x = pcb('../../../../git/sparkfun/FT231X_Breakout/hardware/ft231x-breakout', 0, 0)
local pstest = pcb('../../eagle/switching-ps-test/switching-ps-test', 0, 0)
local vert1_top = merge("vert1_top", ft231x, pstest, 0)

local vert1 = merge("vert1", elseq, vert1_top, 1)

-- vert2
local ftdibasic = pcb('../../../../git/sparkfun/FTDI_Basic_Breakout-5V/Hardware/FTDI Basic-5V', 0, 0)
local adafruitpowerboost1000c = pcb('../../../../git/adafruit/Adafruit-PowerBoost-1000C/Adafruit PowerBoost 1000C Rev B', 0, 0)
local fadecandy = pcb('../../../../git/scanlime/fadecandy/pcb/fc64x8/fc64x8', ftdibasic, 0)

local vert2 = merge("vert2a", ftdibasic, adafruitpowerboost1000c, 1)
vert2 = merge("vert2b", vert2, fadecandy, 1)

-- vert3
local sparkfunlipo = manipulation.rotate_board(pcb('../../../../git/sparkfun/Lipo_Charger_Basic-microUSB/Hardware/SparkFun_Lipo_Charger_Basic-microUSB', 0, 0), 90)
local tinyavrprog = manipulation.rotate_board(pcb('../../../../git/sparkfun/Tiny-AVR-Programmer/Hardware/Tiny_Programmer', 0, 0), 90)

local vert3 = merge("vert3", tinyavrprog, sparkfunlipo, 1)

-- panel
local panel = merge("panel", vert1, vert2, 0)
panel = merge("panel", panel, vert3, 0)
boards.merge_apertures(panel)

local panel_extents = extents.compute_board_extents(panel)
local panel_bt=panel_extents["top"]-panel_extents["bottom"]
local panel_lr=panel_extents["right"]-panel_extents["left"]
print("panel", panel_lr, panel_bt)
assert(boards.save(panel, './final/tkeddie_201512_1'))

os.exit()
TomKeddie
Full Member
Full Member
 
Posts: 183
Joined: Tue Dec 18, 2012 3:26 pm

Re: 3D Gerber Viewer

Postby stryker » Sat Sep 17, 2016 8:40 pm

Hi Doub

Thanks again for this. I just saw newer versions on your site, so have grabbed the latest.

After using it for some time, if you can do this easy, I'd love to add something to the wish list. A way of changing the colours used in the viewer on the fly rather than editing colors\default.lua and restarting. It's not a big thing, nor a high priority. It's just a way to see how the boards might look in the different options from dirtyPCB primarily, but would also allow viewing in the way that someone's board maker of choice builds them. Maybe the option could be behind one of the unused F-keys?

Cheers, Geoff
User avatar
stryker
Newbie
Newbie
 
Posts: 32
Joined: Sun Apr 07, 2013 12:18 am

Re: 3D Gerber Viewer

Postby pablofern » Tue Aug 13, 2019 7:03 am

Tried it on Windows x64 and it works just fine for me
pablofern
Newbie
Newbie
 
Posts: 2
Joined: Tue Aug 13, 2019 7:00 am

Previous

Return to Tools of the trade