agrobot_base/Python/gal5000/probe_params.py

343 lines
13 KiB
Python
Raw Normal View History

2026-01-28 18:05:51 +00:00
import os
import ctypes as C
from ctypes import wintypes as W
# =========================
# CONFIG
# =========================
SDK_DIR = os.path.join(os.path.dirname(__file__), "dlls")
DLL_NAME = "VT_SDK64.dll"
TIMEOUT_MS = 2000
WINDOW_NAME = "GAL5000 4CH Preview (E=AEC toggle, G=AGC toggle, Q=quit)"
# Camera scan/open
DEVICE_UDEF = 0
DEVICE_INDEX = 0
DATA_RAW = 0
# RAW geometry (como você já capturou)
RAW_W = 2592
RAW_H = 2056
# Bayer+NIR pattern (2x2):
# R G
# IR B
# => R = [0::2,0::2], G=[0::2,1::2], IR=[1::2,0::2], B=[1::2,1::2]
# =========================
# PARAM IDs (VT_Param.h)
# =========================
BUF_SIZE = 256
# PARAM_VALUETYPE
VALUE_INT = 0
VALUE_FLOAT = 1
VALUE_STR = 2
# =========================
# PARAM IDs (recorte útil do VT_Param.h)
# =========================
# COMMON / Display interno
PARAM_ID_COMMON_DISPLAYENABLE = 0x00000200
PARAM_ID_COMMON_DISPLAYHWND = 0x00000201
PARAM_ID_COMMON_DISPLAYVSYNC = 0x00000202
PARAM_ID_COMMON_DISPLAYFPS = 0x00000203
PARAM_ID_COMMON_DISPLAYWIDTH = 0x00000204
PARAM_ID_COMMON_DISPLAYHEIGHT = 0x00000205
PARAM_ID_COMMON_DISPLAYPOSX = 0x00000206
PARAM_ID_COMMON_DISPLAYPOSY = 0x00000207
# SFNC Device info
PARAM_ID_SFNC_DEVICETYPE = 0x00001001
PARAM_ID_SFNC_DEVICESCANTYPE = 0x00001002
PARAM_ID_SFNC_DEVICEVENDORNAME = 0x00001003
PARAM_ID_SFNC_DEVICEMODELNAME = 0x00001004
PARAM_ID_SFNC_DEVICEFAMILYNAME = 0x00001005
PARAM_ID_SFNC_DEVICEMANUFACTURERINFO = 0x00001006
PARAM_ID_SFNC_DEVICEVERSION = 0x00001007
PARAM_ID_SFNC_DEVICEFIRMWAREVERSION = 0x00001008
PARAM_ID_SFNC_DEVICESERIALNUMBER = 0x00001009
PARAM_ID_SFNC_DEVICEUSERID = 0x0000100B
# SFNC image format / ROI
PARAM_ID_SFNC_SENSORWIDTH = 0x00001101
PARAM_ID_SFNC_SENSORHEIGHT = 0x00001102
PARAM_ID_SFNC_WIDTHMAX = 0x00001106
PARAM_ID_SFNC_HEIGHTMAX = 0x00001107
PARAM_ID_SFNC_WIDTH = 0x00001111
PARAM_ID_SFNC_HEIGHT = 0x00001112
PARAM_ID_SFNC_OFFSETX = 0x00001113
PARAM_ID_SFNC_OFFSETY = 0x00001114
# SFNC Acquisition / Trigger / Exposure
PARAM_ID_SFNC_ACQUISITIONFRAMERATEENABLE = 0x00001209
PARAM_ID_SFNC_ACQUISITIONLINERATE = 0x0000120A
PARAM_ID_SFNC_ACQUISITIONLINERATEENABLE = 0x0000120B
PARAM_ID_SFNC_TRIGGERSELECTOR = 0x0000120E
PARAM_ID_SFNC_TRIGGERMODE = 0x0000120F
PARAM_ID_SFNC_TRIGGERSOFTWARE = 0x00001210
PARAM_ID_SFNC_TRIGGERSOURCE = 0x00001211
PARAM_ID_SFNC_TRIGGERACTIVATION = 0x00001212
PARAM_ID_SFNC_TRIGGERDELAY = 0x00001214
PARAM_ID_SFNC_TRIGGERDIVIDER = 0x00001215
PARAM_ID_SFNC_TRIGGERMULTIPLIER = 0x00001216
PARAM_ID_SFNC_EXPOSUREMODE = 0x00001217
PARAM_ID_SFNC_EXPOSURETIMEMODE = 0x00001218
PARAM_ID_SFNC_EXPOSURETIMESELECTOR = 0x00001219
PARAM_ID_SFNC_EXPOSURETIME = 0x0000121A
PARAM_ID_SFNC_EXPOSUREAUTO = 0x0000121B
# SENSOR (ROI + Exposure/Gain, etc)
PARAM_ID_SENSOR_OFFSETV = 0x00003001
PARAM_ID_SENSOR_WIDTH = 0x00003002
PARAM_ID_SENSOR_HEIGHT = 0x00003003
PARAM_ID_SENSOR_BLANKINGH = 0x00003004
PARAM_ID_SENSOR_BLANKINGV = 0x00003005
PARAM_ID_SENSOR_EXPOSURETIMERAW = 0x00003010
PARAM_ID_SENSOR_EXPOSUREAUTOENABLE = 0x00003011
PARAM_ID_SENSOR_GAINANALOGRAW = 0x00003020
PARAM_ID_SENSOR_GAINANALOGAUTOENABLE = 0x00003021
PARAM_ID_SENSOR_GAINANALOGAGCMAX = 0x00003022
PARAM_ID_SENSOR_GAINDIGITRAW = 0x0000302A
PARAM_ID_SENSOR_GAINDIGITAUTOENABLE = 0x0000302B
PARAM_ID_SENSOR_GAINDIGITAGCMAX = 0x0000302C
PARAM_ID_SENSOR_BITLUT = 0x00003040
# IPU (Image Process Unit)
PARAM_ID_IPU_BRIGHTNESS = 0x00003100
PARAM_ID_IPU_CONTRAST = 0x00003101
# GRAB (imagem / stream)
PARAM_ID_GRAB_FRAMERATE = 0x00005001
# =========================
# TABELA DE PROBE
# (nome, id, tipo do VALUE_*)
# =========================
PARAMS_TO_PROBE = [
# COMMON display
("COMMON_DISPLAYENABLE", PARAM_ID_COMMON_DISPLAYENABLE, VALUE_INT),
("COMMON_DISPLAYVSYNC", PARAM_ID_COMMON_DISPLAYVSYNC, VALUE_INT),
("COMMON_DISPLAYFPS", PARAM_ID_COMMON_DISPLAYFPS, VALUE_FLOAT),
("COMMON_DISPLAYWIDTH", PARAM_ID_COMMON_DISPLAYWIDTH, VALUE_INT),
("COMMON_DISPLAYHEIGHT", PARAM_ID_COMMON_DISPLAYHEIGHT, VALUE_INT),
("COMMON_DISPLAYPOSX", PARAM_ID_COMMON_DISPLAYPOSX, VALUE_INT),
("COMMON_DISPLAYPOSY", PARAM_ID_COMMON_DISPLAYPOSY, VALUE_INT),
# Device info
("SFNC_DEVICETYPE", PARAM_ID_SFNC_DEVICETYPE, VALUE_INT),
("SFNC_DEVICESCANTYPE", PARAM_ID_SFNC_DEVICESCANTYPE, VALUE_INT),
("SFNC_DEVICEVENDORNAME", PARAM_ID_SFNC_DEVICEVENDORNAME, VALUE_STR),
("SFNC_DEVICEMODELNAME", PARAM_ID_SFNC_DEVICEMODELNAME, VALUE_STR),
("SFNC_DEVICEFAMILYNAME", PARAM_ID_SFNC_DEVICEFAMILYNAME, VALUE_STR),
("SFNC_DEVICEVERSION", PARAM_ID_SFNC_DEVICEVERSION, VALUE_STR),
("SFNC_DEVICEFIRMWAREVERSION",PARAM_ID_SFNC_DEVICEFIRMWAREVERSION, VALUE_STR),
("SFNC_DEVICESERIALNUMBER", PARAM_ID_SFNC_DEVICESERIALNUMBER, VALUE_STR),
("SFNC_DEVICEUSERID", PARAM_ID_SFNC_DEVICEUSERID, VALUE_STR),
# SFNC ROI / image
("SFNC_SENSORWIDTH", PARAM_ID_SFNC_SENSORWIDTH, VALUE_INT),
("SFNC_SENSORHEIGHT", PARAM_ID_SFNC_SENSORHEIGHT, VALUE_INT),
("SFNC_WIDTHMAX", PARAM_ID_SFNC_WIDTHMAX, VALUE_INT),
("SFNC_HEIGHTMAX", PARAM_ID_SFNC_HEIGHTMAX, VALUE_INT),
("SFNC_WIDTH", PARAM_ID_SFNC_WIDTH, VALUE_INT),
("SFNC_HEIGHT", PARAM_ID_SFNC_HEIGHT, VALUE_INT),
("SFNC_OFFSETX", PARAM_ID_SFNC_OFFSETX, VALUE_INT),
("SFNC_OFFSETY", PARAM_ID_SFNC_OFFSETY, VALUE_INT),
# SFNC acquisition / trigger / exposure
("SFNC_ACQFRAMERATEENABLE", PARAM_ID_SFNC_ACQUISITIONFRAMERATEENABLE, VALUE_INT),
("SFNC_ACQLINERATE", PARAM_ID_SFNC_ACQUISITIONLINERATE, VALUE_FLOAT),
("SFNC_ACQLINERATEENABLE", PARAM_ID_SFNC_ACQUISITIONLINERATEENABLE, VALUE_INT),
("SFNC_TRIGGERSELECTOR", PARAM_ID_SFNC_TRIGGERSELECTOR, VALUE_INT),
("SFNC_TRIGGERMODE", PARAM_ID_SFNC_TRIGGERMODE, VALUE_INT),
("SFNC_TRIGGERSOFTWARE", PARAM_ID_SFNC_TRIGGERSOFTWARE, VALUE_INT),
("SFNC_TRIGGERSOURCE", PARAM_ID_SFNC_TRIGGERSOURCE, VALUE_INT),
("SFNC_TRIGGERACTIVATION", PARAM_ID_SFNC_TRIGGERACTIVATION, VALUE_INT),
("SFNC_TRIGGERDELAY", PARAM_ID_SFNC_TRIGGERDELAY, VALUE_FLOAT),
("SFNC_TRIGGERDIVIDER", PARAM_ID_SFNC_TRIGGERDIVIDER, VALUE_INT),
("SFNC_TRIGGERMULTIPLIER", PARAM_ID_SFNC_TRIGGERMULTIPLIER, VALUE_INT),
("SFNC_EXPOSUREMODE", PARAM_ID_SFNC_EXPOSUREMODE, VALUE_INT),
("SFNC_EXPOSURETIMEMODE", PARAM_ID_SFNC_EXPOSURETIMEMODE, VALUE_INT),
("SFNC_EXPOSURETIMESELECTOR",PARAM_ID_SFNC_EXPOSURETIMESELECTOR, VALUE_INT),
("SFNC_EXPOSURETIME", PARAM_ID_SFNC_EXPOSURETIME, VALUE_FLOAT),
("SFNC_EXPOSUREAUTO", PARAM_ID_SFNC_EXPOSUREAUTO, VALUE_INT),
# SENSOR ROI + gains
("SENSOR_OFFSETV", PARAM_ID_SENSOR_OFFSETV, VALUE_INT),
("SENSOR_WIDTH", PARAM_ID_SENSOR_WIDTH, VALUE_INT),
("SENSOR_HEIGHT", PARAM_ID_SENSOR_HEIGHT, VALUE_INT),
("SENSOR_BLANKINGH", PARAM_ID_SENSOR_BLANKINGH, VALUE_INT),
("SENSOR_BLANKINGV", PARAM_ID_SENSOR_BLANKINGV, VALUE_INT),
("SENSOR_EXPOSURETIMERAW", PARAM_ID_SENSOR_EXPOSURETIMERAW, VALUE_INT),
("SENSOR_EXPOSUREAUTOENABLE",PARAM_ID_SENSOR_EXPOSUREAUTOENABLE, VALUE_INT),
("SENSOR_GAINANALOGRAW", PARAM_ID_SENSOR_GAINANALOGRAW, VALUE_INT),
("SENSOR_GAINANALOGAUTOENABLE",PARAM_ID_SENSOR_GAINANALOGAUTOENABLE, VALUE_INT),
("SENSOR_GAINANALOGAGCMAX", PARAM_ID_SENSOR_GAINANALOGAGCMAX, VALUE_INT),
("SENSOR_GAINDIGITRAW", PARAM_ID_SENSOR_GAINDIGITRAW, VALUE_INT),
("SENSOR_GAINDIGITAUTOENABLE",PARAM_ID_SENSOR_GAINDIGITAUTOENABLE, VALUE_INT),
("SENSOR_GAINDIGITAGCMAX", PARAM_ID_SENSOR_GAINDIGITAGCMAX, VALUE_INT),
("SENSOR_BITLUT", PARAM_ID_SENSOR_BITLUT, VALUE_INT),
# IPU
("IPU_BRIGHTNESS", PARAM_ID_IPU_BRIGHTNESS, VALUE_INT),
("IPU_CONTRAST", PARAM_ID_IPU_CONTRAST, VALUE_INT),
# Grab
("GRAB_FRAMERATE", PARAM_ID_GRAB_FRAMERATE, VALUE_FLOAT),
]
# =========================
# STRUCTS (mínimo necessário)
# =========================
class VT_FRAMEINFO(C.Structure):
_fields_ = [
("lFrameID", W.DWORD),
("lBufSize", W.DWORD),
("lWidth", W.DWORD),
("lHeight", W.DWORD),
("lPixBits", C.c_ubyte),
("_pad0", C.c_ubyte * 3),
("pBufPtr", C.POINTER(C.c_ubyte)),
("lFrameStatus", W.DWORD),
("lPixType", W.DWORD),
("lTimeStamp", W.DWORD),
("_reserve", W.DWORD * 8),
]
class VT_DEVPARAM(C.Structure):
_fields_ = [
("bUseName", W.BOOL),
("lParamByID", W.DWORD),
("lParamByName", C.c_char * BUF_SIZE),
]
def devparam_by_id(pid: int) -> VT_DEVPARAM:
p = VT_DEVPARAM()
p.bUseName = False
p.lParamByID = pid
p.lParamByName = b"" # <- CORRETO: bytes (fica zerado / string vazia)
return p
# =========================
# DLL LOAD + prototypes
# =========================
os.add_dll_directory(SDK_DIR)
dll = C.WinDLL(os.path.join(SDK_DIR, DLL_NAME))
print("DLL carregada OK:", dll)
dll.VT_DeviceScan.argtypes = [C.POINTER(C.c_ubyte), C.c_int]
dll.VT_DeviceScan.restype = C.c_int
dll.VT_DeviceOpen.argtypes = [C.c_void_p, C.POINTER(W.HANDLE), C.c_int, C.c_int]
dll.VT_DeviceOpen.restype = C.c_int
dll.VT_SingleFrameCapture.argtypes = [W.HANDLE, C.POINTER(VT_FRAMEINFO), C.c_int, C.c_int, W.BOOL]
dll.VT_SingleFrameCapture.restype = C.c_int
dll.VT_DeviceClose.argtypes = [C.POINTER(W.HANDLE)]
dll.VT_DeviceClose.restype = C.c_int
# Param API
dll.VT_ParamGetValue.argtypes = [W.HANDLE, VT_DEVPARAM, C.c_void_p, C.c_int]
dll.VT_ParamGetValue.restype = C.c_int
dll.VT_ParamSetValue.argtypes = [W.HANDLE, VT_DEVPARAM, C.c_void_p, C.c_int]
dll.VT_ParamSetValue.restype = C.c_int
def ck(ret: int, name: str):
if ret != 0:
print(f"{name} falhou, ret={ret}")
raise RuntimeError(f"{name} falhou, ret={ret}")
def param_get_int(h: W.HANDLE, pid: int) -> int:
p = devparam_by_id(pid)
v = C.c_int(0)
ret = dll.VT_ParamGetValue(h, p, C.byref(v), VALUE_INT)
ck(ret, f"VT_ParamGetValue({hex(pid)})")
return int(v.value)
def param_get_float(h: W.HANDLE, pid: int) -> float:
p = devparam_by_id(pid)
v = C.c_float(0)
ret = dll.VT_ParamGetValue(h, p, C.byref(v), VALUE_FLOAT)
ck(ret, f"VT_ParamGetValue({hex(pid)})")
return float(v.value)
def param_get_str(h: W.HANDLE, pid: int) -> str:
p = devparam_by_id(pid)
# buffer de tamanho razoável (ajusta se precisar)
buf_size = 256
buf = C.create_string_buffer(buf_size)
ret = dll.VT_ParamGetValue(h, p, buf, VALUE_STR)
ck(ret, f"VT_ParamGetValue({hex(pid)})")
# strip em caso de lixo no final
return buf.value.decode(errors="ignore").strip()
def param_supported(h, pid, vtype):
p = devparam_by_id(pid)
minv = C.c_int()
maxv = C.c_int()
inc = C.c_int()
ret = dll.VT_ParamGetRange(h, p,
C.byref(minv),
C.byref(maxv),
C.byref(inc),
vtype)
return ret == 0
def probe_params(h: W.HANDLE):
print("\n==== PARAM PROBE (VT SDK) ====")
print(f"{'Name':35s} {'ID':10s} {'Supported':10s} Value")
print("-" * 70)
for name, pid, vtype in PARAMS_TO_PROBE:
supported = param_supported(h, pid, vtype)
if not supported:
print(f"{name:35s} {hex(pid):10s} {'NO':10s} -")
continue
# tentar ler o valor atual
try:
if vtype == VALUE_INT:
val = param_get_int(h, pid)
elif vtype == VALUE_FLOAT:
val = param_get_float(h, pid)
elif vtype == VALUE_STR:
val = param_get_str(h, pid)
else:
val = "<unknown type>"
print(f"{name:35s} {hex(pid):10s} {'YES':10s} {val}")
except Exception as e:
print(f"{name:35s} {hex(pid):10s} {'YES':10s} <get error: {e}>")
def main():
# scan
n = C.c_ubyte(0)
ret = dll.VT_DeviceScan(C.byref(n), DEVICE_UDEF)
ck(ret, "VT_DeviceScan")
if n.value == 0:
raise RuntimeError("Nenhuma câmera encontrada.")
# open
idx = C.c_ubyte(0)
h = W.HANDLE()
ret = dll.VT_DeviceOpen(C.byref(idx), C.byref(h), DEVICE_INDEX, DEVICE_UDEF)
ck(ret, "VT_DeviceOpen")
print("DeviceOpen OK, handle=", h.value)
probe_params(h)
if __name__ == "__main__":
main()