예제 #1
0
 def _get_communicator(self, dry_run):
     if hasattr(self, '_communicator'):
         return self._communicator
     if dry_run:
         self._communicator = NullCommunicator()
     else:
         self._communicator = UsbPacketCommunicator(self._configuration.circut.print_queue_length)
         self._communicator.start()
     return self._communicator
예제 #2
0
 def _get_communicator(self, dry_run):
     if hasattr(self, '_communicator'):
         return self._communicator
     if dry_run:
         self._communicator = NullCommunicator()
     else:
         self._communicator = UsbPacketCommunicator(
             self._configuration.circut.print_queue_length)
         self._communicator.start()
     return self._communicator
예제 #3
0
 def _change_dripper(self):
     self._stop_current_dripper()
     if self._current_config.dripper.dripper_type == 'emulated':
         pass
     elif self._current_config.dripper.dripper_type == 'photo':
         pass
     elif self._current_config.dripper.dripper_type == 'microcontroller':
         self._communicator = UsbPacketCommunicator(
             self._current_config.circut.calibration_queue_length)
         self._communicator.start()
         self._drip_detector = SerialDripZAxis(
             self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)
 def _get_printer_details(self):
     communicator = UsbPacketCommunicator(self.usb_queue_length)
     communicator.register_handler(IAmMessage, self._ident_call_back)
     communicator.start()
     communicator.send(IdentifyMessage())
     until = time.time() + 5.0
     while (not self.printer_details and time.time() < until):
         time.sleep(0.1)
     communicator.close()
     details = self.printer_details
     self.printer_details = None
     return details
예제 #5
0
 def _get_printer_details(self):
     communicator = UsbPacketCommunicator(self.usb_queue_length)
     communicator.register_handler(IAmMessage, self._ident_call_back)
     communicator.start()
     communicator.send(IdentifyMessage())
     until = time.time() + 5.0
     while (not self.printer_details and time.time() < until):
         time.sleep(0.1)
     communicator.close()
     if not self.printer_details:
         raise MissingPrinterException()
     details = self.printer_details
     self.printer_details = None
     logger.info("Loaded printer \n{}".format(str(details.sn)))
     return details
 def _get_printer_details(self):
     communicator = UsbPacketCommunicator(self.usb_queue_length)
     communicator.register_handler(IAmMessage, self._ident_call_back)
     communicator.start()
     communicator.send(IdentifyMessage())
     until = time.time() + 5.0
     while (not self.printer_details and time.time() < until):
         time.sleep(0.1)
     communicator.close()
     details = self.printer_details
     self.printer_details = None
     return details
 def _get_printer_details(self):
     communicator = UsbPacketCommunicator(self.usb_queue_length)
     communicator.register_handler(IAmMessage, self._ident_call_back)
     communicator.start()
     communicator.send(IdentifyMessage())
     until = time.time() + 5.0
     while (not self.printer_details and time.time() < until):
         time.sleep(0.1)
     communicator.close()
     if not self.printer_details:
         raise MissingPrinterException()
     details = self.printer_details
     self.printer_details = None
     logger.info("Loaded printer \n{}".format(str(details.sn)))
     return details
 def _change_dripper(self):
     self._stop_current_dripper()
     if self._current_config.dripper.dripper_type == 'emulated':
         pass
     elif self._current_config.dripper.dripper_type == 'photo':
         pass
     elif self._current_config.dripper.dripper_type == 'microcontroller':
         self._communicator = UsbPacketCommunicator(self._current_config.circut.calibration_queue_length)
         self._communicator.start()
         self._drip_detector = SerialDripZAxis(self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)
예제 #9
0
    def __init__(self, verbose=False):
        self._verbose = verbose

        self._drips = 0
        self._serial = None
        self._swrev = None
        self._hwrev = None
        self._adcNum = []
        self._adcVal = []
        self._dataRate = None
        self._adcCals = []
        self._move = [0, 0, 0]

        self._usb = UsbPacketCommunicator(10)
        self._usb.register_handler(IAmMessage, self.iAmHandler)
        self._usb.register_handler(DripRecordedMessage, self.dripHandler)
        self._usb.register_handler(ReturnAdcValMessage, self.adcHandler)
        self._usb.start()
        if verbose:
            print "Started usb terminal"
        time.sleep(0.1)
    def __init__(self,verbose=False):
        self._verbose=verbose

        self._drips=0
        self._serial=None
        self._swrev=None
        self._hwrev=None
        self._adcNum=[]
        self._adcVal=[]
        self._dataRate=None
        self._adcCals=[]
        self._move=[0,0,0]

        self._usb = UsbPacketCommunicator(10)
        self._usb.register_handler(IAmMessage, self.iAmHandler)
        self._usb.register_handler(DripRecordedMessage, self.dripHandler)
        self._usb.register_handler(ReturnAdcValMessage, self.adcHandler)
        self._usb.start()
        if verbose:
            print "Started usb terminal"
        time.sleep(0.1)
예제 #11
0
class PrintAPI(object):
    '''API designed to use configuration to print a thing takes a configuration object
    Simple Usage:
        print_api = PrintAPI(configuration_api.get_current_config())
        print_api.print_gcode("file.gcode")
        while print_api.get_status()['status'] != "Complete"
            time.sleep(1)
        print_api.close()
    '''
    def __init__(self, configuration, start_height=0.0):
        logger.info('Print API Startup')
        self._configuration = configuration
        logger.info('Printer Name: %s' % self._configuration.name)
        self._controller = None
        self._zaxis = None
        self._start_height = start_height
        self._current_file_name = None
        self._current_file = None
        if self._configuration.email.on:
            self._email_gateway = EmailGateway(
                self._configuration.email.host, self._configuration.email.port,
                self._configuration.email.username,
                self._configuration.email.password)
            self._notification_service = EmailNotificationService(
                self._email_gateway, self._configuration.email.sender,
                self._configuration.email.recipient)
        else:
            self._notification_service = None

    @property
    def configuration(self):
        '''Returns the current configuration'''

        return self._configuration

    def print_gcode(self,
                    file_name,
                    print_sub_layers=True,
                    dry_run=False,
                    force_source_speed=False):
        '''Take a gcode file and starts the printing it with current settings.'''

        self._current_file_name = file_name
        self._current_file = open(file_name, 'r')
        gcode_reader = GCodeReader(
            self._current_file,
            scale=self._configuration.options.scaling_factor,
            start_height=self._start_height)
        gcode_layer_generator = gcode_reader.get_layers()
        layer_generator = gcode_layer_generator
        self.print_layers(layer_generator,
                          print_sub_layers,
                          dry_run,
                          force_source_speed=force_source_speed)

    def subscribe_to_status(self, callback):
        '''Allows a subscription to printer safety status messages'''

        if hasattr(self, '_communicator'):
            self._communicator.register_handler(PrinterStatusMessage, callback)
        else:
            logger.warning("Printer not running subscription not complete")

    def _get_zaxis(self, dry_run):
        if dry_run:
            return None
        elif self._configuration.dripper.dripper_type == 'photo':
            logger.info("Photo Zaxis")
            return PhotoZAxis(self._start_height,
                              self._configuration.dripper.photo_zaxis_delay)
        elif self._configuration.dripper.dripper_type == 'emulated':
            logger.info("Emulated Zaxis")
            return TimedDripZAxis(self._configuration.dripper.drips_per_mm,
                                  self._start_height,
                                  drips_per_second=self._configuration.dripper.
                                  emulated_drips_per_second)
        elif self._configuration.dripper.dripper_type == 'microcontroller':
            logger.info("Micro Controller Zaxis")
            return SerialDripZAxis(
                self._get_communicator(dry_run),
                self._configuration.dripper.drips_per_mm,
                self._start_height,
            )

    def _get_communicator(self, dry_run):
        if hasattr(self, '_communicator'):
            return self._communicator
        if dry_run:
            self._communicator = NullCommunicator()
        else:
            self._communicator = UsbPacketCommunicator(
                self._configuration.circut.print_queue_length)
            self._communicator.start()
        return self._communicator

    def _get_digital_disseminator(self, dry_run):

        return MicroDisseminator(self.laser_control,
                                 self._get_communicator(dry_run),
                                 self._configuration.circut.data_rate)

    def print_layers(self,
                     layer_generator,
                     print_sub_layers=True,
                     dry_run=False,
                     force_source_speed=False):
        '''Takes a layer_generator object and starts the printing it with current settings.'''

        logger.info("Shuffled: %s" %
                    self._configuration.options.use_shufflelayers)
        logger.info("Sublayered: %s" %
                    self._configuration.options.use_sublayers)
        logger.info("Overlapped: %s" % self._configuration.options.use_overlap)

        if self._configuration.options.use_sublayers and print_sub_layers:
            layer_generator = SubLayerGenerator(
                layer_generator,
                self._configuration.options.sublayer_height_mm)
        if self._configuration.options.use_shufflelayers:
            layer_generator = ShuffleGenerator(
                layer_generator,
                self._configuration.options.shuffle_layers_amount)
        if self._configuration.options.use_overlap:
            layer_generator = OverLapGenerator(
                layer_generator, self._configuration.options.overlap_amount)

        if self._configuration.serial.on:
            self._commander = SerialCommander(self._configuration.serial.port)
        else:
            self._commander = NullCommander()

        self.laser_control = LaserControl(
            self._configuration.cure_rate.override_laser_power_amount)

        transformer = HomogenousTransformer(
            self._configuration.calibration.max_deflection,
            self._configuration.calibration.height,
            self._configuration.calibration.lower_points,
            self._configuration.calibration.upper_points,
        )

        state = MachineState()
        self._status = MachineStatus()

        if dry_run:
            abort_on_error = False
        else:
            abort_on_error = True

        self._zaxis = self._get_zaxis(dry_run)

        disseminator = self._get_digital_disseminator(dry_run)

        path_to_points = PathToPoints(
            disseminator.samples_per_second, transformer,
            self._configuration.options.laser_thickness_mm)

        if force_source_speed:
            override_draw_speed = None
            override_move_speed = None
        else:
            override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None
            override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None

        pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0
        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.slew_delay) / 1000.0)

        if self._configuration.options.wait_after_move_milliseconds > 0:
            wait_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.wait_after_move_milliseconds)
                / 1000.0)
        else:
            wait_speed = None

        self._writer = LayerWriter(disseminator,
                                   path_to_points,
                                   self.laser_control,
                                   state,
                                   move_distance_to_ignore=self._configuration.
                                   options.laser_thickness_mm,
                                   override_draw_speed=override_draw_speed,
                                   override_move_speed=override_move_speed,
                                   wait_speed=wait_speed,
                                   post_fire_delay_speed=post_fire_delay_speed,
                                   slew_delay_speed=slew_delay_speed)

        self._layer_processing = LayerProcessing(
            self._writer,
            state,
            self._status,
            zaxis=self._zaxis,
            max_lead_distance=self._configuration.dripper.max_lead_distance_mm,
            commander=self._commander,
            pre_layer_delay=pre_layer_delay,
            layer_start_command=self._configuration.serial.layer_started,
            layer_ended_command=self._configuration.serial.layer_ended,
            print_start_command=self._configuration.serial.print_start,
            print_ended_command=self._configuration.serial.print_ended,
            dripper_on_command=self._configuration.serial.on_command,
            dripper_off_command=self._configuration.serial.off_command,
        )

        if self._zaxis:
            self._zaxis.set_call_back(self._status.drip_call_back)
            self._zaxis.start()

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            layer_generator,
            self._status,
            abort_on_error=abort_on_error,
        )

        self._controller.start()

    def get_status(self):
        '''Returns a status dictionary of the print containing: 
                start_time
                elapsed_time
                current_layer
                status ->  ['Complete', 'Cancelled', 'Failed', 'Starting', 'Running']
                errors
                waiting_for_drips
                height
                drips
                drips_per_second
                model_height
                skipped_layers
                drip_histor
        '''

        return self._controller.get_status()

    def can_set_drips_per_second(self):
        '''When using an emulated dripper this returns if the use can cahnge the drip rate manually via software'''

        if getattr(self._zaxis, 'set_drips_per_second', False):
            return True
        else:
            return False

    def set_drips_per_second(self, drips_per_second):
        '''Allows a user to set the number of drips per second in realtime whilst using the emulated dripper'''

        if getattr(self._zaxis, 'set_drips_per_second', False):
            self._zaxis.set_drips_per_second(drips_per_second)
        else:
            logger.error('Cannot change drips per second on %s' %
                         type(self._zaxis))
            raise Exception('Cannot change drips per second on %s' %
                            type(self._zaxis))

    def get_drips_per_second(self):
        '''Gets the current setting for drips per second when using the emulated dripper'''

        if getattr(self._zaxis, 'get_drips_per_second'):
            return self._zaxis.get_drips_per_second()
        else:
            logger.warning("Drips per second requested but does not exist")
            return 0.0

    def verify_gcode(self, file_name):
        '''Runs a test of the gcode without printing to verify file intregrity ununsed at this time'''

        self.print_gcode(file_name, print_sub_layers=False, dry_run=True)

    def close(self):
        '''Close the api required before running a second print or shutting down'''

        if self._zaxis:
            self._zaxis.close()
        if self._controller:
            self._controller.close()
        else:
            logger.warning('Stopped before printing')
        if self._current_file:
            self._current_file.close()
            logger.info("File Closed")
        if self._notification_service:
            self._notification_service.send_message(
                "Print Complete", "%s is complete" % self._current_file_name)
예제 #12
0
class PrintAPI(object):
    '''API designed to use configuration to print a thing takes a configuration object
    Simple Usage:
        print_api = PrintAPI(configuration_api.get_current_config())
        print_api.print_gcode("file.gcode")
        while print_api.get_status()['status'] != "Complete"
            time.sleep(1)
        print_api.close()
    '''
    def __init__(self, configuration, start_height=0.0):
        logger.info('Print API Startup')
        self._configuration = configuration
        logger.info('Printer Name: %s' % self._configuration.name)
        self._controller = None
        self._zaxis = None
        self._start_height = start_height
        self._current_file_name = None
        self._current_file = None
        if self._configuration.email.on:
            self._email_gateway = EmailGateway(self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password)
            self._notification_service = EmailNotificationService(self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient)
        else:
            self._notification_service = None

    @property
    def configuration(self):
        '''Returns the current configuration'''

        return self._configuration

    def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False):
        '''Take a gcode file and starts the printing it with current settings.'''

        self._current_file_name = file_name
        self._current_file = open(file_name, 'r')
        gcode_reader = GCodeReader(self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height)
        gcode_layer_generator = gcode_reader.get_layers()
        layer_generator = gcode_layer_generator
        self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed)

    def subscribe_to_status(self, callback):
        '''Allows a subscription to printer safety status messages'''

        if hasattr(self, '_communicator'):
            self._communicator.register_handler(PrinterStatusMessage, callback)
        else:
            logger.warning("Printer not running subscription not complete")

    def _get_zaxis(self, dry_run):
        if dry_run:
            return None
        elif self._configuration.dripper.dripper_type == 'photo':
            logger.info("Photo Zaxis")
            return PhotoZAxis(
                self._start_height,
                self._configuration.dripper.photo_zaxis_delay
                )
        elif self._configuration.dripper.dripper_type == 'emulated':
            logger.info("Emulated Zaxis")
            return TimedDripZAxis(
                self._configuration.dripper.drips_per_mm,
                self._start_height,
                drips_per_second=self._configuration.dripper.emulated_drips_per_second
                )
        elif self._configuration.dripper.dripper_type == 'microcontroller':
            logger.info("Micro Controller Zaxis")
            return SerialDripZAxis(
                self._get_communicator(dry_run),
                self._configuration.dripper.drips_per_mm,
                self._start_height,
                )

    def _get_communicator(self, dry_run):
        if hasattr(self, '_communicator'):
            return self._communicator
        if dry_run:
            self._communicator = NullCommunicator()
        else:
            self._communicator = UsbPacketCommunicator(self._configuration.circut.print_queue_length)
            self._communicator.start()
        return self._communicator

    def _get_digital_disseminator(self, dry_run):

            return MicroDisseminator(
                self.laser_control,
                self._get_communicator(dry_run),
                self._configuration.circut.data_rate
                )

    def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False):
        '''Takes a layer_generator object and starts the printing it with current settings.'''

        logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers)
        logger.info("Sublayered: %s" % self._configuration.options.use_sublayers)
        logger.info("Overlapped: %s" % self._configuration.options.use_overlap)

        if self._configuration.options.use_sublayers and print_sub_layers:
            layer_generator = SubLayerGenerator(layer_generator, self._configuration.options.sublayer_height_mm)
        if self._configuration.options.use_shufflelayers:
            layer_generator = ShuffleGenerator(layer_generator, self._configuration.options.shuffle_layers_amount)
        if self._configuration.options.use_overlap:
            layer_generator = OverLapGenerator(layer_generator, self._configuration.options.overlap_amount)

        if self._configuration.serial.on:
            self._commander = SerialCommander(self._configuration.serial.port)
        else:
            self._commander = NullCommander()

        self.laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)

        transformer = HomogenousTransformer(
            self._configuration.calibration.max_deflection,
            self._configuration.calibration.height,
            self._configuration.calibration.lower_points,
            self._configuration.calibration.upper_points,
            )

        state = MachineState()
        self._status = MachineStatus()

        if dry_run:
            abort_on_error = False
        else:
            abort_on_error = True

        self._zaxis = self._get_zaxis(dry_run)

        disseminator = self._get_digital_disseminator(dry_run)

        path_to_points = PathToPoints(
            disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        if force_source_speed:
            override_draw_speed = None
            override_move_speed = None
        else:
            override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None
            override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None

        pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0
        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        if self._configuration.options.wait_after_move_milliseconds > 0:
            wait_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.wait_after_move_milliseconds) / 1000.0)
        else:
            wait_speed = None

        self._writer = LayerWriter(
            disseminator,
            path_to_points,
            self.laser_control,
            state,
            move_distance_to_ignore=self._configuration.options.laser_thickness_mm,
            override_draw_speed=override_draw_speed,
            override_move_speed=override_move_speed,
            wait_speed=wait_speed,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            state,
            self._status,
            zaxis=self._zaxis,
            max_lead_distance=self._configuration.dripper.max_lead_distance_mm,
            commander=self._commander,
            pre_layer_delay=pre_layer_delay,
            layer_start_command=self._configuration.serial.layer_started,
            layer_ended_command=self._configuration.serial.layer_ended,
            print_start_command=self._configuration.serial.print_start,
            print_ended_command=self._configuration.serial.print_ended,
            dripper_on_command=self._configuration.serial.on_command,
            dripper_off_command=self._configuration.serial.off_command,
            )

        if self._zaxis:
            self._zaxis.set_call_back(self._status.drip_call_back)
            self._zaxis.start()

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            layer_generator,
            self._status,
            abort_on_error=abort_on_error,
            )

        self._controller.start()

    def get_status(self):
        '''Returns a status dictionary of the print containing: 
                start_time
                elapsed_time
                current_layer
                status ->  ['Complete', 'Cancelled', 'Failed', 'Starting', 'Running']
                errors
                waiting_for_drips
                height
                drips
                drips_per_second
                model_height
                skipped_layers
                drip_histor
        '''

        return self._controller.get_status()

    def can_set_drips_per_second(self):
        '''When using an emulated dripper this returns if the use can cahnge the drip rate manually via software'''

        if getattr(self._zaxis, 'set_drips_per_second', False):
            return True
        else:
            return False

    def set_drips_per_second(self, drips_per_second):
        '''Allows a user to set the number of drips per second in realtime whilst using the emulated dripper'''

        if getattr(self._zaxis, 'set_drips_per_second', False):
            self._zaxis.set_drips_per_second(drips_per_second)
        else:
            logger.error('Cannot change drips per second on %s' % type(self._zaxis))
            raise Exception('Cannot change drips per second on %s' % type(self._zaxis))

    def get_drips_per_second(self):
        '''Gets the current setting for drips per second when using the emulated dripper'''

        if getattr(self._zaxis, 'get_drips_per_second'):
            return self._zaxis.get_drips_per_second()
        else:
            logger.warning("Drips per second requested but does not exist")
            return 0.0

    def verify_gcode(self, file_name):
        '''Runs a test of the gcode without printing to verify file intregrity ununsed at this time'''

        self.print_gcode(file_name,  print_sub_layers=False,  dry_run=True)

    def close(self):
        '''Close the api required before running a second print or shutting down'''

        if self._zaxis:
            self._zaxis.close()
        if self._controller:
            self._controller.close()
        else:
            logger.warning('Stopped before printing')
        if self._current_file:
            self._current_file.close()
            logger.info("File Closed")
        if self._notification_service:
            self._notification_service.send_message("Print Complete", "%s is complete" % self._current_file_name)
예제 #13
0
class UsbTestTerminal(object):
    VREF_CAL_POS = 0
    TEMP30_CAL_POS = 1
    TEMP110_CAL_POS = 2
    ADC_KEY_POS = 3
    ADC_PA3_POS = 4
    ADC_TEMP_POS = 5
    ADC_VREF_POS = 6

    def __init__(self, verbose=False):
        self._verbose = verbose

        self._drips = 0
        self._serial = None
        self._swrev = None
        self._hwrev = None
        self._adcNum = []
        self._adcVal = []
        self._dataRate = None
        self._adcCals = []
        self._move = [0, 0, 0]

        self._usb = UsbPacketCommunicator(10)
        self._usb.register_handler(IAmMessage, self.iAmHandler)
        self._usb.register_handler(DripRecordedMessage, self.dripHandler)
        self._usb.register_handler(ReturnAdcValMessage, self.adcHandler)
        self._usb.start()
        if verbose:
            print "Started usb terminal"
        time.sleep(0.1)

    def usbClose(self):
        self._usb.close()

    def laserOff(self):
        move = self._move
        self._usb.send(MoveMessage(move[0], move[1], 0))

    def laserOn(self):
        move = self._move
        self._usb.send(MoveMessage(move[0], move[1], 255))

    def move(self, x, y, laserPower=0):
        self._move = [x, y, laserPower]
        self._usb.send(MoveMessage(x, y, laserPower))

    def setDrips(self, dripCount=0):
        self._usb.send(SetDripCountMessage(dripCount))

    def identify(self):
        self._usb.send(IdentifyMessage())

    def enterBootloader(self, i_am_sure=None):
        if i_am_sure == (0xDEADBEEF):
            self._usb.send(EnterBootloaderMessage())
            if (self._verbose):
                print "Bootloadereded"
        elif (self._verbose):
            print "i_am_sure not loaded with the correct value"
            print "Note: This may lock your peachy into the bootloader"
            print "      if you have old firmware on your board"

    #A non-ideal push/pop queue interface.
    #Doesn't account for mis-matching - May be worth clearing on each request?
    def popAdc(self, timeout=0.1):
        start = time.time()
        timeout = start + timeout  #in seconds
        while (time.time() < timeout):  #wait for data being available or
            if (len(self._adcVal) != 0):
                tmp = [self._adcNum[0], self._adcVal[0]]
                del self._adcNum[0]
                del self._adcVal[0]
                return tmp
            else:
                time.sleep(0.01)

    def clearAdcQueues(self):
        self._adcNum = []
        self._adcVal = []

    def getAdcCalibrations(self):
        if len(self._adcCals) != 3:
            [adcNum, adcVrefCal] = self.getAdcVal(self.VREF_CAL_POS)
            [adcNum, adcTemp30] = self.getAdcVal(self.TEMP30_CAL_POS)
            [adcNum, adcTemp110] = self.getAdcVal(self.TEMP110_CAL_POS)
            self._adcCals = [adcVrefCal, adcTemp30, adcTemp110]

    def getTemperature(self):

        self.getAdcCalibrations()

        #Return actual Temperature in C
        #Formulas taken from STM32F0 datasheet page 252
        adcVrefCal = self._adcCals[self.VREF_CAL_POS]
        adcTemp30 = self._adcCals[self.TEMP30_CAL_POS]
        adcTemp110 = self._adcCals[self.TEMP110_CAL_POS]

        #Get the current Vref and Temperature each time
        [adcNum, adcTemperature] = self.getAdcVal(self.ADC_TEMP_POS)
        [adcNum, adcVref] = self.getAdcVal(self.ADC_VREF_POS)

        vrefCompensation = 1.0 * adcVrefCal / adcVref
        temperature = adcTemperature * vrefCompensation - adcTemp30
        temperature = temperature * (110 - 30) / (adcTemp110 - adcTemp30)
        temperature = temperature + 30

        if (self._verbose):
            print('Temperatures Value={0} Celcius={1}'.format(
                adcTemperature, temperature))

        return temperature

    def getSupplyVoltage(self):

        self.getAdcCalibrations()
        adcVrefCal = self._adcCals[self.VREF_CAL_POS]
        [adcNum, adcVref] = self.getAdcVal(self.ADC_VREF_POS)

        vrefCompensation = 1.0 * adcVrefCal / adcVref

        #calibrated at 3.3V always
        supplyVoltage = 3.3 * vrefCompensation

        if (self._verbose):
            print('Voltage {0}, Value {1}'.format(supplyVoltage, adcVref))

        return supplyVoltage

    def getAdcKeyVal(self):
        return self.getAdcVal(self.ADC_KEY_POS)

    def getAdcVal(self, adcNum):
        '''ADC NUMBERS:
        0 - Vref Calibration Factor
        1 - 30C temperature calibration
        2 - 110C temperature calibration
        3 - ADC key (PA2)
        4 - Pin (PA3)
        5 - Temperature
        6 - Vref (3.3V volts)
        '''

        self._adcNum.append(adcNum)
        self._usb.send(GetAdcValMessage(adcNum))
        if self._verbose:
            print('adcNum: {0}'.format(adcNum))
        return self.popAdc()

    def adcHandler(self, message):
        if (len(self._adcNum) > len(self._adcVal)):
            self._adcVal.append(message.adcVal)
            if self._verbose:
                print('adcNum: {0} adcVal: {1}'.format(self._adcNum[-1],
                                                       self._adcVal[-1]))
        else:
            self.clearAdcQueues()

    def dripHandler(self, message):
        self._drips = message.drips
        if self._verbose:
            print('Recieved drip: {0}'.format(message.drips))

    def iAmHandler(self, message):
        self._serial = message.sn
        self._swrev = message.swrev
        self._hwrev = message.hwrev
        self._dataRate = message.dataRate
        if self._verbose:
            print('Serial number: {0}'.format(message.sn))
            print('SW rev number: {0}'.format(message.swrev))
            print('HW rev number: {0}'.format(message.hwrev))
            print('Data Rate:     {0}'.format(message.dataRate))
예제 #14
0
 def test_init_doesnt_raise_exception(self, mock_PeachyUSB):
     UsbPacketCommunicator(50)
예제 #15
0
class DripperSetupMixIn(object):

    '''Depricated use get_dripper_drips_per_mm'''
    def get_drips_per_mm(self):
        logging.warning("Depricated use get_dripper_drips_per_mm")
        return self.get_dripper_drips_per_mm()

    '''Returns Drips Per mm'''
    def get_dripper_drips_per_mm(self):
        return self._current_config.dripper.drips_per_mm

    '''Returns the configured Dripper Type'''
    def get_dripper_type(self):
        return self._current_config.dripper.dripper_type

    '''Depricated use get_dripper_emulated_drips_per_second'''
    def get_emulated_drips_per_second(self):
        logging.warning("Depricated use get_dripper_emulated_drips_per_second")
        return self.get_dripper_emulated_drips_per_second()

    '''Gets the drips per second to be emulated'''
    def get_dripper_emulated_drips_per_second(self):
        return self._current_config.dripper.emulated_drips_per_second

    '''Depricated use get_dripper_photo_zaxis_delay'''
    def get_photo_zaxis_delay(self):
        logging.warning("Depricated use get_dripper_photo_zaxis_delay")
        return self.get_dripper_photo_zaxis_delay()

    '''Gets the photo delay in seconds'''
    def get_dripper_photo_zaxis_delay(self):
        return self._current_config.dripper.photo_zaxis_delay

    '''Depricated use set_dripper_drips_per_mm'''
    def set_drips_per_mm(self, drips):
        logging.warning("Depricated use set_dripper_drips_per_mm")
        self.set_dripper_drips_per_mm(drips)

    '''Sets Drips Per mm'''
    def set_dripper_drips_per_mm(self, drips):
        self._current_config.dripper.drips_per_mm = drips
        if self._drip_detector:
            self._drip_detector.set_drips_per_mm(drips)
        self.save()

    '''Sets the configured Dripper Type'''
    def set_dripper_type(self, value):
        self._current_config.dripper.dripper_type = value
        self.save()

    '''Depricated use set_dripper_emulated_drips_per_second'''
    def set_emulated_drips_per_second(self, value):
        logging.warning("Depricated use set_dripper_emulated_drips_per_second")
        self.set_dripper_emulated_drips_per_second(value)

    '''Sets the drips per second to be emulated'''
    def set_dripper_emulated_drips_per_second(self, value):
        self._current_config.dripper.emulated_drips_per_second = value
        self.save()

    '''Depricated use set_dripper_photo_zaxis_delay'''
    def set_photo_zaxis_delay(self, value):
        logging.warning("Depricated use set_dripper_photo_zaxis_delay")
        self.set_dripper_photo_zaxis_delay(value)

    '''Sets the photo delay in seconds'''
    def set_dripper_photo_zaxis_delay(self, value):
        self._current_config.dripper.photo_zaxis_delay = value
        self.save()

    '''Sets the drip count back to 0'''
    def reset_drips(self):
        self._drip_detector.reset()

    '''Turns on the counting of drips. Stop must be called to end this.'''
    def start_counting_drips(self, drip_call_back=None):
        self.drip_call_back = drip_call_back
        if self._current_config.serial.on:
            self._commander = SerialCommander(self._current_config.serial.port)
        self._change_dripper()

    def _change_dripper(self):
        self._stop_current_dripper()
        if self._current_config.dripper.dripper_type == 'emulated':
            pass
        elif self._current_config.dripper.dripper_type == 'photo':
            pass
        elif self._current_config.dripper.dripper_type == 'microcontroller':
            self._communicator = UsbPacketCommunicator(self._current_config.circut.calibration_queue_length)
            self._communicator.start()
            self._drip_detector = SerialDripZAxis(self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)

    def _stop_current_dripper(self):
        if self._communicator:
            self._communicator.close()
        if self._drip_detector:
            self._drip_detector.close()
            self._drip_detector = None

    '''Turns off the counting of drips if counting'''
    def stop_counting_drips(self):
        if self._commander:
            self._commander.close()
        self._stop_current_dripper()

    def send_dripper_on_command(self):
        if self._commander:
            self._commander.send_command(self._current_config.serial.on_command)
        else:
            raise Exception("Serial not Started")

    def send_dripper_off_command(self):
        if self._commander:
            self._commander.send_command(self._current_config.serial.off_command)
        else:
            raise Exception("Serial not Started")
예제 #16
0
class DripperSetupMixIn(object):
    '''This is a Mixin for the ConfigurationAPI and exists only for organizational purposes'''
    def get_dripper_drips_per_mm(self):
        '''Returns Drips Per mm'''

        return self._current_config.dripper.drips_per_mm

    def get_dripper_type(self):
        '''Returns the configured Dripper Type'''

        return self._current_config.dripper.dripper_type

    def get_dripper_emulated_drips_per_second(self):
        '''Gets the drips per second to be emulated'''

        return self._current_config.dripper.emulated_drips_per_second

    def get_dripper_photo_zaxis_delay(self):
        '''Gets the photo delay in seconds'''

        return self._current_config.dripper.photo_zaxis_delay

    def set_dripper_drips_per_mm(self, drips):
        '''Sets Drips Per mm'''

        self._current_config.dripper.drips_per_mm = drips
        if self._drip_detector:
            self._drip_detector.set_drips_per_mm(drips)
        self.save()

    def set_dripper_type(self, value):
        '''Sets the configured Dripper Type'''

        self._current_config.dripper.dripper_type = value
        self.save()

    def set_dripper_emulated_drips_per_second(self, value):
        '''Sets the drips per second to be emulated'''

        self._current_config.dripper.emulated_drips_per_second = value
        self.save()

    def set_dripper_photo_zaxis_delay(self, value):
        '''Sets the photo delay in seconds'''

        self._current_config.dripper.photo_zaxis_delay = value
        self.save()

    def reset_drips(self):
        '''Sets the drip count back to 0'''

        self._drip_detector.reset()

    def start_counting_drips(self, drip_call_back=None):
        '''Turns on the counting of drips. Stop must be called to end this.'''

        self.drip_call_back = drip_call_back
        if self._current_config.serial.on:
            self._commander = SerialCommander(self._current_config.serial.port)
        self._change_dripper()

    def _change_dripper(self):
        self._stop_current_dripper()
        if self._current_config.dripper.dripper_type == 'emulated':
            pass
        elif self._current_config.dripper.dripper_type == 'photo':
            pass
        elif self._current_config.dripper.dripper_type == 'microcontroller':
            self._communicator = UsbPacketCommunicator(
                self._current_config.circut.calibration_queue_length)
            self._communicator.start()
            self._drip_detector = SerialDripZAxis(
                self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)

    def _stop_current_dripper(self):
        if self._communicator:
            self._communicator.close()
        if self._drip_detector:
            self._drip_detector.close()
            self._drip_detector = None

    def stop_counting_drips(self):
        '''Turns off the counting of drips if counting'''

        if self._commander:
            self._commander.close()
        self._stop_current_dripper()

    def send_dripper_on_command(self):
        '''If serial commuinication is enabled this send the turn on drips command'''

        if self._commander:
            self._commander.send_command(
                self._current_config.serial.on_command)
        else:
            raise Exception("Serial not Started")

    def send_dripper_off_command(self):
        '''If serial commuinication is enabled this send the turn off drips command'''

        if self._commander:
            self._commander.send_command(
                self._current_config.serial.off_command)
        else:
            raise Exception("Serial not Started")
class DripperSetupMixIn(object):
    '''This is a Mixin for the ConfigurationAPI and exists only for organizational purposes'''

    def get_dripper_drips_per_mm(self):
        '''Returns Drips Per mm'''

        return self._current_config.dripper.drips_per_mm

    def get_dripper_type(self):
        '''Returns the configured Dripper Type'''

        return self._current_config.dripper.dripper_type

    def get_dripper_emulated_drips_per_second(self):
        '''Gets the drips per second to be emulated'''

        return self._current_config.dripper.emulated_drips_per_second

    def get_dripper_photo_zaxis_delay(self):
        '''Gets the photo delay in seconds'''

        return self._current_config.dripper.photo_zaxis_delay

    def set_dripper_drips_per_mm(self, drips):
        '''Sets Drips Per mm'''

        self._current_config.dripper.drips_per_mm = drips
        if self._drip_detector:
            self._drip_detector.set_drips_per_mm(drips)
        self.save()

    def set_dripper_type(self, value):
        '''Sets the configured Dripper Type'''

        self._current_config.dripper.dripper_type = value
        self.save()

    def set_dripper_emulated_drips_per_second(self, value):
        '''Sets the drips per second to be emulated'''

        self._current_config.dripper.emulated_drips_per_second = value
        self.save()

    def set_dripper_photo_zaxis_delay(self, value):
        '''Sets the photo delay in seconds'''

        self._current_config.dripper.photo_zaxis_delay = value
        self.save()

    def reset_drips(self):
        '''Sets the drip count back to 0'''

        self._drip_detector.reset()

    def start_counting_drips(self, drip_call_back=None):
        '''Turns on the counting of drips. Stop must be called to end this.'''

        self.drip_call_back = drip_call_back
        if self._current_config.serial.on:
            self._commander = SerialCommander(self._current_config.serial.port)
        self._change_dripper()

    def _change_dripper(self):
        self._stop_current_dripper()
        if self._current_config.dripper.dripper_type == 'emulated':
            pass
        elif self._current_config.dripper.dripper_type == 'photo':
            pass
        elif self._current_config.dripper.dripper_type == 'microcontroller':
            self._communicator = UsbPacketCommunicator(self._current_config.circut.calibration_queue_length)
            self._communicator.start()
            self._drip_detector = SerialDripZAxis(self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)

    def _stop_current_dripper(self):
        if self._communicator:
            self._communicator.close()
        if self._drip_detector:
            self._drip_detector.close()
            self._drip_detector = None

    def stop_counting_drips(self):
        '''Turns off the counting of drips if counting'''

        if self._commander:
            self._commander.close()
        self._stop_current_dripper()

    def send_dripper_on_command(self):
        '''If serial commuinication is enabled this send the turn on drips command'''

        if self._commander:
            self._commander.send_command(self._current_config.serial.on_command)
        else:
            raise Exception("Serial not Started")

    def send_dripper_off_command(self):
        '''If serial commuinication is enabled this send the turn off drips command'''

        if self._commander:
            self._commander.send_command(self._current_config.serial.off_command)
        else:
            raise Exception("Serial not Started")
예제 #18
0
class CalibrationAPI(object):
    def __init__(self, configuration_manager):
        logger.info("Calibartion API Startup")
        self._configuration_manager = configuration_manager
        self._configuration = self._configuration_manager.load()

        self._point_generator = SinglePointGenerator()
        self._blink_generator = BlinkGenerator()
        self._orientaiton_generator = OrientationGenerator()
        self._alignment_generator = CalibrationLineGenerator()
        self._scale_generator = ScaleGenerator(speed=2.0, radius=1.0)

        self._test_patterns = {
            'Hilbert Space Filling Curve': HilbertGenerator(),
            'Square': SquareGenerator(),
            'Circle': CircleGenerator(),
            'Spiral': SpiralGenerator(),
            'Memory Hourglass': MemoryHourglassGenerator(),
            'Damping Test': DampingTestGenerator(),
            'NESW': NESWGenerator(),
            'Twitch': TwitchGenerator(),
            }

        self._current_generator = self._point_generator

        self._laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)
        transformer = TuningTransformer(scale=self._configuration.calibration.max_deflection)
        self._controller = None
        logger.debug("Setting up audiowriter")

        self._current_generator = self._point_generator

        self._state = MachineState()
        self._status = MachineStatus()

        self._communicator = UsbPacketCommunicator(self._configuration.circut.calibration_queue_length)
        self._communicator.start()
        self._disseminator = MicroDisseminator(
            self._laser_control,
            self._communicator,
            self._configuration.circut.data_rate
            )

        self._path_to_points = PathToPoints(
            self._disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        self._writer = LayerWriter(
            self._disseminator,
            self._path_to_points,
            self._laser_control,
            self._state,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            self._state,
            self._status,
            )

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            self._current_generator,
            self._status,
            abort_on_error=False,
            )

        self.make_pattern_fit()
        self._controller.start()


    def set_print_area(self, width, height, depth):
        self._configuration.calibration.print_area_x = width
        self._configuration.calibration.print_area_y = height
        self._configuration.calibration.print_area_z = depth
        self._save()

    def get_print_area(self):
        return (self._configuration.calibration.print_area_x, self._configuration.calibration.print_area_y, self._configuration.calibration.print_area_z)

    def set_orientation(self, x_flip, yflip, swap_axis):
        self._configuration.calibration.flip_x_axis = x_flip
        self._configuration.calibration.flip_y_axis = yflip
        self._configuration.calibration.swap_axis = swap_axis
        self._save()

    def get_orientation(self):
        return (self._configuration.calibration.flip_x_axis, self._configuration.calibration.flip_y_axis, self._configuration.calibration.swap_axis)

    '''Used to show a single point with no calibration applied'''
    def show_point(self, xyz=[0.5, 0.5, 0.5]):
        # logger.info('Showing point')
        x, y, z = xyz
        self._point_generator.xy = [x, y]
        if (self._current_generator != self._point_generator):
            self._unapply_calibration()
            self._update_generator(self._point_generator)

    '''Used to show a blinking point with no calibration applied used for aligning on and off laser posisition'''
    def show_blink(self, xyz=[0.5, 0.5, 0.0]):
        logger.info('Showing blink')
        x, y, z = xyz
        self._blink_generator.xy = [x, y]
        if (self._current_generator != self._blink_generator):
            self._unapply_calibration()
            self._update_generator(self._blink_generator)

    '''Used to show pattern with no calibration applied used for determining orientation'''
    def show_orientation(self):
        logger.info('Showing Orientation')
        if (self._current_generator != self._orientaiton_generator):
            self._unapply_calibration()
            self._update_generator(self._orientaiton_generator)

    '''Used to show a single line on one axis used to line up calibration grid'''
    def show_line(self):
        logger.info('Showing line')
        self._unapply_calibration()
        self._update_generator(self._alignment_generator)

    '''Used to show a test pattern with calibration applied'''
    def show_test_pattern(self, pattern):
        logger.info('Showing test pattern %s' % pattern)
        if pattern in self._test_patterns.keys():
            self._apply_calibration()
            self._update_generator(self._test_patterns[pattern])
        else:
            logger.error('Pattern: %s does not exist' % pattern)
            raise Exception('Pattern: %s does not exist' % pattern)

    '''Shows the scale square'''
    def show_scale(self):
        logger.info('Showing scale')
        self._unapply_calibration()
        self._update_generator(self._scale_generator)

    def get_max_deflection(self):
        return self._configuration.calibration.max_deflection

    def set_max_deflection(self, deflection):
        self._configuration.calibration.max_deflection = deflection
        self._unapply_calibration()
        self._save()

    '''Allows user so force the laser on'''
    def set_laser_off_override(self, state):
        self._controller.laser_off_override = state

    '''Changes the speed at which the test pattern is drawn in mm/sec'''
    def set_test_pattern_speed(self, speed):
        [pattern.set_speed(speed) for pattern in self._test_patterns.values()]

    '''Changes the height at which the test pattern is drawn in mm'''
    def set_test_pattern_current_height(self, current_height):
        [pattern.set_current_height(current_height) for pattern in self._test_patterns.values()]

    '''returns a list of test patterns'''
    def get_test_patterns(self):
        return self._test_patterns.keys()

    '''Returns the current calibration for the printer'''
    def current_calibration(self):
        return self._configuration.calibration

    '''deprecated use set_lower_points and set_upper_points, set_height'''
    def save_points(self, height, lower_points, upper_points):
        self.set_lower_points(lower_points)
        self.set_upper_points(upper_points)
        self.set_height(height)

    '''Gets the lower calibration points'''
    def get_lower_points(self):
        return self._configuration.calibration.lower_points

    '''Set and saves the suppliled lower calibration'''
    def set_lower_points(self, lower_points):
        self._configuration.calibration.lower_points = lower_points
        self._save()

    '''Gets the upper calibration points'''
    def get_upper_points(self):
        return self._configuration.calibration.upper_points

    '''Set and saves the suppliled upper calibration'''
    def set_upper_points(self, upper_points):
        self._configuration.calibration.upper_points = upper_points
        self._save()

    '''Gets the calibration height'''
    def get_height(self):
        return self._configuration.calibration.height

    '''Set and saves the upper calibration height'''
    def set_height(self, height):
        self._configuration.calibration.height = height
        self._save()

    def _save(self):
        self._configuration_manager.save(self._configuration)
        self.make_pattern_fit()

    # deprecated
    def make_pattern_fit(self):
        for pattern in self._test_patterns.values():
            pattern.set_radius(self.get_largest_object_radius())

    '''Must be called before shutting down applications'''
    def close(self):
        self._controller.close()

    def _update_generator(self, generator):
        self._current_generator = generator
        self._controller.change_generator(self._current_generator)

    def _apply_calibration(self):
        self._path_to_points.set_transformer(
            HomogenousTransformer(
                self._configuration.calibration.max_deflection,
                self._configuration.calibration.height,
                self._configuration.calibration.lower_points,
                self._configuration.calibration.upper_points
                )
            )

    def _unapply_calibration(self):
        self._path_to_points.set_transformer(
            TuningTransformer(scale=self._configuration.calibration.max_deflection))

    def _validate_points(self, points):
        if (len(points) != 4):
            return False
        return True

    '''Based on current calibrations_gets_maximum_size_of_object at the base layer'''
    def get_largest_object_radius(self):
        lowest = None
        for (x, y) in self._configuration.calibration.lower_points.values():
            if not lowest or abs(x) < lowest:
                lowest = abs(x)
            if abs(y) < lowest:
                lowest = abs(y)
        logger.info("Calulated max radius of object as: %s mm" % lowest)
        return lowest

    def stop(self):
            self._controller.stop()
예제 #19
0
class PrintAPI(object):
    def __init__(self, configuration, start_height=0.0):
        logger.info('Print API Startup')
        self._configuration = configuration
        logger.info('Printer Name: %s' % self._configuration.name)
        self._controller = None
        self._zaxis = None
        self._start_height = start_height
        self._current_file_name = None
        self._current_file = None
        if self._configuration.email.on:
            self._email_gateway = EmailGateway(
                self._configuration.email.host, self._configuration.email.port,
                self._configuration.email.username,
                self._configuration.email.password)
            self._notification_service = EmailNotificationService(
                self._email_gateway, self._configuration.email.sender,
                self._configuration.email.recipient)
        else:
            self._notification_service = None

    @property
    def configuration(self):
        return self._configuration

    def print_gcode(self,
                    file_name,
                    print_sub_layers=True,
                    dry_run=False,
                    force_source_speed=False):
        self._current_file_name = file_name
        self._current_file = open(file_name, 'r')
        gcode_reader = GCodeReader(
            self._current_file,
            scale=self._configuration.options.scaling_factor,
            start_height=self._start_height)
        gcode_layer_generator = gcode_reader.get_layers()
        layer_generator = gcode_layer_generator
        self.print_layers(layer_generator,
                          print_sub_layers,
                          dry_run,
                          force_source_speed=force_source_speed)

    def _get_zaxis(self, dry_run):
        if dry_run:
            return None
        elif self._configuration.dripper.dripper_type == 'photo':
            logger.info("Photo Zaxis")
            return PhotoZAxis(self._start_height,
                              self._configuration.dripper.photo_zaxis_delay)
        elif self._configuration.dripper.dripper_type == 'emulated':
            logger.info("Emulated Zaxis")
            return TimedDripZAxis(self._configuration.dripper.drips_per_mm,
                                  self._start_height,
                                  drips_per_second=self._configuration.dripper.
                                  emulated_drips_per_second)
        elif self._configuration.dripper.dripper_type == 'microcontroller':
            logger.info("Micro Controller Zaxis")
            return SerialDripZAxis(
                self._get_communicator(dry_run),
                self._configuration.dripper.drips_per_mm,
                self._start_height,
            )

    def _get_communicator(self, dry_run):
        if hasattr(self, '_communicator'):
            return self._communicator
        if dry_run:
            self._communicator = NullCommunicator()
        else:
            self._communicator = UsbPacketCommunicator(
                self._configuration.circut.print_queue_length)
            self._communicator.start()
        return self._communicator

    def _get_digital_disseminator(self, dry_run):

        return MicroDisseminator(self.laser_control,
                                 self._get_communicator(dry_run),
                                 self._configuration.circut.data_rate)

    def print_layers(self,
                     layer_generator,
                     print_sub_layers=True,
                     dry_run=False,
                     force_source_speed=False):
        logger.info("Shuffled: %s" %
                    self._configuration.options.use_shufflelayers)
        logger.info("Sublayered: %s" %
                    self._configuration.options.use_sublayers)
        logger.info("Overlapped: %s" % self._configuration.options.use_overlap)

        if self._configuration.options.use_sublayers and print_sub_layers:
            layer_generator = SubLayerGenerator(
                layer_generator,
                self._configuration.options.sublayer_height_mm)
        if self._configuration.options.use_shufflelayers:
            layer_generator = ShuffleGenerator(
                layer_generator,
                self._configuration.options.shuffle_layers_amount)
        if self._configuration.options.use_overlap:
            layer_generator = OverLapGenerator(
                layer_generator, self._configuration.options.overlap_amount)

        if self._configuration.serial.on:
            self._commander = SerialCommander(self._configuration.serial.port)
        else:
            self._commander = NullCommander()

        self.laser_control = LaserControl(
            self._configuration.cure_rate.override_laser_power_amount)

        transformer = HomogenousTransformer(
            self._configuration.calibration.max_deflection,
            self._configuration.calibration.height,
            self._configuration.calibration.lower_points,
            self._configuration.calibration.upper_points,
        )

        state = MachineState()
        self._status = MachineStatus()

        if dry_run:
            abort_on_error = False
        else:
            abort_on_error = True

        self._zaxis = self._get_zaxis(dry_run)

        disseminator = self._get_digital_disseminator(dry_run)

        path_to_points = PathToPoints(
            disseminator.samples_per_second, transformer,
            self._configuration.options.laser_thickness_mm)

        if force_source_speed:
            override_draw_speed = None
            override_move_speed = None
        else:
            override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None
            override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None

        pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0
        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.slew_delay) / 1000.0)

        if self._configuration.options.wait_after_move_milliseconds > 0:
            wait_speed = self._configuration.options.laser_thickness_mm / (
                float(self._configuration.options.wait_after_move_milliseconds)
                / 1000.0)
        else:
            wait_speed = None

        self._writer = LayerWriter(disseminator,
                                   path_to_points,
                                   self.laser_control,
                                   state,
                                   move_distance_to_ignore=self._configuration.
                                   options.laser_thickness_mm,
                                   override_draw_speed=override_draw_speed,
                                   override_move_speed=override_move_speed,
                                   wait_speed=wait_speed,
                                   post_fire_delay_speed=post_fire_delay_speed,
                                   slew_delay_speed=slew_delay_speed)

        self._layer_processing = LayerProcessing(
            self._writer,
            state,
            self._status,
            self._zaxis,
            self._configuration.dripper.max_lead_distance_mm,
            self._commander,
            pre_layer_delay,
            self._configuration.serial.layer_started,
            self._configuration.serial.layer_ended,
            self._configuration.serial.print_ended,
            self._configuration.serial.on_command,
            self._configuration.serial.off_command,
        )

        if self._zaxis:
            self._zaxis.set_call_back(self._status.drip_call_back)
            self._zaxis.start()

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            layer_generator,
            self._status,
            abort_on_error=abort_on_error,
        )

        self._controller.start()

    def get_status(self):
        return self._controller.get_status()

    def can_set_drips_per_second(self):
        if getattr(self._zaxis, 'set_drips_per_second', False):
            return True
        else:
            return False

    def set_drips_per_second(self, drips_per_second):
        if getattr(self._zaxis, 'set_drips_per_second', False):
            self._zaxis.set_drips_per_second(drips_per_second)
        else:
            logger.error('Cannot change drips per second on %s' %
                         type(self._zaxis))
            raise Exception('Cannot change drips per second on %s' %
                            type(self._zaxis))

    def get_drips_per_second(self):
        if getattr(self._zaxis, 'get_drips_per_second'):
            return self._zaxis.get_drips_per_second()
        else:
            logger.warning("Drips per second requested but does not exist")
            return 0.0

    def verify_gcode(self, file_name):
        self.print_gcode(file_name, print_sub_layers=False, dry_run=True)

    def close(self):
        if self._zaxis:
            self._zaxis.close()
        if self._controller:
            self._controller.close()
        else:
            logger.warning('Stopped before printing')
        if self._current_file:
            self._current_file.close()
            logger.info("File Closed")
        if self._notification_service:
            self._notification_service.send_message(
                "Print Complete", "%s is complete" % self._current_file_name)
예제 #20
0
    def __init__(self, configuration_manager):
        logger.info("Calibartion API Startup")
        self._configuration_manager = configuration_manager
        self._configuration = self._configuration_manager.load()

        self._point_generator = SinglePointGenerator()
        self._blink_generator = BlinkGenerator()
        self._orientaiton_generator = OrientationGenerator()
        self._alignment_generator = CalibrationLineGenerator()
        self._scale_generator = ScaleGenerator(speed=2.0, radius=1.0)

        self._test_patterns = {
            'Hilbert Space Filling Curve': HilbertGenerator(),
            'Square': SquareGenerator(),
            'Circle': CircleGenerator(),
            'Spiral': SpiralGenerator(),
            'Memory Hourglass': MemoryHourglassGenerator(),
            'Damping Test': DampingTestGenerator(),
            'NESW': NESWGenerator(),
            'Twitch': TwitchGenerator(),
            }

        self._current_generator = self._point_generator

        self._laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)
        transformer = TuningTransformer(scale=self._configuration.calibration.max_deflection)
        self._controller = None
        logger.debug("Setting up audiowriter")

        self._current_generator = self._point_generator

        self._state = MachineState()
        self._status = MachineStatus()

        self._communicator = UsbPacketCommunicator(self._configuration.circut.calibration_queue_length)
        self._communicator.start()
        self._disseminator = MicroDisseminator(
            self._laser_control,
            self._communicator,
            self._configuration.circut.data_rate
            )

        self._path_to_points = PathToPoints(
            self._disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        self._writer = LayerWriter(
            self._disseminator,
            self._path_to_points,
            self._laser_control,
            self._state,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            self._state,
            self._status,
            )

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            self._current_generator,
            self._status,
            abort_on_error=False,
            )

        self.make_pattern_fit()
        self._controller.start()
예제 #21
0
class PrintAPI(object):
    def __init__(self, configuration, start_height=0.0):
        logger.info('Print API Startup')
        self._configuration = configuration
        logger.info('Printer Name: %s' % self._configuration.name)
        self._controller = None
        self._zaxis = None
        self._start_height = start_height
        self._current_file_name = None
        self._current_file = None
        if self._configuration.email.on:
            self._email_gateway = EmailGateway(self._configuration.email.host, self._configuration.email.port, self._configuration.email.username, self._configuration.email.password)
            self._notification_service = EmailNotificationService(self._email_gateway, self._configuration.email.sender, self._configuration.email.recipient)
        else:
            self._notification_service = None

    @property
    def configuration(self):
        return self._configuration

    def print_gcode(self, file_name, print_sub_layers=True, dry_run=False, force_source_speed=False):
        self._current_file_name = file_name
        self._current_file = open(file_name, 'r')
        gcode_reader = GCodeReader(self._current_file, scale=self._configuration.options.scaling_factor, start_height=self._start_height)
        gcode_layer_generator = gcode_reader.get_layers()
        layer_generator = gcode_layer_generator
        self.print_layers(layer_generator, print_sub_layers, dry_run, force_source_speed=force_source_speed)

    def _get_zaxis(self, dry_run):
        if dry_run:
            return None
        elif self._configuration.dripper.dripper_type == 'photo':
            logger.info("Photo Zaxis")
            return PhotoZAxis(
                self._start_height,
                self._configuration.dripper.photo_zaxis_delay
                )
        elif self._configuration.dripper.dripper_type == 'emulated':
            logger.info("Emulated Zaxis")
            return TimedDripZAxis(
                self._configuration.dripper.drips_per_mm,
                self._start_height,
                drips_per_second=self._configuration.dripper.emulated_drips_per_second
                )
        elif self._configuration.dripper.dripper_type == 'microcontroller':
            logger.info("Micro Controller Zaxis")
            return SerialDripZAxis(
                self._get_communicator(dry_run),
                self._configuration.dripper.drips_per_mm,
                self._start_height,
                )

    def _get_communicator(self, dry_run):
        if hasattr(self, '_communicator'):
            return self._communicator
        if dry_run:
            self._communicator = NullCommunicator()
        else:
            self._communicator = UsbPacketCommunicator(self._configuration.circut.print_queue_length)
            self._communicator.start()
        return self._communicator

    def _get_digital_disseminator(self, dry_run):

            return MicroDisseminator(
                self.laser_control,
                self._get_communicator(dry_run),
                self._configuration.circut.data_rate
                )

    def print_layers(self, layer_generator, print_sub_layers=True, dry_run=False, force_source_speed=False):
        logger.info("Shuffled: %s" % self._configuration.options.use_shufflelayers)
        logger.info("Sublayered: %s" % self._configuration.options.use_sublayers)
        logger.info("Overlapped: %s" % self._configuration.options.use_overlap)

        if self._configuration.options.use_sublayers and print_sub_layers:
            layer_generator = SubLayerGenerator(layer_generator, self._configuration.options.sublayer_height_mm)
        if self._configuration.options.use_shufflelayers:
            layer_generator = ShuffleGenerator(layer_generator, self._configuration.options.shuffle_layers_amount)
        if self._configuration.options.use_overlap:
            layer_generator = OverLapGenerator(layer_generator, self._configuration.options.overlap_amount)

        if self._configuration.serial.on:
            self._commander = SerialCommander(self._configuration.serial.port)
        else:
            self._commander = NullCommander()

        self.laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)

        transformer = HomogenousTransformer(
            self._configuration.calibration.max_deflection,
            self._configuration.calibration.height,
            self._configuration.calibration.lower_points,
            self._configuration.calibration.upper_points,
            )

        state = MachineState()
        self._status = MachineStatus()

        if dry_run:
            abort_on_error = False
        else:
            abort_on_error = True

        self._zaxis = self._get_zaxis(dry_run)

        disseminator = self._get_digital_disseminator(dry_run)

        path_to_points = PathToPoints(
            disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        if force_source_speed:
            override_draw_speed = None
            override_move_speed = None
        else:
            override_draw_speed = self._configuration.cure_rate.draw_speed if self._configuration.cure_rate.use_draw_speed else None
            override_move_speed = self._configuration.cure_rate.move_speed if self._configuration.cure_rate.use_draw_speed else None

        pre_layer_delay = self._configuration.options.pre_layer_delay if self._configuration.options.pre_layer_delay else 0.0
        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        if self._configuration.options.wait_after_move_milliseconds > 0:
            wait_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.wait_after_move_milliseconds) / 1000.0)
        else:
            wait_speed = None

        self._writer = LayerWriter(
            disseminator,
            path_to_points,
            self.laser_control,
            state,
            move_distance_to_ignore=self._configuration.options.laser_thickness_mm,
            override_draw_speed=override_draw_speed,
            override_move_speed=override_move_speed,
            wait_speed=wait_speed,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            state,
            self._status,
            self._zaxis,
            self._configuration.dripper.max_lead_distance_mm,
            self._commander,
            pre_layer_delay,
            self._configuration.serial.layer_started,
            self._configuration.serial.layer_ended,
            self._configuration.serial.print_ended,
            self._configuration.serial.on_command,
            self._configuration.serial.off_command,
            )

        if self._zaxis:
            self._zaxis.set_call_back(self._status.drip_call_back)
            self._zaxis.start()

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            layer_generator,
            self._status,
            abort_on_error=abort_on_error,
            )

        self._controller.start()

    def get_status(self):
        return self._controller.get_status()

    def can_set_drips_per_second(self):
        if getattr(self._zaxis, 'set_drips_per_second', False):
            return True
        else:
            return False

    def set_drips_per_second(self, drips_per_second):
        if getattr(self._zaxis, 'set_drips_per_second', False):
            self._zaxis.set_drips_per_second(drips_per_second)
        else:
            logger.error('Cannot change drips per second on %s' % type(self._zaxis))
            raise Exception('Cannot change drips per second on %s' % type(self._zaxis))

    def get_drips_per_second(self):
        if getattr(self._zaxis, 'get_drips_per_second'):
            return self._zaxis.get_drips_per_second()
        else:
            logger.warning("Drips per second requested but does not exist")
            return 0.0

    def verify_gcode(self, file_name):
        self.print_gcode(file_name,  print_sub_layers=False,  dry_run=True)

    def close(self):
        if self._zaxis:
            self._zaxis.close()
        if self._controller:
            self._controller.close()
        else:
            logger.warning('Stopped before printing')
        if self._current_file:
            self._current_file.close()
            logger.info("File Closed")
        if self._notification_service:
            self._notification_service.send_message("Print Complete", "%s is complete" % self._current_file_name)
예제 #22
0
class CalibrationAPI(object):
    '''The calibration API proivides the tools required to setup a Peacy Printer'''

    def __init__(self, configuration_manager):
        logger.info("Calibartion API Startup")
        self._configuration_manager = configuration_manager
        self._configuration = self._configuration_manager.load()

        self._point_generator = SinglePointGenerator()
        self._blink_generator = BlinkGenerator()
        self._orientaiton_generator = OrientationGenerator()
        self._alignment_generator = CalibrationLineGenerator()
        self._scale_generator = ScaleGenerator(speed=2.0, radius=1.0)

        self._test_patterns = {
            'Hilbert Space Filling Curve': HilbertGenerator(),
            'Square': SquareGenerator(),
            'Circle': CircleGenerator(),
            'Spiral': SpiralGenerator(),
            'Memory Hourglass': MemoryHourglassGenerator(),
            'Damping Test': DampingTestGenerator(),
            'NESW': NESWGenerator(),
            'Twitch': TwitchGenerator(),
            }

        self._current_generator = self._point_generator

        self._laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)
        transformer = TuningTransformer(scale=self._configuration.calibration.max_deflection)
        self._controller = None
        logger.debug("Setting up audiowriter")

        self._current_generator = self._point_generator

        self._state = MachineState()
        self._status = MachineStatus()

        self._communicator = UsbPacketCommunicator(self._configuration.circut.calibration_queue_length)
        self._communicator.start()
        self._disseminator = MicroDisseminator(
            self._laser_control,
            self._communicator,
            self._configuration.circut.data_rate
            )

        self._path_to_points = PathToPoints(
            self._disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        self._writer = LayerWriter(
            self._disseminator,
            self._path_to_points,
            self._laser_control,
            self._state,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            self._state,
            self._status,
            )

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            self._current_generator,
            self._status,
            abort_on_error=False,
            )

        self.make_pattern_fit()
        self._controller.start()

    def subscribe_to_status(self, callback):
        '''Provides ability to subscribe to a printer safety status message (PrinterStatusMessage)'''

        self._communicator.register_handler(PrinterStatusMessage, callback)

    def set_print_area(self, width, height, depth):
        '''Set the print area (width, height, depth) in mm'''

        self._configuration.calibration.print_area_x = width
        self._configuration.calibration.print_area_y = height
        self._configuration.calibration.print_area_z = depth
        self._save()

    def get_print_area(self):
        '''Gets the print area (width, height, depth) in mm'''

        return (self._configuration.calibration.print_area_x, self._configuration.calibration.print_area_y, self._configuration.calibration.print_area_z)

    def set_orientation(self, x_flip, yflip, swap_axis):
        '''Allows for compensation of coil hook up by flipping and reversing axis'''

        self._configuration.calibration.flip_x_axis = x_flip
        self._configuration.calibration.flip_y_axis = yflip
        self._configuration.calibration.swap_axis = swap_axis
        self._save()

    def get_orientation(self):
        '''Gets the compensation for coil hook up returns tuple3 of booleans (flip x axis, flip y axis, swap axis) '''

        return (self._configuration.calibration.flip_x_axis, self._configuration.calibration.flip_y_axis, self._configuration.calibration.swap_axis)

    def show_point(self, xyz=[0.5, 0.5, 0.5]):
        '''Used to show a single point with no calibration applied'''

        # logger.info('Showing point')
        x, y, z = xyz
        self._point_generator.xy = [x, y]
        if (self._current_generator != self._point_generator):
            self._unapply_calibration()
            self._update_generator(self._point_generator)

    def show_blink(self, xyz=[0.5, 0.5, 0.0]):
        '''Used to show a blinking point with no calibration applied used for aligning on and off laser posisition'''

        logger.info('Showing blink')
        x, y, z = xyz
        self._blink_generator.xy = [x, y]
        if (self._current_generator != self._blink_generator):
            self._unapply_calibration()
            self._update_generator(self._blink_generator)

    def show_orientation(self):
        '''Used to show pattern with no calibration applied used for determining orientation'''

        logger.info('Showing Orientation')
        if (self._current_generator != self._orientaiton_generator):
            self._unapply_calibration()
            self._update_generator(self._orientaiton_generator)

    def show_line(self):
        '''Used to show a single line on one axis used to line up calibration grid'''

        logger.info('Showing line')
        self._unapply_calibration()
        self._update_generator(self._alignment_generator)

    def show_test_pattern(self, pattern):
        '''Used to show a test pattern with calibration applied'''

        logger.info('Showing test pattern %s' % pattern)
        if pattern in self._test_patterns.keys():
            self._apply_calibration()
            self._update_generator(self._test_patterns[pattern])
        else:
            logger.error('Pattern: %s does not exist' % pattern)
            raise Exception('Pattern: %s does not exist' % pattern)

    def show_scale(self):
        '''Shows the scale square'''

        logger.info('Showing scale')
        self._unapply_calibration()
        self._update_generator(self._scale_generator)

    def get_max_deflection(self):
        '''Gets the maximum allowable deflection of the mirrors as percentage'''

        return self._configuration.calibration.max_deflection
    
    def set_max_deflection(self, deflection):
        '''Sets the maximum allowable deflection of the mirrors as percentage'''

        self._configuration.calibration.max_deflection = deflection
        self._unapply_calibration()
        self._save()

    def set_laser_off_override(self, state):
        '''Allows user so force the laser on'''

        self._controller.laser_off_override = state

    def set_test_pattern_speed(self, speed):
        '''Changes the speed at which the test pattern is drawn in mm/sec'''

        [pattern.set_speed(speed) for pattern in self._test_patterns.values()]

    def set_test_pattern_current_height(self, current_height):
        '''Changes the height at which the test pattern is drawn in mm'''

        [pattern.set_current_height(current_height) for pattern in self._test_patterns.values()]

    def get_test_patterns(self):
        '''returns a list of test patterns'''

        return self._test_patterns.keys()

    def current_calibration(self):
        '''Returns the current calibration for the printer'''

        return self._configuration.calibration

    def save_points(self, height, lower_points, upper_points):
        '''deprecated use set_lower_points and set_upper_points, set_height'''

        self.set_lower_points(lower_points)
        self.set_upper_points(upper_points)
        self.set_height(height)

    def get_lower_points(self):
        '''Gets the lower calibration points'''

        return self._configuration.calibration.lower_points

    def set_lower_points(self, lower_points):
        '''Set and saves the suppliled lower calibration'''

        self._configuration.calibration.lower_points = lower_points
        self._save()

    def get_upper_points(self):
        '''Gets the upper calibration points'''

        return self._configuration.calibration.upper_points

    def set_upper_points(self, upper_points):
        '''Set and saves the suppliled upper calibration'''

        self._configuration.calibration.upper_points = upper_points
        self._save()

    def get_height(self):
        '''Gets the calibration height'''

        return self._configuration.calibration.height

    def set_height(self, height):
        '''Set and saves the upper calibration height'''

        self._configuration.calibration.height = height
        self._save()

    def _save(self):
        self._configuration_manager.save(self._configuration)
        self.make_pattern_fit()

    # deprecated
    def make_pattern_fit(self):
        for pattern in self._test_patterns.values():
            pattern.set_radius(self.get_largest_object_radius())

    def close(self):
        '''Must be called before shutting down applications'''

        self._controller.close()

    def _update_generator(self, generator):
        self._current_generator = generator
        self._controller.change_generator(self._current_generator)

    def _apply_calibration(self):
        self._path_to_points.set_transformer(
            HomogenousTransformer(
                self._configuration.calibration.max_deflection,
                self._configuration.calibration.height,
                self._configuration.calibration.lower_points,
                self._configuration.calibration.upper_points
                )
            )

    def _unapply_calibration(self):
        self._path_to_points.set_transformer(
            TuningTransformer(scale=self._configuration.calibration.max_deflection))

    def _validate_points(self, points):
        if (len(points) != 4):
            return False
        return True

    def get_largest_object_radius(self):
        '''Based on current calibrations_gets_maximum_size_of_object at the base layer'''

        lowest = None
        for (x, y) in self._configuration.calibration.lower_points.values():
            if not lowest or abs(x) < lowest:
                lowest = abs(x)
            if abs(y) < lowest:
                lowest = abs(y)
        logger.info("Calulated max radius of object as: %s mm" % lowest)
        return lowest

    def stop(self):
        '''Stops the calibaration interactivity'''

        self._controller.stop()
예제 #23
0
    def __init__(self, configuration_manager):
        logger.info("Calibartion API Startup")
        self._configuration_manager = configuration_manager
        self._configuration = self._configuration_manager.load()

        self._point_generator = SinglePointGenerator()
        self._blink_generator = BlinkGenerator()
        self._orientaiton_generator = OrientationGenerator()
        self._alignment_generator = CalibrationLineGenerator()
        self._scale_generator = ScaleGenerator(speed=2.0, radius=1.0)

        self._test_patterns = {
            'Hilbert Space Filling Curve': HilbertGenerator(),
            'Square': SquareGenerator(),
            'Circle': CircleGenerator(),
            'Spiral': SpiralGenerator(),
            'Memory Hourglass': MemoryHourglassGenerator(),
            'Damping Test': DampingTestGenerator(),
            'NESW': NESWGenerator(),
            'Twitch': TwitchGenerator(),
            }

        self._current_generator = self._point_generator

        self._laser_control = LaserControl(self._configuration.cure_rate.override_laser_power_amount)
        transformer = TuningTransformer(scale=self._configuration.calibration.max_deflection)
        self._controller = None
        logger.debug("Setting up audiowriter")

        self._current_generator = self._point_generator

        self._state = MachineState()
        self._status = MachineStatus()

        self._communicator = UsbPacketCommunicator(self._configuration.circut.calibration_queue_length)
        self._communicator.start()
        self._disseminator = MicroDisseminator(
            self._laser_control,
            self._communicator,
            self._configuration.circut.data_rate
            )

        self._path_to_points = PathToPoints(
            self._disseminator.samples_per_second,
            transformer,
            self._configuration.options.laser_thickness_mm
            )

        post_fire_delay_speed = None
        slew_delay_speed = None
        if self._configuration.options.post_fire_delay:
            post_fire_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.post_fire_delay) / 1000.0)
        if self._configuration.options.slew_delay:
            slew_delay_speed = self._configuration.options.laser_thickness_mm / (float(self._configuration.options.slew_delay) / 1000.0)

        self._writer = LayerWriter(
            self._disseminator,
            self._path_to_points,
            self._laser_control,
            self._state,
            post_fire_delay_speed=post_fire_delay_speed,
            slew_delay_speed=slew_delay_speed
            )

        self._layer_processing = LayerProcessing(
            self._writer,
            self._state,
            self._status,
            )

        self._controller = Controller(
            self._writer,
            self._layer_processing,
            self._current_generator,
            self._status,
            abort_on_error=False,
            )

        self.make_pattern_fit()
        self._controller.start()
class UsbTestTerminal(object):
    VREF_CAL_POS = 0
    TEMP30_CAL_POS = 1
    TEMP110_CAL_POS = 2
    ADC_KEY_POS = 3
    ADC_PA3_POS = 4
    ADC_TEMP_POS = 5
    ADC_VREF_POS = 6

    def __init__(self,verbose=False):
        self._verbose=verbose

        self._drips=0
        self._serial=None
        self._swrev=None
        self._hwrev=None
        self._adcNum=[]
        self._adcVal=[]
        self._dataRate=None
        self._adcCals=[]
        self._move=[0,0,0]

        self._usb = UsbPacketCommunicator(10)
        self._usb.register_handler(IAmMessage, self.iAmHandler)
        self._usb.register_handler(DripRecordedMessage, self.dripHandler)
        self._usb.register_handler(ReturnAdcValMessage, self.adcHandler)
        self._usb.start()
        if verbose:
            print "Started usb terminal"
        time.sleep(0.1)

    def usbClose(self):
        self._usb.close()

    def laserOff(self):
        move=self._move
        self._usb.send(MoveMessage(move[0],move[1],0))

    def laserOn(self):
        move=self._move
        self._usb.send(MoveMessage(move[0],move[1],255))

    def move(self,x,y,laserPower=0):
        self._move=[x,y,laserPower]
        self._usb.send(MoveMessage(x,y,laserPower))

    def setDrips(self,dripCount=0):
        self._usb.send(SetDripCountMessage(dripCount))

    def identify(self):
        self._usb.send(IdentifyMessage())

    def enterBootloader(self,i_am_sure=None):
        if i_am_sure==(0xDEADBEEF):
            self._usb.send(EnterBootloaderMessage())
            if (self._verbose):
                print "Bootloadereded"
        elif (self._verbose):
            print "i_am_sure not loaded with the correct value"
            print "Note: This may lock your peachy into the bootloader"
            print "      if you have old firmware on your board"

    #A non-ideal push/pop queue interface.
    #Doesn't account for mis-matching - May be worth clearing on each request?
    def popAdc(self,timeout=0.1):
        start=time.time()
        timeout=start+timeout #in seconds
        while(time.time()<timeout): #wait for data being available or 
            if (len(self._adcVal) != 0):
                tmp=[self._adcNum[0],self._adcVal[0]]
                del self._adcNum[0]
                del self._adcVal[0]
                return tmp
            else:
                time.sleep(0.01)

    def clearAdcQueues(self):
        self._adcNum=[]
        self._adcVal=[]

    def getAdcCalibrations(self):
        if len(self._adcCals)!=3:
            [adcNum,adcVrefCal] = self.getAdcVal(self.VREF_CAL_POS)
            [adcNum,adcTemp30] = self.getAdcVal(self.TEMP30_CAL_POS)
            [adcNum,adcTemp110] = self.getAdcVal(self.TEMP110_CAL_POS)
            self._adcCals = [adcVrefCal,adcTemp30,adcTemp110]

    def getTemperature(self):

        self.getAdcCalibrations()

        #Return actual Temperature in C
        #Formulas taken from STM32F0 datasheet page 252
        adcVrefCal = self._adcCals[self.VREF_CAL_POS]
        adcTemp30 = self._adcCals[self.TEMP30_CAL_POS]
        adcTemp110 = self._adcCals[self.TEMP110_CAL_POS]

        #Get the current Vref and Temperature each time
        [adcNum,adcTemperature]=self.getAdcVal(self.ADC_TEMP_POS)
        [adcNum,adcVref]=self.getAdcVal(self.ADC_VREF_POS)

        vrefCompensation = 1.0*adcVrefCal/adcVref
        temperature = adcTemperature*vrefCompensation-adcTemp30
        temperature = temperature*(110-30)/(adcTemp110-adcTemp30)
        temperature = temperature + 30

        if (self._verbose):
            print ('Temperatures Value={0} Celcius={1}'.format(adcTemperature,temperature))

        return temperature

    def getSupplyVoltage(self):

        self.getAdcCalibrations()
        adcVrefCal=self._adcCals[self.VREF_CAL_POS]
        [adcNum,adcVref]=self.getAdcVal(self.ADC_VREF_POS)

        vrefCompensation = 1.0*adcVrefCal/adcVref
        
        #calibrated at 3.3V always
        supplyVoltage = 3.3*vrefCompensation

        if (self._verbose):
            print ('Voltage {0}, Value {1}'.format(supplyVoltage,adcVref))

        return supplyVoltage

    def getAdcKeyVal(self):
        return self.getAdcVal(self.ADC_KEY_POS)

    def getAdcVal(self,adcNum):
        '''ADC NUMBERS:
        0 - Vref Calibration Factor
        1 - 30C temperature calibration
        2 - 110C temperature calibration
        3 - ADC key (PA2)
        4 - Pin (PA3)
        5 - Temperature
        6 - Vref (3.3V volts)
        '''

        self._adcNum.append(adcNum)
        self._usb.send(GetAdcValMessage(adcNum))
        if self._verbose:
            print('adcNum: {0}'.format(adcNum))
        return self.popAdc()

    def adcHandler(self,message):
        if (len(self._adcNum) > len(self._adcVal)):
            self._adcVal.append(message.adcVal)
            if self._verbose:
                print('adcNum: {0} adcVal: {1}'.format(self._adcNum[-1], self._adcVal[-1]))
        else:
            self.clearAdcQueues()

    def dripHandler(self, message):
        self._drips=message.drips
        if self._verbose:
            print('Recieved drip: {0}'.format(message.drips))

    def iAmHandler(self, message):
        self._serial=message.sn
        self._swrev=message.swrev
        self._hwrev=message.hwrev
        self._dataRate=message.dataRate
        if self._verbose:
            print('Serial number: {0}'.format(message.sn))
            print('SW rev number: {0}'.format(message.swrev))
            print('HW rev number: {0}'.format(message.hwrev))
            print('Data Rate:     {0}'.format(message.dataRate))
예제 #25
0
 def prepare(self):
     usb_communicator = UsbPacketCommunicator(50)
     usb_communicator.start()
     usb_communicator.send(EnterBootloaderMessage())
     time.sleep(0.1)  #need to wait for usb
     usb_communicator.close()
예제 #26
0
class DripperSetupMixIn(object):
    '''Depricated use get_dripper_drips_per_mm'''
    def get_drips_per_mm(self):
        logging.warning("Depricated use get_dripper_drips_per_mm")
        return self.get_dripper_drips_per_mm()

    '''Returns Drips Per mm'''

    def get_dripper_drips_per_mm(self):
        return self._current_config.dripper.drips_per_mm

    '''Returns the configured Dripper Type'''

    def get_dripper_type(self):
        return self._current_config.dripper.dripper_type

    '''Depricated use get_dripper_emulated_drips_per_second'''

    def get_emulated_drips_per_second(self):
        logging.warning("Depricated use get_dripper_emulated_drips_per_second")
        return self.get_dripper_emulated_drips_per_second()

    '''Gets the drips per second to be emulated'''

    def get_dripper_emulated_drips_per_second(self):
        return self._current_config.dripper.emulated_drips_per_second

    '''Depricated use get_dripper_photo_zaxis_delay'''

    def get_photo_zaxis_delay(self):
        logging.warning("Depricated use get_dripper_photo_zaxis_delay")
        return self.get_dripper_photo_zaxis_delay()

    '''Gets the photo delay in seconds'''

    def get_dripper_photo_zaxis_delay(self):
        return self._current_config.dripper.photo_zaxis_delay

    '''Depricated use set_dripper_drips_per_mm'''

    def set_drips_per_mm(self, drips):
        logging.warning("Depricated use set_dripper_drips_per_mm")
        self.set_dripper_drips_per_mm(drips)

    '''Sets Drips Per mm'''

    def set_dripper_drips_per_mm(self, drips):
        self._current_config.dripper.drips_per_mm = drips
        if self._drip_detector:
            self._drip_detector.set_drips_per_mm(drips)
        self.save()

    '''Sets the configured Dripper Type'''

    def set_dripper_type(self, value):
        self._current_config.dripper.dripper_type = value
        self.save()

    '''Depricated use set_dripper_emulated_drips_per_second'''

    def set_emulated_drips_per_second(self, value):
        logging.warning("Depricated use set_dripper_emulated_drips_per_second")
        self.set_dripper_emulated_drips_per_second(value)

    '''Sets the drips per second to be emulated'''

    def set_dripper_emulated_drips_per_second(self, value):
        self._current_config.dripper.emulated_drips_per_second = value
        self.save()

    '''Depricated use set_dripper_photo_zaxis_delay'''

    def set_photo_zaxis_delay(self, value):
        logging.warning("Depricated use set_dripper_photo_zaxis_delay")
        self.set_dripper_photo_zaxis_delay(value)

    '''Sets the photo delay in seconds'''

    def set_dripper_photo_zaxis_delay(self, value):
        self._current_config.dripper.photo_zaxis_delay = value
        self.save()

    '''Sets the drip count back to 0'''

    def reset_drips(self):
        self._drip_detector.reset()

    '''Turns on the counting of drips. Stop must be called to end this.'''

    def start_counting_drips(self, drip_call_back=None):
        self.drip_call_back = drip_call_back
        if self._current_config.serial.on:
            self._commander = SerialCommander(self._current_config.serial.port)
        self._change_dripper()

    def _change_dripper(self):
        self._stop_current_dripper()
        if self._current_config.dripper.dripper_type == 'emulated':
            pass
        elif self._current_config.dripper.dripper_type == 'photo':
            pass
        elif self._current_config.dripper.dripper_type == 'microcontroller':
            self._communicator = UsbPacketCommunicator(
                self._current_config.circut.calibration_queue_length)
            self._communicator.start()
            self._drip_detector = SerialDripZAxis(
                self._communicator, 1, 0.0, drip_call_back=self.drip_call_back)

    def _stop_current_dripper(self):
        if self._communicator:
            self._communicator.close()
        if self._drip_detector:
            self._drip_detector.close()
            self._drip_detector = None

    '''Turns off the counting of drips if counting'''

    def stop_counting_drips(self):
        if self._commander:
            self._commander.close()
        self._stop_current_dripper()

    def send_dripper_on_command(self):
        if self._commander:
            self._commander.send_command(
                self._current_config.serial.on_command)
        else:
            raise Exception("Serial not Started")

    def send_dripper_off_command(self):
        if self._commander:
            self._commander.send_command(
                self._current_config.serial.off_command)
        else:
            raise Exception("Serial not Started")