Closed sdaau closed 5 years ago
You're right that this problem is unlikely to be caused by python-gphoto2. I've not heard of wait_for_event
causing a picture to be taken before. With the cameras I've used I have to call wait_for_event
repeatedly until I get the event I'm interested in or a GP_EVENT_TIMEOUT
event. Have a look at the time_lapse.py
example for a typical usage. (This example also includes some configuration manipulation.)
Many thanks for the response @jim-easterbrook :
You're right that this problem is unlikely to be caused by python-gphoto2.
Indeed, so I posted https://github.com/gphoto/libgphoto2/issues/358
I've not heard of wait_for_event causing a picture to be taken before
Neither was I able to find anything about that browsing around on the Net; still, I repeatedly experience this... maybe because it (Canon S3 IS) is an old camera
Have a look at the time_lapse.py example for a typical usage. (This example also includes some configuration manipulation.)
Thanks - while this didn't fix the issue with wait_for_event
taking a picture, it did force me to rewrite, and revealed how I can wait for exposurecompensation
.readonly to change after a change of shootingmode
- and that is with the good old sleep polling check; here is test-sm-ec2.py
:
from __future__ import print_function
from contextlib import contextmanager
import os
import subprocess
import sys
import time
import gphoto2 as gp
@contextmanager
def configured_camera():
# initialise camera
camera = gp.Camera()
camera.init()
# if needed:
#gp.gp_camera_capture_preview(camera) # extend lens (raise mirror?); else nothing quite works on Canon S3 IS; actually without it, program will fail with "GPhoto2Error [-2] Bad parameters"
try:
# adjust camera configuratiuon
cfg = camera.get_config()
capturetarget_cfg = cfg.get_child_by_name('capturetarget')
capturetarget = capturetarget_cfg.get_value()
capturetarget_cfg.set_value('Internal RAM')
imageformat_cfg = cfg.get_child_by_name('imageformat')
imageformat = imageformat_cfg.get_value()
imageformat_cfg.set_value('Unknown value 0001') # Canon S3 IS has no 'Small Fine JPEG'
camera.set_config(cfg)
# use camera
yield camera
except Exception as ex:
print(type(ex).__name__, ex)
finally:
# reset configuration
capturetarget_cfg.set_value(capturetarget)
imageformat_cfg.set_value(imageformat)
camera.set_config(cfg)
# free camera
camera.exit()
def empty_event_queue(camera):
while True:
type_, data = camera.wait_for_event(10)
#print(type_, data)
if type_ == gp.GP_EVENT_TIMEOUT:
return
if type_ == gp.GP_EVENT_FILE_ADDED:
# get a second image if camera is set to raw + jpeg
print('Unexpected new file', data.folder + data.name)
def main():
global shootingmode_cfg
with configured_camera() as camera:
cfg = camera.get_config()
shootingmode_cfg = cfg.get_child_by_name('shootingmode')
shootingmode = shootingmode_cfg.get_value()
exposurecompensation_cfg = cfg.get_child_by_name('exposurecompensation')
exposurecompensation = exposurecompensation_cfg.get_value()
print("{} {}: shootingmode '{}', exposurecompensation ro={}".format(time.time(), "Start", shootingmode, exposurecompensation_cfg.get_readonly()))
shootingmode_cfg.set_value("Manual")
camera.set_config(cfg)
cfg = camera.get_config()
shootingmode_cfg = cfg.get_child_by_name('shootingmode')
shootingmode = shootingmode_cfg.get_value()
exposurecompensation_cfg = cfg.get_child_by_name('exposurecompensation')
exposurecompensation = exposurecompensation_cfg.get_value()
oldecro = exposurecompensation_cfg.get_readonly()
man01ts = time.time()
print("{} {}: shootingmode '{}', exposurecompensation ro={}".format(man01ts, "After Manual 01", shootingmode, oldecro))
shootingmode_cfg.set_value("Auto")
camera.set_config(cfg)
# nothing - does not in itself get a fresh readonly value:
#cfg = camera.get_config()
#camera.set_config(cfg)
cfg = camera.get_config()
child_count = cfg.count_children()
testarr = []
for child in cfg.get_children():
child_type = child.get_type()
testarr.append("{} {}".format(child_type, child.get_name()))
#~ empty_event_queue(camera) # takes picture w/ Canon S3 IS (via wait_for_event)
cfg = camera.get_config()
shootingmode_cfg = cfg.get_child_by_name('shootingmode')
shootingmode = shootingmode_cfg.get_value()
exposurecompensation_cfg = cfg.get_child_by_name('exposurecompensation')
exposurecompensation = exposurecompensation_cfg.get_value()
ecro = exposurecompensation_cfg.get_readonly()
while (oldecro == ecro):
time.sleep(0.01)
cfg = camera.get_config() # ecro will not change value without this
exposurecompensation_cfg = cfg.get_child_by_name('exposurecompensation')
ecro = exposurecompensation_cfg.get_readonly()
print(ecro)
aut01ts = time.time()
print("{} {}: shootingmode '{}', exposurecompensation ro={} (delta={:.3f})".format(aut01ts, "After Auto 01", shootingmode, exposurecompensation_cfg.get_readonly(), aut01ts-man01ts))
return 0
if __name__ == "__main__":
sys.exit(main())
This is what it outputs:
$ python2 test-sm-ec2.py
1548364594.27 Start: shootingmode 'Auto', exposurecompensation ro=0
1548364596.54 After Manual 01: shootingmode 'Manual', exposurecompensation ro=1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
0
1548364598.68 After Auto 01: shootingmode 'Auto', exposurecompensation ro=0 (delta=2.139)
I've seen the delta
go as low as 1.188 sec, but usually it tends to be around 2 sec. EDIT: Also, going from "Auto" to "Manual" shootingmode
is fine (no delay/wait needed to see exposurecompensation ro change), its going from "Manual" to "Auto" that is a problem (?!)
Since with this I can get to the change of exposurecompensation
.readonly without using wait_for_event
- I do not need to worry about wait_for_event
taking a picture in this case, though it would be great to solve that too.
So I guess this solves my issue on the python side of things - though I'd love to hear if there are any ideas, so as to why do I experience this (they couldn't reproduce the issue with a different camera and my script over at https://github.com/gphoto/libgphoto2/issues/358)
I'm not sure if this is an issue with python-gphoto2 per se, but it is first where I've noticed it, so I thought, it wouldn't harm asking here first.
I've been testing
python-gphoto2
on Ubuntu 18.04 with a Canon S3 IS:On this camera,
shootingmode
is "Auto", thenexposurecompensation
should be a read/write property;shootingmode
is "Manual", thenexposurecompensation
should be a read-only property.For other properties, I'm usually able to just set them to a different value, and then can read them back and confirm the new value is set. However, if I change
shootingmode
, I have to wait at least 2 seconds before I can seeexposurecompensation
(or rather, its read-only property) updated.To work around this, I tried using wait_for_event, in the hopes that I'd get an event when
exposurecompensation
has been changed in response to the change ofshootingmode
, so I don't have totime.sleep
for an arbitrary value. However, this didn't end up working either, because for some reason,camera.wait_for_event
causes a picture to be taken - and if I had set up a exposure duration of say 8 seconds, it needs to wait for all those 8 seconds in order to complete!So I have in essence 2 questions:
exposurecompensation
's read-only property to change (and not more, that is, as soon as possible), in response to a change ofshootingmode
- without sleeping for arbitrary times (or usingwait_for_event
with the photo-taking problem):camera.wait_for_event
take a picture/photo? Shouldn't it just wait for an event? Can it be persuaded not to take a photo, but simply to wait for events?Here is the script,
test-sm-ec.py
:Here are the results of few invocations of the script - first, as posted:
As is, with SLEEPTIME = 1 - note the read-only property of the exposurecompensation property is not returned correctly after a sleep(1), but is correctly returned after wait_for_event, which however takes a picture (and may take even longer to wait out):
Here with SLEEPTIME = 2 and ENDWITHAUTO=1 (after calling the script once previously to set up an end Auto mode):
Same, with SLEEPTIME = 1 - again, the read-only property of the exposurecompensation property is not returned correctly after a sleep(1), but is correctly returned after wait_for_event, which however takes a picture (and may take even longer to wait out):