Hello Guest it is October 23, 2019, 10:40:22 PM

Author Topic: Poor Mans Wizard  (Read 298 times)

0 Members and 1 Guest are viewing this topic.

Poor Mans Wizard
« on: January 19, 2019, 01:29:30 PM »
Hi All,
as I promised I thought I would start a new thread to show an idea that I have used on a few occasions to generate
Gcode files.

This thread started with:

https://www.machsupport.com/forum/index.php?topic=39284.0

Where I wrote some code for OP to 'jewel' some material. Chad was interested in the idea of opening a file and putting
the Gcode in it rather than executing it immediately with successive mcCntlGcodeExecuteWait() API commands.

Here it is:

Code: [Select]
function m125()
local inst=mc.mcGetInstance()
-- create the wxFrame window
    mainframe = wx.wxFrame( wx.NULL,          -- no parent
                        wx.wxID_ANY,          -- whatever for wxWindow ID
                        "DummyFrame", -- frame caption
                        wx.wxDefaultPosition, -- place the frame in default position
                        wx.wxDefaultSize,     -- default frame size
                        wx.wxDEFAULT_FRAME_STYLE ) -- use default frame styles

    -- create a panel in the frame
    panel = wx.wxPanel(mainframe, wx.wxID_ANY)--We are not going to show it but we need to have this to use the File dialog

local file = wx.wxFileDialog(panel, "Select Data File", "", "", "Text files (*.txt)|*.txt|Tap files (*.tap)|*.tap",
                             wx.wxFD_SAVE,wx.wxDefaultPosition,wx.wxDefaultSize, "File Dialog" );
        if(file:ShowModal() == wx.wxID_OK)then
            path = file:GetPath()
            fileHandle=io.open(path,"w+")
        end
--
--
--
--
-- Jewel Data.....to be edited as required
--
local jewelWidth=50
local jewelLength=100
local toolDiameter=6
local nominalStepover=0.66
local plungeSpeed=300
local retractZ=2
local safeZ=20
local jewelDwellTime=500
--
-- End of data block
--
local startXpos
local startYpos
local jewelZheight

local stepoverX,numjewelX
local stepoverY,numjewelY
local i=0
local j=0
-- Save the current position as the start of the jeweling area....you have jogged to the start haven't you????
startXpos=mc.mcCntlGcodeInterpGetPos(inst,mc.X_AXIS)
startYpos=mc.mcCntlGcodeInterpGetPos(inst,mc.Y_AXIS)
jewelZheight=mc.mcCntlGcodeInterpGetPos(inst,mc.Z_AXIS)
-- Calculate the required step over to meet the nominal step over as closely as possible but be an integral
-- number of 'jewels'
-- Reduce jewelWidth in X and Y by the diameter of the tool
jewelWidth=jewelWidth-toolDiameter
jewelLength=jewelLength-toolDiameter
-- Calculate the exact number of 'jewels' required to match the nomininal Steppover
numjewelX=jewelWidth / (nominalStepover * toolDiameter)
numjewelY=jewelLength / (nominalStepover * toolDiameter)
-- Find the integer number of 'jewels'
numjewelX=math.modf(numjewelX)
numjewelY=math.modf(numjewelY)
-- Calculate the actual stepover to be used so that an integral number of 'jewels' are perfomed
stepoverX=jewelWidth / numjewelX
stepoverY=jewelLength / numjewelY
--
--
local retract="g0 z "..tostring(jewelZheight+retractZ)
local safeHeight="g0 z "..tostring(jewelZheight+safeZ)
--mc.mcCntlGcodeExecute(inst,retract..'\n'..'g1 f'..tostring(plungeSpeed)..'\n')
fileHandle:write(retract..'\n'..'g1 f '..tostring(plungeSpeed)..'\n')
for i=0,numjewelX,i+1 do
for j=0,numjewelY,j+1  do
jewelX=startXpos + (i * stepoverX)
jewelY=startYpos + (j * stepoverY)
--mc.mcCntlGcodeExecute(inst,'g0 x '..tostring(jewelX)..' y '.. tostring(jewelY)..'\n'..
-- 'g1 z '..tostring( jewelZheight)..'\n'..
-- 'g4 p'..tostring(jewelDwellTime)..'\n'..
-- retract..'\n')
fileHandle:write('g0 x '..tostring(jewelX)..' y '..tostring(jewelY)..'\n')
fileHandle:write('g1 z '..tostring(jewelZheight)..'\n')
fileHandle:write('g4 p '..tostring(jewelDwellTime)..'\n')
fileHandle:write(retract..'\n')
end
end
--mc.mcCntlGcodeExecuteWait(inst,safeHeight)
fileHandle:write(safeHeight..'\n')
fileHandle:flush()
fileHandle:close()
end
if (mc.mcInEditor()==1)then
m125()
end

Essentially all I have done is open a file dialogue so you can open a new file, or open an existing file with a normal Browse window
and then use exactly the same code that did the jeweling but replaced the mc.CntlGcodeExecuteWait() commands (I just
commented them out) with suitable file write commands.

Note that this code will run if you MDI <m125>.

The procedure would then be:
1) Jog to the location of the first (lower lefthand) 'jewel'
2) Lower the Z axis until the tool/brush makes contact with the material with sufficient force to effect the jewel
3) MDI <m125>

I have attached a coy of the file generated. Not very sophisticated....at best a poor mans Wizard.....and I am a poor man!

Craig
« Last Edit: January 19, 2019, 01:34:29 PM by joeaverage »
My wife left with my best friend...
     and I miss him!
Re: Poor Mans Wizard
« Reply #1 on: January 19, 2019, 02:20:52 PM »
Thanks, Craig.   Once I'm at my laptop again I'm going to comb through this.
Chad Byrd
Re: Poor Mans Wizard
« Reply #2 on: January 20, 2019, 01:31:59 AM »
Hi Chad,
have started digging into the wxWidgets morass.....and surprise surprise I'm making some progress.

There are broadly speaking 19 different dialogs. The one in the code I have posted is an example of a FileDialog.
Other dialogs that may be useful to you and I are TextEntryDialog, NumberEntryDialog and MessageDialog.

I could never understand why it is for instance that it was necessary to have a Frame, called mainframe in my example,
and a panel within that frame, called panel in my example, but was not in fact used????

What I have learnt is that a dialog, essentially a bunch of code to do some nifty things, requires a parent structure because a fair
proportion of the code that does all that nifty stuff is inherited from the parent.

There again in the example posted 'mainframe' is the top level, note that its first parameter, usually its parent is wx.NULL,
ie no parent. Note that 'panel' which lives inside the frame has its first parameter as 'mainframe', so 'panel' parent
is 'mainframe' and 'panel' inherits code from 'mainframe'.

When I have defined 'file' as a FileDialog its first parameter or parent is 'panel'. So FileDialog 'file' inherits from both
'panel' its immediate parent but also from 'mainframe' as well.

It is possible to have a FileDialog WITHOUT a parent but then it misses out on all that code. For instance we know that
most windows can be resized by dragging the boundaries. That functionality is associated with Frame. Thus if we had
a FileDialog that does NOT inherit from a Frame then that resize functionality would be lost.

The next thing I have learnt is that while the FileDialog in my code is:
Code: [Select]
local file = wx.wxFileDialog(panel, "Select Data File", "", "", "Text files (*.txt)|*.txt|Tap files (*.tap)|*.tap",
                             wx.wxFD_SAVE,wx.wxDefaultPosition,wx.wxDefaultSize, "File Dialog" );

It does not DO ANYTHING YET. That is the purpose of the constructor.....in my example the constructor is:

Code: [Select]
file:ShowModal()
Its that statement that causes the defined file dialog to be displayed on screen.
If a Dialog has a constructor it also needs a destructor and in many cases when we hit <OK> or <Save> or <Yes>
in a Dialog window that triggers the destruction of the dialog.

Yes after spending a couple of hours reading and writing snippets of code to test what I've read its starting to make a
little sense!

Craig

My wife left with my best friend...
     and I miss him!
Re: Poor Mans Wizard
« Reply #3 on: January 20, 2019, 12:53:38 PM »
Craig,
That's  some in depth research. 
I was trying to just make a macro that would, when ran, open a save dialog box that would write to a text file.  And that's all.  I kept getting a panel error using your example and the M400 or M401 example. 
So, from what you have said, it wasn't getting the parent components, I was trying to ignore the mainframe and it wasn't going right.
So, I've got to have the mainframe to do this.

Chad Byrd
Re: Poor Mans Wizard
« Reply #4 on: January 20, 2019, 01:13:21 PM »
Hi Chad,
yes that is my understanding. Without inheriting from parents our dialogs lose critical functionality or tip over
altogether.

If have encounterd a quirk. wxWidgets has a dialog wxNumberEntryDialog which would be  of great value to us CNCers
but the ZeroBrane editor and Lua compiler don't support it. They do support a cut-down el-cheapo version called
wxGetNumberFromUser but that will accept positive integers only. Not quite sure what I'm missing there.

I feel a call be made to Daz-the-Gaz and/or Smurph coming up!

Craig
My wife left with my best friend...
     and I miss him!
Re: Poor Mans Wizard
« Reply #5 on: January 20, 2019, 01:30:56 PM »
Yes I agree!   
I have used dialog boxes to get user input, text and integers.  There is a thread on here somewhere with that information.   Brett pointed me in the right direction for that.   If I were on my laptop I would find the post and copy a link;  but I'm on my phone at the moment.
Chad Byrd