# # Template driver for the Knauer BlueShadow Pump 40P # vim: ts=8 sts=2 sw=2 expandtab autoindent smartindent nocindent # driver knauer_pump = { debug_threshold = 0; vendor = knauer; device = pump40p; protocol = knauer_ap; class = environment; simulation_group = environment_simulation; # group dummy = { type = text; readable = 1; data = false; control = false; nxsave = false; var status = { read_command = 'STATUS?'; read_function = read_status; } var glp = { read_command = 'GLP?'; read_function = read_glp; property real_data = ' '; } } group pump = { var remote = { type = int; readable = 1; read_command = 'REMOTE?'; read_function = remote_read; writeable = 1; write_function = remote_write; } var state = { type = text; readable = 1; read_command = ' '; fetch_function = state_fetch; } var status = { type = text; readable = 1; read_command = ' '; fetch_function = status_fetch; } var volume_pv = { type = float; readable = 1; read_command = ' '; fetch_function = volume_fetch; #checkrange_function = volume_reject; property 'units' = 'mL'; } var volume_sp = { type = float; writeable = 1; write_command = ' '; write_function = volume_write; driveable = pump/volume_pv checkstatus_function = volume_checkstatus; halt_function = volume_halt; lowerlimit = 0; upperlimit = 100; tolerance = 0.01; readable = 1; read_command = ' '; fetch_function = volume_checkpumping; property 'units' = 'mL'; } var ratio_pv = { type = text; readable = 1; read_command = ' '; fetch_function = ratios_fetch; property 'units' = 'percent'; } var ratio_sp = { type = text; writeable = 1; write_command = ' '; write_function = ratios_write; checkrange_function = ratios_check; property 'units' = 'percent'; } var flow_pv = { type = float; readable = 1; read_command = ' '; fetch_function = flow_fetch; property 'units' = 'mL/min'; } var flow_sp = { type = float; writeable = 1; write_command = ' '; write_function = flow_write; lowerlimit = 0; upperlimit = 10; property 'units' = 'mL/min'; } } group stuff = { readable = 60; type = text; data = false; control = false; nxsave = false; var an_out = { read_command = 'AN_OUT?'; } var boardinfo = { read_command = 'BOARDINFO?'; } var config = { read_command = 'CONFIG?'; } var cprofinfo = { read_command = 'CPROFINFO?'; } var dout = { read_command = 'DOUT?'; } var error = { read_command = 'ERROR?'; } var errors = { read_command = 'ERRORS?'; } var flushpmp = { read_command = 'FLUSHPMP?'; } var head = { read_command = 'HEAD?'; } var head_par = { read_command = 'HEAD_PAR?'; } var identify = { read_command = 'IDENTIFY?'; } var lpg = { read_command = 'LPG?'; } var oem = { read_command = 'OEM?'; } var opt = { read_command = 'OPT?'; } var plim = { read_command = 'PLIM?'; } var pressure = { read_command = 'PRESSURE?'; } var prfastacq = { read_command = 'PRFASTACQ?'; } var purge = { read_command = 'PURGE?'; } var remote = { read_command = 'REMOTE?'; } var rfid = { read_command = 'RFID?'; } var service = { read_command = 'SERVICE?'; } var sysinfo = { read_command = 'SYSINFO?'; } var 'units' = { read_command = 'UNITS?'; } var valves = { read_command = 'VALVES?'; } } group prog = { readable = 30; type = text; var line_01 = { read_command = "TT_GET:1,1"; } var line_02 = { read_command = "TT_GET:1,2"; } var line_03 = { read_command = "TT_GET:1,3"; } var line_04 = { read_command = "TT_GET:1,4"; } var line_05 = { read_command = "TT_GET:1,5"; } } group glp = { type = text; readable = 1; fetch_function = fetch_from_glp; var board_time = { read_command = '0'; } var motor_time = { read_command = '1'; } var head_count = { read_command = '3'; } var head_time = { read_command = '4'; } var head_volm = { read_command = '5'; } var head_voln = { read_command = '6'; } var head_pwrhi = { read_command = '7'; } var head_pwrlo = { read_command = '8'; } var pump_revs = { read_command = '9'; } var pump_volm = { read_command = '10'; } var pump_voln = { read_command = '11'; } var pump_pwrhi = { read_command = '12'; } var pump_pwrlo = { read_command = '13'; } } group status = { type = text; readable = 1; fetch_function = fetch_from_status; var state = { read_command = '1'; } var cur_error = { read_command = '2'; } var cur_run_time = { read_command = '3'; } var flow_rate = { read_command = '4'; } var lpg_0 = { read_command = '5'; } var lpg_1 = { read_command = '6'; } var lpg_2 = { read_command = '7'; } var lpg_3 = { read_command = '8'; } var evt_0 = { read_command = '9'; } var evt_1 = { read_command = '10'; } var evt_2 = { read_command = '11'; } var evt_3 = { read_command = '12'; } var evt_4 = { read_command = '13'; } var evt_5 = { read_command = '14'; } var evt_6 = { read_command = '15'; } var evt_7 = { read_command = '16'; } var cur_pres = { read_command = '17'; } var start_in = { read_command = '18'; } var error_in = { read_command = '19'; } } code fetch_from_glp = {%% set index ${cmd_str} set data [hgetpropval ${tc_root}/dummy/glp real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > ${index} } { sct result [lindex ${dlist} ${index}] } else { sct result "" } set cmd "@@NOSEND@@" %%} code fetch_from_status = {%% set index ${cmd_str} set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > ${index} } { sct result [lindex ${dlist} ${index}] } else { sct result "" } set cmd "@@NOSEND@@" %%} code read_glp = {%% if { [string equal -nocase -length 6 ${data} "ERROR:"] } { } else { set dlist [split [lindex [split ${data} ":"] 1] ","] sct real_data "[join [lrange ${dlist} 0 end] ,]" set data "Hidden in real_data property" } %%} code read_status = {%% set dlist [split [lindex [split ${data} ":"] 1] ","] sct real_data "[join [lrange ${dlist} 0 end] ,]" set data "Hidden in real_data property" %%} code status_fetch = {%% set index 1 set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set status_code [lindex ${dlist} ${index}] set cmd "@@NOSEND@@" if { ${status_code} == 3 } { sct result "PUMPING" } else { sct result "IDLE" } %%} code state_fetch = {%% set index 1 set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set state_code [lindex ${dlist} ${index}] set cmd "@@NOSEND@@" if { ${state_code} < 0 || ${state_code} > 9 } { sct geterror "Invalid device_state ${state_code}" error "[sct geterror]" } set slist [list "SYS_ST_INITIALIZING" \ "SYS_ST_OFF" \ "SYS_ST_IDLE" \ "SYS_ST_RUN" \ "SYS_ST_HOLD" \ "SYS_ST_PURGE" \ "SYS_ST_STANDBY" \ "SYS_ST_FAILED" \ "SYS_ST_RUNATEND" \ ] sct result [lindex ${slist} ${state_code}] %%} code halt = {%% set rlist [hval ${tc_root}/pump/ratio_sp] set ratio_tgt [join [split ${rlist} /] ,] set cmd "RAMP:0,0,${ratio_tgt},0,0,0,0,0,0,0,0,2" %%} code flow_fetch = {%% set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set flow_pv [lindex ${dlist} 4] sct result [expr {0.001 * ${flow_pv}}] set cmd "@@NOSEND@@" %%} code flow_write = {%% set data [sct target] set cmd "@@NOSEND@@" set nextState idle if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } %%} code ratios_check = {%% set rlist [split ${setpoint} /] if { [llength ${rlist}] != 4 } { sct geterror "${setpoint} has [llength ${rlist}] components, needs 4" error [sct geterror] } set sum [expr [lindex ${rlist} 0] + [lindex ${rlist} 1] + [lindex ${rlist} 2] + [lindex ${rlist} 3]] if { ${sum} != 100 } { sct geterror "sum is ${sum}, must be 100" error [sct geterror] } %%} code ratios_fetch = {%% set data [hgetpropval ${tc_root}/dummy/status real_data] set dlist [split ${data} ","] set ratio_vals "[lindex ${dlist} 5]/[lindex ${dlist} 6]/[lindex ${dlist} 7]/[lindex ${dlist} 8]" sct result ${ratio_vals} set cmd "@@NOSEND@@" %%} code ratios_write = {%% set data [sct target] set cmd "@@NOSEND@@" set nextState idle if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } %%} code remote_read = {%% if { [string equal -length 7 ${data} "REMOTE:"] } { set data [lindex [split ${data} :] 1] } else { sct geterror "bad response" error "[sct geterror]" } %%} code remote_write = {%% if { ${par} == 0 } { set cmd "LOCAL" } else { set cmd "REMOTE" } %%} code volume_fetch = {%% set data [hgetpropval ${tc_root}/dummy/glp real_data] set dlist [split ${data} ","] if { [llength ${dlist}] > 11 } { set pump_volm [lindex ${dlist} 10] set pump_voln [lindex ${dlist} 11] set pump_volume [expr {${pump_volm} + 0.000001 * ${pump_voln}}] } else { set pump_volume 0.0 } sct raw_volume ${pump_volume} if { [hpropexists [sct] base_volume] } { set pump_volume [expr {${pump_volume} - [sct base_volume]}] } elseif { [hpropexists [sct] raw_volume] } { sct base_volume [sct raw_volume] } sct result [format "%.2f" ${pump_volume}] set cmd "@@NOSEND@@" %%} code volume_write = {%% hsetprop ${tc_root}/[sct driveable] base_volume [hgetpropval ${tc_root}/[sct driveable] raw_volume] hset ${tc_root}/[sct driveable] 0.0 set flow_tgt [expr {int(1000.0 * [hval ${tc_root}/pump/flow_sp])}] set ratio_tgt [join [split [hval ${tc_root}/pump/ratio_sp] /] ,] set cmd "RAMP:0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0,3" sct pumping 1 set data ${par} if { ${data} != [sct oldval] } { debug_log ${tc_root} 1 "[sct] changed to new:${data}, from old:[sct oldval]" sct oldval ${data} sct update ${data} sct utime readtime } %%} code volume_checkpumping = {%% set cmd "@@NOSEND@@" set nextState idle if { [hpropexists [sct] pumping] && [sct pumping] } { if { [hpropexists [sct] driving] && [sct driving] } { volume_checkstatus "${tc_root}" } set sp "[sct target]" set pv "[hval ${tc_root}/[sct driveable]]" if { (${sp} - ${pv}) <= [sct tolerance] } { set flow_tgt 0 set ratio_tgt [join [split [hval ${tc_root}/pump/ratio_sp] /] ,] set cmd "RAMP:0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0,2" set nextState noResponse sct driving 0 sct pumping 0 } } %%} code volume_halt = {%% set flow_tgt 0 set ratio_tgt [join [split [hval ${tc_root}/pump/ratio_sp] /] ,] set cmd "RAMP:0,${flow_tgt},${ratio_tgt},0,0,0,0,0,0,0,0,2" sct send ${cmd} %%} code volume_reject = {%% sct geterror "cannot use hset on [sct]" error "[sct geterror]" %%} }