#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#
# Copyright 2012-2017 Frédéric Magniette, Miguel Rubio-Roy
# This file is part of Pyrame.
#
# Pyrame is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Pyrame is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with Pyrame. If not, see <http://www.gnu.org/licenses/>
import time,json
import scpi
# CLASS ##########################################################
class mm_ki_6517_class(scpi.scpi):
# Available channels
channels=["1"]
def __init__(self):
super(mm_ki_6517_class,self).__init__("mm_ki_6517")
def check_range(self,range):
retcode,res=super(mm_ki_6517_class,self).check_range(range,[])
if retcode==0:
return 0,res
if retcode==1:
return 1,":AUTO ON"
if retcode==2:
return 1," "+res
def config(self,mm_ki_6517_id):
command= r"*CLS\n" # clear status and error queue
command+=r":INIT:CONT ON\n" # continuous INIT of trigger model
command+=r":SYST:TSC ON\n" # read temperature
command+=r":UNIT:TEMP C\n" # temperature in Celsius
command+=r"FORM:DATA ASC\n" # read in ASCII
command+=r"FORM:ELEM ALL\n" # read all elements
command+=r":TRAC:FEED:PRET:SOUR MAN\n" # buffer store source manual
command+=r":SYST:TST:TYPE REL\n" # timestamp relative
command+=r":SYST:TST:REL:RES" # reset timestamp
return super(mm_ki_6517_class,self).config(mm_ki_6517_id,command)
def reset(self,mm_ki_6517_id):
command= r"*RST\n" # reset
command+=r":INIT:CONT ON\n" # continuous INIT of trigger model
command+=r":SYST:TSC ON\n" # read temperature
command+=r":UNIT:TEMP C\n" # temperature in Celsius
command+=r"FORM:DATA ASC\n" # read in ASCII
command+=r"FORM:ELEM ALL\n" # read all elements
command+=r":SYST:TST:TYPE REL\n" # timestamp relative
command+=r":SYST:TST:REL:RES" # reset timestamp
retcode,res=self.free_command(ki_6517_id,command)
if retcode==0:
return 0,res
time.sleep(1)
command="SYST:ZCH OFF" # turn off zero-check
return self.free_command(mm_ki_6517_id,command)
def get_conf_cmd_dc_current(self,mm_ki_6517_id,range="undef",resolution="undef"):
conf_cmd=":FUNC 'CURR:DC'"
#range
if range!="undef":
retcode,res=self.check_range(range)
if retcode==0:
return 0,res
range=res
conf_cmd+=r"\n:CURR:DC:RANG%s"%(range)
#resolution
if resolution!="undef":
if resolution.lower().endswith("plc"):
retcode,res=self.check_resolution(resolution,"plc")
if retcode in [0,3]:
return 0,"Invalid PLC resolution"
resolution=res
if retcode==2:
conf_cmd+=r"\nCURR:NPLC %s"%(resolution)
else:
retcode,res=self.check_resolution(resolution,"s")
if retcode in [0,3]:
return 0,"Invalid resolution"
resolution=res
if retcode==2:
conf_cmd+=r"\nCURR:APER %s"%(resolution)
return 1,conf_cmd
def get_dc_current(self,mm_ki_6517_id,range="undef",resolution="undef"):
retcode,res=self.get_conf_cmd_dc_current(mm_ki_6517_id,range,resolution)
if retcode==0:
return 0,"unable to set range and resolution: %s"%(res)
conf_cmd=res
measure_query="FETCH?"
retcode,res=self.measure(mm_ki_6517_id,range,resolution,conf_cmd,measure_query)
if retcode==0:
return 0,res
if res.split(",")[0][-3:]!="ADC":
return 0,"set instrument in current mode"
if res.split(",")[0][-4:-3]=="O":
return 1,"OL"
return 1,str(float(res.split(",")[0][:-4]))
def get_temp(self,mm_ki_6517_id):
conf_cmd=""
measure_query="FETCH?"
retcode,res=self.measure(mm_ki_6517_id,"","",conf_cmd,measure_query)
if retcode==0:
return 0,res
if res.split(",")[4][-7:]!="exttemp":
return 0,"temperature reading disabled, reset or reconfigure instrument"
return 1,str(float(res.split(",")[4][:-8]))
def timed_acq(self,mm_ki_6517_id,value_type,nb_measures,period,vrange,resolution):
if value_type=="dc_current":
retcode,res=self.get_conf_cmd_dc_current(mm_ki_6517_id,vrange,resolution)
if retcode==0:
return 0,"unable to set range and resolution: %s"%(res)
else:
return 0,"unknown value_type %s"%(value_type)
conf_cmd=res+r"\n"
conf_cmd+=r":TRAC:FEED:PRET:SOUR MAN\n" # buffer store source manual
conf_cmd+=r":SYST:TST:TYPE REL\n" # relative timer
conf_cmd+=r":TRIG:SOUR TIM\n" # trigger source to timer
conf_cmd+=r":TRIGger:TIMer %f\n"%(float(period)) # trigger period
conf_cmd+=r":TRIGger:COUNt %d\n"%(int(nb_measures)) # trigger count
conf_cmd+=r":TRACe:POINts %d\n"%(int(nb_measures)) # buffer size
conf_cmd+=r":TRACe:CLEar\n" # clear buffer
conf_cmd+=r":SYST:TST:REL:RES\n" # reset clock
conf_cmd+=r":TRAC:FEED:CONT NEXT" # start
retcode,res=self.free_command(mm_ki_6517_id,conf_cmd)
if retcode==0:
return 0,"error configuring buffered acq: %s"%(res)
query=":STAT:MEAS:EVEN?"
finished=False
while not finished:
retcode,res=self.free_query(mm_ki_6517_id,query)
if retcode==0:
return 0,"error getting measurement register: %s"%(res)
finished=(int(res)&512)==512 # 512 = Buffer Full (BUF)
time.sleep(0.2)
measure_query=":TRAC:DATA?" # get data
retcode,res=self.free_query(mm_ki_6517_id,measure_query)
if retcode==0:
return 0,"error getting buffer on attempt %d: %s"%(attempt,res)
buf=res.split(",")
elements=["dc_current","time","nb","chan","temp","ohm","vsrc"]
try:
el=elements.index(value_type)
except:
el=0
data=[]
for i in range(len(buf)/7):
t=buf[i*7+1]
if t[-4:]=="secs":
t=t[:-4]
v=buf[i*7+el]
if v[-8:] in ["Cexttemp","Kexttemp"]:
v=v[:-8]
if v[-3:] in ["ADC","ADC","OHM"]:
v=v[:-3]
if v[-1:] in ["N","Z","O","U","R","L"]:
v=v[:-1]
datum={}
datum["time"]="%f"%float(t)
datum["value"]="%e"%float(v)
data.append(datum)
return 1,json.dumps(data)
# CREATE POOL ####################################################
me=mm_ki_6517_class()
# COMMANDS #######################################################
def init():
scpi.submod=submod
# Functions
[docs]def init_mm_ki_6517(mm_ki_6517_id,conf_string):
"""Initialize mm_ki_6517 power supply identified by *mm_ki_6517_id*
*conf_string* must include the parameter:
- bus: conf_string of the underlying link module (GPIB, TCP, ...)
- channel: channel on which the id will act"""
return me.init(mm_ki_6517_id,conf_string)
[docs]def deinit_mm_ki_6517(mm_ki_6517_id):
"Deinitialize an mm_ki_6517"
return me.deinit(mm_ki_6517_id)
[docs]def config_mm_ki_6517(mm_ki_6517_id):
"Configure an mm_ki_6517"
return me.config(mm_ki_6517_id)
[docs]def inval_mm_ki_6517(mm_ki_6517_id):
"Invalidate an mm_ki_6517"
return me.inval(mm_ki_6517_id)
[docs]def reset_mm_ki_6517(mm_ki_6517_id):
"Send RST signal to PS"
return me.reset(mm_ki_6517_id)
[docs]def get_dc_current_mm_ki_6517(mm_ki_6517_id,range="undef",resolution="undef"):
"""Get DC current in Ampers.
The optional *range* can be: auto or a value in Ampers
The optional *resolution* is either the number of power-line cycles that will be used to integrate, followed by PLC (e.g. 10PLC) or the number of seconds followed by s (e.g. 0.2s)
MIN or MAX can be used for both parameters (for resolution, MAX means the highest resolution)."""
return me.get_dc_current(mm_ki_6517_id,range,resolution)
[docs]def get_temp_mm_ki_6517(mm_ki_6517_id):
"Get temperature in degrees Celsius."
return me.get_temp(mm_ki_6517_id)
[docs]def timed_acq_mm_ki_6517(mm_ki_6517_id,value_type,nb_measures,period,range="undef",resolution="undef"):
"Make a timed acquisition every *period* seconds of *nb_measures* of *value_type* with *range* and *resolution*"
return me.timed_acq(mm_ki_6517_id,value_type,nb_measures,period,range,resolution)
[docs]def free_command_mm_ki_6517(mm_ki_6517_id,command):
"Send a raw command to the PS"
return me.free_command(mm_ki_6517_id,command)
[docs]def free_query_mm_ki_6517(mm_ki_6517_id,query):
"Send a raw query to the PS"
return me.free_query(mm_ki_6517_id,query)
[docs]def get_error_queue_mm_ki_6517(mm_ki_6517_id):
"Read error queue until the end (code 0)"
return me.get_error_queue(mm_ki_6517_id)