Hello Guest it is March 28, 2024, 06:32:38 AM

Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Messages - rhtuttle

391
Mach4 General Discussion / Mach4 Spindle Speed Linearity Hack
« on: November 21, 2017, 07:32:06 PM »
Nice to be able to contribute something instead of asking everyone else for help solving my problems.
For those of us that don’t have VFD’s or spindle motors that are particularly linear in their speed ramps this will get you a lot closer.  Much like Mach3’s linearity.dat. 

You must have a spindle speed encoder for this to generate the linearity.csv file by running one of the scripts but you could generate one by hand as well.  The format of the file consists of 4 columns: Pulley/Gear, Speed you request, value from 0 to 100, Speed you need to enter to get the speed you want.  The value between 0 to 100 is not used by my script but could be used by those with modbus.  The entries in the file look like this

0,49,6,105
0,84,8,140
0,119,10,175
0,153,12,210
0,189,14,245
0,223,16,280
0,259,18,315
0,294,20,350
0,330,22,385
0,365,24,420
This was done on Mach4 build 3481 on the wxLathe screenset but I believe it will work for the mill as well.
The process consists of a few steps. 

1.     CREATE A PACKAGE of your current profile: Help->Support->Package Current Profile

2.   Create a button somewhere on your screen and copy the script below into the Left Up Script.  It is currently set to run from 6% to 80% by steps of 2 and spins at those steps for 5 seconds each to get the spindle to equilibrium.  You can modify those settings if you wish.  I don’t use my lathe at more than 80% power and it doesn’t really turn at less than 6%. Save the screen.  This script will generate a list of settings for the gear and put it in the History Log.  Clear the history log. This will lock up your screen while it runs!  Do this for each pulley/gear you have.  Save the file to ‘Linearity.csv’.  Open it with excel and save it.  You should be able to now open it with notepad and get the 4 columns for each gear.

3.   Copy the ‘spindlespeed.mcs to your profiles macro folder.  You’re now ready to go.  If you run an MDI of m3 s400 you should see the actual RPM very close to 400 but the command RPM will be something else.

4.   If you want to have the command and requested RPM’s visible do the following.  Create a register in gRegs0 called ssCMND, give it a value of one and I made it persistent.  I moved/sized the Spindle Tab items so that I could fit another DRO above the existing ‘PGM RPM’ dro.  Set the PG RPM dro to read only with a gray background and a black foreground set its height to 20 so that it looks more like a text than a dro.  Name the new DRO ‘ssCMND’.  Select it’s ‘Register’ property to the ‘gRegs0/ssCMND’  from the drop down list box.  In its Left Up Script enter this code:  mc.mcCntlMdiExecute(mc.mcGetInstance(),'s'..tostring(scr.GetProperty('ssCMND','Value')))

Now when you change the spindle speed through the mdi, gcode or through the ssCMND dro the old PGM RPM dro will show the speed necessary to get the requested speed and the ssCMND dro will show what speed was commanded.  If anyone knows of a way to improve it please feel free to help.   Hope this is clear enough and of use to someone else.

Code: [Select]
--spindlspeed.mcs
local inst = mc.mcGetInstance()
  local profile = mc.mcProfileGetName(inst)
  local mcPath = mc.mcCntlGetMachDir(inst)
  local nGears=10
  local tblSS = {}
  local gear=1
  local cmdSS=2
  local pctSS=3 
  local newSS=4
 
  function parseLine(s)
    local gr,cmd,pc,nw
    local i=1
for w in s:gmatch("([^,]+)") do
      if i==1 then
        gr=tonumber(w)
  elseif i==2 then
    cmd=tonumber(w)
  elseif i==3 then
    pc=tonumber(w)
  elseif i==4 then
    nw=tonumber(w)
      end
  i=i+1
    end  
    return gr,cmd,pc,nw
  end
 
  function interpolate(x,x0,y0,x1,y1)
      return y0+(x-x0)*(y1-y0)/(x1-x0)
  end
 
  function ssmLoadTable()
    local fName=''..mcPath.."\\Profiles\\"..profile.."\\Modules\\Linearity.csv"
local ssFile=io.open(fName,"r")     
    if ssFile==nil then
      wx.wxMessageBox("File: "..fName.." Not Found")
  return 0
    end
for i=1, nGears do
  tblSS[i]={}
end
  i=1
    local gr,cmd,pc,nw
local currGR=1
for line in ssFile:lines() do
      gr,cmd,pc,nw=parseLine(line)
  if currGR~=gr then
    i=1
currGR=gr
  end
  tblSS[gr+1][i]={}
      tblSS[gr+1][i][1]=gr
      tblSS[gr+1][i][2]=cmd
  tblSS[gr+1][i][3]=pc
  tblSS[gr+1][i][4]=nw
  i=i+1
    end
    ssFile:close()
-- wx.wxMessageBox("end of read")
return 1
  end

  function ssmGetNewSS(gear,cmd)
    if cmd==0 then
      return cmd
    end
    for i=1,#tblSS[gear+1] do
      if tblSS[gear+1][i][2]== cmd then
--      wx.wxMessageBox('equal:'..tostring(tblSS[gear+1][i][4]))-- case of exact match
      return tblSS[gear+1][i][4]
  end
  if tblSS[gear+1][i][2]>cmd then
        if i==1 then
--        wx.wxMessageBox('first entry')--case of first entry , can't go lower
      return tblSS[gear+1][i][4]
    end
--wx.wxMessageBox('interpolate')
        return interpolate(cmd,tblSS[gear+1][i-1][2],tblSS[gear+1][i-1][4],tblSS[gear+1][i][2],tblSS[gear+1][i][4])     
      end
    end
--  wx.wxMessageBox('over max: '..tostring(tblSS[gear+1][#tblSS[gear+1]][4]))-- case over the limit return limit
    return tblSS[gear+1][#tblSS[gear+1]][4]  --change 4 to 3 to return percent for a modbus number?
  end

function spindlespeed(rpm)
  local inst = mc.mcGetInstance();
  rpm = mc.mcSpindleGetCommandRPM(inst);
 
  local rslt=ssmLoadTable()
  if rslt~=1 then
    wx.wxMessageBox("load failure: "..tostring(rslt))
    return 0
  end
  local gear=mc.mcSpindleGetCurrentRange(inst)
  rslt=ssmGetNewSS(gear,rpm)
  mc.mcSpindleSetCommandRPM(inst,rslt)
  local hReg, rc=mc.mcRegGetHandle(inst,'gRegs0/ssCMND')
  if hReg~=nil then
    mc.mcRegSetValue(hReg,rpm)
  end
--  wx.wxMessageBox(tostring(rslt))
  mc.mcCntlSetLastError(inst,string.format("New SS: %.0f",rslt))
end

if (mc.mcInEditor() == 1) then
  spindlespeed();
end

Spindle Speed Macro

Code: [Select]
[/--spindlspeed.mcs
local inst = mc.mcGetInstance()
  local profile = mc.mcProfileGetName(inst)
  local mcPath = mc.mcCntlGetMachDir(inst)
  local nGears=10
  local tblSS = {}
  local gear=1
  local cmdSS=2
  local pctSS=3 
  local newSS=4
 
  function parseLine(s)
    local gr,cmd,pc,nw
    local i=1
for w in s:gmatch("([^,]+)") do
      if i==1 then
        gr=tonumber(w)
  elseif i==2 then
    cmd=tonumber(w)
  elseif i==3 then
    pc=tonumber(w)
  elseif i==4 then
    nw=tonumber(w)
      end
  i=i+1
    end  
    return gr,cmd,pc,nw
  end
 
  function interpolate(x,x0,y0,x1,y1)
      return y0+(x-x0)*(y1-y0)/(x1-x0)
  end
 
  function ssmLoadTable()
    local fName=''..mcPath.."\\Profiles\\"..profile.."\\Modules\\Linearity.csv"
local ssFile=io.open(fName,"r")     
    if ssFile==nil then
      wx.wxMessageBox("File: "..fName.." Not Found")
  return 0
    end
for i=1, nGears do
  tblSS[i]={}
end
  i=1
    local gr,cmd,pc,nw
local currGR=1
for line in ssFile:lines() do
      gr,cmd,pc,nw=parseLine(line)
  if currGR~=gr then
    i=1
currGR=gr
  end
  tblSS[gr+1][i]={}
      tblSS[gr+1][i][1]=gr
      tblSS[gr+1][i][2]=cmd
  tblSS[gr+1][i][3]=pc
  tblSS[gr+1][i][4]=nw
  i=i+1
    end
    ssFile:close()
-- wx.wxMessageBox("end of read")
return 1
  end

  function ssmGetNewSS(gear,cmd)
    if cmd==0 then
      return cmd
    end
    for i=1,#tblSS[gear+1] do
      if tblSS[gear+1][i][2]== cmd then
--      wx.wxMessageBox('equal:'..tostring(tblSS[gear+1][i][4]))-- case of exact match
      return tblSS[gear+1][i][4]
  end
  if tblSS[gear+1][i][2]>cmd then
        if i==1 then
--        wx.wxMessageBox('first entry')--case of first entry , can't go lower
      return tblSS[gear+1][i][4]
    end
--wx.wxMessageBox('interpolate')
        return interpolate(cmd,tblSS[gear+1][i-1][2],tblSS[gear+1][i-1][4],tblSS[gear+1][i][2],tblSS[gear+1][i][4])     
      end
    end
--  wx.wxMessageBox('over max: '..tostring(tblSS[gear+1][#tblSS[gear+1]][4]))-- case over the limit return limit
    return tblSS[gear+1][#tblSS[gear+1]][4]  --change 4 to 3 to return percent for a modbus number?
  end

function spindlespeed(rpm)
  local inst = mc.mcGetInstance();
  rpm = mc.mcSpindleGetCommandRPM(inst);
 
  local rslt=ssmLoadTable()
  if rslt~=1 then
    wx.wxMessageBox("load failure: "..tostring(rslt))
    return 0
  end
  local gear=mc.mcSpindleGetCurrentRange(inst)
  rslt=ssmGetNewSS(gear,rpm)
  mc.mcSpindleSetCommandRPM(inst,rslt)
  local hReg, rc=mc.mcRegGetHandle(inst,'gRegs0/ssCMND')
  if hReg~=nil then
    mc.mcRegSetValue(hReg,rpm)
  end
--  wx.wxMessageBox(tostring(rslt))
  mc.mcCntlSetLastError(inst,string.format("New SS: %.0f",rslt))
end

if (mc.mcInEditor() == 1) then
  spindlespeed();
end
[code]

[code]

HTH

RT[/code][/code]

392
Mach4 General Discussion / Re: m3 gets special treatment?
« on: November 21, 2017, 02:33:17 PM »
Many thanks, very well written.

393
Mach4 General Discussion / Re: m3 gets special treatment?
« on: November 21, 2017, 09:02:26 AM »
Many thanks for that, it works both with gcodes and mdi input.  I have been able to develop a hack like mach3's linearity.dat and can now get my spindle speed to within a couple of revs from what it is supposed to be.  If I requested s500 previously it would spin at 450 and s2000 would spin at 2170.  Unfortunately the new commandRPM displays not 500 but the 553 needed to get 500.

I can see how the modbus would be an excellent route but my  little board does not support it.

So it begs the question, who sets the voltage level? Does mach set a register value that vendors read or do the motion control vendors read the spindle gear table values and derive the amount of current?

394
Mach4 General Discussion / Re: m3 gets special treatment?
« on: November 20, 2017, 03:22:44 PM »
Thanks Steve,

I didn't get that impression from the scripting manual:

M codes in the column “User Scriptable And Internal Function” have internal functions in Mach4, but also allow user scripts. These codes are further divided into those that call the function internal to Mach4 OR a user script and those that run both. M3 to M5 and M7 to M9 are codes that control the spindle and coolant functions. If there is no user script for these codes they turn on/off their respective signals as defined inside Mach4. However, if a user script is present, the script will be run instead. This gives the user the power to create custom codes for custom spindle and coolant applications, but if the machine simply needs to turn on/off an output, no programming is required.

Might consider updating those to indicate that they will not allow parameters.

Thanks for the example but I need to know when the spindle speed has been requested to change or changed.  It appeared (with a cursory glance) that I could use the PGM RPM dro's onUpdateScript event to capture the value but after testing, the value returned is the one before the update.

Do I write a function that loops every 200 milliseconds and checks to see if that value changes?  Is there a better way?

TIA

RT

395
Mach4 General Discussion / Re: m3 gets special treatment?
« on: November 20, 2017, 02:00:50 PM »
deleted both the m3.mcc and the m3.mcs.bak

loaded Mach4 and in the mdi ran m3 s1000 and hParam still comes back nil: 'hParam==nil'




396
Mach4 General Discussion / m3 gets special treatment?
« on: November 19, 2017, 06:21:05 PM »
Here is the code for two macros, identical except one is the  m3.mcs file and the other is m300.mcs file code

If the 'm3 s500' is called from the mdi hParam == nil, if the 'm300 s500' is called from the mdi hParam ~= nil.
Does m3 get stripped of it's parameters?  If so why and how do you capture the requested s value?

function m3(hParam)
   if (hParam ~= nil) then
      wx.wxMessageBox('hParam~=nil')
   else
      wx.wxMessageBox('hParam==nil')
   end   

end

if (mc.mcInEditor() == 1) then
    m3()
end

function m300(hParam)
   if (hParam ~= nil) then
      wx.wxMessageBox('hParam~=nil')
   else
      wx.wxMessageBox('hParam==nil')
   end   

end

if (mc.mcInEditor() == 1) then
    m300()
end


tia

RT

397
Mach4 General Discussion / Actual Spindle Speed DRO delay
« on: November 13, 2017, 01:46:40 PM »
Running PMDX 411 and Gecko G540 on build 3481 on a lathe.

I have a cheap opto sensor on my spindle that works very well reporting the actual spindle speed as verified with a tach.

I noticed that when I issue a M5 that the Dro that shows the actual speed does not return to zero for about 3-5 seconds from the time that the spindle actually stops spinning.

Does anyone know if this is due to the opto, PMDX or Mach4 not updating?

I was using this DRO value to check to see if the spindle had overloaded and stopped and it was not disabling movement promptly.

Is there a better way to handle this? (I am electronically challenged so hopefully I don't have to create some citrcuit ;D)

TIA

RT

398
Mach4 Plugins / Re: mcX360 Plugin for Lua
« on: November 11, 2017, 05:53:58 PM »
Daz, works a charm!

They may have been in the other one but I have never seen a list of all the codes listed anywhere.

Thanks!

RT

399
Mach4 Plugins / Re: mcX360 Plugin for Lua
« on: November 10, 2017, 05:51:42 PM »
Daz,

Everyone always something more. ;D

In Lee's mach3 plugin the thumb sticks had another capability by depressing them straight down.  Would it be possible to expose that as a button click in your next release of the  plugin?

RT

400
Mach4 General Discussion / Re: Check if Enabled
« on: November 10, 2017, 05:47:12 PM »
Thank you Daz.

I need to be more diligent.  I looked at the signals and must have scanned too fast because I missed it.  They're not alphabetical.

TYOGO

RT