Hello Guest it is March 28, 2024, 07:25:54 PM

Author Topic: How to mark an axis as "Homed"  (Read 2936 times)

0 Members and 1 Guest are viewing this topic.

Re: How to mark an axis as "Homed"
« Reply #10 on: October 07, 2019, 09:49:54 AM »
Quote
I rather suspect that Mach4 is continuing in the existing homing mode, that you have changed mode has not yet taken effect.

If memory serves there is an API that causes Mach to re-read the .ini file, and then and only then does the change take effect.

Went digging through the API reference and couldn't find anything like you are describing (only a save to INI command). That's probably due to me not understanding how the INI works just yet!

Thanks for all the time and help you've given me. Really made a ton of progress yesterday with all of this.

Mike
Re: How to mark an axis as "Homed"
« Reply #11 on: October 07, 2019, 12:28:50 PM »
From Andy at Warp9!

Quote
Hi,

The short answer is that the the SmoothStepper plugin never looks at the mcAxisSetHomeInPlace parameter. Mach4 looks at that parameter and then decides if it should do a home in place operation on that axis (motors) or tell the SmoothStepper to home that axis (motors) .

In order to set that parameter in Mach4 correctly, you need to do a couple other operations
rc = mc.mcCntlConfigStart(inst);
and
rc = mc.mcCntlConfigStop(inst); -- takes the machine out of the config state.
You may also need to do (but I don't think you will need to since you are only modifying a Mach parameter):
local hICU_Command = mc.mcRegGetHandle(inst, string.format("ESS/Force_Config_Update"))
mc.mcRegSetValueLong(hICU_Command, 1)

The second video walks you through the details...

Please understand that you are messing with your config file... you can destroy it if you are not careful! I would recommend backing up your entire c:\mach4Hobby folder before you do any of this.

Will try tonight and see if I can get it working.
Re: How to mark an axis as "Homed"
« Reply #12 on: October 07, 2019, 12:33:44 PM »
The machine.ini file contains all of the Mach4 settings you are currently using for that 'Profile' in that profiles directory. e.g. myLathe ini is:
C:\Mach4Hobby\Profiles\myLathe\machine.ini

To save or load settings:
mcProfileSave
mcProfileReload

Some motion controllers do not allow you to change motor/other settings on the fly, rather they require a complete restart.

HTH

RT
Re: How to mark an axis as "Homed"
« Reply #13 on: October 08, 2019, 12:52:31 PM »
I spent some time last night trying to get this to work and unfortunately didn't see any change in behavior from what I described before.

Here is my function. The goal is to home in place after having set a home offset equivalent to the drive current position. After homing, the DRO's should display the correct position, all the G54 offsets should be zero, and the LEDs should be illuminated showing the axes as homed. All without moving any axes.

The line "serialError, position = mcServo.GetPosition(address, ctsPerInch)" is a function I made as part of a custom library to communicate to my servos over serial. I'm 99.9% it is working correctly as it always returns the correct value for position (in unit of inches).

Code: [Select]
function mcServo.AbsolutePositionRecovery()
       
        --define local variables
local rError = 0
local sError = 0
local xPosition
local yPosition
local zPosition
local sPosition

        --change Mach 4 config for all axes to home in place, save & reload the profile
mc.mcCntlConfigStart(inst)
mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 5, 1)
mc.mcCntlConfigStop(inst)
mc.mcProfileSave(inst)
mc.mcProfileReload(inst)

        --Gets the motor counts per inch for each axis
        --Then queries the servo drives for their position
        --Exits the function with an error code if any drive transmission failed
local XctsInch = mc.mcMotorGetCountsPerUnit(inst, 0)
local YctsInch = mc.mcMotorGetCountsPerUnit(inst, 1)
local ZctsInch = mc.mcMotorGetCountsPerUnit(inst, 2)
local SctsInch = mc.mcMotorGetCountsPerUnit(inst, 5)
sError, xPosition = mcServo.GetPosition("00", XctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, yPosition = mcServo.GetPosition("01", YctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, zPosition = mcServo.GetPosition("02", ZctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, sPosition = mcServo.GetPosition("05", SctsInch)
if sError ~= 0 then; rError = 1; return rError end

        --Sets the home offset equal to the position received from the drives
        --Need to multiply by -1 to invert the counts
        --Because the drive polarity on all these servos is inverted
mc.mcAxisSetHomeOffset(inst, 0, (xPosition*-1))
mc.mcAxisSetHomeOffset(inst, 1, (yPosition*-1))
mc.mcAxisSetHomeOffset(inst, 2, (zPosition*-1))
mc.mcAxisSetHomeOffset(inst, 5, (sPosition*-1))

        --Mach 4 API call to home axes (in-place)
mc.mcAxisHome(inst, 0)
mc.mcAxisHome(inst, 1)
mc.mcAxisHome(inst, 2)
mc.mcAxisHome(inst, 5)

--change Mach 4 config for all axes to home normally, save & reload the profile
        mc.mcCntlConfigStart(inst)
mc.mcAxisSetHomeInPlace(inst, 0, 0)
mc.mcAxisSetHomeInPlace(inst, 1, 0)
mc.mcAxisSetHomeInPlace(inst, 2, 0)
mc.mcAxisSetHomeInPlace(inst, 5, 0)
mc.mcCntlConfigStop(inst)
mc.mcProfileSave(inst)
mc.mcProfileReload(inst)

return rError
end

When I run this, the code still wants to bump all of the axes into their home switches. The home offset does seem to get set correctly.

After posting this to Warp 9, I was given a few ideas to try:

Quote
Hi Mike,

My guess is that your problem is that you are doing everything inside a single lua function, which has all of it calls made all in a single sequence.

However, I doubt that Mach4 is actually changing the profile and reloading it immediately when you call those functions, but rather queuing up the changes to be made after the screen scripts (or macros) finish running (the screen script is executed 40 or 50 times each second).

My guess is that if you broke your function into several separate function blocks that you called and waited for a moment before you called the next one, it would work like you wanted. If it did, then we would know that you would need to set up a state machine approach, for this operation. Assuming you have this in your screen script, the first pass through would make the changes to the conifg, and increment the state counter. The next time the screen script runs (1/40th or 1/50th of a second later, it would do the next chunk and increment the state counter. It would repeat this as many times as necessary, but it looks like your code would only need 3 times, or maybe 5 times if you had a do nothing pause step in between the real steps.


Let me know how it goes, but first try making 3 smaller functions that you call from the MDI and see if it works like you would expect it to.

I'm going to try that recommendation and see if it makes any difference.

I'm very much open to ideas or suggestions. Really would love to get this working. Understanding how Mach scans code and executes changes is a huge learning curve for me, but I think it is worth it.

Offline smurph

*
  • *
  •  1,544 1,544
  • "That there... that's an RV."
    • View Profile
Re: How to mark an axis as "Homed"
« Reply #14 on: October 08, 2019, 01:49:08 PM »
Code: [Select]
        --change Mach 4 config for all axes to home in place, save & reload the profile
mc.mcCntlConfigStart(inst)
mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 5, 1)
mc.mcCntlConfigStop(inst)
mc.mcProfileSave(inst)
mc.mcProfileReload(inst)

Why use all of the profile stuff when you are doing nothing with the profile at all? 

mc.mcCntlConfigStart(inst) puts the machine in the configuration state.  The idea is that you would then write things to the profile with mcProfile* functions.  Then call mc.mcCntlConfigStop(inst).  This is EXACTLY what we do with the control configuration dialog.

1. Enter the config state.
2. Read the profile's existing settings and display them in the dialog.
3. Allow the user to make changes.
4. If Ok or Apply is pressed, write the changes to the profile.  Then mc.mcProfileFlush(), which makes the changes stick.
5. Exit the config state.  This causes the control to re-read the profile and bring in the new settings. 

This is a very controlled process and can only be done with the control in the Idle state.  Not good for on-the-fly changes at run time. 

Code: [Select]
        --Set Mach 4 to home all axes in place at run time to take effect immediately. 
        --The changes will be written to the profile when Mach is shut down.
        --If you don't want the changes to be permanent, then change them back before shutting down Mach.
mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 5, 1)

Steve
Re: How to mark an axis as "Homed"
« Reply #15 on: October 08, 2019, 03:06:27 PM »
Quote
Why use all of the profile stuff when you are doing nothing with the profile at all?

Probably because I don't yet know what I am doing  ;D

Quote
mc.mcCntlConfigStart(inst) puts the machine in the configuration state.  The idea is that you would then write things to the profile with mcProfile* functions.  Then call mc.mcCntlConfigStop(inst).  This is EXACTLY what we do with the control configuration dialog.

1. Enter the config state.
2. Read the profile's existing settings and display them in the dialog.
3. Allow the user to make changes.
4. If Ok or Apply is pressed, write the changes to the profile.  Then mc.mcProfileFlush(), which makes the changes stick.
5. Exit the config state.  This causes the control to re-read the profile and bring in the new settings.

Do you think this is the same process I would follow for changing the homing mode to "home in place"? Is the API call mc.mcAxisSetHomeInPlace() the correct one to do this or do I need to use a mcProfile command?

Quote
This is a very controlled process and can only be done with the control in the Idle state.  Not good for on-the-fly changes at run time.

This is ONLY going to be used when the machine is idle, either during a start-up script that prompts me to enable the control then home, or when the user presses the REF ALL HOME button.  Is there an easy way to check for idle? I've used the mc.mcCntlGetState() command but have never found a reference for what each state corresponds to the number returned from this call. I will add this as a condition for the homing to be allowed.

Based on the advice above, I'm thinking it might look something like this:

Code: [Select]
--change Mach 4 config for all axes to home in place, save & reload the profile
mc.mcCntlConfigStart(inst)
mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 5, 1)
        mc.mcProfileFlush(inst)
mc.mcCntlConfigStop(inst)
(inst)

Would this immediately make the changes, or would I need to wait a full scan of the code for the changes to take effect?

Thanks again to everyone for the time and help. It is very appreciated.

Offline smurph

*
  • *
  •  1,544 1,544
  • "That there... that's an RV."
    • View Profile
Re: How to mark an axis as "Homed"
« Reply #16 on: October 08, 2019, 04:41:14 PM »
I gave you the correct answer and then possibly muddied the water by trying to demonstrate how and why the profile functions are used.  For on the fly changes, which is what you are doing, do this:
Code: [Select]
--Set Mach 4 to home all axes in place at run time to take effect immediately.
--The changes will be written to the profile when Mach is shut down.
--If you don't want the changes to be permanent, then change them back before shutting down Mach.
mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 5, 1)

--Mach 4 API call to home all of the axes (in-place)
--The home offset in the config dialog will automatically be applied! 
-- No need to programmatically set the home offset every time as it probably won't change.
mc.mcAxisHomeAll(inst)
 
        --Do we really need to swap back? 
mc.mcAxisSetHomeInPlace(inst, 0, 0)
mc.mcAxisSetHomeInPlace(inst, 1, 0)
mc.mcAxisSetHomeInPlace(inst, 2, 0)
mc.mcAxisSetHomeInPlace(inst, 5, 0)

Use the above code. 

But to clarify the profile use case: (which you should NOT use in this circumstance).
Code: [Select]
--change Mach 4 config for all axes to home in place, save & reload the profile
mc.mcCntlConfigStart(inst)
mc.mcProfileWriteInt(inst, "Axis0", "HomeInPlace", 1)
mc.mcProfileWriteInt(inst, "Axis1", "HomeInPlace", 1)
mc.mcProfileWriteInt(inst, "Axis2", "HomeInPlace", 1)
mc.mcProfileWriteInt(inst, "Axis5", "HomeInPlace", 1)
mc.mcProfileFlush(inst)
mc.mcCntlConfigStop(inst)

Either way will work.  But going the config state and profile route is a LOT slower. 

Also, for brevity, none of these examples are looking at the return codes from the API calls.  You REALLY want to do that in your real live script. 

One more thing.  Usually, for ABS encoders, this would be the setup:

1. Conifgure Mach axis homing tab. 
2. Set home in place for each axis with a ABS encoder. 
3. Set the offset for each axis in machine coordinates.  Find this for each axis prior to configuring the homing by:
   a. Put the position DROs in machine coordinates mode.
   b. Jog to the desired home position and record the current machine coordinates.  This will become your home offset.
4. Set the desire home order.  Base 1.  Z is usually 1 on a mill.  X and Y can usually be homed together set as 2. Maybe not important for ABS encoders.  But set it for completeness. 

Then the regular homing buttons will just set the home offset with no modifications required.  After a RefAll, issuing "G00 G53 X0 Y0" in MDI should carry the axes to the home positions. 

You do not need to set the home offsets again unless you change the encoder to table relationship. In most cases, this would only need to be done once and would not need to be update unless the machine was repaired or something.  If you are worried that this relationship will change and need to be updated every so often, I would consider that a mechanical problem that needs to be fixed.  Loose servo motor coupler, etc.. 

But if you have to have the optional switch homing, then you can expand on this stuff.  If want to use the profile method to set the home offsets, look at the profile and find an Axis# section (where # is 0 to 5) to get the keys you are interested in.  (section, key, value)

If you set values wit the mcProfile*() functions, use mcProfileFlush() to make the modifications stick.  If you modify axis values with the API functions, use mcProfileSave() to make the modifications stick.

Steve
Re: How to mark an axis as "Homed"
« Reply #17 on: October 09, 2019, 09:37:52 AM »
Good news! I got it working! Thanks again to all who helped me out.

I ended up having to do a ton of test scripts to get an understanding of what exactly Mach 4 was doing with the code I was running.

Here are the key snippets I figured out to make this work (and I am sure they were discussed above already):
  • Mach 4 does not apply the changes made by calling mc.mcAxisSetHomeInPlace() until I later call mc.mcProfileSave()
  • There is some short period of time in which Mach 4 does not respond to the changes to the "Home in Place" command
  • This period of time is something greater than 10ms but less than or equal to 50ms

I figured this out by added 3 test buttons to the screen. One turned ON home in place, one ran the homing code, and one turned OFF home in place. If I clicked through these in sequence, the code worked great. If I put them together in a script, it didn't work at all. I was going to build a state machine, but figured I would try a raw delay first and that worked great (wx.wxMilliSleep()). This has yet to fail at 50ms, but if I set it to 10ms, some axes will home in place while others won't. I decided to play it safe and choose 100ms. There may be a cleaner way to do this, but execution time isn't important to me since it only runs one time at startup.

The code is executed while the axes are enabled. I can have the axes anywhere and they don't need to be moved. I get the current position of the motors from the drives which is tracked mechanically in the encoders while the machine is powered off. I throw this value into the homing offset then home in place. Finally the home offset and home in place values are returned to normal and the code ends. This still allows me to home to my switches like normal if I want. It is cool to see a tenth or two of movement when I disable and later re-enable. It is the closest thing to position feedback into Mach that I have.

Here is the code contained in the Ref All Home button:

Code: [Select]
--RefAllHome()
local e1 = 0

local HomeBox = wx.wxMessageBox("Do you wish to restore absolute position data from Servo Drives? \n \nChoose YES to restore homing data. \nChoose NO to Home to Limit Switches. \nChoose CANCEL to skip homing.", "Homing Type",18)
if HomeBox == 2 then
e1 = mcServo.AbsolutePositionRecovery()
if e1 ~= 0  then
wx.wxMessageBox("Home Position Recovery Failed! \n \n Axes must be referenced to switch before operation.", "Homing Failed",4)
else
wx.wxMessageBox("Home Position successfully read from Servo Drives", "Step 3/5 - Homing",4)
end
elseif HomeBox == 8 then
wait = coroutine.create (RefAllHome) --This is the code from the ref all home button
end


And the code for absolute homing using Allen Bradley Ultra 3000 servo drives, consuming data over RS485 Serial Host commands:

Code: [Select]
function mcServo.AbsolutePositionRecovery()

local rError = 0
local sError = 0
local xPosition = 0
local yPosition = 0
local zPosition = 0
local sPosition = 0

mc.mcAxisSetHomeInPlace(inst, 0, 1)
mc.mcAxisSetHomeInPlace(inst, 1, 1)
mc.mcAxisSetHomeInPlace(inst, 2, 1)
mc.mcAxisSetHomeInPlace(inst, 6, 1)
mc.mcProfileSave(inst)

wx.wxMilliSleep(100) --Sleep 100 milliseconds

local XctsInch = mc.mcMotorGetCountsPerUnit(inst, 0)
local YctsInch = mc.mcMotorGetCountsPerUnit(inst, 1)
local ZctsInch = mc.mcMotorGetCountsPerUnit(inst, 2)
local SctsInch = mc.mcMotorGetCountsPerUnit(inst, 6)
sError, xPosition = mcServo.GetPosition("00", XctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, yPosition = mcServo.GetPosition("01", YctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, zPosition = mcServo.GetPosition("02", ZctsInch)
if sError ~= 0 then; rError = 1; return rError end
sError, sPosition = mcServo.GetPosition("05", SctsInch)
if sError ~= 0 then; rError = 1; return rError end

mc.mcAxisSetHomeOffset(inst, 0, (xPosition*-1))
mc.mcAxisSetHomeOffset(inst, 1, (yPosition*-1))
mc.mcAxisSetHomeOffset(inst, 2, (zPosition*-1))
mc.mcAxisSetHomeOffset(inst, 6, (sPosition*-1))

mc.mcAxisHomeAll(inst)

wx.wxMilliSleep(100) --Sleep 100 milliseconds

mc.mcAxisSetHomeOffset(inst, 0, 0)
mc.mcAxisSetHomeOffset(inst, 1, 0)
mc.mcAxisSetHomeOffset(inst, 2, 0)
mc.mcAxisSetHomeOffset(inst, 6, 0)

mc.mcAxisSetHomeInPlace(inst, 0, 0)
mc.mcAxisSetHomeInPlace(inst, 1, 0)
mc.mcAxisSetHomeInPlace(inst, 2, 0)
mc.mcAxisSetHomeInPlace(inst, 6, 1) --Leave Spindle as Home in Place
mc.mcProfileSave(inst)

wx.wxMilliSleep(100) --Sleep 100 milliseconds

return rError

end

Thanks again to all!
Re: How to mark an axis as "Homed"
« Reply #18 on: October 09, 2019, 10:02:19 AM »
Thank you for posting the results of your endeavors.  Posts like these go a long way to furthering the knowledge bank for Mach4 users.

BTW, Stumbled across your Grizzly mill build on Hobby-Machinist.  Spent two hour reading the whole thread.  Great photos, explanation and design.

RT
Re: How to mark an axis as "Homed"
« Reply #19 on: October 09, 2019, 10:27:25 AM »
RT,

Thanks for the complement! I keep that as a log for my own enjoyment as much as sharing it with others. Just something fun to play with after work. Keeps me from going crazy working at a computer all day  ;D

Happy to share when I get stuff working!

Mike