Skip to content

Instantly share code, notes, and snippets.

@pigeonhill

pigeonhill/M3 Brackets.lua

Last active Jul 31, 2021
Embed
What would you like to do?
M3 Focus & Exposure Bracketing
--[[
@title M3B
@chdk_version 1.6
@subtitle Bracketing Options
#mode = 0 "Focus bracket?" {Off X2INF Min2INF Manual}
#bracket = 0 "Exposure bracket?" {Off 1(4Ev) 1(3Ev) 1(2Ev) 2(2Ev) 3(2Ev) ISO Auto Wind3Ev Wind4Ev}
#sky = 0 "Sky Bracket?" {Off 2Ev 3Ev 4Ev 5Ev 6Ev ETTR}
@subtitle Bracketing Settings
#infinity = 3 "Infinity Focus (xH)" [2 4]
#overlap = 15 "Overlap (um)" [5 30]
#hilit = 5 "% Histo HiLit" [1 30]
#start = 1 "Histo Upper Quartiles" [1 4]
#pmag = 1 "Assumed Pupil Mag" [1 6]
#isoval = 0 "ISO Bracketing Value" {400 800 1600 3200}
@subtitle Other Settings
#dofs = 0 "DoF Display" {Blur DoFs Both}
#diff = 0 "Diffraction Aware?" {Off On}
#traf = 0 "Traffic Lights" {Off On}
#evmode = 0 "Exposure Survey" {Off On}
#sleep_time = 2 "Delay (s)"
#bookends = 1 "Bookends?" {Off On}
#histoon = 0 "CHDK Histogram" {Off On}
#screen_off = 0 "Screen?" {Off On}
#log = 0 "Log?" {Off On Reset}
#help = 0 "Console" {Off On}
#lens = 0 "Lens Name?" {Off On}
Notes:
* This version only runs on the M3 with the fmath library version of CHDK and the camera should be in M mode
* Focus funtionality needs a registered EF-M lens. Non registered EF-M lenses can only be used with exposure bracketing.
* Script best suited with WA lenses ;-)
* Set the CHDK ALT button to PLAY as m-FN used as a second shutter button
* Register your EF-M lens below in the lens_info() function.
* This script is not designed for macro focus stacking, it is intended for deep focus photography only, albeit from near to infinity.
* If you reset/delete the log, you need set the log menu to on or off after.
* When paused, at the assess point, you can refocus and change focal length and aprture to see the impact on bracketing.
* If traffic light (TL) feedback is enabled, once an image is captured, the left hand TL shows the near DoF's focus overlap state, relative to the last image captured...
...and the right TL shows the far DoF's overlap state relative to the last image captured. Yellow = same focus; green = a positive overlap; red = a negative overlap (a gap).
* Changing focal length or aperture will reset the traffic lights.
* In addition, as you manually focus bracket, the centre info area of the bar changes from showing the focal length and the number of brackets, to the fL and the blur at the overlap
* At the assess point, you can exit ALT mode and assess exposure deltas in Evs.
* Use pmag to refine focus overlap insurance. Use 1 for a telephoto lens...
* ...for a retrofocus lens simply guess the pupil mag (exit/entrance ration), but round up, ie slightly over estimate.
* All UI presented distances, ie focus and DoFs, are relative to the sensor plane.
* Note: If the bar disappears, just do a half shutter press.
Release 1.636
photography.grayheron.net
July 2021
--]]
require "drawings"
props=require'propcase'
capmode = require("capmode")
bi = get_buildinfo()
current_focus_mode = get_focus_mode()
current_mode = capmode.get_name()
if current_focus_mode ~= 1 then set_mf(1) end
set_exit_key("down")
if histoon == 0 then set_config_value(1060,0) else set_config_value(1060,1) end
inf = 81000 -- infinity trap
dirty = true
set_console_autoredraw(1)
set_console_layout(0,0,45,3)
tg = 242
tv_str = {"32", "25.4","20","16", "12.7", "10","8", "6.3","5","4","3.2", "2.5","2",
"1.6", "1.3", "1", "0.8", "0.6", "0.5", "0.4", "0.3", "1/4", "1/5", "1/6", "1/8", "1/10", "1/13",
"1/15", "1/20", "1/25", "1/30", "1/40", "1/50", "1/60", "1/80", "1/100", "1/125", "1/160", "1/200",
"1/250", "1/320", "1/400", "1/500", "1/640","1/800", "1/1000", "1/1250", "1/1600","1/2000","1/2500",
"1/3200","1/4000", "1/5000", "1/6400", "1/8000", "1/10000", "1/12500", "1/16000", "1/20000", "1/25000",
"1/32000", "1/40000" }
-- Check if OK to use
if (bi.platform ~= "m3") then
print("Only runs on M3")
sleep(3000)
return
end
if tonumber(bi.build_revision) < 5869 then
print("Update CHDK build")
sleep(3000)
return
end
if capmode.get_name() ~= "M" then
print("Put camera in M mode")
sleep(3000)
return
end
if log == 2 then
print_screen(1)
print("Log reset")
print("Reset log menu")
sleep(3000)
print_screen(0)
return
end
function units(xx)
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 update_DoFs(xx) -- update DoF related stuff
h = (1000*F*F)/(n*overlap) -- short hyperfocal (mm)
H = h + F -- 'full' hyperfocal (mm), as measured from the lens front principal, ie NOT the sensor
local q = xx-t
u = (((q*(q-4*F)):sqrt() + q)/2):int() -- focus distance in mm from front principal
if xx < inf then
ndof = (F*F)/(u-F)
ndof = ndof+(h*(F-h*pmag))/(pmag*(u+h-F))
ndof = (ndof+(pmag*(2*F+h+t)-F)/pmag)
else
ndof = H
end
if 2*u < h:int() then
fdof = (F*F)/(u-F)
fdof = fdof-(h*(F+h*pmag))/(pmag*(u-h-F))
fdof = (fdof+(pmag*(2*F-h+t)-F)/pmag)
num = 0
local uc = u
repeat
num = num + 1
new_uc = 2*F*F*(pmag-1) + F*(uc-2*pmag*u) + h*pmag*uc
new_uc = (new_uc/( F*(2*pmag-1) + pmag*(h-2*uc)))
uc = new_uc
until uc:int() >= (H/3):int()
num = num + 1
elseif u < H:int() then
fdof = (F*F)/(u-F)
fdof = fdof-(h*(F+h*pmag))/(pmag*(u-h-F))
fdof = (fdof+(pmag*(2*F-h+t)-F)/pmag)
num = 2
else
fdof = fmath.new(inf+1)
num = 1
end
end
function get_focus_distance_upper() -- NOTE - NOT USED IN THIS SCRIPT (left here as a reference)
local x = -1
if (bi.platsub == "101a") then
x = peek(0x00244916, 2)
elseif (bi.platsub == "120f") then
x = peek(0x0024495A, 2)
else
error('Not 101a or 120f')
end
if x ~= -1 then return x*10 else return x end
end
function get_focus_distance_lower() -- returns lower focus distance in mm, but note 'accuracy' is 1cm from Canon
local x = -1
if (bi.platsub == "101a") then
x = peek(0x00244918, 2)
elseif (bi.platsub == "120f") then
x = peek(0x0024495C, 2)
else
error('Not 101a or 120f')
end
if x == -1 then return -1 else return x*10 end
end
function refocus_to(xx) -- Only moves towards infinity. Returns requested focus distance in mm
local current_x = get_focus_distance_lower() -- current focus distance in mm to nearest cm. Based on Canon lower EXIF value
local steps_total = 0
local steps = 1
local last_step_count = steps_total
local steps_back = 0
if xx < current_x then return -1 end -- don't use
local last_step_x = current_x
while current_x < xx do
call_event_proc("EFLensCom.MoveFocus", steps, 1) -- move smallest step you can towards infinity
steps_total = steps_total + steps
sleep(25) -- for system to catch up
current_x = get_focus_distance_lower() -- Get Canon lower EXIF value
if (current_x ~= last_step_x) and (current_x < xx) then -- just went through an intermediate step change, ie not yet reached the step that covers xx
last_step_x = current_x
last_step_count = steps_total -- close enough
end
end
-- now fine tune position backwards if required
steps_back = ((current_x - xx) * (steps_total - last_step_count)) / (current_x - last_step_x)
if steps_back > 0 then
for i = 1, steps_back do call_event_proc("EFLensCom.MoveFocus", -steps, 1) end
end
sleep(25) -- for system to catch up
current_x = get_focus_distance_lower()
return xx -- request focus position, eg the 'best' estimate in mm as to where we really are
end
function lens_name()
local get_lens_name_fn = 0xfc2f3fd5
if (bi.platsub == "101a") then get_lens_name_fn = 0xfc2f3fc3 end
if call_event_proc('System.Create') == -1 then error('Unknown Error') end
local ppname = call_event_proc('AllocateMemory', 8)
if ppname == -1 or ppname == 0 then error('Unknown Error') end
local plen = ppname + 4
poke(ppname, 0)
poke(plen, 0)
local status = call_func_ptr(get_lens_name_fn, ppname, plen)
local pname = peek(ppname)
local len = peek(plen)
call_event_proc('FreeMemory', ppname)
if ppname == -1 or ppname == 0 then error('Unknown Error') end
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 restore()
clr = tg
draw.replace(obj5,"rectf",hdmi+0,0,hdmi+10,15,clr,clr) -- update left traffic light
draw.replace(obj6,"rectf",hdmi+350,0,hdmi+360,15,clr,clr) -- update right traffic light
set_tv96_direct(s)
set_av96_direct(av)
press("shoot_half")
repeat sleep(10) until get_shooting()
release("shoot_half")
sleep(50)
repeat sleep(10) until (not get_shooting())
if current_focus_mode ~= 1 then set_mf(0) end
if (current_mode ~= "M") then capmode.set(current_mode) end
set_lcd_display(1)
print_screen(0)
cls()
sleep(1000)
exit_alt()
end
function my_restore()
clr = tg
draw.replace(obj5,"rectf",hdmi+0,0,hdmi+10,15,clr,clr) -- update left traffic light
draw.replace(obj6,"rectf",hdmi+350,0,hdmi+360,15,clr,clr) -- update right traffic light
set_tv96_direct(s)
set_av96_direct(av)
press("shoot_half")
repeat sleep(10) until get_shooting()
release("shoot_half")
sleep(50)
repeat sleep(10) until (not get_shooting())
if current_focus_mode ~= 1 then set_mf(0) end
if (current_mode ~= "M") then capmode.set(current_mode) end
set_lcd_display(1)
print_screen(0)
cls()
sleep(1000)
exit_alt()
end
function set_up()
if current_focus_mode ~= 1 then set_mf(1) end -- just in case
if (current_mode ~= "M") then capmode.set("M") end -- just in case
press("shoot_half")
repeat sleep(10) until get_shooting()
dof = get_dofinfo()
F = fmath.new(dof.focal_length,1000) -- focal length in mm (real)
s = get_prop(props.TV)
av = get_prop(props.AV)
n = fmath.new(av96_to_aperture(av),1000) -- aperture number as a real
s_ev = s
release("shoot_half")
repeat sleep(10) until (not get_shooting())
last_s = s
x = get_focus_distance_lower()
end
function myshoot()
local prevcnt = hook_shoot.count()
local rawprevcnt = hook_raw.count()
press 'shoot_full_only'
repeat sleep(10) until prevcnt ~= hook_shoot.count()
release 'shoot_full_only'
repeat sleep(10) until rawprevcnt ~= hook_raw.count()
end
function X_bracket() -- multi image capture options
set_tv96_direct(s) -- just in case
if bracket == 0 then
snap()
elseif bracket == 1 then
snap()
set_tv96_direct(s - 96 * 4)
snap()
elseif bracket == 2 then
snap()
set_tv96_direct(s - 96 * 3)
snap()
elseif bracket == 3 then
snap()
set_tv96_direct(s - 96 * 2)
snap()
elseif bracket == 4 then
snap()
set_tv96_direct(s - 96 * 2)
snap()
set_tv96_direct(s - 96 * 4)
snap()
elseif bracket == 5 then
snap()
set_tv96_direct(s - 96 * 2)
snap()
set_tv96_direct(s - 96 * 4)
snap()
set_tv96_direct(s - 96 * 6)
snap()
elseif bracket == 6 then
local iso = get_iso_mode()
set_iso_mode(100)
snap()
local isov = 400
if isoval == 1 then
isov = 800
elseif isoval == 2 then
isov = 1600
elseif isoval == 3 then
isov = 3200
end
set_iso_mode(isov)
snap()
set_iso_mode(iso)
elseif bracket == 7 then
shot_histo_enable(1)
snap()
sleep(100)
lower = 1024 - 1024*hilit/100
test=get_histo_range(lower,1024)
step = 0
while test > 0 do
step = step + 1
set_tv96_direct(s + 96 * 2 * step)
local ecnt = get_exp_count()
snap()
test=get_histo_range(lower,1024)
repeat sleep(10) until (get_exp_count() ~= ecnt)
end
shot_histo_enable(0)
elseif bracket > 7 then
snap()
local iso = get_sv96()
set_sv96(iso+96*(bracket-5))
set_tv96_direct(s + 96*(bracket-5))
snap()
set_sv96(iso)
end
set_tv96_direct(s)
end
function bookend()
set_tv96_direct(960)
set_av96_direct(get_max_av96())
local ecnt = get_exp_count()
shoot()
set_tv96_direct(s)
set_av96_direct(av)
repeat sleep(10) until (get_exp_count() ~= ecnt)
end
function hiatus()
local M = fmath.new(Mmax,1000)
local Fr = fmath.new(Fmax,1000)
-- Note the following is an estimate of the mag at f, based on simply scaling the max mag by the focal length ratio
-- A better model would be to explicity measure the mag at a focal length, or at least at the zooms and interpolate
-- Maybe in the future ;-)
m=M*F/Fr
t = (F * (1 + m) * (1 + m))
t = MFD - t/m -- this is an estimate of the spilt thin lens thickness (mm)
return t
end
function lens_info()
if lens_name() == "EF-M11-22mm f/4-5.6 IS STM" then -- calculate lens thickness from manufacturer's data
--if lens_name() == "E-M11-22mm f/4-5.6 IS STM" then -- calculate lens thickness from manufacturer's data
-- add other lenses as required, ie replace the following for your lens
-- For the above lens, 300 is the lens max magnification x 1000, ie from manufacturer's data or your measurement
-- 22000 is the lens maximun zoom, or the prime, focal length in microns
-- 150 is the lens minimum focus distance (mm), ie from manufacturer's data or your measurement
Fmax = 22000 -- Longest focal length (mm) * 1000
Mmax = 300 -- Max magnification * 1000
MFD = 150 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
elseif lens_name() == "EF-M28mm f/3.5 MACRO IS STM" then
Fmax = 28000 -- Longest focal length (mm) * 1000
Mmax = 1000 -- Max magnification * 1000
MFD = 97 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
elseif lens_name() == "EF-M55-200mm f/4.5-6.3 IS STM" then
Fmax = 200000 -- Longest focal length (mm) * 1000
Mmax = 210 -- Max magnification * 1000
MFD = 960 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
elseif lens_name() == "EF-M18-55mm f/3.5-5.6 IS STM" then
Fmax = 55000 -- Longest focal length (mm) * 1000
Mmax = 240 -- Max magnification * 1000
MFD = 150 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
elseif lens_name() == "EF-M15-45mm f/3.5-6.3 IS STM" then
Fmax = 45000 -- Longest focal length (mm) * 1000
Mmax = 250 -- Max magnification * 1000
MFD = 250 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
--[[
elseif lens_name() == "10-20mm" then
Fmax = 20000 -- Longest focal length (mm) * 1000
Mmax = 130 -- Max magnification * 1000
MFD = 240 -- Minimum Focus Distance in mm
t = hiatus() -- distance between front and rear principals
return true
elseif lens_name() == "your lens" then
copy template above
]]
else -- lens not recognised, so don't use
return false
end
end
function update()
if get_gui_screen_width() == 360 then
hdmi = 0
else
hdmi = 60
end
update_DoFs(x) -- update u and DoFs
draw.replace(obj1,"rectf",hdmi+0,0,hdmi+360,15,tg,tg) -- clear the info bar
if x > inf then
temp = ">=H:INF"
elseif u >= H:int() then
temp = ">=H:"..units(fmath.new(x,1))
else
temp = "#"..num..":"..units(fmath.new(x,1))
end
draw.replace(obj2,"string",hdmi+20,0,temp,"white",tg) -- draw focus position info
local inf_blur = ((overlap*(H-F))/(u-F))
if x >= inf then inf_blur = fmath.new(0,1) end
if diff == 1 then -- show impact of diffraction on infinity blur
inf_blur = (inf_blur*inf_blur + (1342*n/1000)*(1342*n/1000)):sqrt()
end
inf_blur = inf_blur:int()
if get_alt_mode() and evmode > 0 and not image then -- change to Ev or Exp feedback
local temp_s = get_user_tv96()
local qqq = get_user_tv_id()
if qqq == 33 then temp = "oops" else temp = tv_str[qqq+16].."s" end
if temp_s > 2000 or s_ev > 2000 then
temp = " BULB:"..temp
else
temp_s = fmath.new(temp_s,96)
temp_s = fmath.new(s_ev,96)-temp_s
if (10*temp_s):int() == 0 then
temp_s = " "..temp_s:tostr(1)
elseif (10*temp_s):int() > 0 then
temp_s = "+"..temp_s:tostr(1)
else
temp_s = temp_s:tostr(1)
end
temp = temp_s.."Ev:"..temp
end
else
local qqq = get_user_tv_id()
if qqq == 33 then temp = "oops" else temp = tv_str[qqq+16].."s" end
temp = F:int().."mm:"..temp
end
draw.replace(obj3,"string",hdmi+120, 0,temp,"white",tg)
if dofs == 0 then
temp = units(ndof)..":"..inf_blur.."um"
elseif dofs == 2 then
if u < H:int() then
temp = units(ndof)..":"..units(fdof)
else
temp = units(ndof)..":"..inf_blur.."um"
end
elseif dofs == 1 then
if u < H:int() then
temp = units(ndof)..":"..units(fdof)
else
temp = units(ndof)..":INF"
end
end
draw.replace(obj4,"string",hdmi+245,0,temp,"white",tg)
if traf == 1 and image then -- display traffic lights
local clr = tg
if x == last_image_x then
clr = "yellow"
elseif (ndof >= last_image_ndof) and (ndof <= last_image_fdof) then
clr = "green"
elseif (ndof > last_image_fdof) or (ndof < last_image_ndof) then
clr = "red"
end
draw.replace(obj5,"rectf",hdmi+0,0,hdmi+10,15,clr,clr) -- update left traffic light
if x == last_image_x then
clr = "yellow"
elseif (fdof <= last_image_fdof) and (fdof >= last_image_ndof) then
clr = "green"
elseif (fdof > last_image_fdof) or (fdof < last_image_ndof) then
clr = "red"
end
draw.replace(obj6,"rectf",hdmi+350,0,hdmi+360,15,clr,clr) -- update right traffic light
local ee = (F*(pmag-1))/(pmag) -- pupil extension in mm
local blur = ee*(u+last_image_u)-2*u*last_image_u
blur = blur + F*(u+last_image_u-2*ee)
blur = blur*n
blur = ((1000*F*F*(u-last_image_u))/blur):int() -- blur at overlap in microns
if blur < 0 then blur = -blur end
if x < inf then
temp = F:int().."mm:"..blur.."um"
else
temp = F:int().."mm:".."???"
end
draw.replace(obj3,"string",120, 0,temp,"white",tg)
else
clr = tg
draw.replace(obj5,"rectf",hdmi+0,0,hdmi+10,15,clr,clr) -- update left traffic light
draw.replace(obj6,"rectf",hdmi+350,0,hdmi+360,15,clr,clr) -- update right traffic light
end
draw.overdraw()
dirty = false
end
function snap() -- single image capture
press("shoot_half")
repeat sleep(10) until (get_shooting())
myshoot()
release("shoot_half")
repeat sleep(10) until (not get_shooting())
end
function check_focus_etc()
dof = get_dofinfo()
local test_x = get_focus_distance_lower()
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 or test_n ~= n then
dirty = true
image = false
elseif test_x ~= x then
dirty = true
end
F = test_F
n = test_n
x = test_x
end
function check_buttons_etc()
wait_click(50) -- check for a button press
if is_key("shoot_full") then -- taking a single image
click("shoot_full")
last_image_ndof = ndof
last_image_fdof = fdof
last_image_x = x
last_image_u = u
repeat sleep(10) until ecnt ~= (get_exp_count())
ecnt = get_exp_count()
image = true
dirty = true
elseif is_key("up") and get_alt_mode() then -- Change ISO requested
click("up")
elseif is_key("right") and get_alt_mode() then -- ETTR requested
set_ETTR()
--dirty = true
elseif is_key("set") and get_alt_mode() then
click("set")
elseif is_key("left") and get_alt_mode() then
click("left")
--dirty = true
elseif is_key("shoot_half") and get_alt_mode() then -- do a manual refresh of the info bar
s_ev = get_user_tv96()
dirty = true
elseif is_key("print") and get_alt_mode() then -- M-Fn button pressed
if mode == 3 then -- take an exposure bracket set
set_up()
sleep(sleep_time*1000)
X_bracket()
if sky == 6 then -- take an auto ETTR exposure bracket for the sky
set_ETTR()
snap()
elseif sky > 0 then -- take a single exposure shot for the sky
set_tv96_direct(s + 96*(sky+1))
snap()
end
set_tv96_direct(s)
last_image_ndof = ndof
last_image_fdof = fdof
last_image_x = x
last_image_u = u
finish = false
image = true
dirty = true
elseif mode > 0 then -- do some auto focus bracketing
finish = true
end
elseif is_key("display") and get_alt_mode() then
if get_config_value(1060) == 0 then set_config_value(1060,1) else set_config_value(1060,0) end
dirty = true
end
if get_alt_mode() ~= last_alt_state then -- ALT state changed
last_alt_state = get_alt_mode()
image = false
s_ev = get_user_tv96() -- reset ev feedback
dirty = true
end
if (last_s ~= get_user_tv96()) then
dirty = true
last_s = get_user_tv96()
end
end
function set_ETTR()
local histo={}
local percent = 0
local total = 0
histo,total=get_live_histo()
total = 0
local max = #histo
local start = ((4-start)*max)/4
for i = start,(max-1),1 do total = total + histo[i] end -- get the total count in the requested quartiles
local n2 = (max*hilit)/100
for i = (max-1),(max-1-n2), -1 do percent = percent + histo[i] end -- get the total count in the requested %
percent = (100*percent)/total
press("shoot_half")
repeat sleep(10) until get_shooting()
s = get_tv96()
set_user_tv96(s)
release("shoot_half")
repeat sleep(10) until (not get_shooting())
if percent > 0 then -- overexposed
i = 0
repeat
percent = 0
wheel_right() -- move 1 stop, but note camera must be set to 1/3 stops
wheel_right()
wheel_right()
histo,total=get_live_histo()
total = 0
for j = start,(max-1),1 do total = total + histo[j] end
for j = (max-1),(max-1-n2), -1 do percent = percent + histo[j] end
percent = (100*percent)/total
until percent <= 0
repeat
percent = 0
wheel_left()
histo,total=get_live_histo()
total = 0
for j = start,(max-1),1 do total = total + histo[j] end
for j = (max-1),(max-1-n2), -1 do percent = percent + histo[j] end
percent = (100*percent)/total
until percent > 0
wheel_right()
elseif percent <= 0 then -- underexposed
i = 0
repeat
percent = 0
wheel_left() -- move 1 stop, but note camera must be set to 1/3 stops
wheel_left()
wheel_left()
histo,total=get_live_histo()
total = 0
for j = start,(max-1),1 do total = total + histo[j] end
for j = (max-1),(max-1-n2), -1 do percent = percent + histo[j] end
percent = (100*percent)/total
until percent > 0
repeat
percent = 0
wheel_right()
histo,total=get_live_histo()
total = 0
for j = start,(max-1),1 do total = total + histo[j] end
for j = (max-1),(max-1-n2), -1 do percent = percent + histo[j] end
percent = (100*percent)/total
until percent <= 0
end
return
end
-- Main Section
if lens == 1 then
print_screen(-1)
print(lens_name())
sleep(3000)
return
end
set_up()
if lens_info() == false then -- only capture requested exposure brackets
print("Non EFM lens, taking X(s) Only")
sleep(sleep_time*1000)
if bookends == 1 then bookend() end
X_bracket()
if bookends == 1 then bookend() end
my_restore()
return
end
if mode == 2 then -- move to focus minimum
repeat
x = get_focus_distance_lower()
call_event_proc("EFLensCom.FocusSearchNear")
sleep(50)
until x == get_focus_distance_lower()
end
print_screen(0) -- switch off logging until bracketing
if help == 0 then -- then switch off console display
set_console_layout(0,0,1,0)
print("")
set_console_autoredraw(-1)
else
set_console_layout(0,0,45,2)
end
-- Set up the bar drawing objects
obj1 = draw.add("rectf", 0, 0, 0, 0, tg,tg)
obj2 = draw.add("string", 0, 0, "","white",tg)
obj3 = draw.add("string", 0,0,"","white",tg)
obj4 = draw.add("string",0,0,"","white",tg)
obj5 = draw.add("rectf", 0, 0, 0, 0, tg,tg)
obj6 = draw.add("rectf", 0, 0, 0, 0, tg,tg)
last_alt_state = get_alt_mode()
image = false -- no image taken yet
last_image_ndof = fmath.new(0)
last_image_fdof = fmath.new(0)
last_image_x = fmath.new(0)
last_image_u = fmath.new(0)
ecnt = get_exp_count()
finish = false
repeat -- stay here while in asssess/shooting mode. THIS IS THE PIVOT POINT OF THE SCRIPT
check_focus_etc()
check_buttons_etc()
if screen_needs_refresh() then dirty = true end
if dirty then update() end
sleep(300) -- no need to check too often
until finish -- then take menu requested custom brackets
set_up() -- for focus bracketing
if log == 1 then
set_console_autoredraw(-1)
print_screen(-1)
print("...")
print(os.date())
set_console_autoredraw(1)
end
t1=os.time() -- start the clock
draw.clear()
print_screen(0)
print("Bracketing Started")
if log == 1 then print_screen(-1) end -- switch focus bracketing logging on
if bookends == 1 then bookend() end
t1=sleep_time-(os.time()-t1)
if t1 > 0 then sleep(t1*1000) end
if screen_off == 1 then set_lcd_display(0) end
print("1/"..num.." @ "..units(fmath.new(x)))
X_bracket() -- First exposure(s)
i = 1
while (u < (H/3):int()) do -- capture the rest of the focus brackets up to H/3
-- Note that focus bracketing is calculated/updated in u space, but actual refocusing is in x space
-- All console feedback is in x space, ie distance estimates measured from the sensor
new_u = 2*F*F*(pmag-1) + F*(u-2*pmag*u) + h*pmag*u
new_u = (new_u/( F*(2*pmag-1) + pmag*(h-2*u))):int() -- new u in mm, using DOFIS model
if new_u <= u then new_u = u + 5 end -- move at least 5mm, just in case. Remember: script is not designed for macro work!
u = new_u
x = (u + F + (F*F)/(u-F) + t) -- next focus bracket estimate in x space: in mm from f(1+m)+t+u
refocus_to(x:int())
i = i + 1 -- keep track of number of images taken
print(i.."/"..num.." @ "..units(x))
X_bracket()
x = x:int()
end
if u < H:int() then -- take image(s) at H
temp = ((F*F)/(H-F) + F + t + H)
refocus_to(temp:int())
print("@H = "..units(temp))
X_bracket()
end
if u < infinity*H:int() then -- take image(s) at infinity*H
temp = ((F*F)/(infinity*H-F) + F + t + infinity*H)
if temp:int() > inf then -- adjust as at/beyond lens infinity
repeat
infinity = infinity - 1
temp = ((F*F)/(infinity*H-F) + F + t + infinity*H)
until temp:int() < inf or infinity == 2
end
refocus_to(temp:int())
print("@"..infinity.."xH = "..units(temp))
X_bracket()
end
if sky == 6 then -- take an auto ETTR exposure bracket for the sky
set_ETTR()
snap()
set_tv96_direct(s)
print("Sky X")
elseif sky > 0 then -- take a single exposure shot for the sky
set_tv96_direct(s + 96*(sky+1))
snap()
set_tv96_direct(s)
print("Sky X")
end
if bookends == 1 then bookend() end
my_restore()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment