Esempio n. 1
0
def read_regs(mst: modbus.Instrument, start: int, count: int):
    return mst.read_registers(start, count)
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()
Esempio n. 3
0
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)

    print 'Done.'
Esempio n. 4
0
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"
Esempio n. 5
0
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,
        end_time - start_time,
    )
Esempio n. 6
0
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)

    print 'Done.'
Esempio n. 7
0
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