Last active
July 15, 2022 15:36
-
-
Save pigeonhill/3656fce88badb50d258995a48840d326 to your computer and use it in GitHub Desktop.
Thin Lens Functionalised Focus
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--[[ | |
@title TLFF | |
@chdk_version 1.6 | |
#log = 0 "Log?" {Off On} | |
Notes: | |
* This test script only runs on the M3, M10 or M100 with the XIMR version of CHDK. But note, not tested on the M100. | |
* Go to https://drive.google.com/drive/folders/1drk1xi6kMMIeF5xSqXgnpjGCffF8CVkd?usp=sharing for XIMR builds | |
* | |
* The script is a proof of principle of using a thin lens approximation to estimate focus distance from the sensor plane | |
Release 0.51 ALPHA | |
photography.grayheron.net | |
July 2022 | |
--]] | |
bi = get_buildinfo() | |
set_exit_key("down") -- change as required | |
set_console_autoredraw(1) | |
set_console_layout(0,0,45,3) | |
focus_count = -999 | |
reset_lens = false | |
INF = 999000 -- infinity trap | |
count = 0 | |
U = 0 | |
-- Check a couple of things first | |
if not ((bi.platform == "m3") or (bi.platform == "m10") or (bi.platform == "m100")) then | |
print("Doesn't run on this Cam") | |
sleep(3000) | |
return | |
end | |
if get_gui_screen_width() ~= 360 then | |
print("Need an XIMR build") | |
sleep(3000) | |
return | |
end | |
-- Functions -- | |
function units(xx) -- pretty print of focus distance | |
local xr ="" | |
if xx:int() > 5000 then | |
xr=(xx/1000):tostr(1).."m" | |
elseif xx:int() > 1000 then | |
xr=(xx/10):tostr(0).."cm" | |
else | |
xr=(xx):tostr(0).."mm" | |
end | |
return xr | |
end | |
function get_focus_distance_lower() -- returns lower focus distance in mm, but note 'accuracy' is 1cm from Canon | |
local x=-1 | |
if (bi.platform=="m3") and (bi.platsub=="101a") then | |
x=peek(0x00244918, 2) | |
elseif (bi.platform=="m3") and (bi.platsub=="120f") then | |
x=peek(0x0024495C, 2) | |
elseif (bi.platform=="m3") and (bi.platsub=="121a") then | |
x=peek(0x0024495C, 2) | |
elseif (bi.platform=="m10") then -- same address in 110d, 110f, 110g | |
x=peek(0x00272018, 2) | |
elseif (bi.platform=="m100") and (bi.platsub=="100a") then | |
x=peek(0x001FC7FC, 2) | |
else | |
print('Wrong platform') | |
end | |
if x == -1 then return -1 else return x*10 end -- in mm | |
end | |
function get_focus_distance_upper() -- returns upper focus distance in mm, but note 'accuracy' is 1cm from Canon | |
local x=-1 | |
if (bi.platform=="m3") and (bi.platsub=="101a") then | |
x=peek(0x00244916, 2) | |
elseif (bi.platform=="m3") and (bi.platsub=="120f") then | |
x=peek(0x0024495A, 2) | |
elseif (bi.platform=="m3") and (bi.platsub=="121a") then | |
x=peek(0x0024495A, 2) | |
elseif (bi.platform=="m10") then -- same address in 110d, 110f, 110g | |
x=peek(0x00272016, 2) | |
elseif (bi.platform=="m100") and (bi.platsub=="100a") then | |
x=peek(0x001FC7FA, 2) | |
else | |
print('Wrong platform') | |
end | |
if x == -1 then return -1 else return x*10 end | |
end | |
function lens_name() -- does what it says | |
local pname = 0 | |
if (bi.platform=="m3") then | |
if (bi.platsub == "101a") then | |
pname = 0x00244969 | |
else | |
pname = 0x002449ad | |
end | |
elseif (bi.platform=="m10") then | |
pname = 0x272065 | |
elseif (bi.platform=="m100") and (bi.platsub == "100a") then | |
pname = 0x1FC84E | |
end | |
local len = peek(pname-1,1) | |
local i = 0 | |
local t = {} | |
while i < len do | |
local c = peek(pname + i, 1) | |
if c == 0 then break end | |
table.insert(t, string.char(c)) | |
i = i + 1 | |
end | |
local name = table.concat(t) | |
return name | |
end | |
function lens_cal() -- called at the start and when focal length changes: sets lens to MFD | |
call_event_proc('InitializeAdjustmentSystem') | |
temp = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
repeat | |
temp = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
call_event_proc("EFLensCom.FocusSearchFar") | |
sleep(20) | |
until temp == call_event_proc('GetEFLensFocusPositionWithLensCom') -- make sure we are at 'infinity' | |
repeat -- to find some useful data | |
call_event_proc("EFLensCom.MoveFocus", -1, 1) | |
sleep(20) | |
until get_focus_distance_lower() < 81000 | |
xc = get_focus_distance_lower() -- Canon lower focus distance 'infinity' start | |
sleep(20) | |
far_count = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
print("far count:"..far_count) | |
temp = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
repeat | |
temp = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
call_event_proc("EFLensCom.FocusSearchNear") | |
sleep(10) | |
until temp == call_event_proc('GetEFLensFocusPositionWithLensCom') -- make sure we are at MFD | |
near_count = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
MFD = fmath.new(get_focus_distance_lower(),1) | |
k = (MFD*(MFD-4*F)):sqrt() | |
total_count = far_count - near_count -- lens max number of steps at the current focal length | |
reset_lens = false | |
print("FL = "..F:int()) | |
print("Total count = "..total_count) | |
-- Use the following to log focus against counts | |
if log == 1 then | |
print_screen(1) | |
print("--") | |
print("FL= "..F:int().."mm") | |
print("Stepper Motor Counts") | |
for j = 1, total_count do | |
print(j) | |
end | |
print("TLFF distances (mm)") | |
for j = 1, total_count do | |
x = TL_focus_pos(j) | |
print(x:int()) | |
end | |
print("--") | |
print_screen(0) | |
end | |
end | |
function TL_focus_pos(nn) -- functioalised estimate of focus from the stepper motor position | |
local a = fmath.new(get_focus_distance_lower(),1) | |
local b = fmath.new(get_focus_distance_upper(),1) | |
local c = ((2*a*b)/(a+b)):int() | |
local d = MFD | |
-- use a, b or c to 'scale'' the basic functional form | |
return (total_count*MFD - 2*F*nn)/(total_count-nn) - (a*nn)/(total_count) | |
end | |
function set_up() | |
dof = get_dofinfo() | |
F = fmath.new(dof.focal_length,1000) -- focal length in mm (real) | |
end | |
function lens_info() | |
if lens_name() == "EF-M11-22mm f/4-5.6 IS STM" then -- calculate lens thickness from manufacturer's data | |
return true | |
elseif lens_name() == "EF-M28mm f/3.5 MACRO IS STM" then | |
return true | |
elseif lens_name() == "EF-M55-200mm f/4.5-6.3 IS STM" then | |
return true | |
elseif lens_name() == "EF-M18-55mm f/3.5-5.6 IS STM" then | |
return true | |
elseif lens_name() == "EF-M15-45mm f/3.5-6.3 IS STM" then | |
return true | |
else -- lens not recognised | |
return false | |
end | |
end | |
function check_focus() | |
dof = get_dofinfo() | |
dirty = false | |
local test_count = call_event_proc('GetEFLensFocusPositionWithLensCom') | |
local test_n = fmath.new(av96_to_aperture(get_user_av96()),1000) | |
local test_F = fmath.new(dof.focal_length,1000) | |
if test_F ~= F then -- recalibrate lens and update focus position | |
dirty = true | |
reset_lens = true | |
elseif test_count ~= focus_count then -- update focus position | |
dirty = true | |
end | |
F = test_F | |
focus_count = test_count | |
end | |
function update() -- update focus position estimate in the console | |
count = call_event_proc('GetEFLensFocusPositionWithLensCom') - near_count | |
x = TL_focus_pos(count) | |
if x:int() < INF and count <= total_count then | |
print(units(x)..",Lower = "..get_focus_distance_lower()..",Upper = "..get_focus_distance_upper()..",count = "..count) | |
else | |
print("oo") | |
end | |
end | |
-- Main Section -- | |
if lens_info() == false then -- then don't use | |
print("Can't use for now") | |
sleep(3000) | |
return | |
end | |
call_event_proc('FA.Create') -- assume only need to call this once | |
sleep(100) | |
set_up() | |
lens_cal() | |
finish = false | |
repeat -- stay here | |
check_focus() | |
if reset_lens then lens_cal() end -- focal length changed so recalibrate lens | |
if screen_needs_refresh() then dirty = true end | |
if dirty then update() end | |
sleep(100) -- adjust a required | |
until finish -- exit via pressing ALT exit button |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment