Fix captures 2/3 perdues + miroir + stabilite camera post-prise
- post_capture_grace=10 : ignore les erreurs -52 transitoires juste apres une prise (Canon EOS a besoin ~1s pour stabiliser le capteur) - Threshold abandon capture : 3 -> 8 erreurs consecutives - Threshold reconnexion : 5 -> 10 erreurs consecutives - Avant chaque prise : eosviewfinder=1 pour garantir miroir leve - Apres prise : viewfinder relance + sleep 1s + drain 8 evenements - Sim auto-detect : pas de USB reset (evite boucle -52), verification fonctionnelle avec un capture_preview() avant de valider la camera - Sim poll : 15s au lieu de 10s Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -753,22 +753,30 @@ class PB:
|
|||||||
# ── Thread caméra ────────────────────────────────────────────────────────
|
# ── Thread caméra ────────────────────────────────────────────────────────
|
||||||
def _cam_loop(self):
|
def _cam_loop(self):
|
||||||
errs = 0
|
errs = 0
|
||||||
|
post_capture_grace = 0 # frames de grâce après une prise (ignore erreurs transitoires)
|
||||||
while True:
|
while True:
|
||||||
# En simulation : tentative de connexion automatique toutes les 10s
|
# En simulation : tentative de connexion automatique toutes les 15s
|
||||||
|
# Pas de USB reset ici — reset seulement en cas de reconnexion
|
||||||
if self.sim:
|
if self.sim:
|
||||||
time.sleep(10)
|
time.sleep(15)
|
||||||
_usb_reset_done()
|
|
||||||
for _ in range(2):
|
for _ in range(2):
|
||||||
try:
|
try:
|
||||||
c = gp.Camera(); c.init()
|
c = gp.Camera(); c.init()
|
||||||
|
# Vérification fonctionnelle : un preview doit réussir
|
||||||
|
_f = c.capture_preview(); _bytes = bytes(_f.get_data_and_size())
|
||||||
if self.cam:
|
if self.cam:
|
||||||
try: self.cam.exit()
|
try: self.cam.exit()
|
||||||
except: pass
|
except: pass
|
||||||
self.cam = c; self.sim = False; self.prev_actif = True
|
self.cam = c; self.sim = False; self.prev_actif = True
|
||||||
|
surf = pygame.image.load(io.BytesIO(_bytes))
|
||||||
|
surf = pygame.transform.scale(surf, (W, H))
|
||||||
|
with self.flock: self.frame = surf
|
||||||
print("DSLR détecté automatiquement")
|
print("DSLR détecté automatiquement")
|
||||||
break
|
break
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"Auto-detect caméra: {e}")
|
print(f"Auto-detect caméra: {e}")
|
||||||
|
try: c.exit()
|
||||||
|
except: pass
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
continue
|
continue
|
||||||
if self.prev_actif:
|
if self.prev_actif:
|
||||||
@@ -776,8 +784,15 @@ class PB:
|
|||||||
if self.cam is None:
|
if self.cam is None:
|
||||||
raise RuntimeError("camera None")
|
raise RuntimeError("camera None")
|
||||||
if self.cap_demande:
|
if self.cap_demande:
|
||||||
# Déclenchement sans mouvement miroir :
|
# Avant la prise : activer le viewfinder EOS (miroir levé, liveview ON)
|
||||||
# eosremoterelease garde le LV actif sur Canon EOS
|
try:
|
||||||
|
cfg_c = self.cam.get_config()
|
||||||
|
vf = cfg_c.get_child_by_name('eosviewfinder')
|
||||||
|
vf.set_value(1)
|
||||||
|
self.cam.set_config(cfg_c)
|
||||||
|
time.sleep(0.2)
|
||||||
|
except: pass
|
||||||
|
# Déclenchement obturateur seul via eosremoterelease
|
||||||
triggered = False
|
triggered = False
|
||||||
try:
|
try:
|
||||||
cfg_c = self.cam.get_config()
|
cfg_c = self.cam.get_config()
|
||||||
@@ -805,21 +820,42 @@ class PB:
|
|||||||
rl.set_value('None')
|
rl.set_value('None')
|
||||||
self.cam.set_config(cfg_c)
|
self.cam.set_config(cfg_c)
|
||||||
except: pass
|
except: pass
|
||||||
|
# Relance le viewfinder et laisse le capteur se stabiliser
|
||||||
|
try:
|
||||||
|
cfg_c = self.cam.get_config()
|
||||||
|
vf = cfg_c.get_child_by_name('eosviewfinder')
|
||||||
|
vf.set_value(1)
|
||||||
|
self.cam.set_config(cfg_c)
|
||||||
|
except: pass
|
||||||
|
time.sleep(1.0) # stabilisation capteur Canon entre deux prises
|
||||||
|
# Drainer les événements résiduels
|
||||||
|
for _ in range(8):
|
||||||
|
try:
|
||||||
|
self.cam.wait_for_event(50)
|
||||||
|
except: break
|
||||||
self.cap_result=ch; self.cap_demande=False; self.cap_done.set()
|
self.cap_result=ch; self.cap_demande=False; self.cap_done.set()
|
||||||
errs = 0
|
errs = 0; post_capture_grace = 10
|
||||||
else:
|
else:
|
||||||
f=self.cam.capture_preview(); data=bytes(f.get_data_and_size())
|
f=self.cam.capture_preview(); data=bytes(f.get_data_and_size())
|
||||||
surf=pygame.image.load(io.BytesIO(data))
|
surf=pygame.image.load(io.BytesIO(data))
|
||||||
surf=pygame.transform.scale(surf,(W,H))
|
surf=pygame.transform.scale(surf,(W,H))
|
||||||
with self.flock: self.frame=surf
|
with self.flock: self.frame=surf
|
||||||
errs = 0
|
errs = 0
|
||||||
|
if post_capture_grace > 0:
|
||||||
|
post_capture_grace -= 1
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if post_capture_grace > 0:
|
||||||
|
# Erreurs transitoires post-capture normales sur EOS — on ignore
|
||||||
|
post_capture_grace -= 1
|
||||||
|
print(f"cam post-capture ({post_capture_grace} restants): {e}")
|
||||||
|
time.sleep(0.2)
|
||||||
|
else:
|
||||||
errs += 1
|
errs += 1
|
||||||
print(f"cam erreur ({errs}): {e}")
|
print(f"cam erreur ({errs}): {e}")
|
||||||
if self.cap_demande and errs >= 3:
|
if self.cap_demande and errs >= 8:
|
||||||
# abandon de la capture en cours
|
# abandon de la capture seulement après 8 erreurs consécutives
|
||||||
self.cap_result=None; self.cap_demande=False; self.cap_done.set()
|
self.cap_result=None; self.cap_demande=False; self.cap_done.set()
|
||||||
if errs >= 5:
|
if errs >= 10:
|
||||||
# reconnexion automatique
|
# reconnexion automatique
|
||||||
print("Caméra perdue — tentative de reconnexion...")
|
print("Caméra perdue — tentative de reconnexion...")
|
||||||
self.prev_actif = False
|
self.prev_actif = False
|
||||||
@@ -839,11 +875,10 @@ class PB:
|
|||||||
except Exception as re:
|
except Exception as re:
|
||||||
print(f"Reconnexion échouée ({_nb_retry+1}): {re}")
|
print(f"Reconnexion échouée ({_nb_retry+1}): {re}")
|
||||||
else:
|
else:
|
||||||
# 10 tentatives échouées → bascule en simulation
|
|
||||||
self.sim = True
|
self.sim = True
|
||||||
print("Caméra introuvable → mode simulation")
|
print("Caméra introuvable → mode simulation")
|
||||||
else:
|
else:
|
||||||
time.sleep(0.1)
|
time.sleep(0.2)
|
||||||
else:
|
else:
|
||||||
time.sleep(0.05)
|
time.sleep(0.05)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user