191 lines
8.8 KiB
Python
191 lines
8.8 KiB
Python
"""Class definition of PowerFlex Drives."""
|
|
|
|
from cpppo.server.enip.get_attribute import proxy_simple
|
|
import traceback
|
|
from common import reverse_parameter_name, bitfield, CIP_value
|
|
|
|
|
|
class powerflex(proxy_simple):
|
|
"""Generic powerflex drive."""
|
|
|
|
pass
|
|
|
|
|
|
COMMAND_MAP = {"Logic Status": {
|
|
0: "Run Ready",
|
|
1: "Active",
|
|
2: "Command Direction",
|
|
3: "Actual Direction",
|
|
4: "Accelerating",
|
|
5: "Decelerating",
|
|
6: "Alarm",
|
|
7: "Fault",
|
|
8: "At Setpoint Speed",
|
|
9: "Manual",
|
|
16: "Running",
|
|
17: "Jogging",
|
|
18: "Stopping",
|
|
19: "DC Brake",
|
|
20: "DB Active",
|
|
21: "Speed Mode",
|
|
22: "Position Mode",
|
|
23: "Torque Mode",
|
|
24: "At Zero Speed",
|
|
25: "At Home",
|
|
26: "At Limit",
|
|
27: "Current Limit",
|
|
28: "Bus Freq Reg",
|
|
29: "Enable On",
|
|
30: "Motor Overload",
|
|
31: "Regen",
|
|
}, "Logic Command": {
|
|
0: "Normal Stop",
|
|
1: "Start",
|
|
2: "Jog 1",
|
|
3: "Clear Fault",
|
|
6: "Manual",
|
|
16: "Coast Stop",
|
|
17: "Current Limit Stop",
|
|
18: "Run",
|
|
19: "Jog 2",
|
|
}}
|
|
|
|
|
|
class powerflex755(powerflex):
|
|
"""Specific parameters and their addresses, for the PowerFlex 750 Series AC drives."""
|
|
|
|
RUNNING_PARAMETERS = dict(output_frequency=powerflex.parameter('@0x93/1/9', 'REAL', 'Hz'),
|
|
speed_ref=powerflex.parameter('@0x93/2/9', 'REAL', 'Hz'),
|
|
motor_velocity=powerflex.parameter('@0x93/3/9', 'REAL', 'Hz/RPM'),
|
|
output_current=powerflex.parameter('@0x93/7/9', 'REAL', 'Amps'),
|
|
output_voltage=powerflex.parameter('@0x93/8/9', 'REAL', 'VAC'),
|
|
output_power=powerflex.parameter('@0x93/9/9', 'REAL', 'kW'),
|
|
output_powerfactor=powerflex.parameter('@0x93/10/9', 'REAL', 'kW'),
|
|
dc_bus_volts=powerflex.parameter('@0x93/11/9', 'REAL', 'VDC'),
|
|
elapsed_mwh=powerflex.parameter('@0x93/13/9', 'REAL', 'MWh'),
|
|
elapsed_kwh=powerflex.parameter('@0x93/14/9', 'REAL', 'kWh'),
|
|
elapsed_run_time=powerflex.parameter('@0x93/15/9', 'REAL', 'Hrs'),
|
|
speed_ref_a_stpt=powerflex.parameter('@0x93/546/9', 'REAL', 'Hz'),
|
|
)
|
|
|
|
CONFIGURATION_PARAMETERS = dict(motor_namplate_volts=powerflex.parameter('@0x93/25/9', 'REAL', 'VAC'),
|
|
motor_namplate_amps=powerflex.parameter('@0x93/26/9', 'REAL', 'Amps'),
|
|
motor_namplate_hertz=powerflex.parameter('@0x93/27/9', 'REAL', 'Hertz'),
|
|
motor_namplate_rpm=powerflex.parameter('@0x93/28/9', 'REAL', 'RPM'),
|
|
motor_namplate_powerunits=powerflex.parameter('@0x93/29/9', 'DINT', 'HP/kW'),
|
|
motor_namplate_power=powerflex.parameter('@0x93/30/9', 'REAL', 'HP/kW'),
|
|
motor_poles=powerflex.parameter('@0x93/31/9', 'DINT', 'Poles'),
|
|
pwm_frequency=powerflex.parameter('@0x93/38/9', 'REAL', 'kHz'),
|
|
rated_volts=powerflex.parameter('@0x93/20/9', 'REAL', 'VAC'),
|
|
rated_amps=powerflex.parameter('@0x93/21/9', 'REAL', 'Amps'),
|
|
rated_kw=powerflex.parameter('@0x93/22/9', 'REAL', 'kW'),
|
|
speed_units=powerflex.parameter('@0x93/300/9', 'DINT', 'Hz/RPM'),
|
|
duty_rating=powerflex.parameter('@0x93/306/9', 'DINT', 'ND/HD/LD'),
|
|
reset_meters=powerflex.parameter('@0x93/336/9', 'DINT', 'Ready/Energy/Time'),
|
|
db_resistor_type=powerflex.parameter('@0x93/382/9', 'DINT', 'Internal/External'),
|
|
db_resistor_ohms=powerflex.parameter('@0x93/383/9', 'REAL', 'Ohms'),
|
|
db_resistor_watts=powerflex.parameter('@0x93/384/9', 'REAL', 'Watts'),
|
|
speed_ref_a_sel=powerflex.parameter('@0x93/545/9', 'DINT', 'Param'),
|
|
)
|
|
|
|
COMMAND_PARAMETERS = dict(logic_status=powerflex.parameter('@0x07/3/4', 'DINT', 'Bits'),
|
|
logic_command=powerflex.parameter('@0x07/4/1', 'BOOL', 'Bits'))
|
|
|
|
PARAMETERS = powerflex.PARAMETERS.copy()
|
|
PARAMETERS.update(RUNNING_PARAMETERS)
|
|
PARAMETERS.update(CONFIGURATION_PARAMETERS)
|
|
PARAMETERS.update(COMMAND_PARAMETERS)
|
|
# PARAMETERS = dict(powerflex.PARAMETERS + RUNNING_PARAMETERS + CONFIGURATION_PARAMETERS)
|
|
|
|
def __init__(self, hostname):
|
|
"""Intitialize the class."""
|
|
super().__init__(hostname, route_path=[], send_path='')
|
|
self.PARAMETER_NAMES = [reverse_parameter_name(p) for p in self.PARAMETERS]
|
|
self.PARAMETER_NAMES = self.PARAMETER_NAMES[3:]
|
|
|
|
self.RUNNING_PARAMETER_NAMES = [reverse_parameter_name(p) for p in self.RUNNING_PARAMETERS]
|
|
self.CONFIGURATION_PARAMETER_NAMES = [reverse_parameter_name(p) for p in self.CONFIGURATION_PARAMETERS]
|
|
self.COMMAND_PARAMETER_NAMES = [reverse_parameter_name(p) for p in self.COMMAND_PARAMETERS]
|
|
self.running_values = {}
|
|
self.configuration_values = {}
|
|
self.command_values = {}
|
|
|
|
for p in self.RUNNING_PARAMETERS:
|
|
self.running_values[reverse_parameter_name(p)] = CIP_value(reverse_parameter_name(p), self.RUNNING_PARAMETERS[p][2])
|
|
|
|
for p in self.CONFIGURATION_PARAMETERS:
|
|
self.configuration_values[reverse_parameter_name(p)] = CIP_value(reverse_parameter_name(p), self.CONFIGURATION_PARAMETERS[p][2])
|
|
|
|
for p in self.COMMAND_PARAMETERS:
|
|
self.command_values[reverse_parameter_name(p)] = CIP_value(reverse_parameter_name(p), self.COMMAND_PARAMETERS[p][2])
|
|
# print("Speed Ref A Set: {}".format(self.write_parameter("Speed Ref A Sel", 'DINT', 546))) # Set the Speed ref to read from Ethernet Adapter
|
|
|
|
def get_all_values(self):
|
|
"""Retrieve all values stored for the VFD."""
|
|
temp = self.configuration_values.copy()
|
|
temp.update(self.running_values)
|
|
return temp
|
|
|
|
def write_parameter(self, param_name, param_type, value):
|
|
"""Write a parameter to the VFD."""
|
|
param = '%s = (%s)%s' % (param_name, param_type, value)
|
|
print(param)
|
|
try:
|
|
via = self
|
|
with via: # establish gateway, detects Exception (closing gateway)
|
|
val, = via.write(
|
|
via.parameter_substitution(param), checking=True)
|
|
if val:
|
|
return True
|
|
else:
|
|
return False
|
|
except Exception as exc:
|
|
print("Exception writing Parameter %s: %s, %s", param, exc, traceback.format_exc())
|
|
return False
|
|
|
|
def read_all(self):
|
|
"""Read all values from the list of parameter names."""
|
|
self.read_running()
|
|
self.read_configuration()
|
|
self.read_command()
|
|
return self.get_all_values()
|
|
|
|
def read_running(self):
|
|
"""Read Running Parameter values from the list of parameter names."""
|
|
values = list(self.read(self.parameter_substitution(self.RUNNING_PARAMETER_NAMES)))
|
|
for x in range(0, len(values)):
|
|
if values[x] is not None:
|
|
self.running_values[self.RUNNING_PARAMETER_NAMES[x]].update(values[x][0])
|
|
return self.running_values
|
|
|
|
def read_configuration(self):
|
|
"""Read Running Parameter values from the list of parameter names."""
|
|
values = list(self.read(self.parameter_substitution(self.CONFIGURATION_PARAMETER_NAMES)))
|
|
for x in range(0, len(values)):
|
|
if values[x] is not None:
|
|
self.configuration_values[self.CONFIGURATION_PARAMETER_NAMES[x]].update(values[x][0])
|
|
return self.configuration_values
|
|
|
|
def read_command(self):
|
|
"""Read Command Parameter values from the list of parameter names."""
|
|
values = list(self.read(self.parameter_substitution(self.COMMAND_PARAMETER_NAMES)))
|
|
for x in range(0, len(values)):
|
|
if values[x] is not None:
|
|
bit_map = bitfield(values[x][0])
|
|
value_map = {}
|
|
for i in range(0, len(bit_map)):
|
|
try:
|
|
value_map[COMMAND_MAP[self.COMMAND_PARAMETER_NAMES[x]][i]] = bit_map[i]
|
|
except KeyError:
|
|
pass
|
|
self.command_values[self.COMMAND_PARAMETER_NAMES[x]].update(value_map)
|
|
return self.command_values
|
|
|
|
def start(self):
|
|
"""Start the VFD."""
|
|
return self.write_parameter("Logic Command", "INT", 2)
|
|
|
|
def stop(self):
|
|
"""Start the VFD."""
|
|
return self.write_parameter("Logic Command", "INT", 1)
|