A bit of an update on my progress with exploiting 'GetEFLensFocusPositionWithLensCom'
As a proof of principle I've created a couple of functions.
The first initialising the lens at script start up or when focal length changes, by creating two look up tables (LUTs), one to hold where the Canon reported focus (I use lower) changes and the other to hold the 'GetEFLensFocusPositionWithLensCom' step value at this position.
function set_up_lens() -- create Steps & Focus LUTs
-- This function may take a while to run for some lenses, ie with lots of steps
-- However, as long as you don't change focal length, you only need to run this once
-- You will need to call this function after any focal length change
call_event_proc("EFLensCom.FocusSearchNear")
call_event_proc("EFLensCom.FocusSearchNear") -- just in case ;-)
sleep(100)
step_count = {}
x_at_count ={}
local i = 1
local j = 1
-- Note this function doesn't require the step count at MFD to be zero
-- It does assume, however, the LUTs don't change; other than explicity when focal length is changed
step_count[j] = call_event_proc('GetEFLensFocusPositionWithLensCom') -- doesn't seem to be different to calling 'GetEFLensFocusPositionWithoutLensCom'
x_at_count[j] = get_focus_distance_lower()
local last_lower = get_focus_distance_lower()
print("Inialising Lens")
while get_focus_distance_upper() < inf do
i = i + 1
call_event_proc("EFLensCom.MoveFocus", 1, 1)
sleep(25) -- this could be changed, but only through testing
if get_focus_distance_lower() > last_lower then -- just gone through a Canon focus step change
j = j + 1
step_count[j] = call_event_proc('GetEFLensFocusPositionWithLensCom')
last_lower = get_focus_distance_lower()
x_at_count[j] = last_lower
end
end
if log == 1 then -- print of LUTs
print("Steps LUT")
for i = 1, #step_count do
print(step_count[i])
end
print("Focus LUT")
for i = 1, #step_count do
print(x_at_count[i])
end
end
call_event_proc("EFLensCom.FocusSearchNear")
sleep(100)
print("Lens ready")
end
The second function is called if focus changes and, at the moment, I've used a three value, 2nd order Lagrange estimation.
function get_x_based_on_step_pos() -- estimate of focus distance in mm from the sensor plane
-- This function uses a Lagrange estimation scheme, based on a 2nd order three point interpolation assumption
local n = #step_count
local t = call_event_proc('GetEFLensFocusPositionWithLensCom') -- step value at current focus
sleep(25)
local j = 1
for i = 2, n do
j = i - 1
if t <= step_count[i] then break end
end
if j >= (n-1) then j = n - 2 end -- handle being at the end of the LUT tables
if get_focus_distance_lower() > 81000 then -- at/beyond any useful lens data
return get_focus_distance_upper()
end
local t1 = step_count[j]
local t2 = step_count[j+1]
local t3 = step_count[j+2]
local pt = fmath.new(0)
pt = pt + (x_at_count[j]*(t-t2)*(t-t3))/((t1-t2)*(t1-t3))
pt = pt + (x_at_count[j+1]*(t-t1)*(t-t3))/((t2-t1)*(t2-t3))
pt = pt + (x_at_count[j+2]*(t-t1)*(t-t2))/((t3-t1)*(t3-t2))
return pt:int() -- focus position in mm
end
I've tested the functions in my Lanscape Bracketing script and things seem to be working as expected.
The functions are insensitive to position of the step count zero, ie it doesn't need to be at the MFD.
For example, here is one log
-540 150
-444 160
-372 170
-336 180
-309 190
-280 210
-252 220
-227 240
-201 250
-179 280
-163 300
-146 330
-127 360
-114 400
-101 450
-90 500
-79 560
-71 630
-62 710
-56 810
-49 930
-43 1080
-37 1270
-32 1540
-26 1940
-22 2590
-17 3840
-13 7600
Which graphically looks like the attached, showing counts vs focus at the each Canon focus change.
It's early days regarding the worth/value of the above. The inialisation is slow, some 10s on an 11-22 lens, and will be proportionally slower with a lens with more steps. But the LUT approach only gets called at script start up or when the FL changes.
Bottom line: the above gives the user the ability to estimate the focus at every step, ie rather than 'just' having the upper or lower reported values.
I'll keep on refinging things and report back on my progress as I (hopefully) make it ;-)