Esempio n. 1
0
    def __init__(self, receive_callback=None, debug=False):
        self.debug = debug

        self.serial_device = SerialDevice()
        self.receive_callback = receive_callback

        self.get_status_callback = None

        # status

        self.status = {
            'state': None,
            'angle': {
                'a1': 0.0,
                'a2': 0.0,
                'a3': 0.0,
                'a4': 0.0,
                'a5': 0.0,
                'a6': 0.0,
                'rail': 0.0,
            },
            'cartesian': {
                'tx': 0.0,
                'ty': 0.0,
                'tz': 0.0,
                'rx': 0.0,
                'ry': 0.0,
                'rz': 0.0,
            },
            'pump_pwm': 0,
            'valve_pwm': 0,
            'motion_mode': 0,
        }
Esempio n. 2
0
 def connectClicked_Callback(self):
     if self.dev == None:
         self.dev = SerialDevice(self.port)
         self.setWidgetEnableOnConnect()
     else:
         self.connectPushButton.setText('Connect')
         self.dev.close()
         self.dev = None
         self.setWidgetEnableOnDisconnect()
Esempio n. 3
0
 def ble(self):
     self.device = BleDevice(self)
     logging.info('Starting Sparklet')
     self.device.start()
     logging.info('Hit <ENTER> to disconnect')
     input()
     self.device.stop()
     self.stop_animation_process()
     logging.info('Sparklet stopped')
class MasterArmV2:
    # Device IDs to allow for the axis config.
    deviceIDs = [0x01, 0x02, 0x03, 0x04, 0x05]

    # create an instance of SerialDevice()
    serial_dev = SerialDevice()

    # that instance is passed as argument to BplSerial
    global_serial = BplSerial(serial_dev, len(deviceIDs))

    def __init__(self):
        self.deviceIDs = [0xC1, 0xC2, 0xC3, 0xC4, 0xC5]
        self.global_serial.deviceIDs = self.deviceIDs

    def usb_list(self):
        '''
        Prints a list of available serial ports.
        This is a helper function and is non-essential.
        :return: None
        '''
        comports = serial.tools.list_ports.comports()
        print('***\nCOM PORT LIST:')
        for comport in comports:
            print(comport, comport.device)
        print('***\n')

    def connect(self):
        self.global_serial.connect(COM_PORT, BAUD)

    def get_packets(self):
        packets = self.global_serial.serial_device.readdata()
        return packets

    def parse_packets(self, packets):
        return [
            self.global_serial.serial_device.parsepacket(p) for p in packets
        ]
Esempio n. 5
0
class SimpleGuiMainWindow(QtGui.QMainWindow,Ui_MainWindow):

    def __init__(self,parent=None):
        super(SimpleGuiMainWindow,self).__init__(parent)
        self.setupUi(self)
        self.setupTimer()
        self.connectActions()
        self.initialize()

    def setupTimer(self):
        """
        Setup timer object
        """
        self.timer = QtCore.QTimer()
        self.timer.setInterval(TIMER_INTERVAL_MS)
        try:
            self.timer.timeout.connect(self.timer_Callback)
        except AttributeError:
            self.connect(self.timer,QtCore.SIGNAL("timeout()"),self.timer_Callback)        

    def connectActions(self):
        self.portLineEdit.editingFinished.connect(self.portChanged_Callback)
        self.connectPushButton.pressed.connect(self.connectPressed_Callback)
        self.connectPushButton.clicked.connect(self.connectClicked_Callback)
        self.measurePushButton.clicked.connect(self.measureClicked_Callback)

    def initialize(self):
        self.port = DFLT_PORT
        self.portLineEdit.setText(self.port) 
        self.setWidgetEnableOnDisconnect()
        self.dev = None
        self.isLogging = False
        self.logPath = '/Users/x1sc0/datalog.txt';
        self.createLogFile()

    def portChanged_Callback(self):
        self.port = str(self.portLineEdit.text())

    def connectPressed_Callback(self):
        if self.dev == None:
            self.connectPushButton.setText('Disconnect')
            self.portLineEdit.setEnabled(False)

    def connectClicked_Callback(self):
        if self.dev == None:
            self.dev = SerialDevice(self.port)
            self.setWidgetEnableOnConnect()
        else:
            self.connectPushButton.setText('Connect')
            self.dev.close()
            self.dev = None
            self.setWidgetEnableOnDisconnect()

    def measureClicked_Callback(self):
        if self.isLogging:
            self.timer.stop()
            self.isLogging = False
            self.pwrTextEdit.setText("")
            self.ldrTextEdit.setText("")
        else:
            self.timer.start()
            self.isLogging = True

    def timer_Callback(self):
        data = self.dev.getMeasurement()
        pwr = str(data[0])
        ldr = str(data[1])
        self.pwrTextEdit.setText(pwr)
        self.ldrTextEdit.setText(ldr)
        self.logger.log(logging.DEBUG,data)

    def createLogFile(self):
        logging.basicConfig(filename=self.logPath,
                            level=logging.DEBUG,
                            format='%(asctime)s %(message)s', 
                            datefmt='%m/%d/%Y %I:%M:%S')

        self.logger = logging.getLogger(__name__)

    def setWidgetEnableOnConnect(self):
        self.pwrTextEdit.setEnabled(True)
        self.ldrTextEdit.setEnabled(True)
        self.measurePushButton.setEnabled(True)
        self.portLineEdit.setEnabled(False)

    def setWidgetEnableOnDisconnect(self):
        self.pwrTextEdit.setEnabled(False)
        self.ldrTextEdit.setEnabled(False)
        self.measurePushButton.setEnabled(False)
        self.portLineEdit.setEnabled(True)

    def main(self):
        self.show()
Esempio n. 6
0
class Reach5Mini():
    """Reach5Mini Class: Example class used for interfacing with the Reach5Mini attached on the serial port (COM_PORT)
        Has example functionality for sending commands (eg. position, velocity, mode),
        and requesting data (eg. position, current, mode, serial number).
    """
    # 5 device IDs to allow for the 5 axis config.
    deviceIDs = [0x01, 0x02, 0x03, 0x04, 0x05]
    # create an instance of SerialDevice()
    serial_dev = SerialDevice()
    # that instance is passed as argument to BplSerial
    global_serial = BplSerial(serial_dev, len(deviceIDs))
    # If more than one serial device is required (i.e. for multiple grabbers),
    # create additional instances of SerialDevice() and BplSerial()
    # EG: serial_dev_2 = SerialDevice()
    # global_serial_2 = BplSerial(serial_dev_2)

    global_serial.deviceIDs = deviceIDs

    def connect(self):
        self.global_serial.connect(COM_PORT, BAUD)

    def usb_list(self):
        '''
        Prints a list of available serial ports.
        This is a helper function and is non-essential.
        :return: None
        '''
        comports = serial.tools.list_ports.comports()
        print('***\nCOM PORT LIST:')
        for comport in comports:
            print(comport, comport.device)
        print('***\n')

    def enable_all(self):
        '''
        Axes must be enabled before they will respond to further commands.
        :return: None
        '''
        for devid in self.deviceIDs:
            self.global_serial.send_mode(devid, Mode.STANDBY)
        print('Reach5Mini enable_all()')

    def disable_all(self):
        '''
        Disable all axes
        :return: None
        '''
        for devid in self.deviceIDs:
            self.global_serial.send_mode(devid, Mode.DISABLE)
        print('Reach5Mini disable_all()')

    def set_position(self, device_id, position):
        """Set device position: in radians for rotate, or millimetre for grabber"""
        self.global_serial.send_position(device_id, position)
        print('Reach5Mini sent position for device', device_id, ':', position)

    def set_velocity(self, device_id, velocity):
        """Set device velocity: in radians per second for rotate, or millimetres per second for grabber"""
        self.global_serial.send_velocity(device_id, velocity)
        print('Reach5Mini sent velocity for device', device_id, ':', velocity)

    def set_openloop(self, device_id, openloop):
        """Set device openloop: in radians per second for rotate, or millimetres per second for grabber - 
            THIS CAN BE DANGEROUS, NOT RECOMMENDED
        """
        self.global_serial.send_openloop(device_id, openloop)
        print('Reach5Mini sent openloop for device', device_id, ':', openloop)

    def set_current(self, device_id, current):
        """Set device current: in mA - THIS CAN BE DANGEROUS, NOT RECOMMENDED"""
        self.global_serial.send_current(device_id, current)
        print('Reach5Mini sent current for device', device_id, ':', current)

    def set_mode(self, device_id, mode):
        """Set device mode: refer to MODE list in RS1_hardware.py for details"""
        self.global_serial.send_mode(device_id, mode)
        print('Reach5Mini sent mode for device', device_id, ':', mode)

    def get_voltage(self):
        '''
        See NOTES ON RECEIVING INFO FROM RS1 at top of document
        for optimisation of this and subsequent get_... functions
        :return: float
        '''
        self.global_serial.send_request_packet(self.deviceIDs[4],
                                               PacketID.SUPPLYVOLTAGE)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(
            self.deviceIDs[4])
        voltage = this_motor[PacketID.SUPPLYVOLTAGE]
        print('voltage:', str(voltage))
        return voltage

    def get_mode(self, deviceID):
        self.global_serial.send_request_packet(deviceID, PacketID.MODE)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(deviceID)
        mode = this_motor[PacketID.MODE]
        print('mode:', str(mode))
        return mode

    def get_current(self, deviceID):
        self.global_serial.send_request_packet(deviceID, PacketID.CURRENT)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(deviceID)
        current = this_motor[PacketID.CURRENT]
        print('current:', str(current))
        return current

    def get_velocity(self, deviceID):
        self.global_serial.send_request_packet(deviceID, PacketID.VELOCITY)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(deviceID)
        velocity = this_motor[PacketID.VELOCITY]
        print('velocity:', str(velocity))
        return velocity

    def get_position(self, deviceID):
        self.global_serial.send_request_packet(deviceID, PacketID.POSITION)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(deviceID)
        position = this_motor[PacketID.POSITION]
        print('position:', str(position))
        return position

    def get_model_number(self):
        self.global_serial.send_request_packet(self.deviceIDs[4],
                                               PacketID.MODEL_NUMBER)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(
            self.deviceIDs[4])
        model_number = this_motor[PacketID.MODEL_NUMBER]
        print('model number:', str(model_number))
        return model_number

    def get_serial_number(self):
        self.global_serial.send_request_packet(self.deviceIDs[4],
                                               PacketID.SERIAL_NUMBER)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(
            self.deviceIDs[4])
        serial_number = this_motor[PacketID.SERIAL_NUMBER]
        print('serial number:', str(serial_number))
        return serial_number

    def get_firmware_version(self):
        self.global_serial.send_request_packet(self.deviceIDs[4],
                                               PacketID.VERSION)
        time.sleep(
            0.1)  # give the serial protocol 0.1 seconds to receive the message
        self.global_serial.updateMotor(1)
        this_motor = self.global_serial.get_motor_by_device_id(
            self.deviceIDs[4])
        version = this_motor[PacketID.VERSION]
        print('firmware version:', str(version))
        return version
Esempio n. 7
0
 def __init__(self, receive_callback=None, debug=False):
     # The component to which this extension is attached
     self.serial_device = SerialDevice()
     self.receive_callback = receive_callback
     self.debug = debug
Esempio n. 8
0
class Mirobot:
    def __init__(self, receive_callback=None, debug=False):
        # The component to which this extension is attached
        self.serial_device = SerialDevice()
        self.receive_callback = receive_callback
        self.debug = debug

    #COMMUNICATION #

    # send a message
    def send_msg(self, msg):
        if self.is_connected():
            self.serial_device.send(msg,  terminator='\r\n')
        if self.debug:
            print('Message sent: ', msg)

    # message receive handler
    def _receive_msg(self, msg):
        msg = msg.decode('utf-8')
        if self.debug:
            print('Message received:', msg)
        if self.receive_callback is not None:
            try:
                self.receive_callback(msg)
            except Exception as e:
                print(e)
                print('Receive callback error: ', sys.exc_info()[0])

    # check if we are connected
    def is_connected(self):
        return self.serial_device.is_open

    # connect to the mirobot
    def connect(self, portname, receive_callback=None):
        self.serial_device.portname = portname
        self.serial_device.baudrate = 115200
        self.serial_device.stopbits = 1
        self.serial_device.listen_callback = self._receive_msg

        if receive_callback is not None:
            self.receive_callback = receive_callback

        self.serial_device.open()

    # set the receive callback
    def set_receive_callback(self, receive_callback):
        self.receive_callback = receive_callback

    # disconnect from the mirobot
    def disconnect(self):
        self.serial_device.close()

    # COMMANDS #

    # home each axis individually
    def home_individual(self):
        msg = '$HH'
        self.send_msg(msg)

    # home all axes simultaneously
    def home_simultaneous(self):
        msg = '$H'
        self.send_msg(msg)

    # set the hard limit state
    def set_hard_limit(self, state):
        msg = '$21=' + str(int(state))
        self.send_msg(msg)

    # set the soft limit state
    def set_soft_limit(self, state):
        msg = '$21=' + str(int(state))
        self.send_msg(msg)

    # unlock the shaft
    def unlock_shaft(self):
        msg = 'M50'
        self.send_msg(msg)

    # send all axes to their respective zero positions
    def go_to_zero(self):
        self.go_to_axis(0, 0, 0, 0, 0, 0, 2000)

    # send all axes to a specific position
    def go_to_axis(self, a1, a2, a3, a4, a5, a6, speed):
        msg = 'M21 G90'
        msg += ' X' + str(a1)
        msg += ' Y' + str(a2)
        msg += ' Z' + str(a3)
        msg += ' A' + str(a4)
        msg += ' B' + str(a5)
        msg += ' C' + str(a6)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # increment all axes a specified amount
    def increment_axis(self, a1, a2, a3, a4, a5, a6, speed):
        msg = 'M21 G91'
        msg += ' X' + str(a1)
        msg += ' Y' + str(a2)
        msg += ' Z' + str(a3)
        msg += ' A' + str(a4)
        msg += ' B' + str(a5)
        msg += ' C' + str(a6)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # point to point move to a cartesian position
    def go_to_cartesian_ptp(self, x, y, z, a, b, c, speed):
        msg = 'M20 G90 G0'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # linear move to a cartesian position
    def go_to_cartesian_lin(self, x, y, z, a, b, c, speed):
        msg = 'M20 G90 G1'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # point to point increment in cartesian space
    def increment_cartesian_ptp(self, x, y, z, a, b, c, speed):
        msg = 'M20 G91 G0'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # linear increment in cartesian space
    def increment_cartesian_lin(self, x, y, z, a, b, c, speed):
        msg = 'M20 G91 G1'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # set the pwm of the air pump
    def set_air_pump(self, pwm):
        msg = 'M3S' + str(pwm)
        self.send_msg(msg)

    # set the pwm of the gripper
    def set_gripper(self, pwm):
        msg = 'M4E' + str(pwm)
        self.send_msg(msg)
Esempio n. 9
0
def findAnimaticsDevicePort(baudrate):
    serialPortList = findSerialDevicePorts()
    matchingList = []
    for port in serialPortList:
        try:
            dev = SerialDevice(port=port,
                               baudrate=baudrate,
                               timeout=0.1,
                               write_write_delay=0.1,
                               write_read_delay=0.1,
                               debug=DEBUG)
            dev.flushInput()
            dev.flushOutput()
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET)+'WAKE ',delay_write=True)
            time.sleep(0.1)
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET)+'WAKE ',delay_write=True)
            time.sleep(0.1)
            dev.flushInput()
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET)+'ECHO ',delay_write=True)
            dev.readlines()
            response = dev.writeRead(chr(MOTOR_ADDRESS_OFFSET)+'RPI ',use_readline=False,check_write_freq=True)
            dev.close()
            # Animatics response will either be 'RPI 3.141592741 '
            # or '3.141592741 ' depending on ECHO setting
            # Must enable ECHO so it will work when multiple motors are chained
            response = response.replace(chr(MOTOR_ADDRESS_OFFSET)+'RPI ','')
            if (0 < len(response)) and (response[0] == '3'):
                print("Found an Animatics device!")
                return port
        except serial.SerialException:
            pass

    if len(matchingList) == 0:
        err_str = 'Could not find Animatics device. Check connections and power or specify port.\n'
        err_str += 'Tried ports: ' + str(serialPortList)
        raise RuntimeError(err_str)
    elif 1 < len(matchingList):
        err_str = 'Found more than one Animatics device. Specify port.'
        err_str += 'Matching ports: ' + str(matchingList)
        raise RuntimeError(err_str)
    else:
        return matchingList[0]
Esempio n. 10
0
 def serial(self):
     self.device = SerialDevice(self)
     logging.info('Starting Sparklet')
     self.device.start()
     self.stop_animation_process()
     logging.info('Sparklet stopped')
Esempio n. 11
0
class Sparklet:
    def __init__(self):
        signal(SIGINT, self.on_sigint)
        self.animations_dir = os.path.join(os.getcwd(), 'animations')
        os.makedirs(self.animations_dir, exist_ok=True)
        self.protocol = EPXProtocol()
        self.animator_process = None

        self.command_handlers = [
            self.on_connect_headerrq,
            self.on_clear_display,
            self.on_display_brightness,
            self.on_enumerate_animations,
            self.on_preview_color,
            self.on_upload_frame8,
            self.on_upload_animation8,
            self.on_upload_pixel8,
            self.on_remove_animation,
            self.on_store_animation,
            self.on_play_stored_animation8,
            self.on_play_stored_animation8_byname,
            self.on_set_device_name,
            self.on_request_thumbnail,
            self.on_set_key,
            self.on_console_command
        ]
        with open('settings.yaml', 'r') as fh:
            self.settings = yaml.load(fh, Loader=yaml.FullLoader)
        #self.start_animation_process()

    def start_animation_process(self):
        #self.animator = Animator()
        self.frames_queue = Queue()
        self.count = 0
        args = (self.frames_queue, )
        self.animator_process = Process(target=play_frames, args=args)
        self.animator_process.start()

    def stop_animation_process(self):
        if not self.animator_process:
            return

    def run_animation_process(self, target, args):
        if self.animator_process:
            self.animator_process.terminate()
            self.animator_process.join()
        self.animator_process = Process(target=target, args=args)
        self.animator_process.start()

    def ble(self):
        self.device = BleDevice(self)
        logging.info('Starting Sparklet')
        self.device.start()
        logging.info('Hit <ENTER> to disconnect')
        input()
        self.device.stop()
        self.stop_animation_process()
        logging.info('Sparklet stopped')

    def serial(self):
        self.device = SerialDevice(self)
        logging.info('Starting Sparklet')
        self.device.start()
        self.stop_animation_process()
        logging.info('Sparklet stopped')

        
    def on_sigint(self, signum, frame):
        self.device.stop()
        logging.info('Sparklet stopped')
        exit(0)
    
    def on_read_notify(self):
        logging.info(f'Sparklet.on_read_notify')

    def on_read_request(self, offset):
        logging.info(f'Sparklet.on_read_request {offset}')

    def on_write_request(self, data, offset):
        logging.debug(f'Sparklet.on_write_request received {len(data)} bytes at {datetime.now().strftime("%m/%d/%Y-%I:%M:%S.%f")}')
    
        commands, send_ack = self.protocol.decode(data)
        for command in commands:
            header, payload = command
            logging.info(f'Sparklet.on_write_request {EPXCommand(header.command)} - {header.transaction_id}')
            logging.debug(f'Sparklet.on_write_request {payload}')

            handler = self.command_handlers[header.command - 1]
            success = handler(header, payload)

        if send_ack:
            frames = self.protocol.encode_binaryack()
            logging.debug(f'Sparklet.on_write_request sending BINARY ACK at {datetime.now().strftime("%m/%d/%Y-%I:%M:%S.%f")}')
            self._send_frames(frames)
        return True

    def _send_frames(self, frames):
        for frame in frames:
            logging.debug(f'Sparklet.on_enumerate_animations sent {len(frame)} bytes')
            self.device.write(frame)
        return True        

    def on_connect_headerrq(self, command, payload):
        data = {
            'status': 'success',
            'TransactionID': command.transaction_id,
            'data': {
                'FIRMWARE': '0.1',
                'DEVICENAME': self.device.name,
                'CAPABILITIES': ['STORAGE'], #'PREVIEW', 
                'BATTERY': { 'PCT': 100 },
                'DISPLAYWIDTH': DISPLAYWIDTH,
                'DISPLAYHEIGHT': DISPLAYHEIGHT,
                'AUTOPLAY': 1,
                'BRIGHTNESS': self.settings['brightness']
            },
        }

        frames = self.protocol.encode(data, ProtocolFormat.JSON.value, 0)
        return self._send_frames(frames)

    def on_clear_display(self, header, payload):
        self.run_animation_process(clear_display, ())
        return True
    
    def on_display_brightness(self, header, payload):
        self.settings['brightness'] = payload.Brightness
        with open('settings.yaml', 'w') as fh:
            yaml.dump(self.settings, fh)
        return True
    
    def get_animations_list(self):
        files = [f for f in os.listdir(self.animations_dir)]
        animations = []
        for file in files:
            filepath = os.path.join(self.animations_dir, file)
            st = os.stat(filepath)
            
            animation = Animation.load(filepath)

            item = {}
            item['ID'] =  animation.id
            item['Filename'] = animation.name
            item['Size'] = st.st_size
            item['UTC'] = animation.utc

            animations.append(item)
        return animations

    def on_enumerate_animations(self, header, payload):
        df = os.statvfs('/')
        space_used = df.f_bfree / df.f_blocks * 100
        
        data = {
            'status': 'success',
            'TransactionID': payload.TransactionID,
            'StorageUsed': space_used,
            'Sequences': self.get_animations_list()
        }

        frames = self.protocol.encode(data, ProtocolFormat.JSON.value, 0)
        return self._send_frames(frames)

    def on_preview_color(self, header, payload):
        pass
    
    def on_upload_frame8(self, header, payload):
        # TODO: 
        # upload_frame requires a serious amount of CPU 
        # to support live preview. The support for interprocess
        # communication is a bit weak on Python and shared memory
        # support is not coming till Python3.8 which is not yet 
        # supported on Raspberry Pi
        
        # self.frames_queue.put(payload.data)
        # self.count += 1
        # logging.info(f'put={self.frames_queue.qsize()}')
        return True
    
    def on_upload_animation8(self, header, payload):
        pass
    
    def on_upload_pixel8(self, header, payload):
        pass
    
    def on_remove_animation(self, header, payload):
        files = [f for f in os.listdir(self.animations_dir)]
        for file in files:
            filepath = os.path.join(self.animations_dir, file)
            animation = Animation.load(filepath)
            if animation.id == payload.ID:
                os.remove(filepath)
                break
        return True

    def on_store_animation(self, header, payload):
        filename = os.path.join(self.animations_dir, payload.name)
        Animation.save(filename, payload)
        return True
    
    def on_play_stored_animation8(self, header, payload):
        self.run_animation_process(play_by_id, (payload.ID,))
        return True
    
    def on_play_stored_animation8_byname(self, header, payload):
        self.run_animation_process(play_by_id, (payload.Name,))
        return True
    
    def on_set_device_name(self, header, payload):
        pass
    
    def on_request_thumbnail(self, header, payload):
        pass
        
    def on_set_key(self, header, payload):
        pass
    
    def on_console_command(self, header, payload):
        pass
Esempio n. 12
0
class Mirobot:
    def __init__(self, receive_callback=None, debug=False):
        self.debug = debug

        self.serial_device = SerialDevice()
        self.receive_callback = receive_callback

        self.get_status_callback = None

        # status

        self.status = {
            'state': None,
            'angle': {
                'a1': 0.0,
                'a2': 0.0,
                'a3': 0.0,
                'a4': 0.0,
                'a5': 0.0,
                'a6': 0.0,
                'rail': 0.0,
            },
            'cartesian': {
                'tx': 0.0,
                'ty': 0.0,
                'tz': 0.0,
                'rx': 0.0,
                'ry': 0.0,
                'rz': 0.0,
            },
            'pump_pwm': 0,
            'valve_pwm': 0,
            'motion_mode': 0,
        }

    # COMMUNICATION #

    # send a message
    def send_msg(self, msg, get_status=True):
        if self.is_connected():
            self.serial_device.send(msg,  terminator='\r\n')
        if self.debug:
            print('Message sent: ', msg)

        if get_status:
            self.get_status()

    # message receive handler
    def _receive_msg(self, msg):
        msg = msg.decode('utf-8')
        if self.debug:
            print('Message received:', msg)
        if self.receive_callback is not None:
            try:
                self.receive_callback(msg)
            except Exception as e:
                print(e)
                print('Receive callback error: ', sys.exc_info()[0])

        if msg.startswith('<'):
            self._recv_status(msg)

    def _recv_status(self, msg):
        pars = self.ownerComp.par

        msg = msg.strip('<').strip('>')

        state = msg.split(',')[0]
        if state is not None:
            pars.Status = state

        msg = ','.join(msg.split(',')[1:])

        angle = re.match(r'Angle\(ABCDXYZ\):(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),', msg)

        if angle is not None:
            a4, a5, a6, rail, a1, a2, a3 = angle.groups()

            self.status['angle']['a1'] = float(a1)
            self.status['angle']['a2'] = float(a2)
            self.status['angle']['a3'] = float(a3)
            self.status['angle']['a4'] = float(a4)
            self.status['angle']['a5'] = float(a5)
            self.status['angle']['a6'] = float(a6)

        cart = re.match(r'.*Cartesian\scoordinate\(XYZ\sRxRyRz\):(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),(-*\d*.\d*),', msg)
        if cart is not None:
            tx, ty, tz, rx, ry, rz = cart.groups()
            self.status['cartesian']['tx'] = float(tx)
            self.status['cartesian']['ty'] = float(ty)
            self.status['cartesian']['tz'] = float(tz)
            self.status['cartesian']['rx'] = float(rx)
            self.status['cartesian']['ry'] = float(ry)
            self.status['cartesian']['rz'] = float(rz)

        pump_pwm = re.match(r'.*Pump\sPWM:(\d+)', msg)
        if pump_pwm is not None:
            self.status['pump_pwm'] = int(pump_pwm.groups(0)[0])

        valve_pwm = re.match(r'.*Valve\sPWM:(\d+)', msg)
        if valve_pwm is not None:
            self.status['valve_pwm'] = int(valve_pwm.groups(0)[0])

        motion_mode = re.match(r'.*Motion_MODE:(\d+)', msg)
        if motion_mode is not None:
            self.status['motion_mode'] = int(motion_mode.groups(0)[0])

        if self.get_status_callback is not None:
            self.get_status_callback(self.status)

        if self.debug:
            pprint(self.status)

    # check if we are connected
    def is_connected(self):
        return self.serial_device.is_open

    # connect to the mirobot
    def connect(self, portname, receive_callback=None):
        self.serial_device.portname = portname
        self.serial_device.baudrate = 115200
        self.serial_device.stopbits = 1
        self.serial_device.listen_callback = self._receive_msg

        if receive_callback is not None:
            self.receive_callback = receive_callback

        self.serial_device.open()

    # set the receive callback
    def set_receive_callback(self, receive_callback):
        self.receive_callback = receive_callback

    # disconnect from the mirobot
    def disconnect(self):
        self.serial_device.close()

    # COMMANDS #

    # get the current status
    def get_status(self, callback=None):
        msg = '?'
        self.get_status_callback = callback
        self._send_msg(msg, get_status=False)

    # home each axis individually
    def home_individual(self):
        msg = '$HH'
        self.send_msg(msg, get_status=False)

    # home all axes simultaneously
    def home_simultaneous(self):
        msg = '$H'
        self.send_msg(msg, get_status=False)

    # set the hard limit state
    def set_hard_limit(self, state):
        msg = '$21=' + str(int(state))
        self.send_msg(msg, get_status=False)

    # set the soft limit state
    def set_soft_limit(self, state):
        msg = '$21=' + str(int(state))
        self.send_msg(msg, get_status=False)

    # unlock the shaft
    def unlock_shaft(self):
        msg = 'M50'
        self.send_msg(msg)

    # send all axes to their respective zero positions
    def go_to_zero(self):
        self.go_to_axis(0, 0, 0, 0, 0, 0, 2000)

    # send all axes to a specific position
    def go_to_axis(self, a1, a2, a3, a4, a5, a6, speed):
        msg = 'M21 G90'
        msg += ' X' + str(a1)
        msg += ' Y' + str(a2)
        msg += ' Z' + str(a3)
        msg += ' A' + str(a4)
        msg += ' B' + str(a5)
        msg += ' C' + str(a6)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # increment all axes a specified amount
    def increment_axis(self, a1, a2, a3, a4, a5, a6, speed):
        msg = 'M21 G91'
        msg += ' X' + str(a1)
        msg += ' Y' + str(a2)
        msg += ' Z' + str(a3)
        msg += ' A' + str(a4)
        msg += ' B' + str(a5)
        msg += ' C' + str(a6)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # point to point move to a cartesian position
    def go_to_cartesian_ptp(self, x, y, z, a, b, c, speed):
        msg = 'M20 G90 G0'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # linear move to a cartesian position
    def go_to_cartesian_lin(self, x, y, z, a, b, c, speed):
        msg = 'M20 G90 G1'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # point to point increment in cartesian space
    def increment_cartesian_ptp(self, x, y, z, a, b, c, speed):
        msg = 'M20 G91 G0'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # linear increment in cartesian space
    def increment_cartesian_lin(self, x, y, z, a, b, c, speed):
        msg = 'M20 G91 G1'
        msg += ' X' + str(x)
        msg += ' Y' + str(y)
        msg += ' Z' + str(z)
        msg += ' A' + str(a)
        msg += ' B' + str(b)
        msg += ' C' + str(c)
        msg += ' F' + str(speed)
        self.send_msg(msg)
        return

    # set the pwm of the air pump
    def set_air_pump(self, pwm):
        msg = 'M3S' + str(pwm)
        self.send_msg(msg)

    # set the pwm of the gripper
    def set_gripper(self, pwm):
        msg = 'M4E' + str(pwm)
        self.send_msg(msg)
Esempio n. 13
0
 def __init__(self):
     Base.__init__(self)
     SerialDevice.__init__(self)
     self.calibration = None
Esempio n. 14
0
def findAnimaticsDevicePort(baudrate):
    serialPortList = findSerialDevicePorts()
    matchingList = []
    for port in serialPortList:
        try:
            dev = SerialDevice(port=port,
                               baudrate=baudrate,
                               timeout=0.1,
                               write_write_delay=0.1,
                               write_read_delay=0.1,
                               debug=DEBUG)
            dev.flushInput()
            dev.flushOutput()
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET) + 'WAKE ',
                               delay_write=True)
            time.sleep(0.1)
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET) + 'WAKE ',
                               delay_write=True)
            time.sleep(0.1)
            dev.flushInput()
            dev.writeCheckFreq(chr(MOTOR_ADDRESS_OFFSET) + 'ECHO ',
                               delay_write=True)
            dev.readlines()
            response = dev.writeRead(chr(MOTOR_ADDRESS_OFFSET) + 'RPI ',
                                     use_readline=False,
                                     check_write_freq=True)
            dev.close()
            # Animatics response will either be 'RPI 3.141592741 '
            # or '3.141592741 ' depending on ECHO setting
            # Must enable ECHO so it will work when multiple motors are chained
            response = response.replace(chr(MOTOR_ADDRESS_OFFSET) + 'RPI ', '')
            if (0 < len(response)) and (response[0] == '3'):
                print("Found an Animatics device!")
                return port
        except serial.SerialException:
            pass

    if len(matchingList) == 0:
        err_str = 'Could not find Animatics device. Check connections and power or specify port.\n'
        err_str += 'Tried ports: ' + str(serialPortList)
        raise RuntimeError(err_str)
    elif 1 < len(matchingList):
        err_str = 'Found more than one Animatics device. Specify port.'
        err_str += 'Matching ports: ' + str(matchingList)
        raise RuntimeError(err_str)
    else:
        return matchingList[0]