t-oster / LibLaserCut

a platform independant library to control Lasercutters. This is the base library for VisiCut
http://visicut.org
Other
59 stars 55 forks source link

Hooks for Realtime and Out-of-Sequence Operations. #158

Open tatarize opened 4 years ago

tatarize commented 4 years ago

As mentioned in t-oster/VisiCut#577 there is some need for realtime and out of sequence operations. Since you first and foremost this would require backend support first especially with hooks for the backend to perform these operations and declare if they have the feature.

I've tried to map them out for some work in MeerK40t. A lot of them are covered in GRBL since it's pretty popular and open. And largely has mapped out what people want and given it to them. So a lot of those features for other boards are subsets of GRBL. ( https://github.com/gnea/grbl/wiki/Grbl-v1.1-Commands )

Realtime operations are operations that often skip the buffered data in order to change the state on the fly.

Out of Sequence operations are things you might want to do with a laser that are not merely sending it a program sequence of operations and having them perform them.

LaserWeb at some point had a drivers protocol where it would ask for features possessed so some drivers could likely lack a feature. Or simply not have it possible given the protocols. The routine here would be to ask the driver for the features it has through some mechanism, and have established hooks in the base class to use these.

I've included a couple extra lasers LibLaserCut doesn't support and one I've reverse engineered and nobody supports as examples of possibility.


Jogging. Basically all lasers have jogging, usually done through moves. This also permits a lot of different alternative command sequences like tracing the job by moving the laser around the outer part of the job, or performing tests.

GRBL: this is sent with the whole $J= prefix and is non-mode shifting move codes. $J=X(pos) Y(pos), with a lot of optional gcode flags. M2 Nano: this is sent with some basic commands inside rapid mode. Usually with a I(RLTB)(distance)S1P. Ruida: this is sent as a single UDP packet with the right command prefix something like "d900027f7f7f3170" and the weird 7 bit encoding (unswizzled) Moshiboard: this is send via USB with a complete program packet, in absolute value of the desired end position. 79:13:27:01:00:00:C5:00:00:00:5D:00:00:00:00:0D:25:25:25:25:2D:2D:00:00:00. Where the control codes, 79, C5, 5D, 0D, 25, 2D can vary among the 16 different swizzled forms.


Jogging cancel

GRBL also has a realtime reset command for the jogging. This seems to be to stop a fairly continuous motion. ctrl-x sent at anytime, reacts instantly. M2 Nano can issue a soft reset to purge the buffer. Can be sent at most times will purge react instantly. Ruida: I dunno any way to stop a move in process. Moshiboard: could call Stop since the jogs are small programs.


Home

GRBL: accepts a $H command and there are a couple G-codes that can do this. M2 Nano: Performs homing when sent "PP" in any single packet. Usually IPP. Ruida: sends a command: d82c Moshiboard: Homing on a moshi is a command that says go to the absolute poisition of 0,0


Unlock Rail

GRBL: M18 unlocks and disables the steppers. M2 Nano: Triggered by IDS2P or any command with a S2 value. Ruida: I dunno. Moshiboard: A7 and anything in the command values: '08', '11', '48', '13', '18', '31', '58', '33', '0c', '19', '4c', '1b', '1c', '39', '5c', or '3b'. which is the same thing as stop. During idle this unlocks rail, and while running a programs stops that program. Likely both.


Lock Rail Sometimes you'd want to do this if your laser doesn't automatically lock the rail and you want to clean the mirrors, but it's kinda rare.

GRBL: You can enable the steppers and tell it to power them. M2 Nano: Ending with S1P locks the rails. Ruida: I dunno. Moshiboard: None known.


Linger Laser Fire. Sometimes a thing, always scary. This would be used to punch through a board to start with or test fire the laser.

GRBL: there is some way to linger the laser in a spot. M2 Nano: IDS1P turns on / IUS1P turns off. Ruida: I dunno if this is possible. Moshiboard: everything is written in these program things and sent A6 and there's nothing for leaving the laser on. Since the control flags cover laser-on/laser-off and a destination.


Soft reset. Halts and resets board without power cycle.

GRBL. Explicit and realtime. ctrl-x soft resets the board. Halts the program, throws an alarm. M2 Nano. Sending I will soft reset, must be accompanied by also halting the flow of packets on the driver side. Ruida, again I dunno. Moshiboard: Sends USB command A7xx where xx is '08', '11', '48', '13', '18', '31', '58', '33', '0c', '19', '4c', '1b', '1c', '39', '5c', or '3b'. Pause/Resume

GRBL: Takes realtime commands ! for feed hold. And ~ for resume. M2 Nano: Takes realtime command "P" which pauses. Also "P" which resumes. These must be in different packets. Ruida: Moshiboard:


Speed/Power/Rapid overrides.

GRBL: These are explicit in GRBL. It does ±1% or ±10% for speed, power, or rapid movements. M2 Nano: Since the entire file isn't sent on the fly overrides will just involve changing the state of something producing in the information on the fly. If this is a pre-defined egv file that wouldn't be possible. But, it's pretty easy to just tell it to move at a different speed. Though these could take a few seconds to kick in. Cannot change rapid speed. Ruida: I dunno. There's some buttons for cut scale and go scale. Moshiboard: All moshi commands are a precompiled program, changing speed while running is doubtful and moshidraw has no option for that.


Misc.

GRBL: Safety Door, Spindle Stop, Flood Coolant, Mist Coolant. -- Mostly triggers some weird stuff like forcing a safety door alarm, and using coolant for regular non-laser projects or triggering those particular switches on the board that might be reused for other things. M2 Nano: -- Ruida: -- Moshiboard: -- That should be it for out of sequence non-program mode commands. Basically anything you wouldn't find saved in a file of laser code.


Information requests.

GRBL: '?' status report. This provides information on machine state and current position and some modal information. M2 Nano: Sends the CH341x chip a status request which provides information about CRC errors, low power, mode completion, and business. Since it's running on the fly it'll know, speed, power, and location information. Since most of the controlling is done locally. Ruida: Ruida sends for a lot of information is specific requests DA00xxxx and the requested information index. And the machine responds DA01xxxx. These things include job count, current position in X, Y, Z and U. The min and max power settings, the current set speed, the previous work time, get frame, and a lot more. Moshiboard: Requests are sent via usb with ACxx which is the requested amount of bytes this then advances until it's read this data and then it know the Moshiboard version. It also sends status requests like the M2 Nano since it also uses a CH341x chip. This information contains error information and state information. So idle and working state information.


The really odd one there is information requests. These are useful to be relayed back to the user, the most useful is position. Current position, finished with current job, and some other elements might be useful but other things like position of the second laser isn't something other devices are going to need much of. But the same general outline in the driver would be true there. You say what type of information you have out of a given list of known information and the driver can request that information agnostic of the underlying device.

t-oster commented 4 years ago

How about defining a bunch of interfaces and the driver can choose to implement them. Visicut can then check with instanceof if the driver eg supports jogging and can show the interface if needed? However this would fix them per driver and maybe it would be preferable to have them checked more dynamically so the driver can choose according to it's settings. Or maybe the interface also get a isXXsupported method which returns a boolean

tatarize commented 4 years ago

You could also just modify the LaserCutter.java class directly to include those commands. So give it a bunch of stuff to check what it supports.

    /**
     * If you lasercutter supports autofocus, override this method,
     * to let programs like VisiCut know, that they don't need to focus.
     */
    public boolean isAutoFocus() {
        return false;
    }

and

    /**
     * Override this method, return true and override the
     * estimateJobDuration-method to allow Programs to use
     * your driver to estimate the duration of a job before
     * executing
     */
    public boolean canEstimateJobDuration() {
        return false;
    }

    /**
     * Returns an estimated time, how long the job would take
     * in seconds
     */
    public int estimateJobDuration(LaserJob job) {
        throw new RuntimeException("Method not implemented");
    }

This is the methodology that was already implemented for the various other things. Estimation of job duration, autofocus,

Then you'd always know that functionality is there. So if Visicut gets modified to check it doesn't have to check the classes or have a bunch of interfaces sitting around. It can just see if that driver has an unlock_rail function, then unlock the rail if it does.

The providing information stuff would need to be sort of predefined into relevant information, and how it wants it parsed.

    public boolean canHomeDevice() {
      return false;
    }

    public void homeDevice() {
      throw new RuntimeException("Method not implemented");
    }

    public boolean canUnlockRail() {
      return false;
    }

    public void unlockRail() {
      throw new RuntimeException("Method not implemented");
    }

    public boolean canJog() {
      return false;
    }

    public boolean jog(double x, double y, double dpi) {
      throw new RuntimeException("Method not implemented");
    }

    public boolean canCancelJog() {
      return false;
    }

    public boolean cancelJog(double x, double y, double dpi) {
      throw new RuntimeException("Method not implemented");
    }

    public boolean providesInformation(String info) {
      return false;
    }

    public LaserProperty provideInformation(String info) {
      throw new RuntimeException("Method not implemented");
    }

A cursory implementation, not sure about jogging with dpi but clearly you give units for the other parts. But, the short term thing would be just defining what things you'd want drivers to be able to support, and give them a place to do that. But, just blanking them all out anyway because meh.

Also, I used the same throw error as the estimateJobDuration() call used for these but I know that clearly 'throw new UnsupportedOperationException("Not supported yet.");` is the more obvious error class to throw.

And really getting that stuff right from the get-go is really helpful. Especially a predefined list things information to provide. And I didn't do things like pause and cancel and resume, so it's not exaustive but really you're not going to send it GRBL a door alarm message to force it to say the door is opened or whatever. But, maybe you'd want hooks for that.

t-oster commented 4 years ago

yes, this would probably make even more sense.... We should ask for the most wanted and most useful features and try not to bloat the UI too much.

What is the use-case of jogging? Doesn't the Lasercutter have hardware buttons for that? Maybe we should start a poll?

tatarize commented 4 years ago

Well, the UI wouldn't have to bloat at all. You could support the feature in the driver and yet, never give a crap in the UI that that is a feature that is supported by the driver. If somebody else wanted to use liblasercut, they could maybe use that feature but it's not a requirement to change anything about the UI at all. Just giving a canCancel() and cancel() functions, doesn't mean you ever call them.

Jogging and moving the head without cutting as an out of sequence operation lets you outline the project you're going to run to make sure it's positioned correctly and can fit the space. GRBL also has some setups for joystick controls which is why they have cancel jog. When release the joystick it stops moving. And no. Most K40 devices do not have hardware buttons. My machine quite clearly does not. But, also, just the existence of hardware buttons doesn't make software buttons unusable. Even modified K40s with more advanced GRBL boards do not have hardware buttons.

t-oster commented 4 years ago

Speaking of which: VisiCut has a "move to position" option when you right-click into the drawing area. Right now this creates a dummy job imho, but maybe we can refactor this to use the jog-feature if supported. I know that I don't have to use all functions, but I was talking about not blindly including every function that is possible, but rather find out what really makes sense in that context.

tatarize commented 4 years ago

Yeah, I wouldn't include GRBLs trigger mist coolant or flood coolant. But, there's really not many other things that do things. And certainly you could just pick the useful ones. My list there is kinda exhaustive, there's a couple other things like cancel job but that stuff is about it. I ran through a lot of things including lasers nobody decoded like Moshiboard. There's just not that many things lasers can do. I guess Ruida can run two lasers or something which is kinda interesting.