def writeCommitPower(commit=True): if commit: device.write( 0xf100, util.u16_to_data(1)) # write Commit Power Control Settings else: device.write( 0xf100, util.u16_to_data(0)) # write Commit Power Control Settings return readCommitPower()
def restorePowerControl(restore=True): if restore: device.write(0xf101, util.u16_to_data( 1)) # write Restore Power Control Default Settings else: device.write(0xf101, util.u16_to_data( 0)) # write Restore Power Control Default Settings return readRestorePowerControl()
def stop_button(self, state=True): """ Note that upon power loss, all registers reset to 0, so B3:2/6 must reset to 1 for proper operation :param state: bool for "press the stop button" :return: None """ # Stop button is nominally high (1) and goes low (0) when pressed if state: self.device.write(1, suns_util.u16_to_data(1)) else: self.device.write(1, suns_util.u16_to_data(0))
def writePF_Ena(Ena=True): # Modbus F104 codes # 0 - Fixed CosPhi mode # 1 - CosPhi(P) mode # 2 - Fixed Q mode # 3 - Q(U) + Q(P) mode # 4 - RRCR mode if Ena: device.write(0xf104, util.u16_to_data(0)) # write power factor enable else: device.write(0xf104, util.u16_to_data(4)) # write power factor enable return readPF_Ena()
def active_power(self, params=None): """ Get/set active power of EUT Params: Ena - Enabled (True/False) P - Active power in %Wmax (positive is exporting (discharging), negative is importing (charging) power) WinTms - Randomized start time delay in seconds RmpTms - Ramp time in seconds to updated output level RvrtTms - Reversion time in seconds :param params: Dictionary of parameters to be updated. :return: Dictionary of active settings for HFRT control. """ if params is not None: if params['P'] is not None: targ_power = params['P'] if 0 <= targ_power <= 150: self.ctrl_device.write( 4790, suns_util.u16_to_data(int(targ_power))) else: print('Genset target power out of range.') else: params = {} params['P'] = 25000 return params
def fixed_pf(self, params=None): """ Get/set fixed power factor control settings. Params: Ena - Enabled (True/False) PF - Power Factor set point WinTms - Randomized start time delay in seconds RmpTms - Ramp time in seconds to updated output level RvrtTms - Reversion time in seconds :param params: Dictionary of parameters to be updated. :return: Dictionary of active settings for fixed factor. """ if self.inv is None: der.DERError('DER not initialized') try: if params is not None: pf = params.get('PF') # Configuring Grid Management Services Control with Sunny Explorer # Cos phi (if supported by the device): Read Modbus register 30825. If the value 1075 can be read # from this register, the power factor is specified via system control. if pf is not None: if pf > 0: reg = 1042 # leading else: reg = 1041 # lagging self.inv.write(40025, util.u32_to_data(int(reg))) reg = int(abs(round(pf, 4) * 10000)) self.inv.write(40024, util.u16_to_data(int(reg))) ena = params.get('Ena') if ena is not None: if ena is True: reg = 1075 # 1075 = cos phi, specified by PV system control # reg = 1074 # 1075 = cos phi, direct specific. else: reg = 303 if reg != util.data_to_u32(self.inv.read(40200, 2)): self.inv.write(40200, util.u32_to_data(int(reg))) else: params = {} reg = self.inv.read(40200, 2) if util.data_to_u32(reg) == 1075: params['Ena'] = True else: params['Ena'] = False pf = None params['PF'] = pf except Exception, e: der.DERError(str(e))
def reactive_power(self, params=None): """ Set the reactive power Params: Ena - Enabled (True/False) Q - Reactive power as %Qmax (positive is overexcited, negative is underexcited) WinTms - Randomized start time delay in seconds RmpTms - Ramp time in seconds to updated output level RvrtTms - Reversion time in seconds :param params: Dictionary of parameters to be updated. :return: Dictionary of active settings for Q control. """ if params is not None: if params['Q'] is not None: targ_q = params['Q'] if 0 <= targ_q <= 50: self.ctrl_device.write(4729, suns_util.u16_to_data(int(targ_q))) else: print('Genset target reative power out of range.') else: params = {} return params
def test_u16_to_data(self): self.assertEqual(util.u16_to_data(int(4660)), b'\x12\x34') self.assertEqual(util.u16_to_data(int(37428)), b'\x92\x34')
def reset_button(self, state=False): if state: self.device.write(0, suns_util.u16_to_data(1)) else: self.device.write(0, suns_util.u16_to_data(0))
def switch_close(self): """ Close the switch associated with this device """ self.device.write(self.reg, suns_util.u16_to_data(0))
def switch_open(self): """ Open the switch associated with this device """ self.device.write(self.reg, suns_util.u16_to_data(1))
def simulator_button(self, state=False): if state: self.device.write(5, suns_util.u16_to_data(1)) else: self.device.write(5, suns_util.u16_to_data(0))
def utility_button(self, state=False): if state: self.device.write(3, suns_util.u16_to_data(1)) else: self.device.write(3, suns_util.u16_to_data(0))
def islanding_button(self, state=False): if state: self.device.write(2, suns_util.u16_to_data(1)) else: self.device.write(2, suns_util.u16_to_data(0))
def enableFloats(): device.write(7999, util.u16_to_data(9020)) # enable float values device.write(3247, util.u16_to_data(1)) # enable float values device.write(8000, util.u16_to_data(1)) # enable float values device.write(7999, util.u16_to_data(9021)) # enable float values
def writePower(power=100): device.write(0xf001, util.u16_to_data(power)) # write power return readPower()