[DONE - lens.focus updated] Lua Request/Idea

Started by garry23, June 18, 2016, 05:53:21 PM

Previous topic - Next topic

0 Members and 2 Guests are viewing this topic.

garry23

David/Alex

As you prepare for the next Lua uplift in the nightlies, I was wondering if you could consider adding in an error check in lens.focus.

The error check would look for soft limit reached (macro or inf end), such that the user can take script action.

At the moment if that error is generated, the script stops as there is no way in Lua (as far as I know) to detect that error and act on it.

Cheers

Garry

dmilligan

I thought I already mentioned it, but the function returns (boolean) whether or not the call was successful, this is just missing from the documentation.

garry23

Sorry David, I didn't pick up on that.

Does that mean I can intercept the soft focus limit error before that error stops my script?

garry23

David

My Lua coding is slow as I have to test on the camera. Nevertheless I have looked at lens.focus returns and it seems to return true or false, even if soft focus limit not reached.

The code in the Lua module is this :

static int luaCB_lens_focus(lua_State * L)
{
    LUA_PARAM_INT(num_steps, 1);
    LUA_PARAM_INT_OPTIONAL(step_size, 2, 2);
    LUA_PARAM_BOOL_OPTIONAL(wait, 3, true);
    LUA_PARAM_INT_OPTIONAL(extra_delay, 4, 0);
    lua_pushboolean(L, lens_focus(num_steps, step_size, wait, extra_delay));
    return 1;
}


Which to my dumb eyes looks like it returns 1 (true?) everytime.

I'm a little confused to say the least.

So the question in my mind is: what does lens-focus return, ie what does a true or false return mean?

a1ex

The focus tests in api_test.lua actually stop on error. Try them.

garry23

Alex

Thanks: I'll look through those.

What I'm trying to do is intercept the soft focus limit reached, before it stops Lua working, and take appropriate action.

Cheers

Garry

garry23

A1ex

I looked at the api_test and I thought I got it, but when I use the following code snippet, I can't get it to run.

As I say, 'all' I'm trying to do is detect the soft limit error.

Any help/hints would be gratefully received :)

elseif keymenu.submenu["Focus bracketing?"].value == "FP2MAC" then
repeat
a1=a2
b1=b2
repeat
lens_error = lens.focus(1,1,true)
b2 = lens.dof_far
a2 = lens.dof_near
if a2 == a1 then -- move lens a bit more just to be sure
lens_error = lens.focus(1,1,true)
b2 = lens.dof_far
a2 = lens.dof_near
end
fp = lens.focus_distance
until b2 < a1 or lens_error == false
lens_error = lens.focus(-1,1,true) -- move forward one step for focus bracket overlap
take_brackets()
until lens_error == false
end

BBA

@garry23
I have been out travelling to Switzerland.
If I can help, please look at this piece of code I used when scanning a lens step by step testing the return of lens.focus as dmilligan had told it (thanks a lot).
...
ret = lens.focus(num_steps, step_size, wait, extra_delay)
stret = "false"
if ret then stret = "true" end
...
The script gets the return of lens.focus in the "ret" variable and tests it's value.
I don't see how to join a file (I have plotted the return values to see at which step the false value is output....) I am sure I miss something.

garry23

@BBA

Many thanks for trying to help.

I think I'm getting confused over what wait is doing, ie it's a bol.

'All' my script does is 'look' for lens.focus to return a false, which I'm interpreting as a soft limit reached, ie an error, however, lens.focus seems to return a false even if the lens is no where near the soft limit.

Once again, thanks for trying to help me.

BBA

Here is my code (if it can help).
For the moment, I don't actually see what is wrong with your code.



require('logger')
scan_log = nil

-- Declare a few global variables for the script
a1 = 0
b1 = 0
a2 = 0
b2 = 0

fp = 0
fp1 = 0
fp2 = 0
inf = 100000

ic = 0
istep = 0
num_steps = 0

delay = 3000

BB_ST1 = "TEST"
BB_ST2 = "TEST"
BB_ST3 = "TEST"
BB_ST4 = "TEST"

--  BB_move_focus (num_steps[, step_size=2[, wait=true[, extra_delay=0]]])
--  with log

function BB_move_focus(num_steps, step_size, wait, extra_delay)
local ret = true
local stret = "true"

    msleep(300) -- BBA
    fp1 = lens.focus_distance


        --  lens.focus (num_steps[, step_size=2[, wait=true[, extra_delay=0]]])
        --[[
            Moves the focus motor a specified number of steps. Only works in LV.

            Parameters:

            num_steps int
            step_size int (default 2)
            wait bool (default true)
            extra_delay int (default 0)
        --]]
   
    [color=green]ret = lens.focus(num_steps, step_size, wait, extra_delay)  -- step size fixed at 1 to count steps and detect changes
    stret = "false"
    if ret then stret = "true" end[/color]
   
    istep = istep+num_steps
    msleep(400) -- BBA
    fp2 = lens.focus_distance
    scan_log:writef("%d,\" move_focus(%d,%d) : before = \",%d,\" / after = \",%d %5s",istep,num_steps,step_size,fp1,fp2,stret)
    scan_log:writef(",\" dof near = \",%s,\" dof far = \",%s\n", lens.dof_near, lens.dof_far)
   
    return ret
   
end



function BB_scan_focus_range()
local ret = true

    menu.close()
   
    scan_log = logger("ML/logs/scan.log") -- if file already exists in /ML/LOGS dir, new log lines will be appended
   
    ic = 0                          -- steps counter
    istep = 0
   
    scan_log:writef("lens = %s\n\n",lens.name)
    BB_ST1 = tostring(camera.aperture.value)
    scan_log:writef("     aperture = %s \n",BB_ST1)
    BB_ST2 = tostring(lens.hyperfocal)
    scan_log:writef("     hyperfocal = %s mmm\n",BB_ST2)
   
    lv.start()

    msleep(delay)
   
   
    while ( ic <= 30 ) do
       
       
        fp = lens.focus_distance
       
        if fp >= inf  -- dépasser 100000
        then
            ic = ic + 1
           
        end
       
        ret = BB_move_focus(-1,1,true,0)  -- vers infini(-1), 1 step, wait for focus motor to stabilize
       
    end
       
    scan_log:close()

end

BB_scan_menu = menu.new
{
    parent = "Shoot",
    name = "Scan focus range ",
    help = "Remember: FROM Macro end TO Infinity+",
    --  depends_on = DEPENDS_ON.LIVEVIEW,
    submenu =
    {
        {
            name = "Run Script",
            help = "Does what it says after pressing SET",
            select = function(this)
                 task.create(BB_scan_focus_range)
            end,
        }
    }
}


garry23

@BBA

Thanks for sharing :)

Do you assume the lens.focus return bol value is TRUE if the lens.focus functioned correctly or incorrectly?

BBA

About timings, you are right, mine is very slow, purposely. I have to be sure the value of focal distance has changed. I think if you don't wait enough, the lens has not got the time to send its status back, I saw it at least for the focal distance; maybe, it's also true with the boolean returned...

Quote
Do you assume the lens.focus return bol value is TRUE if the lens.focus functioned correctly or incorrectly?

If you refer to the green lines where sret is initialized and then changed, it's only a way of programming things. it is given one of the two values (yes to false) and afterwards, changed if the real value is the opposite.

garry23

@BBA

I think I'll have to give up as I'm getting a headache!

This code simply will not work, ie detect the soft limit error

elseif keymenu.submenu["Focus bracketing?"].value == "FP2MAC" then
repeat
a1=a2
b1=b2
repeat
lens_error = lens.focus(1,1,true)
b2 = lens.dof_far
a2 = lens.dof_near
if a2 == a1 then -- move lens a bit more
lens_error = lens.focus(1,1,true)
b2 = lens.dof_far
a2 = lens.dof_near
end
fp = lens.focus_distance
until b2 < a1 or lens_error == false
lens_error = lens.focus(-1,1,true) -- move forward one step for focus bracket overlap
take_brackets()
until lens_error == false
end

a1ex


garry23

Sorry A1ex

This test script works as I would 'hope', ie the soft limit error is displayed in LV, but the script carries on working.

function focus()
local lens_error
repeat
lens_error = lens.focus(1,1,true)
until lens_error == false
-- now move the other way having detected the soft limit
lens_error = lens.focus(-10,1,true)
end

scrnshot_menu = menu.new
{
    name = "Test",
select = function(this)
task.create(focus)
end
}


My code, below, simply refuses to work through the soft limit error :(

BBA

This one works

function focus()
local lens_error
repeat
    msleep(100)
  lens_error = lens.focus(1,1,true)
    msleep(400)
until lens_error == false
-- now move the other way having detected the soft limit
lens_error = lens.focus(-10,1,true)
end

scrnshot_menu = menu.new
{
    name = "Test",
  select = function(this)
   task.create(focus)
  end
}


Note : moving towards macro end (put the lens just before macro end to go faster)

BBA

I think the moving direction (sign of first parameter in lens.focus) should be changed.

This one works if you put the lens just before infinity: you then start the script : immediately after, switch to LV to see the error message "focus limit reached"


function focus()
local lens_error
repeat
  lens_error = lens.focus(-1,1,true)
until lens_error == false
-- now move the other way having detected the soft limit
lens_error = lens.focus(10,1,true)
end

scrnshot_menu = menu.new
{
    name = "Test",
  select = function(this)
   task.create(focus)
  end
}

garry23

@BBA

First, thanks for continuing to try and help me.

Here is a test script that works:

function focus()
local stop = false
repeat
if lens.focus(1,1,true) then stop = false else stop = true end
until stop
-- now move the other way having detected the soft limit
lens.focus(-10,1,true)
end

scrnshot_menu = menu.new
{
    name = "Test",
select = function(this)
task.create(focus)
end
}


All this does is drive the lens to the macro end and stop when lens.focus return a false.

However, if i use the same approach in my full script, the above simple coding doesn't work, which implies something else is wrong, but I can't work out what.

Here is the snippet of the full script. One part of the code runs from the focus point to infinity (and works ok), the other runs from the focus point to the macro (and doesn't run: no errors just the lens.focus doesn't run).

it's a mystery.

if lens.focus_distance < inf and no_tv_error then
if keymenu.submenu["Focus bracketing?"].value == "FP2INF" then
repeat
a1=a2
b1=b2
repeat
lens.focus(-1,1,true)
b2 = lens.dof_far
a2 = lens.dof_near
fp = lens.focus_distance
until a2 > b1 or fp >= inf
lens.focus(1,1,true) -- move back one step for focus bracket overlap
take_brackets()
until fp >= inf
else
repeat
a1=a2
b1=b2
repeat
if lens.focus(1,1,true) then stop = false else stop = true end
b2 = lens.dof_far
a2 = lens.dof_near
fp = lens.focus_distance
until b2 < a1 or stop
if not stop then lens.focus(-1,1,true) end -- move forward one step for focus bracket overlap
take_brackets()
until stop == true
end
end


BTW I have tried removing all the a1 a2 b1 b2 checks, ie just using the stop and it still doesn't run :(

BBA

@garry23
In the 2d case, the outer repeat/until loop depends on the initial value of the variable "stop". It should be initialized to false before running that "chunk".

garry23

@BBA

It is.

I'll just keep playing with the script until I find my (sic) error.

Cheers

Garry

garry23

@BBA

BTW your observation is not quite right, as repeat always runs through the loop once, ie it checks at the end, not the beginning  ;)

garry23

@BBA (David/A1ex)

I've worked out what is going on in my script and it pivots around this code:

repeat
if lens.focus(1,1,true) then stop = false else stop = true end
until stop


lens.focus seems to return a false when it is first called. It then returns true.

As I'm looking for a false return, and 'only' associating that with a soft limit.

I tried this, ie not waiting for focus, but still have problems as lens.focus seems to return true and false even if it is functioning, ie it must reporting other 'errors'

[code]repeat
if lens.focus(1,1,false) then stop = false else stop = true end
until stop
[/code]


a1ex

Hypothesis: maybe when the lens is at one endpoint (either infinity or macro), Canon firmware may report error even if you try to move in the other direction.

Does it help if you use larger steps?

Also, does it help if you execute a few focus steps without checking them?

garry23

A1ex

You are thinking how I've been thinking, ie ways to work around it using 'state logic'.

BTW the problem is not at the ends.

That is, if the focus is, say, in the middle, then lens.focus seems to return a false, then a true, even if (AF) wait is false.

I'll carry on testing, but I'm moving to another 'solution' now, which I know works, ie use lens.dof_near as my 'macro stop'.

BBA

@garry23
To share my experiments, this very simple script has worked for me :

function move_focus_to_macro()

    repeat
    until not lens.focus(1,1,true) -- 1=towards macro end, 1 step at a time, waiting for lens to complete
   
end

scrnshot_menu = menu.new
{
    name = "Test",
  select = function(this)
   task.create(move_focus_to_macro)
  end
}


(if necessary, I had a 5dm3 and an EF24mmf1.4L II USM)
It is rather fast, so I don't think fast timings are a problem as I speculated earlier.
With another one, not so simple (and slower), a similar code is used to move the lens to macro end and then to begin scanning the lens in the opposite direction till the infinity end.

Quote
BTW your observation is not quite right, as repeat always runs through the loop once, ie it checks at the end, not the beginning  ;)

You are perfectly right; I must have been tired to write such a terrible thing ???