From 6e308647c5540c080fdc4fe808395a298f4649b9 Mon Sep 17 00:00:00 2001 From: "CSSC-WORK\\murmur" Date: Wed, 4 Dec 2024 20:27:46 +0800 Subject: [PATCH] =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E2=80=9Cscpi=E6=8C=87?= =?UTF-8?q?=E4=BB=A4=E7=BC=96=E8=BE=91=E5=8A=9F=E8=83=BD=E2=80=9D=E7=A4=BA?= =?UTF-8?q?=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- visa-scpi-example/File.cpp | 153 ++++++++++++++++++++++++++++++++ visa-scpi-example/File.inp | 35 ++++++++ visa-scpi-example/File.py | 109 +++++++++++++++++++++++ visa-scpi-example/commands.json | 9 ++ visa-scpi-example/comments.json | 9 ++ visa-scpi-example/index.html | 153 ++++++++++++++++++++++++++++++++ visa-scpi-example/parse_inp.py | 55 ++++++++++++ visa-scpi-example/server.py | 43 +++++++++ 8 files changed, 566 insertions(+) create mode 100644 visa-scpi-example/File.cpp create mode 100644 visa-scpi-example/File.inp create mode 100644 visa-scpi-example/File.py create mode 100644 visa-scpi-example/commands.json create mode 100644 visa-scpi-example/comments.json create mode 100644 visa-scpi-example/index.html create mode 100644 visa-scpi-example/parse_inp.py create mode 100644 visa-scpi-example/server.py diff --git a/visa-scpi-example/File.cpp b/visa-scpi-example/File.cpp new file mode 100644 index 0000000..8c3daaf --- /dev/null +++ b/visa-scpi-example/File.cpp @@ -0,0 +1,153 @@ +// C++ script created by FSW: 04:12:2024 14:23:36 + +#include +#include +#include + +// forward declarations +static bool write_command(const ViSession& handle, const std::string& command); +static bool write_query(const ViSession& handle, const std::string& query, ViPBuf result_buffer, const ViUInt32 buffer_size, ViPUInt32 read_count = nullptr); +static bool process_system_error(const ViSession& handle); +static unsigned char get_esr(const ViSession& handle); + + +static ViSession g_analyzer; + +// assign your own variables +static ViByte g_result[1000000]; + + +static bool write_command( const ViSession& handle, const std::string& command ) +{ + ViStatus status = viWrite(handle, (ViBuf)command.c_str(), command.length(), VI_NULL); + + // return true if successful + return ((status >= VI_SUCCESS) && process_system_error(handle)); +} + +static bool write_query( const ViSession& handle, const std::string& query, ViPBuf result_buffer, const ViUInt32 buffer_size, ViPUInt32 read_count ) +{ + ViStatus status = viWrite(handle, (ViBuf)query.c_str(), query.length(), VI_NULL); + if (status >= VI_SUCCESS) + { + status = viRead(handle, result_buffer, buffer_size, read_count); + } + // return true if successful + return ((status >= VI_SUCCESS) && process_system_error(handle)); +} + +static bool process_system_error(const ViSession& handle) +{ + bool success = true; + const unsigned char EsrErrorMask = 0x3C; + + if ((get_esr(handle) & EsrErrorMask) != 0) + { + char err_buf[256]; + ViUInt32 readCount; + viWrite(handle, (ViBuf)":SYST:ERR?", 10, VI_NULL); + viRead(handle, (ViPBuf)err_buf, sizeof(err_buf), &readCount); + err_buf[readCount] = '\0'; + std::cout << err_buf << std::endl; + viWrite(handle, (ViBuf)"*CLS", 4, VI_NULL); + success = false; + } + return success; +} + +static unsigned char get_esr(const ViSession& handle) +{ + char esr_buf[16]; + ViUInt32 readCount; + viWrite(handle, (ViBuf)"*ESR?", 5, VI_NULL); + viRead(handle, (ViPBuf)esr_buf, sizeof(esr_buf), &readCount); + esr_buf[readCount] = '\0'; + return (static_cast(std::stoi(std::string(esr_buf)))); +} + + +int main () +{ + ViSession defaultRM; + bool success = true; + + // create a VISA session and return a handle to it + viOpenDefaultRM(&defaultRM); + // create a VISA session to the connected device and return a handle to it + viOpen(defaultRM, (ViRsrc)"TCPIP::169.254.177.77::inst0::INSTR", VI_NULL, VI_NULL, &g_analyzer); + + success = write_command( g_analyzer, "*RST" ); + + success = write_command( g_analyzer, "*CLS" ); + + success = write_command( g_analyzer, ":SYST:DISP:UPD ON" ); + + success = write_command( g_analyzer, ":INIT:CONT OFF" ); + + success = write_command( g_analyzer, ":SENS:FREQ:STAR 1000000000" ); + + success = write_command( g_analyzer, ":SENS:FREQ:STOP 2000000000" ); + + success = write_command( g_analyzer, ":DISP:WIND:TRAC:Y:SCAL:RLEV -30" ); + + success = write_command( g_analyzer, ":DISP:WIND:TRAC:Y:SCAL:RLEV 30" ); + + success = write_command( g_analyzer, ":SENS:BAND:RES:AUTO OFF" ); + + success = write_command( g_analyzer, ":SENS:BAND:RES:AUTO ON" ); + + success = write_command( g_analyzer, ":SENS:BAND:VID:AUTO OFF" ); + + success = write_command( g_analyzer, ":SENS:BAND:VID:AUTO ON" ); + + success = write_command( g_analyzer, ":SENS:FREQ:MODE SWE" ); + + success = write_command( g_analyzer, ":DISP:WIND1:SIZE LARG" ); + + success = write_command( g_analyzer, ":CALC1:MARK1:FUNC:STR:STAT ON" ); + + success = write_command( g_analyzer, ":CALC1:MARK1:FUNC:STR:STAT OFF" ); + + success = write_command( g_analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ); + + success = write_command( g_analyzer, ":SENS:POW:ACH:BAND:CHAN 300000" ); + + success = write_command( g_analyzer, ":SENS:POW:ACH:PRES CN" ); + + success = write_command( g_analyzer, ":CALC:MARK1:STAT ON" ); + + success = write_command( g_analyzer, ":CALC:MARK1:X 1200000000" ); + + success = write_command( g_analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ); + + success = write_command( g_analyzer, ":SENS:POW:ACH:PRES CN" ); + + success = write_command( g_analyzer, ":SENS:POW:ACH:PRES CN" ); + + success = write_command( g_analyzer, ":CALC:MARK:FUNC:POW:SEL CN0" ); + + success = write_command( g_analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ); + + success = write_command( g_analyzer, ":SENS:FREQ:SPAN 1000000" ); + + success = write_command( g_analyzer, ":SENS:FREQ:SPAN 1000000000" ); + + success = write_command( g_analyzer, ":CALC:MARK1:STAT ON" ); + + success = write_command( g_analyzer, ":CALC:MARK1:X 1200000000" ); + + success = write_command( g_analyzer, ":CALC:DELT2:STAT ON" ); + + success = write_command( g_analyzer, ":CALC:DELT2:X 1600000000" ); + + success = write_command( g_analyzer, ":INIT:SPUR" ); + + success = write_command( g_analyzer, ":MMEM:NAME 'C:\R_S\Instr\user\FSW_ScreenShot_2024-12-04_14-22-12.PNG'" ); + + success = write_command( g_analyzer, ":HCOP:IMM1" ); + + viClose(g_analyzer); + viClose(defaultRM); + + return 0; +} diff --git a/visa-scpi-example/File.inp b/visa-scpi-example/File.inp new file mode 100644 index 0000000..7bc1fb0 --- /dev/null +++ b/visa-scpi-example/File.inp @@ -0,0 +1,35 @@ +*RST +*CLS +:SYST:DISP:UPD ON +:INIT:CONT OFF +:SENS:FREQ:STAR 1000000000 +:SENS:FREQ:STOP 2000000000 +:DISP:WIND:TRAC:Y:SCAL:RLEV 0 +:DISP:WIND:TRAC:Y:SCAL:RLEV 0 +:SENS:BAND:RES:AUTO OFF +:SENS:BAND:RES:AUTO ON +:SENS:BAND:VID:AUTO OFF +:SENS:BAND:VID:AUTO ON +:SENS:FREQ:MODE SWE +:DISP:WIND1:SIZE LARG +:CALC1:MARK1:FUNC:STR:STAT ON +:CALC1:MARK1:FUNC:STR:STAT OFF +:CALC:MARK:FUNC:POW:SEL CN +:SENS:POW:ACH:BAND:CHAN 300000 +:SENS:POW:ACH:PRES CN +:CALC:MARK1:STAT ON +:CALC:MARK1:X 1200000000 +:CALC:MARK:FUNC:POW:SEL CN +:SENS:POW:ACH:PRES CN +:SENS:POW:ACH:PRES CN +:CALC:MARK:FUNC:POW:SEL CN0 +:CALC:MARK:FUNC:POW:SEL CN +:SENS:FREQ:SPAN 1000000 +:SENS:FREQ:SPAN 1000000000 +:CALC:MARK1:STAT ON +:CALC:MARK1:X 1200000000 +:CALC:DELT2:STAT ON +:CALC:DELT2:X 1600000000 +:INIT:SPUR +:MMEM:NAME 'C:\R_S\Instr\user\FSW_ScreenShot_2024-12-04_14-22-12.PNG' +:HCOP:IMM1 \ No newline at end of file diff --git a/visa-scpi-example/File.py b/visa-scpi-example/File.py new file mode 100644 index 0000000..9b88270 --- /dev/null +++ b/visa-scpi-example/File.py @@ -0,0 +1,109 @@ +# python script created by FSW: 04:12:2024 14:23:54 + +import pyvisa as visa + +def write_command(instrument, command) : + instrument.write(command) + return process_system_error(instrument) + +def write_query(instrument, command) : + buffer = instrument.query(command) + bSuccess = process_system_error(instrument) + return bSuccess, buffer + +def process_system_error(instrument) : + bSuccess = True + EsrErrorMask = 0x3C + if ((get_esr(instrument) & EsrErrorMask) != 0) : + print(instrument.query(":SYST:ERR?")) + instrument.write("*CLS") + bSuccess = False + return bSuccess + +def get_esr(instrument) : + esr = instrument.query("*ESR?") + return int(esr) + + +VisaResourceManager = visa.ResourceManager() + +# connect to analyzer +Analyzer = VisaResourceManager.open_resource("TCPIP::169.254.177.77::inst0::INSTR") + +success = write_command( Analyzer, "*RST" ) + +success = write_command( Analyzer, "*CLS" ) + +success = write_command( Analyzer, ":SYST:DISP:UPD ON" ) + +success = write_command( Analyzer, ":INIT:CONT OFF" ) + +success = write_command( Analyzer, ":SENS:FREQ:STAR 1000000000" ) + +success = write_command( Analyzer, ":SENS:FREQ:STOP 2000000000" ) + +success = write_command( Analyzer, ":DISP:WIND:TRAC:Y:SCAL:RLEV -30" ) + +success = write_command( Analyzer, ":DISP:WIND:TRAC:Y:SCAL:RLEV 30" ) + +success = write_command( Analyzer, ":SENS:BAND:RES:AUTO OFF" ) + +success = write_command( Analyzer, ":SENS:BAND:RES:AUTO ON" ) + +success = write_command( Analyzer, ":SENS:BAND:VID:AUTO OFF" ) + +success = write_command( Analyzer, ":SENS:BAND:VID:AUTO ON" ) + +success = write_command( Analyzer, ":SENS:FREQ:MODE SWE" ) + +success = write_command( Analyzer, ":DISP:WIND1:SIZE LARG" ) + +success = write_command( Analyzer, ":CALC1:MARK1:FUNC:STR:STAT ON" ) + +success = write_command( Analyzer, ":CALC1:MARK1:FUNC:STR:STAT OFF" ) + +success = write_command( Analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ) + +success = write_command( Analyzer, ":SENS:POW:ACH:BAND:CHAN 300000" ) + +success = write_command( Analyzer, ":SENS:POW:ACH:PRES CN" ) + +success = write_command( Analyzer, ":CALC:MARK1:STAT ON" ) + +success = write_command( Analyzer, ":CALC:MARK1:X 1200000000" ) + +success = write_command( Analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ) + +success = write_command( Analyzer, ":SENS:POW:ACH:PRES CN" ) + +success = write_command( Analyzer, ":SENS:POW:ACH:PRES CN" ) + +success = write_command( Analyzer, ":CALC:MARK:FUNC:POW:SEL CN0" ) + +success = write_command( Analyzer, ":CALC:MARK:FUNC:POW:SEL CN" ) + +success = write_command( Analyzer, ":SENS:FREQ:SPAN 1000000" ) + +success = write_command( Analyzer, ":SENS:FREQ:SPAN 1000000000" ) + +success = write_command( Analyzer, ":CALC:MARK1:STAT ON" ) + +success = write_command( Analyzer, ":CALC:MARK1:X 1200000000" ) + +success = write_command( Analyzer, ":CALC:DELT2:STAT ON" ) + +success = write_command( Analyzer, ":CALC:DELT2:X 1600000000" ) + +success = write_command( Analyzer, ":INIT:SPUR" ) + +success = write_command( Analyzer, ":MMEM:NAME 'C:\R_S\Instr\user\FSW_ScreenShot_2024-12-04_14-22-12.PNG'" ) + +success = write_command( Analyzer, ":HCOP:IMM1" ) + + +# back to local mode +success = write_command(Analyzer, "@LOC") + +# cleanup +Analyzer.close() +VisaResourceManager.close() diff --git a/visa-scpi-example/commands.json b/visa-scpi-example/commands.json new file mode 100644 index 0000000..bd8c139 --- /dev/null +++ b/visa-scpi-example/commands.json @@ -0,0 +1,9 @@ +{ + ":SENS:FREQ:STAR": "1000000000", + ":SENS:FREQ:STOP": "2000000000", + ":DISP:WIND:TRAC:Y:SCAL:RLEV": "0", + ":SENS:POW:ACH:BAND:CHAN": "300000", + ":CALC:MARK1:X": "1200000000", + ":SENS:FREQ:SPAN": "1000000000", + ":CALC:DELT2:X": "1600000000" +} \ No newline at end of file diff --git a/visa-scpi-example/comments.json b/visa-scpi-example/comments.json new file mode 100644 index 0000000..0b12e0c --- /dev/null +++ b/visa-scpi-example/comments.json @@ -0,0 +1,9 @@ +{ + ":SENS:FREQ:STAR": "\u8d77\u59cb\u9891\u7387", + ":SENS:FREQ:STOP": " ", + ":DISP:WIND:TRAC:Y:SCAL:RLEV": " ", + ":SENS:POW:ACH:BAND:CHAN": " ", + ":CALC:MARK1:X": " ", + ":SENS:FREQ:SPAN": " ", + ":CALC:DELT2:X": " " +} \ No newline at end of file diff --git a/visa-scpi-example/index.html b/visa-scpi-example/index.html new file mode 100644 index 0000000..e140a6a --- /dev/null +++ b/visa-scpi-example/index.html @@ -0,0 +1,153 @@ + + + + + + SCPI命令参数编辑器 + + + +

SCPI命令参数编辑器

+
+ + + + \ No newline at end of file diff --git a/visa-scpi-example/parse_inp.py b/visa-scpi-example/parse_inp.py new file mode 100644 index 0000000..6f0b466 --- /dev/null +++ b/visa-scpi-example/parse_inp.py @@ -0,0 +1,55 @@ +import re +import json +import os + +def parse_inp_file(file_path): + commands_dict = {} + comments_dict = {} + + with open(file_path, 'r') as f: + lines = f.readlines() + + for line in lines: + # 去除首尾空格并按空格分割 + parts = line.strip().split(' ') + if len(parts) == 2: # 只处理有一个参数的指令 + command, value = parts + # 检查参数是否为数字(包括科学计数法) + if re.match(r'^-?\d+\.?\d*([eE][-+]?\d+)?$', value): + commands_dict[command] = value + + # 读取注释文件 + comments_file_path = 'visa-scpi-example/comments.json' + if not os.path.exists(comments_file_path): + with open(comments_file_path, 'w') as f: + # 为空时,创建一个空的注释文件,将commands_dict的值以“”表示 + comments_dict = {key: " " for key in commands_dict.keys()} + json.dump(comments_dict, f) + else: + with open(comments_file_path, 'r') as f: + comments_dict = json.load(f) + + # 保存为JSON文件 + with open('visa-scpi-example/commands.json', 'w') as f: + json.dump(commands_dict, f, indent=2) + + return commands_dict, comments_dict + +def save_comments(comments_dict): + with open('visa-scpi-example/comments.json', 'w') as f: + json.dump(comments_dict, f, indent=2) + +def update_inp_file(file_path, command, new_value): + with open(file_path, 'r') as f: + lines = f.readlines() + + updated_lines = [] + for line in lines: + parts = line.strip().split(' ') + if len(parts) == 2 and parts[0] == command: + updated_lines.append(f"{command} {new_value}\n") + else: + updated_lines.append(line) + + with open(file_path, 'w') as f: + f.writelines(updated_lines) \ No newline at end of file diff --git a/visa-scpi-example/server.py b/visa-scpi-example/server.py new file mode 100644 index 0000000..3060c18 --- /dev/null +++ b/visa-scpi-example/server.py @@ -0,0 +1,43 @@ +from flask import Flask, request, jsonify, send_from_directory +from parse_inp import parse_inp_file, update_inp_file, save_comments +import os + +app = Flask(__name__) + +# 确保在启动时解析inp文件 +INP_FILE_PATH = 'visa-scpi-example/File.inp' + +@app.route('/') +def index(): + commands, comments = parse_inp_file(INP_FILE_PATH) + return send_from_directory(os.path.abspath('visa-scpi-example'), 'index.html') + +@app.route('/commands.json') +def get_commands(): + return send_from_directory(os.path.abspath('visa-scpi-example'), 'commands.json') + +@app.route('/update_command', methods=['POST']) +def update_command(): + data = request.json + try: + update_inp_file(INP_FILE_PATH, data['command'], data['value']) + # 更新后重新解析文件 + parse_inp_file(INP_FILE_PATH) + return jsonify({'success': True}) + except Exception as e: + return jsonify({'success': False, 'error': str(e)}), 500 + +@app.route('/save_comments', methods=['POST']) +def save_comments_route(): + comments = request.json + save_comments(comments) + return jsonify({'success': True}) + +@app.route('/comments.json') +def get_comments(): + return send_from_directory(os.path.abspath('visa-scpi-example'), 'comments.json') + +if __name__ == '__main__': + # 启动时先解析一次文件 + parse_inp_file(INP_FILE_PATH) + app.run(debug=True) \ No newline at end of file