def __init__(self, serial_device, slave_address, debug=False, cache=True, retries=3): """Initialize the driver Args: serial_device (str): The serial device to use slave_address (int): The address of the slave device debug (bool): Whether debugging output from minimal modbus should be enabled cache (bool): Whether system configuration values (which are expected not to change within the runtime of the program) should be cached """ LOGGER.info('__init__ called, serial device: %s, slave address: %s', serial_device, slave_address) Instrument.__init__(self, serial_device, slave_address) self.serial.baudrate = 9600 self.serial.stopbits = 2 self.serial.timeout = 2.0 self.retries = retries # Variables self.debug = debug self.cache = cache # Cache self.system_conf = {} self.channel_conf = {} LOGGER.info('__init__ complete')
def __init__(self, port, slaveaddress, bimaster=False): Instrument.__init__(self, port, slaveaddress) self.serial.baudrate = 9600 self.serial.bytesize = serial.EIGHTBITS self.serial.parity = serial.PARITY_NONE self.serial.stopbits = serial.STOPBITS_ONE self.serial.timeout = 1 self.mode = MODE_RTU self.bimaster = bimaster
class EUROTHERM_MODULE(): """ Class to manipulate a single Eurotherm Module """ def __init__(self, path, number, digits): """ Instrument class initalizes a connection through the desired port.""" # Path = COM / dev/tty*** Port self.device = Instrument(path, number) self.device.debug = False # Baudrate for Module is 9600 self.device.serial.baudrate = 9600 # Number Of Decimals used by the module. Temperature has 1 decimal while flowrate has 0. self.digits = digits # Select's the setpoint found in the config file as the active setpoint. self.set_active_setpoint(configuration['sp_select_default']) # Writing def set_active_setpoint(self, value): """ Set's the active setpoint to the value specified. """ if 0 <= value and value <= 1: self.device.write_register(configuration['sp_select_default'], value, self.digits) def set_setpoint(self, value): """ Set's the value in the active setpoint to the value given """ if self.read_setpoint_low_limit( ) <= value and value <= self.read_setpoint_high_limit(): self.device.write_register(configuration['sp_select_address'], value, self.digits) # Reading def read_value(self): """ Read value from the first register. This is the current value found on the Eurotherm Module. """ return self.device.read_register(1, self.digits) def read_setpoint_select(self): """ Reads the active setpoint from the 15th register. """ return self.device.read_register(15, self.digits) def read_setpoint_value(self): """ Reads the active setpoint's value from the register specified in the config.py. """ return self.device.read_register(configuration['sp_value_address'], self.digits) def read_setpoint_high_limit(self): """ Reads the active setpoint's high limit value from the register specified in the config.py. """ return self.device.read_register(configuration['sp_high_limit'], self.digits) def read_setpoint_low_limit(self): """ Reads the active setpoint's low limit value from the register specified in the config.py. """ return self.device.read_register(configuration['sp_low_limit'], self.digits)
def __init__(self, port): """ inititalizes the ModbusInstrument at a certain COM-Port Arguments: port -- path to serial port, e.g. for Windows "COM1" """ ModbusInstrument.__init__(self, port, 1) self.lock = Lock() self. self.loops = [] for i in range(0, 8): self.loops.append(Loop(self, i * 256, self.lock))
def __init__(self, path, number, digits): """ Instrument class initalizes a connection through the desired port.""" # Path = COM / dev/tty*** Port self.device = Instrument(path, number) self.device.debug = False # Baudrate for Module is 9600 self.device.serial.baudrate = 9600 # Number Of Decimals used by the module. Temperature has 1 decimal while flowrate has 0. self.digits = digits # Select's the setpoint found in the config file as the active setpoint. self.set_active_setpoint(configuration['sp_select_default'])
def connect(self): try: if(self.is_connected): self._instrument.close() self._instrument = Instrument( port=self._port, mode=MODE_RTU, slaveaddress=self._slave_addr) self._instrument.serial.baudrate = self._baudrate self._instrument.serial.timeout = 1 self._instrument.mode = MODE_RTU # RCU Hardware Setting # Read RCU Hardware Setting # firmware version information firmware_version_number_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_FIRMWARE_VERSION_NUMBER, number_of_registers=1, functioncode=_MODBUS_READ_INPUT_REGISTERS) self.firmware_version_number = firmware_version_number_reg[0] # runtime voltage setting information runtime_voltage_setting_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_RUNTIME_VOLTAGE_SETTING, number_of_registers=1, functioncode=_MODBUS_READ_HOLDING_REGISTERS) self.runtime_voltage_setting = float( runtime_voltage_setting_reg[0])/128 # runtime currnet setting information runtime_current_setting_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_RUNTIME_CURRENT_SETTING, number_of_registers=1, functioncode=_MODBUS_READ_HOLDING_REGISTERS) self.runtime_current_setting = float( runtime_current_setting_reg[0])/128 # Set voltage conversion if self.runtime_voltage_setting > 48.0: self.voltage_conversion = 0.02229 else: self.voltage_conversion = 0.01155 if self.runtime_voltage_setting > 48.0: self.current_conversion = 0.02014 else: self.current_conversion = 0.04028 return True except: self.is_connected = False return False
def __init__(self, label, slave_id, slave_address, setupsAdr, setupsCount, variablesAdr, variablesCount, port): self.label = label self.id = slave_id self.port = port self.slave_address = slave_address self.setupsAdr = setupsAdr self.setupsCount = setupsCount self.variablesAdr = variablesAdr self.variablesCount = variablesCount try: self.instrument = Instrument(self.port, slave_address) except: self.status = "ERROR" traceback.print_exc() self.status = "NEW" self.variable_values = [] self.config_values = []
def open_serial(self): if (self._serialtype == 'serial'): try: self._serial = Serial() self._serial.port = self._port self._serial.baudrate = self._baudrate self._serial.open() self.Warning_Signal.emit('打开串口成功') return 1 except: self.Warning_Signal.emit('打开串口失败') return 0 elif(self._serialtype == 'modbus'): try: self._serial = Instrument(self._port, 1) self._serial.serial.baudrate = self._baudrate self.Warning_Signal.emit('打开串口成功') return 1 except: self.Warning_Signal.emit('打开串口失败') return 0
def initInstrument(self): global SDM630v2, SDM120 energy_device_data = EnergyDeviceModel.get() self.logger.debug( 'found device: %s %s %d' % (energy_device_data.energy_device_id, energy_device_data.port_name, energy_device_data.slave_address)) try: self.instrument = Instrument( port=energy_device_data.port_name, slaveaddress=energy_device_data.slave_address) except Exception as e: self.logger.error("initInstrument() failed: {}".format(str(e))) raise # Get this from the database self.instrument.serial.baudrate = energy_device_data.baudrate self.instrument.serial.bytesize = energy_device_data.bytesize self.instrument.serial.parity = energy_device_data.parity self.instrument.serial.stopbits = energy_device_data.stopbits self.instrument.serial.timeout = energy_device_data.serial_timeout self.instrument.debug = energy_device_data.debug self.instrument.mode = energy_device_data.mode self.instrument.close_port_after_each_call = energy_device_data.close_port_after_each_call self.modbusConfig = SDM630v2 for i in range(len(modbusConfigOptions)): if energy_device_data.modbus_config == modbusConfigOptions[i][ MB.NAME]: self.modbusConfig = modbusConfigOptions[i] self.logger.debug("Modbus config {} selected (default: {}).".format( self.modbusConfig[MB.NAME], SDM630v2[MB.NAME])) self.readSerialNumber(energy_device_data.port_name, energy_device_data.slave_address)
def connect_to(portName: str): print('connecting to ', portName) if data.modbus: data.modbus.serial.close() try: data.modbus = Instrument(portName, 1) data.modbus.serial.baudrate = 115200 data.modbus.serial.timeout = 0.1 data.modbus.serial.rts = 0 data.modbus.serial.dtr = 0 print(data.modbus.serial.rts, data.modbus.serial.dtr) data.modbus.clear_buffers_before_each_transaction = True data.channel.send(ViewMessage.CONNECTED(portName)) except SerialException: data.modbus = None data.channel.send(ViewMessage.ERROR('Connessione fallita!'))
def read_string(self, *args, **kwargs): """Read string from instrument (with retries) The argument definition is the same as for the minimalmodbus method, see the full documentation `read_string <https://minimalmodbus.readthedocs.io/en/master/apiminimalmodbus .html#minimalmodbus.Instrument.read_string>`_ for details. """ for retry in range(0, self.retries + 1): try: return Instrument.read_string(self, *args, **kwargs) except ValueError as exception: if retry < self.retries: LOGGER.warning("Communication error in read_string, retrying %s " "out of %s times", retry + 1, self.retries) continue else: raise exception
def read_string(self, *args, **kwargs): """Read string from instrument (with retries) The argument definition is the same as for the minimalmodbus method, see the full documentation `read_string <https://minimalmodbus.readthedocs.io/en/master/apiminimalmodbus .html#minimalmodbus.Instrument.read_string>`_ for details. """ for retry in range(0, self.retries + 1): try: return Instrument.read_string(self, *args, **kwargs) except ValueError as exception: if retry < self.retries: LOGGER.warning( "Communication error in read_string, retrying %s " "out of %s times", retry + 1, self.retries) continue else: raise exception
def main(): # Serial port parameters port = "COM2" slaveNumber = 1 BAUDRATE = 9600 STOPBITS = 1 PARITY = "E" BYTESIZE = 8 # Register parameters. # registers - list of registers which will be logged. #START_REGISTER = 1100 #NUMBER_OF_REGISTERS = 10 registers = {'engine_right':1100, 'engine_left':1101, 'light_level':1102, \ 'camera_id':1103, 'noop':1104, 'motor_direction_left':1105, \ 'motor_direction_right':1106} # open log file name = "logs/log_"+time.strftime("%d_%b_%Y_%H_%M_%S") + ".txt" logFile = open(name, 'a') # Connect to robot motka = Instrument(port, slaveNumber) motka.serial.baudrate = BAUDRATE motka.serial.stopbits = STOPBITS motka.serial.parity = PARITY motka.serial.bytesize = BYTESIZE #Read data from device and write it to log file print "Logger started. If you want to stop press Cntrl+C " try: while 1: data = [] for value in registers.values(): data.append( motka.read_register(value) ) writeData(logFile, data) except KeyboardInterrupt: print "Logger was stopped by keyboard interrupt" except: logFile.close() motka.close() raise logFile.close() motka.close()
#!/usr/bin/env python import sys import time from minimalmodbus import Instrument if __name__ == "__main__": if len(sys.argv) < 2: print 'Usage: %s [COM]' % sys.argv[0] exit(1) port = sys.argv[1] inst = Instrument(port, 1) inst.serial.baudrate = 57600 inst.serial.timeout = 0.1 for i in range(1, 16): try: inst.address = i response = inst.read_registers(0x0001, 1) except IOError: pass else: print hex(response[0]) fw_version = response[0] & 0x0FFF hw_version = response[0] >> 12 print 'Slave {}: FW {:03X}, HW {:01X}'.format(i, fw_version, hw_version) time.sleep(0.01)
def packet_print(packet): return ':'.join('{:02X}'.format(ord(c)) for c in packet) if __name__ == "__main__": if len(sys.argv) < 4: print 'Usage: %s [COM] [SLAVE_ADDRESS] [MSP.bin]' % sys.argv[0] exit(1) print ':: Modbus updater' port = sys.argv[1] slave_address = int(sys.argv[2]) fmw = sys.argv[3] inst = Instrument(port, slave_address) inst.serial.baudrate = 57600 inst.serial.timeout = 0.1 # print inst # inst.debug = True # Try to reset FW and run bootloader. print 'Sending reset to FW... ', try: inst.write_registers(RESET_ADDRESS, [0xFFFF]) except IOError: print '[no response]' except ValueError: print '[wrong response]' else: print '[OK]'
from minimalmodbus import Instrument if len(sys.argv) < 3: print('Usage: {} [EFFECT] [COM] [SLAVE] <baudrate=57600>'.format( sys.argv[0])) exit(1) effect = sys.argv[1] port = sys.argv[2] slave = int(sys.argv[3]) try: baudrate = int(sys.argv[4]) except Exception: baudrate = 57600 instrument = Instrument(port, slave) instrument.serial.baudrate = baudrate instrument.serial.timeout = 1 def signal_handler(signal, frame): print('Turning all LEDs off.') instrument.write_registers(0x1000, [0x0000] * NEOPIXEL_SIZE) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) kwargs = {} effects = ['flash', 'blink', 'noise', 'rainbow', 'blank'] if effect == 'flash': klass = NeopixelsFlash elif effect == 'blink':
import signal import time from minimalmodbus import Instrument if len(sys.argv) < 3: print 'Usage: {} [COM] [SLAVE] <baudrate=57600>'.format(sys.argv[0]) exit(1) port = sys.argv[1] slave = int(sys.argv[2]) try: baudrate = int(sys.argv[3]) except Exception: baudrate = 57600 instrument = Instrument(port, slave) instrument.serial.baudrate = baudrate instrument.serial.timeout = 1 def signal_handler(signal, frame): print('Turning all LEDs off.') instrument.write_registers(0x1000, [0x0000] * NEOPIXEL_SIZE) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) led = [[0, 0, 0] for x in xrange(NEOPIXEL_SIZE)] j = 1 k = 1 print 'Rainbow.'
from minimalmodbus import Instrument # Number of Modbus reads. READS = 1000 # Number of registers to be read. REGISTERS = 1 if __name__ == "__main__": if len(sys.argv) < 3: print 'Usage: %s [COM] [SLAVE_ADDRESS]' % sys.argv[0] exit(1) port = sys.argv[1] slave_address = int(sys.argv[2]) inst = Instrument(port, slave_address) inst.serial.baudrate = 57600 inst.serial.timeout = 1 start_time = time.time() for i in range(READS): response = inst.read_registers(0x0000, REGISTERS) if response[0] != 0x0000: print 'IR inputs: {:02X}'.format(response[0]) end_time = time.time() print 'Duration of {} reads from {} register: {:.2f} seconds.'.format( READS, REGISTERS,
class Bearing_Serial(QObject): Warning_Signal = pyqtSignal(str) def __init__(self, com, baudrate, serialtype): super(Bearing_Serial, self).__init__() self._port = com self._baudrate = baudrate self._serialtype = serialtype def set_setting(self, com, baudrate, serialtype): self._port = com self._baudrate = baudrate self._serialtype = serialtype def open_serial(self): if (self._serialtype == 'serial'): try: self._serial = Serial() self._serial.port = self._port self._serial.baudrate = self._baudrate self._serial.open() self.Warning_Signal.emit('打开串口成功') return 1 except: self.Warning_Signal.emit('打开串口失败') return 0 elif(self._serialtype == 'modbus'): try: self._serial = Instrument(self._port, 1) self._serial.serial.baudrate = self._baudrate self.Warning_Signal.emit('打开串口成功') return 1 except: self.Warning_Signal.emit('打开串口失败') return 0 def read_data(self, n=0): if (self._serialtype == 'serial'): try: if n > 0: return self._serial.read(n) else: self._serial.reset_input_buffer() data = self._serial.readline() return data except: self.Warning_Signal.emit('读取数据失败,请检查串口!') elif (self._serialtype == 'modbus'): try: data = self._serial.read_registers(0, 8) return data except: self.Warning_Signal.emit('读取数据失败,请检查串口!') def send_data(self, data): if (self._serialtype == 'serial'): self._serial.write(data) def close(self): if (self._serialtype == 'serial'): try: self._serial.close() except IOError: self.Warning_Signal.emit('关闭串口失败') elif (self._serialtype == 'modbus'): pass
#!/usr/bin/env python if __name__ == '__main__': import sys from minimalmodbus import Instrument if len(sys.argv) < 3: print 'Usage: {} [COM] [SLAVE] <baudrate=57600>'.format(sys.argv[0]) exit(1) port = sys.argv[1] slave = int(sys.argv[2]) try: baudrate = int(sys.argv[3]) except Exception: baudrate = 57600 instrument = Instrument(port, slave) instrument.serial.baudrate = baudrate instrument.serial.timeout = 1 instrument.write_registers( 0x0002, # Address [0xFFFF], # Data, any value will do. )
class EnergyModbusReader: energy_device_id = None instrument = None appSocketIO = None modbusConfig = None def __init__(self, energy_device_id, appSocketIO=None): self.logger = logging.getLogger( 'nl.oppleo.services.EnergyModbusReader') self.energy_device_id = energy_device_id self.appSocketIO = appSocketIO self.oppleoConfig: OppleoConfig = OppleoConfig() self.logger.debug('Production environment, calling initInstrument()') self.initInstrument() self.threadLock = threading.Lock() def initInstrument(self): global SDM630v2, SDM120 energy_device_data = EnergyDeviceModel.get() self.logger.debug( 'found device: %s %s %d' % (energy_device_data.energy_device_id, energy_device_data.port_name, energy_device_data.slave_address)) try: self.instrument = Instrument( port=energy_device_data.port_name, slaveaddress=energy_device_data.slave_address) except Exception as e: self.logger.error("initInstrument() failed: {}".format(str(e))) raise # Get this from the database self.instrument.serial.baudrate = energy_device_data.baudrate self.instrument.serial.bytesize = energy_device_data.bytesize self.instrument.serial.parity = energy_device_data.parity self.instrument.serial.stopbits = energy_device_data.stopbits self.instrument.serial.timeout = energy_device_data.serial_timeout self.instrument.debug = energy_device_data.debug self.instrument.mode = energy_device_data.mode self.instrument.close_port_after_each_call = energy_device_data.close_port_after_each_call self.modbusConfig = SDM630v2 for i in range(len(modbusConfigOptions)): if energy_device_data.modbus_config == modbusConfigOptions[i][ MB.NAME]: self.modbusConfig = modbusConfigOptions[i] self.logger.debug("Modbus config {} selected (default: {}).".format( self.modbusConfig[MB.NAME], SDM630v2[MB.NAME])) self.readSerialNumber(energy_device_data.port_name, energy_device_data.slave_address) def readSerialNumber(self, port_name=None, slave_address=None): self.logger.debug('readSerialNumber()') if self.modbusConfig[MB.SN][MB.ENABLED]: if self.modbusConfig[MB.SN][MB.TYPE] == MB.TYPE_REGISTER: serial_Hi = self.instrument.read_register( \ self.modbusConfig[MB.SN][MB.HI][MB.REGISTER_ADDRESS], \ self.modbusConfig[MB.SN][MB.HI][MB.NUMBER_OF_DECIMALS], \ self.modbusConfig[MB.SN][MB.HI][MB.FUNCTION_CODE], \ self.modbusConfig[MB.SN][MB.HI][MB.SIGNED] \ ) serial_Lo = self.instrument.read_register( \ self.modbusConfig[MB.SN][MB.LO][MB.REGISTER_ADDRESS], \ self.modbusConfig[MB.SN][MB.LO][MB.NUMBER_OF_DECIMALS], \ self.modbusConfig[MB.SN][MB.LO][MB.FUNCTION_CODE], \ self.modbusConfig[MB.SN][MB.LO][MB.SIGNED] \ ) self.logger.debug( 'readSerialNumber() serial_Hi:{} serial_Lo:{}'.format( serial_Hi, serial_Lo)) self.oppleoConfig.kWhMeterSerial = str((serial_Hi * 65536) + serial_Lo) self.logger.info( 'kWh meter serial number: {} (port:{}, address:{})'.format( self.oppleoConfig.kWhMeterSerial, port_name, slave_address)) else: self.logger.warn( 'modbusConfig serialNumber type {} not supported!'.format( self.modbusConfig[MB.SN][MB.TYPE])) self.oppleoConfig.kWhMeterSerial = 99999999 else: self.oppleoConfig.kWhMeterSerial = 99999999 return self.oppleoConfig.kWhMeterSerial def getTotalKWHHValue(self): self.logger.debug('Production environment, getting real data') return self.getProdTotalKWHHValue() def getMeasurementValue(self): self.logger.debug('Production environment, getting real data') return self.getProdMeasurementValue() def getProdTotalKWHHValue(self): if self.modbusConfig[MB.TOTAL_ENERGY][MB.TYPE] == MB.TYPE_FLOAT: return round( self.try_read_float( value_desc='kwh', registeraddress=self.modbusConfig[MB.TOTAL_ENERGY][ MB.REGISTER_ADDRESS], functioncode=self.modbusConfig[MB.TOTAL_ENERGY][ MB.FUNCTION_CODE], number_of_registers=self.modbusConfig[MB.TOTAL_ENERGY][ MB.NUMBER_OF_REGISTERS], byteorder=self.modbusConfig[MB.TOTAL_ENERGY][ MB.BYTE_ORDER]), 1) else: self.logger.warn( 'modbusConfig total_kWh type {} not supported!'.format( self.modbusConfig[MB.TOTAL_ENERGY][MB.TYPE])) return 0 def try_read_float_from_config(self, name, el): # self.logger.debug("try_read_float_from_config name:{} el:{}".format(name, str(el))) if not el[MB.ENABLED]: self.logger.debug("Modbus element {} not enabled".format(name)) return 0 if el[MB.TYPE] != MB.TYPE_FLOAT: self.logger.warn( "Type {} for modbus element {} not supported (must be {})". format(el[MB.TYPE], name, MB.TYPE_FLOAT)) return 0 return round( self.try_read_float(value_desc=name, registeraddress=el[MB.REGISTER_ADDRESS], functioncode=el[MB.FUNCTION_CODE], number_of_registers=el[MB.NUMBER_OF_REGISTERS], byteorder=el[MB.BYTE_ORDER]), 1) def getProdMeasurementValue(self): L1_P = self.try_read_float_from_config( 'l1_p', self.modbusConfig[MB.L1][MB.POWER]) L1_V = self.try_read_float_from_config( 'l1_v', self.modbusConfig[MB.L1][MB.VOLT]) L1_A = self.try_read_float_from_config( 'l1_a', self.modbusConfig[MB.L1][MB.AMP]) L1_kWh = self.try_read_float_from_config( 'l1_kWh', self.modbusConfig[MB.L1][MB.ENERGY]) L2_P = self.try_read_float_from_config( 'l2_p', self.modbusConfig[MB.L2][MB.POWER]) L2_V = self.try_read_float_from_config( 'l2_v', self.modbusConfig[MB.L2][MB.VOLT]) L2_A = self.try_read_float_from_config( 'l2_a', self.modbusConfig[MB.L2][MB.AMP]) L2_kWh = self.try_read_float_from_config( 'l2_kWh', self.modbusConfig[MB.L2][MB.ENERGY]) L3_P = self.try_read_float_from_config( 'l3_p', self.modbusConfig[MB.L3][MB.POWER]) L3_V = self.try_read_float_from_config( 'l3_v', self.modbusConfig[MB.L3][MB.VOLT]) L3_A = self.try_read_float_from_config( 'l3_a', self.modbusConfig[MB.L3][MB.AMP]) L3_kWh = self.try_read_float_from_config( 'l3_kWh', self.modbusConfig[MB.L3][MB.ENERGY]) kWh = self.try_read_float_from_config( 'kWh', self.modbusConfig[MB.TOTAL_ENERGY]) Hz = self.try_read_float_from_config('hz', self.modbusConfig[MB.FREQ]) return { "energy_device_id": self.energy_device_id, "kwh_l1": L1_kWh, "kwh_l2": L2_kWh, "kwh_l3": L3_kWh, "a_l1": L1_A, "a_l2": L2_A, "a_l3": L3_A, "v_l1": L1_V, "v_l2": L2_V, "v_l3": L3_V, "p_l1": L1_P, "p_l2": L2_P, "p_l3": L3_P, "kw_total": kWh, "hz": Hz } """ minimalmodbus.read_float raises: TypeError, ValueError if functioncode is unknown, number_of_registers is out of bounds ModbusException NoResponseError("No communication with the instrument (no answer)") serial.SerialException (inherited from IOError) """ def try_read_float(self, value_desc, registeraddress, functioncode, number_of_registers, byteorder, default=0): value = default maxRetries = 3 tries = 1 # Used by MeasureElectricityUsageThread and ChargerHandlerThread while True: try: with self.threadLock: value = self.instrument.read_float(registeraddress, functioncode, number_of_registers, byteorder) # Yield if we can, allow other time constraint threads to run if self.appSocketIO is not None: self.appSocketIO.sleep(0.01) return value except (ModbusException, NoResponseError, SerialException) as e: # Recoverable IO errors, try again self.logger.debug( "Could not read value {} due to potential recoverable exception {}" .format(value_desc, e)) except (TypeError, ValueError, Exception) as e: # Catch all, won't recover self.logger.warning( "Failed to read {} from modbus due to exception {}. Using {}" .format(value_desc, e, value)) return value if tries >= maxRetries: # No more retries, fail now self.logger.warning( "Failed to read {} from modbus after trying {} times. Using {}" .format(value_desc, tries, value)) return value tries += 1 # Wait before retry if self.appSocketIO is not None: self.appSocketIO.sleep(0.05) self.logger.debug( "Trying again ({}) to read modbus for {}...".format( (tries), value_desc))
#!/usr/bin/env python import sys from minimalmodbus import Instrument if __name__ == "__main__": if len(sys.argv) < 3: print 'Usage: %s [COM] [SLAVE_ADDRESS]' % sys.argv[0] exit(1) port = sys.argv[1] slave_address = int(sys.argv[2]) inst = Instrument(port, slave_address) inst.serial.baudrate = 57600 inst.serial.timeout = 1 # inst.debug = True # print inst # Read both registers from slave. response = inst.read_registers(0x0000, 1) print 'IR inputs: {:02X}'.format(response[0])
def read_regs(mst: modbus.Instrument, start: int, count: int): return mst.read_registers(start, count)
def write_regs(mst: modbus.Instrument, start: int, data: list): mst.write_registers(start, data)
import signal import time from minimalmodbus import Instrument if len(sys.argv) < 3: print 'Usage: {} [COM] [SLAVE] <baudrate=57600>'.format(sys.argv[0]) exit(1) port = sys.argv[1] slave = int(sys.argv[2]) try: baudrate = int(sys.argv[3]) except Exception: baudrate = 57600 instrument = Instrument(port, slave) instrument.serial.baudrate = baudrate instrument.serial.timeout = 1 def signal_handler(signal, frame): print('Turning all LEDs off.') instrument.write_registers(0x1000, [0x0000] * NEOPIXEL_SIZE) sys.exit(0) signal.signal(signal.SIGINT, signal_handler) led = [[0, 0, 0] for x in xrange(NEOPIXEL_SIZE)] j = 1 k = 1 print 'Rainbow.' while True:
class RCUModbusAdapter: """ RCU MODBUS interface This is the python class object for Xnergy RCU ROS Driver MODBUS RTU adapter class. RCUModbus Interface python class object require to input serialport to initiate the class object RCUModbusInterface class object generally provide three function: a) Trigger RCU unit to charge through MODBUS RTU b) Trigger RCU unit to discharge through MODBUS RTU c) Trigger RCU unit to update status and capture the information into RCUModbusInterface object variables """ def __init__(self, port="/dev/ttyUSB0", slave_addr=16, baudrate=9600): """ Initialize RCU modbus rtu """ self.is_connected = True self.firmware_version_number = -1 self.runtime_voltage_setting = -1 self.runtime_current_setting = -1 self.charge_status = -1 self.charge_status_message = 'None' self.voltage_conversion = -1 self.current_conversion = -1 self.rcu_lock = Lock() self._baudrate = baudrate self._slave_addr = slave_addr self._port = port self.errors = [] self._previous_shadow_error_high = 0 self._previous_shadow_error_low = 0 def connect(self): try: if(self.is_connected): self._instrument.close() self._instrument = Instrument( port=self._port, mode=MODE_RTU, slaveaddress=self._slave_addr) self._instrument.serial.baudrate = self._baudrate self._instrument.serial.timeout = 1 self._instrument.mode = MODE_RTU # RCU Hardware Setting # Read RCU Hardware Setting # firmware version information firmware_version_number_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_FIRMWARE_VERSION_NUMBER, number_of_registers=1, functioncode=_MODBUS_READ_INPUT_REGISTERS) self.firmware_version_number = firmware_version_number_reg[0] # runtime voltage setting information runtime_voltage_setting_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_RUNTIME_VOLTAGE_SETTING, number_of_registers=1, functioncode=_MODBUS_READ_HOLDING_REGISTERS) self.runtime_voltage_setting = float( runtime_voltage_setting_reg[0])/128 # runtime currnet setting information runtime_current_setting_reg = self._instrument.read_registers(registeraddress=_MODBUS_ADDRESS_RUNTIME_CURRENT_SETTING, number_of_registers=1, functioncode=_MODBUS_READ_HOLDING_REGISTERS) self.runtime_current_setting = float( runtime_current_setting_reg[0])/128 # Set voltage conversion if self.runtime_voltage_setting > 48.0: self.voltage_conversion = 0.02229 else: self.voltage_conversion = 0.01155 if self.runtime_voltage_setting > 48.0: self.current_conversion = 0.02014 else: self.current_conversion = 0.04028 return True except: self.is_connected = False return False # self._instrument.serial.timeout = 0.4 def enable_charge(self): """ Enable RCU to charge """ return self.write_bit(_MODBUS_ADDRESS_ENABLE_CHARGING, 1) def disable_charge(self): """ Disable RCU to charge """ return self.write_bit(_MODBUS_ADDRESS_ENABLE_CHARGING, 0) def write_bit(self, register_address, input_value): """ Sending command to RCU unit with threading lock to prevent parallel access to interface """ self.rcu_lock.acquire() result = False try: self._instrument.write_bit( registeraddress=register_address, value=input_value) result = True except serial.serialutil.SerialException as e: rospy.logwarn( "Serial exception when writing into a register. %s", str(e)) except (minimalmodbus.NoResponseError, minimalmodbus.InvalidResponseError) as e: rospy.logwarn("%s.", str(e)) self.rcu_lock.release() return result def reset_errors(self): self._previous_shadow_error_low = 0 self._previous_shadow_error_high = 0 def get_rcu_status(self): """ Get charging and hardware information from RCU unit and store the information to RCUModbusInterface object variable """ self.rcu_lock.acquire() # charging status information try: data = self._instrument.read_registers(registeraddress=0, number_of_registers=_MODBUS_NUM_REGISTERS, functioncode=_MODBUS_READ_INPUT_REGISTERS) except serial.serialutil.SerialException as e: rospy.logwarn("Could not read holding register. %s", str(e)) self.charge_status = ChargerState.RCU_NOT_CONNECTED self.charge_status_message = translate_charge_status( self.charge_status) self.rcu_lock.release() return except (minimalmodbus.NoResponseError, minimalmodbus.InvalidResponseError) as e: rospy.logdebug("Invalid Modbus response.") self.charge_status = ChargerState.RCU_NOT_CONNECTED self.charge_status_message = translate_charge_status( self.charge_status) self.rcu_lock.release() return except: rospy.logwarn("Could not read holding register.") self.charge_status = ChargerState.RCU_NOT_CONNECTED self.charge_status_message = translate_charge_status( self.charge_status) self.rcu_lock.release() return charge_status = data[_MODBUS_ADDRESS_CHARGE_STATUS] self.charge_status = charge_status self.charge_status_message = translate_charge_status(charge_status) # rcu device id information self.rcu_device_id = data[_MODBUS_ADDRESS_RCU_DEVICE_ID] # RCU real time error self.errors = [] rcu_error_low = data[_MODBUS_ADDRESS_RCU_ERROR_LOW] if rcu_error_low > 0: for error in rcu_error_data_list: if (rcu_error_low & error): error_msg = translate_error_code(error, 'low') self.errors.append(error_msg) rcu_error_high = data[_MODBUS_ADDRESS_RCU_ERROR_HIGH] if not rcu_error_high > 0: for error in rcu_error_data_list: if (rcu_error_high & error): error_msg = translate_error_code(error, 'high') self.errors.append(error_msg) # Shadow Error shadow_error_low = data[_MODBUS_ADDRESS_SHADOW_ERROR_LOW] # append only new shadow errors to error list new_shadow_error_low = (~self._previous_shadow_error_low ) & shadow_error_low if new_shadow_error_low > 0: for error in rcu_error_data_list: if (new_shadow_error_low & error): error_msg = translate_error_code(error, 'low') self.errors.append(error_msg) self._previous_shadow_error_low = shadow_error_low shadow_error_high = data[_MODBUS_ADDRESS_SHADOW_ERROR_HIGH] # append only new shadow errors to error list new_shadow_error_high = (~self._previous_shadow_error_high ) & shadow_error_high if new_shadow_error_high > 0: for error in rcu_error_data_list: if (new_shadow_error_high & error): error_msg = translate_error_code(error, 'high') self.errors.append(error_msg) self._previous_shadow_error_high = shadow_error_high # output current information output_current = data[_MODBUS_ADDRESS_OUTPUT_CURRENT] self.output_current = float(output_current) * self.current_conversion # battery voltage information battery_voltage = data[_MODBUS_ADDRESS_BATTERY_VOLTAGE] self.battery_voltage = float(battery_voltage) * self.voltage_conversion # RCU Hardware Status variable # device temperature information self.device_temperature = data[_MODBUS_ADDRESS_DEVICE_TEMPERATURE] # coil temperature information self.coil_temperature = data[_MODBUS_ADDRESS_COIL_TEMPERATURE] self.rcu_lock.release()
#!/usr/bin/env python import sys import time from minimalmodbus import Instrument if __name__ == "__main__": if len(sys.argv) < 2: print 'Usage: %s [COM]' % sys.argv[0] exit(1) port = sys.argv[1] inst = Instrument(port, 1) inst.serial.baudrate = 57600 inst.serial.timeout = 0.1 for i in range(1, 16): try: inst.address = i response = inst.read_registers(0x0001, 1) except IOError: pass else: print hex(response[0]) fw_version = response[0] & 0x0FFF hw_version = response[0] >> 12 print 'Slave {}: FW {:03X}, HW {:01X}'.format( i, fw_version, hw_version) time.sleep(0.01)
def reconnect(self): ModbusInstrument.__init__(self, port, 1) print('reconnected')
class Slave: def __init__(self, label, slave_id, slave_address, setupsAdr, setupsCount, variablesAdr, variablesCount, port): self.label = label self.id = slave_id self.port = port self.slave_address = slave_address self.setupsAdr = setupsAdr self.setupsCount = setupsCount self.variablesAdr = variablesAdr self.variablesCount = variablesCount try: self.instrument = Instrument(self.port, slave_address) except: self.status = "ERROR" traceback.print_exc() self.status = "NEW" self.variable_values = [] self.config_values = [] def getConfig(self, adr): if self.status == "OK": return self.config_values[adr] else: return 0 def getValue(self, adr): if self.status == "OK": return self.variable_values[adr - self.variablesAdr] else: return 0 def getVariables(self): try: self.variable_values = self.instrument.read_registers( self.variablesAdr, self.variablesCount) self.status = "OK" except IOError: self.status = "ERROR" traceback.print_exc() def getConfigs(self): try: self.config_values = self.instrument.read_registers( self.setupsAdr, self.setupsCount) self.status = "OK" except IOError: self.status = "ERROR" traceback.print_exc() def setConfigs(self): try: #TODO Detener el hilo de actualización de las variables self.instrument.write_registers(self.setupsAdr, self.config_values) self.status = "OK" except IOError: self.status = "ERROR" traceback.print_exc() def run(self): if self.status != "OK": self.getConfigs() self.getVariables() def simulate(self): print('Simulating from slave: %s' % self.id) from random import randint self.variable_values = [ randint(0, 100) for i in range(self.variablesCount) ] self.status = "SIMULATE"