Esempio n. 1
0
    def send_gcode_command(self, command, hide_command=False):
        if "G28" in command:
            self.last_commanded_position.x = 0
            self.last_commanded_position.y = 0
        # TODO add G92 check for the positioning

        # clean the command a little
        command = command.replace("\n", "").replace("\r", "").upper()
        if command == " " or command == "":
            return

        # some commands require to update the feeder status
        # parse the command if necessary
        if "M110" in command:
            cs = command.split(" ")
            for c in cs:
                if c[0] == "N":
                    self.line_number = int(c[1:]) - 1
                    self.command_buffer.clear()

        # check if the command is in the "BUFFERED_COMMANDS" list and stops if the buffer is full
        if any(code in command for code in BUFFERED_COMMANDS):
            if "F" in command:
                self.feedrate = self.feed_regex.findall(command)[0][0]
            if "X" in command:
                self.last_commanded_position.x = self.x_regex.findall(
                    command)[0][0]
            if "Y" in command:
                self.last_commanded_position.y = self.y_regex.findall(
                    command)[0][0]

            # wait until the lock for the buffer length is released -> means the board sent the ack for older lines and can send new ones
            with self.command_send_mutex:  # wait until get some "ok" command to remove extra entries from the buffer
                pass

        # send the command after parsing the content
        # need to use the mutex here because it is changing also the line number
        with self.serial_mutex:
            line = self._generate_line(command)

            self.serial.send(line)  # send line
            self.logger.log(settings_utils.LINE_SENT, line.replace("\n", ""))

            # TODO fix the problem with small geometries may be with the serial port being to slow. For long (straight) segments the problem is not evident. Do not understand why it is happening

        with self.command_buffer_mutex:
            if (len(self.command_buffer) >= self.command_buffer_max_length
                    and not self.command_send_mutex.locked()):
                self.command_send_mutex.acquire(
                )  # if the buffer is full acquire the lock so that cannot send new lines until the reception of an ack. Notice that this will stop only buffered commands. The other commands will be sent anyway

        if not hide_command:
            self.handler.on_new_line(
                line)  # uses the handler callback for the new line

        if firmware.is_marlin(
                self._firmware
        ):  # updating the command only for marlin because grbl check periodically the buffer status with the status report command
            self._update_timeout(
            )  # update the timeout because a new command has been sent
Esempio n. 2
0
    def _generate_line(self, command, no_buffer=False, n=None):
        line = command
        # TODO add a "fast mode" remove spaces from commands and reduce number of decimals
        # removing spaces is in conflict with the emulator... Need to update the parser there also
        # fast mode test
        if self.is_fast_mode:
            line = command.split(" ")
            new_line = []
            for l in line:
                if l.startswith("X"):
                    l = "X" + self.command_resolution.format(float(
                        l[1:])).rstrip("0").rstrip(".")
                elif l.startswith("Y"):
                    l = "Y" + self.command_resolution.format(float(
                        l[1:])).rstrip("0").rstrip(".")
                new_line.append(l)
            line = "".join(new_line)

        # marlin needs line numbers and checksum (grbl doesn't)
        if firmware.is_marlin(self._firmware):
            # add line number
            if n is None:  # check if the line number was specified or if must increase the number of the sequential command
                self.line_number += 1
                n = self.line_number
            if self.is_fast_mode:
                line = "N{}{}".format(n, line)
            else:
                line = "N{} {} ".format(n, line)
            # calculate marlin checksum according to the wiki
            cs = 0
            for i in line:
                cs = cs ^ ord(i)
            cs &= 0xff

            line += "*{}\n".format(cs)  # add checksum to the line

        elif firmware.is_grbl(self._firmware):
            if line != firmware.GRBL.buffer_command:
                line += "\n"

        else:
            line += "\n"

        # store the line in the buffer
        with self.command_buffer_mutex:
            self.command_buffer.append(self.line_number)
            self.command_buffer_history["N{}".format(self.line_number)] = line
            if no_buffer:
                self.command_buffer.popleft(
                )  # remove an element to get a free ack from the non buffered command. Still must keep it in the buffer in the case of an error in sending the line

        return line
Esempio n. 3
0
    def _on_device_ready(self):
        if firmware.is_marlin(self._firmware):
            self._reset_line_number()

        # grbl status report mask setup
        # sandypi need to check the buffer to see if the machine has cleaned the buffer
        # setup grbl to show the buffer status with the $10 command
        #   Grbl 1.1 https://github.com/gnea/grbl/wiki/Grbl-v1.1-Configuration
        #   Grbl 0.9 https://github.com/grbl/grbl/wiki/Configuring-Grbl-v0.9
        # to be compatible with both will send $10=6 (4(for v0.9) + 2(for v1.1))
        # the status will then be prompted with the "?" command when necessary
        # the buffer will contain Bf:"usage of the buffer"
        if firmware.is_grbl(self._firmware):
            self.send_gcode_command("$10=6")

        # send the "on connection" script from the settings
        self.send_script(self.settings['scripts']['connected']["value"])
Esempio n. 4
0
 def _reset_line_number(self, line_number=2):
     # Marlin may require to reset the line numbers
     if firmware.is_marlin(self._firmware):
         self.logger.info("Resetting line number")
         self.send_gcode_command("M110 N{}".format(line_number))