--[[ @title video exposure control by fudgey 2010/08/23 Requires CHDK built with native call support Thanks to ewavr (method) and reyalp (lua things, eventprocs) This script uses several event procedures (native function calls) which supposedly are portable across many camera models, but may not exist or may fail to work on others or the way to register them on a570 may cause problems. In addition, even on the author's a570 100e this script causes frequent crashes. You have been warned, try at your own risk! If 1, camera will reset to autoexposure when script ends: @param a set auto exp on exit? @default a 1 How large adjust steps to use. 32 is 1/3 stop, 96 is full stop: @param t tv96init @default t 847 @param u av96init @default u 443 @param v svinit @default v 0 @param b tv96 step (96=full stop) @default b 32 @param c av96 step (96=full stop) @default c 32 @param d sv step (unknown unit) @default d 128 The script uses certain camera functions to set exposure values. Tv and Av functions appear to return whatever value they actually set. If this argument is zero, the camera return value is used as the current exposure value shown on the console and as the seed value for the next adjustment. Thus the camera may will limit the adjustment range. If you feel brave and optimistic, set this to '1' to see if you can go further than the camera wants to let you go. On a570 it looks like camera limits are at or near CHDK override limits, not the usual Canon UI limits. There are built-in limits in the script too, you may need to relax them too to do this: @param e override cam limits @default e 0 --]] --[[ todo: - find a way to get working start value for ISO (currently just gives 0 which is not right) - show Av in 1/f - show Tv in milliseconds or fractional or divisor from video frame rate - ND filter control (ExpCtrlTool.ND or whatever CHDK uses?). I can't do this since I don't have a suitable camera. --]] tv96=t av96=u sv96=v TVSTEP=b AVSTEP=c SVSTEP=d OVERRIDE=e -- don't run in play mode rec,vid,mode=get_mode() print("rec:",rec,"vid:",vid) sleep(1000) if rec~=true then error("Not in rec mode.") end --************************************************************************** -- configure limiting values here --************************************************************************** -- tv96 is tied to exposure time in seconds by equation tv = 2^-(tv96/96) tv96_min=5*96 -- 448 crashes a570, this one seems stable (1/30 s is slightly slower than 30 fps but this works in 60 fps mode too) -- av96 is tied to aperture number N in f/N by equation av96 = 96 * 2*log2(N) av96_min=2*96 --av96_min=get_prop(prop.MIN_AV) -- returns 0 for my cam, which sounds dangerous (literally). Also, require "propcase" hangs during video record. av96_max=8*96 -- (f/16) -- sv96 is tied to ISO speed rating S by equation sv96 = 96 * 2*log2(S/3.125) -- but the sv96 used in this script is not really sv96. I don't know what it is, -- possibly a 10-bit PGA amp gain control setting ranging from 0 to 1024 for ISO100 to ISO800 (or 1600, but that's a software mode) -- that's a 3 Ev range, so a step size of 128 crudely approximates 1/3 stop change sv96_min=0 sv96_max=2000 if (type(call_event_proc) ~= "function" ) then error("your CHDK does not support native calls") end -- this is required for event procedure AllocateMemory if (call_event_proc("System.Create") == -1) then error("SystemEventInit failed") end --required for PT_DoAELock and UnlockAE if (call_event_proc("SS.Create") == -1) then error("SystemEventInit failed") end -- this is required for event procedures ExpCtrlTool.* if (call_event_proc("Capture.Create") == -1) then error("Capture.Create failed") end -- this is required for event procedures SetAE_ShutterSpeed, MoveIrisToAv, SetCDSGain if (call_event_proc("FA.Create") == -1) then error("FA CREATE failed") end if (call_event_proc("InitializeAdjustmentSystem") == -1) then error("InitializeAdjustmentSystem failed") end -- returns 0 if no ND present, 1 if ND present and real diaphragm NOT present, 2 if both ND & diaphragm present. nd=get_nd_present() if nd==1 then iris=false else iris=true end -- to make lua happy tv96=get_tv96() av96=get_av96() sv96=get_sv96() decrease=0 increase=1 -- 1/3 stop Tv adjustment -- too slow tv crashes the cam. function tv_adj(incr) if incr==increase then tv96=tv96-32 else tv96=tv96+32 end -- prevent tv from going slower than safe minumum or higher than signed short can go if tv9632767 then tv96=32767 end -- adjust tv ret=call_event_proc("SetAE_ShutterSpeed",tv96) -- Canon's function seems to return sane values, let's use them as limits: if OVERRIDE ~= 1 then tv96=ret end -- change menu text to show new value curmenu[curitem].name=function() return(tostring(string.format("%s %d", "Tv", tv96))) end end -- 1/3 stop Av adjustment function av_adj(incr) if iris==true then if incr==increase then av96=av96-AVSTEP else av96=av96+AVSTEP end -- prevent tv from going slower than safe minumum or higher than signed short can go if av96av96_max then av96=av96_max end -- adjust iris ret=call_event_proc("MoveIrisToAv",av96) -- Canon's function seems to return sane values, let's use them as limits: if OVERRIDE ~= 1 then av96=ret end -- change menu text to show new value curmenu[curitem].name=function() return(tostring(string.format("%s %d", "Av", av96))) end end end function sv_adj(incr) if incr==increase then sv96=sv96-SVSTEP else sv96=sv96+SVSTEP end -- range limit if sv96sv96_max then sv96=sv96_max end -- 0 to 1024 vale range to ISO 100--800 or 1600 range (I think) ret=call_event_proc("SetCDSGain",sv96) --print("SetCDSGain="..ret) --this one appears to return 0 always --sleep(500) curmenu[curitem].name=function() return(tostring(string.format("%s %d", "Sv", sv96))) end end -- go to manual exposure mode function manualexp() ret=call_event_proc("PT_DoAELock") end function autoexp() ret=call_event_proc("PT_UnlockAE") end function menuitem(name,item) t={item = item} if type(name) ~= "function" then t.name = function() return(tostring(name)) end else t.name = name end return t end mainmenu={ menuitem("Tv "..tv96,tv_adj), menuitem("Av "..av96,av_adj), menuitem("Sv "..sv96,sv_adj), } function domenu() curmenu=mainmenu curitem=1 while true do cls() print("U/D:pick | quit:MENU") print("L/R:adj | record:SET ") if curitem > 1 then print(string.format("|%s",curmenu[curitem-1].name())) else print("-----------------------") end print(string.format(">%s",curmenu[curitem].name())) if curmenu[curitem+1] then print(string.format("|%s",curmenu[curitem+1].name())) else print("-----------------------") end wait_click(5000) if is_pressed("down") then if curmenu[curitem+1] then curitem = curitem + 1 end elseif is_pressed("up") then if curitem > 1 then curitem = curitem - 1 end elseif is_pressed("left") then if type(curmenu[curitem].item) == "function" then curmenu[curitem].item(increase) end elseif is_pressed("right") then if type(curmenu[curitem].item) == "function" then curmenu[curitem].item(decrease) end elseif is_pressed("set") then print("recording") --click "shoot_full" post_levent_to_ui("PressMovieButton") sleep(1000) -- update values in menu tv96=get_tv96() mainmenu[1].name=function() return(tostring(string.format("%s %d", "Tv", tv96))) end av96=get_av96() mainmenu[2].name=function() return(tostring(string.format("%s %d", "Av", av96))) end sv96=get_sv96() mainmenu[3].name=function() return(tostring(string.format("%s %d", "Sv", sv96))) end --manualexp() elseif is_pressed("menu") then break end end end function restore() if a==1 then print("enabling autoexposure") autoexp() end end function set_tvinit(init) tv96=init end function set_avinit(init) av96=init end function set_svinit(init) sv96=init end manualexp() -- startup values tv96=get_tv96() av96=get_av96() sv96=get_sv96() -- diese zeilen sorgen für unbenutzbarkeit des scripts -- ich möchte dieinitialwerte über parameter belegen können -- geht aber nicht, warum? -- Fehler: attempt to perform arithmetic on global `pos' (a table value) tv96=t av96=u sv96=v domenu() restore()