area515 / Photonic3D

Control software for resin 3D printers
http://photonic3d.com
GNU General Public License v3.0
133 stars 112 forks source link

How best to tie machine-specific UI & lifecycle functions to machine configurations #115

Open jmkao opened 8 years ago

jmkao commented 8 years ago

What do you think is the best way to tie machine specific UI and lifecycle (e.g. hooks at start/stop and saving some state) requirements to the machine configurations without having to have a separate fork of the whole project for each type of printer?

On the simple end, there may be just machines with no X or Y axes, where the page may layout better without the unnecessary buttons.

On the more complex end, there are machines like the Kudo3D Titan 1 which need a number of custom buttons to operate. For example, the Titan 1 has no endstops, so G28 is not safe to run (I've asked Kudo3D to make a firmware change to disable that function in their version of Marlin). Instead, you set the software zero point by gradually lowering the absolute Z=0 point with successive pairs of:

G90
G92 Z<distance>
G0 Z0
G91

while in absolute (G90) mode. There are buttons in their modified version of projectlayer that perform this sequence for distance 10, 1, and 0.1mm.

Once this is done, homing is done as

G90
G0 Z0
G91

Other machines might need different extra buttons to control machine specific functionality.

Since the zero point is soft, it doesn't survive firmware reboots. There would also need to be a way to save some state when the printer is stopped. One would need to be able to add a machine specific hook when a printer is stopped to execute M114 and save the Z height listed there, and then set the software offset to that same value with G92 when the machine is next started. Other machines might need different post-start or pre-stop operations like turning on/off lights, fans, or other accessories.

None of this logic would be desirable to hardcode into the UI or the Java implementation of start/stop.

WesGilster commented 8 years ago

Angular is pretty modular and gracefully collapses functionality very nicely so I don't really see the need for separate forks.

I see your idea of machine hooks to to gather state information, but first think about the chicken vs. egg issue that idea creates. Which comes first, the variable that injects into the gcode, or the hooks that assign the variable...

I've used a different philosophy for delivering similar functionality that stays consistent with the way we provide other pieces of common 3d printer functionality. The situation I had was that I wanted to have overriding capabilities for lift speed and distance. At first I thought I'd use regexs to capture certain gcodes that set the speed and distance in the parser and feed them back into variables so that the GUI could modify them.

Instead, I decided on implementing modular printing functions for which you could define Freemarker templates. Unfortunately I ended keeping the presumptuous "gcode" phrase in those field names which was a very poor choice of naming. Anyway, I decided to abstract these pieces of common functionality by utilizing variables in templates(like everything else we do), as opposed to extracting the values and setting the variables with the hooks approach. In fact, these variables are already held and maintained inside of the AbstractPrintFileProcessor anyway, they just need to saved back to the printer configuration, or "printer supplement" file in the case of a community maintained printer profile.

So to describe how I would implement it with the M114 is that we'd abstract the concept into a nice name like getPrinterHomingGcode. Some printers might not define any functionality for this freemarker template. Turns out that the mUVe1 does have printer homing but they are endstop based, but it's still the perfect place for the homing gcode. Now that we have such a function, the AbstractPrintFileProcessor knows the perfect time to call such a function.

At this point, I can see a few pieces of functionality that could use some work:

  1. I don't have a grand mechanism to query for printer functions other than to ask if the freemarker template for that particular piece of functionality is empty on the printer profile. (Not a huge priority)
  2. A mechanism to save state. A.For Printers: to keep the things like absolute positions as you described. (higher priority) B.For PrintJobs: in case you happen to want to start a print, stop a print, start another print, stop that print, and resume the first on the same printer. (I would consider this a very low priority feature)