프로그래밍/Python

[Python] E4446A Spectrum Analyzer 화면캡쳐하기 (PyVISA)

채윤아빠 2023. 5. 2. 08:32
728x90
반응형

개요

PyVISA를 이용하여 E4446A Spectrum Analyzer 계측기의 현재 화면을 그대로 캡쳐하여 가져오는 방법을 알아 보도록 하겠습니다.


SCPI 명령을 이용한 화면캡쳐하기

아래는 E4446A Spectrum Analyzer 계측기의 현재 화면을 캡쳐하여 가져와 파일로 저장하는 코드입니다.

from pyvisa import ResourceManager

_host = '192.168.0.47'
_port = 5025

rm = ResourceManager() # visa 객체를 생성합니다.

# 지정한 HOST와 PORT를 사용하여 서버에 접속합니다. 
psa_client = rm.open_resource(f'TCPIP{_port}::{_host}::INSTR')

print (psa_client.query('*IDN?')) # 기기 정보를 출력합니다.

psa_client.write(f"MMEM:STORE:SCREEN 'C:TEMP.GIF'") # PSA screenshot
# img = psa_client.query_binary_values('HCOPy:SDUMp:DATA?') # 이진 데이터를 가져오기는 하지만, 변환 어려움
psa_client.write("MMEM:DATA? 'C:TEMP.GIF'")
img = psa_client.read_raw()

header_index = img.find(b'GIF')
if (header_index > 0): # find GIF header
    img = img[header_index:]

# 화면 캡쳐 파일 저장하기
with open('psa.gif', 'wb') as f:
    f.write(img)

위 코드에서 "MMEM:STORE:SCREEN 'C:TEMP.GIF'" 명령을 보내면, 스펙트럼의 현재 화면을 'TEMP.GIF' 파일로 저장하게 됩니다.

 

이제 스펙트럼 내부에 저장된 캡쳐 파일을 받아오면 되는데, 이 때 사용하는 명령이 "MMEM:DATA? 'C:TEMP.GIF'" 입니다.

일반적으로 visa에서 명령에 대한 결과를 받을 때는 query() 함수를 이용하게 되는데, 이 함수는 아스키 문자열일 경우에는 문제가 없으나, 이미지 파일과 같은 바이너리 데이터를 받으려 할 때는 오류가 발생합니다. 그래서 query() 함수를 이용하지 않고, write() 함수와 read_raw() 함수를 조합하면 바이너리 데이터를 받아올 수 있습니다.

 

문제는 read_raw() 함수를 이용하여 받은 바이너리 데이터(bytes)의 헤더에는 바이너리 데이터에 대한 길이 정보가 문자열로 포함되어 있어서 이를 직접 파싱해 주어야 합니다. 보통은 "#512345"와 같은 형식의 헤더가 붙는데, "#5"는 헤더라는 의미고 나머지 "12345"가 뒤따라올 바이너리 데이터의 길이가 됩니다.

 

일일이 파싱을 해도 되지만, GIF 캡쳐 파일을 받는 경우이므로, 바이너리로 "GIF"를 찾으면 이 부분이 이미지 파일의 시작과 동일하여 찾은 부분부터 끝까지 이미지 파일로 저장하도록 하였습니다.

 

SCPI 명령에 대한 상세한 설명은 E4446A Spectrum Analyzer 계측기에 대한 Programer's Guide 문서를 참고하시기 바랍니다.