synman / Octoprint-Bettergrblsupport

Better Grbl Support Plugin for Octoprint based (loosely) on the original Grbl Support plugin developed by mic159
https://github.com/synman/Octoprint-Bettergrblsupport/wiki
64 stars 19 forks source link

Warn if pending jog will (implicitly) re-enable spindle / laser #63

Open synman opened 2 years ago

synman commented 2 years ago

It is possible to have M3 active with S > 0 prior to executing something such as a machine home or jog. The behavior is inconsistent between them which can lead to the spindle / laser powering back on.

For example:

  1. Machine is active in some manner. M3 S10000 are set
  2. The Machine is Machine Homed
  3. The spindle/laser will power down for this operation and remain powered down upon completion
  4. A Go to Work Origin or typical jog command is executed (work origin is basically just a jog to 0,0)
  5. The spindle/laser will power back up because nothing ever took them out of M3.

Insert a warning / confirmation request at the beginning of step 4 if M3 /M4 are active and S>{weak laser value}.

The current values ($G results),as well as mode, state, x, y, z should be placed in a shared dict and the existing individual variables removed.

WrigglyTentacles commented 2 years ago

Are you saying you want to poll the controller to see if the spindle/laser is active before a command of any kind is issued? Or are you saying that you want to analyze the gcode and check if there is a rapid move coming up before an M5 is issued?

synman commented 2 years ago

Shortly before writing up this issue I was at my CNC machine and I had turned turned the spindle on (M3 S10000).

While the spindle was running, I executed a Machine Home. The spindle powered down.

Curious at this point I then did a jog to a "safe" location. The spindle spun back up as it moved to that position.

Seemed a smidge dangerous so I'm thinking a simple check is needed prior to a framing operation, jog / work home that warns you if the machine is not in M5 and S > {weak laser} value.

I've got x, y, z, speed, power, state, and mode all defined as individual variables today. This would be a good time to consolidate them into a dict and pass them along to the view models that need them (tab and sidebar).

A couple nights ago I put in the hooks for catching the current state of the spindle mode / power level by integrating $G into the plugin connection logic. With bgs keeping track of them from that point forward (it continuously monitors the outbound buffer) the plugin always knows what their values are.

    # $G response
    if line.startswith("[GC:"):
        parserState = line.replace("[", "").replace("]", "").replace("GC:", "")

        for state in parserState.split(" "):
            if state in ("G90", "G91"):
                self.positioning = int(state[2:3])
                self._logger.debug("parser state indicates [%s] distance mode", "absolute" if self.positioning == 0 else "relative")

            elif state in ("G0", "G1", "G2", "G3", "G38.2", "G38.3", "G38.4", "G38.5", "G80"):
                self._logger.debug("parser state indicates [%s] motion mode", state)
            elif state in ("G54", "G55", "G56", "G57", "G58", "G59"):
                self._logger.debug("parser state indicates [%s] coordinate system available", state)
            elif state in ("G17", "G18", "G19"):
                self._logger.debug("parser state indicates [%s] plane selected", state)
            elif state in ("G20", "G21"):
                self._logger.debug("parser state indicates [%s] uom active", "metric" if state == "G21" else "imperial")
            elif state in ("G93", "G94"):
                self._logger.debug("parser state indicates [%s] feed rate mode", state)
            elif state in ("M3", "M4", "M5"):
                self._logger.debug("parser state indicates [%s] spindle state", state)
            elif state in ("M7", "M8", "M9"):
                self._logger.debug("parser state indicates [%s] coolant state", state)

            elif state.startswith("F"):
                self.grblSpeed = round(float(state.replace("F", "")))
                self._logger.debug("parser state indicates feed rate of [%d]", self.grblSpeed)
            elif state.startswith("S"):
                self.grblPowerLevel = round(float(state.replace("S", "")))
                self._logger.debug("parser state indicates spindle speed of [%d]", self.grblPowerLevel)
            elif state.startswith("T"):
                self._logger.debug("parser state indicates tool #[%s] active", state.replace("T", ""))

            self._plugin_manager.send_plugin_message(self._identifier, dict(type="grbl_state", speed=self.grblSpeed, power=self.grblPowerLevel))

        return self.pick_a_response(None)