Syringe Pumps / Depositing Viscous Materials
-
@DocTrucker said in Syringe Pumps / Depositing Viscous Materials:
@dc42 @T3P3Tony @droftarts do you know where in the list of priorities parallel gcode streams are? Six months or more like two years after a load of other dependencies?
It's hard to say. We have one other user wanting parallel GCode streams at present. The low-level support is already implemented, but we need to decide on the mechanisms that will control the second stream. Many use cases would be served by a single GCode print file containing commands for both streams, with an additional command that forces whatever stream is ahead to wait for the other to catch up. That wouldn't work for your use case, which needs to send commands to the second stream from a separate file such as a trigger macro.
-
Currently my only option appears to be:
- Trigger a macro on the syringe approaching end of travel.
- [Macro] trigger a change of tool (or swap drives for active tool) to the spare syringe and drive.
- Resume print.
- Use the raspberry pi based live g-code parsing to inject moved into vfollowing G1 commands that would not delay the overall G1 move, but would allow the slow, incremental refill of the syringe.
With concurrent moves this would look something like:
- Macro triggered by limit switch on syringe.
- [Macro] Wait for moves on currently inactive (unlikely to be any moves underway) syringe to complete.
- [Macro] change of tool (or swap drives for active tool) to the spare syringe and drive.
- [Macro] Run a G1 command that runs in parallel to the other g code commands that refills the syringe.
- Resume print.
- [Syringe comfortably refills in the time taken to deplete the second syringe]
- Macro triggered by limit switch on syringe.
- [Macro] Wait for moves on currently inactive (unlikely to be any moves underway) syringe to complete.
- [Macro] change of tool (or swap drives for active tool) to the full syringe and drive.
- [Macro] Run a G1 command that runs in parallel to the other g code commands that refills the syringe.
- etc...
More bullet points in the second list but it is far easier (for me) to implement!
-
Let's suppose that we provide the following mechanisms:
-
A mechanism to assign each axis to one or other movement queue. So in M584 you would specify which movement queue any new axes you create would be assigned to. That assignment would probably be fixed.
-
A mechanism for wait for both movement queues to empty (probably M400 with an extra parameter).
-
Movement commands involving axes assigned to one movement queue would be permitted to happen concurrently with movement commands involving axes assigned to the other movement queue.
Would that be sufficient for your use case? If you think it would, can you write the macros that would be needed?
-
-
@dc42 I will have a look at that and respond shortly. Just cleared some other work from my desk to leave me able to tackle this.
-
@dc42 How's this looking (need to double check pin labelling for expansion card)...
Config file snippets:
M584 X0 Y1:3 Z2 E5 A4 B6 ; Apply drive mapping to axes - E on expansion card. ; A4 = Physical rotational axis connected to main board. ; E5 = Primary Syringe Extruder connected to expansion board. ; B6 = Secondary Syringe Extruder connected to expansion board. ; M92, M350, M566, M203, M201, M906 all as expected, B settings mirror E. M574 B2 S1 P"e5stop" ; Set active low endstops on Z via pin e5stop for secondary syringe pump. ; Define inputs ; e4stop = Primary syringe extruder empty (on expansion board) ; e6stop = Secondary syringe extruder empty (on expansion board) M950 J0 C"^e4stop" ; Input 0 uses e3Stop pin, pullup enabled M950 J1 C"^e6stop" ; Input 1 uses e4Stop pin, pullup enabled ; Define triggers M581 T2 P0 S0 R0 ; Run sys/trigger2.g on falling edge on input 0 at any time. M581 T3 P1 S0 R0 ; Run sys/trigger3.g on falling edge on input 1 at any time. M98 P"trigger2.g"
trigger2.g
; This is used to: ; Map the secondary syringe extruder drive to B. ; Map the primary syringe extruder drive to E. ; Drive the B axis to it's limit. ; Carry on with pint while B retracts & refills. M400 [magic argument to wait for parallel moves to complete] M584 E5 B6 ; Apply drive mapping to axes - E on expansion card. ; E5 = This syringe extruder. ; B6 = other syringe extruder. ; e3stop = Primary syringe extruder full (on expansion board) ; e5stop = Secondary syringe extruder full (on expansion board) M574 B2 S1 P"e5stop" ; Set active low endstops on Z via pin e5stop G1 [magic argument to make this move parallel] B-100 H1 ; Print process continues
trigger3.g
; This is used to: ; Map the primary syringe extruder drive to B. ; Map the secondary syringe extruder drive to E. ; Start driving the B axis to it's limit. ; Carry on with pint while B retracts & refills. M400 [magic argument to wait for parallel moves to complete] M584 E6 B5 ; Apply drive mapping to axes - E on expansion card. ; E6 = This syringe extruder. ; B5 = other syringe extruder. ; e3stop = Primary syringe extruder full (on expansion board) ; e5stop = Secondary syringe extruder full (on expansion board) M574 B2 S1 P"e3stop" ; Set active low endstops on Z via pin e3stop G1 [magic argument to make this move parallel] B-100 H1 ; Print process continues
Thankfully I should be able to test most of this aside from having moves running in parallel.
-
Making progress! Test rig assembled for dual syringing, just need to work on the fitting the two switches per axis and get on with testing the non-parallel move parts of the macros...
Looking at the pause on flow (although this is driving at a higher rate than I would need) I think I may need to do a stages switch over for the syringes where I use mix ratios to go from 100% one syringe to 100% the other in a number of steps, rather than one step.
@dc42 would it be neater than what I proposed a couple of posts ago to change mixing ratios on the fly and have some way of excluding an extruder drive from lock in with the others for the retract?
-
...some of that pause is due to the hysteresis introduced by the slight shifting of the syringe in the holder, and in the part that holds the plunger handle.
-
More testing. Two switches are wired up to the e0 and e1 inputs. The e0 switch calls trigger2.g and e1 is wired up as the limit for axis B. (Need to test whether you can drive to home switch on E axis)
This video shows the basic function. Empty switch is pressed which calls for a drive to home. The home limit is then triggered when the cylinder is full.
The following video simulates what would happen if the axis were triggered in the middle of a move. You can clearly see the trigger is a lower priority than the G1 command. The G1 move is started, the cylinder move is started, the empty switch pressed and the G1 move completes before executing the trigger macro:
Can this be changed so that the trigger is a higher priority than G1?
If so is there a guide to how I could store the position of the axis before the home drive and then re-apply it after the home drive to save it doing some strange things? This may also be useful if swapping from one drive to the other as the active extruder.
If the trigger priority can't be changed it has obvious implications on the positioning of the switches, and forces a requirement to parse the g-code. There must be spare space after the switch trigger, and the gcode must be parse to ensure no extruder move is long enough to travel further than that distance.
Edit: Confirmed drive to limit does not behave the same on the extrusion axis as the other axis. There doesn't appear to be a H parameter that means the G1 will terminate on a specific input.
-
There's no real way to interrupt a long G1 move at the moment. Breaking the single long move up into smaller shorter moves would allow an interrupt to get in between.
-
Could perhaps remap endstops instead of triggers?
-
Currently working on using the trigger to signal the syringe is nearly empty and swapping the drives around with M584 between E and B so I can do a home drive in the B axis and carry on with the other axis as E, which can't do home drives.
Very nearly working as it should do - but obviously no parrallel motion without gcode parsing. To be fair since the syringes are fixed volume the switches could all be precoded in the build file.
Some oddness that smells like a bug but need to do some more work on that before raising it.
Edit:
Bug1: https://forum.duet3d.com/topic/22292/bug-rrf-3-3beta2-g92-b0-changes-e-axis-position
Bug2: https://forum.duet3d.com/topic/22295/bug-2-rrf-3-3beta2-axis-hanging-after-m584-re-assignemnt/10 -
Some more tests on this system.
To be clear this is not the only approach for achieving the end goal of minimal down time for the syringe extruder. Hard coding the syringe retractions and changeovers into the build files would be a way of achieving this. This work as presented currently would also be better suited to a single syringe system as the change over has no benefit as presented. But it has help uncover a few peculiarities in the firmware, so not lost effort.
In the following tests there are two trigger routines associated with switches that will be used to tell the system a syringe is running low on material. These triggers switch the currently active syringe which is running low to the B axis and the other syringe back to the E axis from the B axis. After the drives are switched a drive to home is commanded on the B axis to refill the empty syringe.
The build file that is used is a simple octagon with 1mm drive on the syringes for each 1mm of head travel. This may not be a fit ratio for the final build but works well for tests. I've a python script that walks around the perimeter of the octagon and outputs G1 commands for every 1mm of head displacement.
Test 1 - Basic command line test with extruder drive switch over.
In this test the only commands I and sending from the console is G1 E25 F500 and I trigger the switches to simulate the syringe running empty and hitting its limit after drawing back to the home position.
Test 2 - Using the above functionality in a live print that only comprises of G1 moves of the X, Y, and E axis.
Here the challenges start to come to light.
- A considerable delay between the trigger of the empty switch and the stopping of the system.
- The full syringe begins to move before the empty syringe retracts. The retract command is called from the same trigger file as the swap of drives. Therefore the machine appears to see the trigger, change the drives, do a bit more from the main gcode
- Retract executes after the full extruder has moved a bit.
- A pause while the machine does nothing for a few seconds.
- Normal service then resumes.
Test 3 - Basic command line test with extruder drive switch over, but with M300 peeps either side of the trigger files.
Running the "G1 E25 F500" command from the Duet Web Control again and manually triggering the limit switches to simulate the syringes running empty. In this test everything runs as expected.
Test 4 - Using the triggers from test 3 with beeps in a print as per test 2.
The addition of the M300 peeps exaggerate the interleaving of commands from the trigger file and the main gcode stream. A change over no looks like:
- Empty switch triggered.
- Machine carries on a bit
- X/Y motion pauses.
- Machine peeps
- X/Y motion resumes with the other syringe driving.
- X/Y motion pauses.
- Empty syringe completes a home drive.
- Machine sits idle for a few seconds
- X/Y motion resumes and build process continues.
This looks exaggerated with the two syringes but the switch has probably saved the system from raising some strange errors. If I hadn't carried out the atomic command changing over the drives and was working on a single extruder what would have happened when the machine tried to carry on with a few more lines of gcode with no E drive assigned?
Test 5 - Adding pause commands to the triggers just inside the M300 commands that bookend the trigger files.
Yeah, so this highlighted the fact that the M25/M24 commands call the pause and resume macros. This would have been messy if I were working with fluid as on each pause the head jumps back to the middle before returning after. That said everything else happens as expected aside from the initial peep being missing completely, and the final peep occurring some moves after the resume as it both were outside of the M25/M24 commands.
I'll add the final macros at some point today. Changing between computers to do the tests so don't have them to hand right now.
-
As promised here are the trigger files and other macros. More much neater looking videos to follow shortly including single syringe mode.
For Running Two Syringes
trigger2.g
M25 M300 M98 P"set_secondary_syringe.g" G91 G1 H1 B-100 F400 ; Drive empty syringe to limit. G90 M300 M24
trigger3.g
M25 M300 M98 P"set_primary_syringe.g" G91 G1 H1 B-100 F400 ; Drive empty syringe to limit. G90 M300 M24
set_primary_syringe.g
M584 E3 B4 ; Set primary syringe to active M574 B1 S1 P"ystop" ; Set limit switch M84 E0 ; A needed bodge!
set_secondary_syringe.g
M584 E4 B3 ; Swap drives M574 B1 S1 P"xstop" ; Set limit M84 E0 ; A needed bodge!
For Running One Syringe
trigger2.g
M25 M300 M98 P"set_secondary_syringe.g" G91 G1 H1 B-100 F400 ; Drive empty syringe to limit. G90 M98 P"set_primary_syringe.g" M300 M24
-
Moved the M300 peeps to within the M25 and M24, and modified the pause and resume system gcode files to stop the machine excessively moving and virtually dribbling all over the work place!
Dual Syringe Mode:
And what makes more sense without any parallel motions or hard coded retracts single syringe motion:
This system is now fit for trials, but the implementation is a bit messy with needing to disable the pause/resume macro functionality. A pause because a syringe has run low and a user pause are two different things, and I certainly wouldn't want additional XY movement for the former, but may for the latter.
I'll work at a slower pace at hard coding parallel syringe movements into the build file as a demonstrator of what would be ideal, but don't expect that video any time soon!
-
@dc42 said in Syringe Pumps / Depositing Viscous Materials:
Let's suppose that we provide the following mechanisms:
-
A mechanism to assign each axis to one or other movement queue. So in M584 you would specify which movement queue any new axes you create would be assigned to. That assignment would probably be fixed.
-
A mechanism for wait for both movement queues to empty (probably M400 with an extra parameter).
-
Movement commands involving axes assigned to one movement queue would be permitted to happen concurrently with movement commands involving axes assigned to the other movement queue.
Would that be sufficient for your use case? If you think it would, can you write the macros that would be needed?
@dc42 I think I have demonstrated what you recommended now? I think All I would change is adding a gcode command to the beginning of the trigger files to wait for moves to complete on parallel gcode streams, and modify the home drive so that it occurred on a parallel stream rather than the main stream and that G1 home command didn't block until it completed?
-
-
Not significant progress, but switches mounted and action proven without needing to manually trigger them. Got myself muddled with the rising and falling edge on the trigger and input inversion but other than that working smoothly.
This will go quiet for a while while I look at a hard coded version where B retraction moves are in parallel to the other moves. Will look funky, but that puts more into the GCode file than I would like. Material levels etc are something that I would like macros on the machine to deal with and have the slicer oblivious.
Edit: Example macros removed as the triggers missbehaved when I removed M300. 3.3beta2 is being a nuisance with triggers.
-
@DocTrucker said in Syringe Pumps / Depositing Viscous Materials:
This system is now fit for trials, but the implementation is a bit messy with needing to disable the pause/resume macro functionality. A pause because a syringe has run low and a user pause are two different things, and I certainly wouldn't want additional XY movement for the former, but may for the latter.
I am wondering whether the filament change pause GCode M600 could be used instead of M25. It's intended to be used in the file being printed, so I would need to check whether it will work when used outside that file.
-
@dc42 I'll have a look. The macros/triggers stipped working after I removed the M300 - which is odd. The triggers paused the machine properly rather than just functioning as an interlock to prevent other commands from the queue creeping in.
-
@dc42 Just reading up on M600 now and it's better with being able to avoid the pause.g with an empty filament-change.g but not ideal;
- You still resume with M24, and there is no way to dodge (or use an alternative) resume.g
- It behaves differently in that firing M25 when idle will cause an error, firing M600 will put an idle machine into a paused state.
So, I'll test it for completeness (feedback soon) but it's not much use without being able to specify an alternative than resume.g.
-
Messy, very messy on 3.3beta2. When using M600 the delay before refilling the syringe is longer (as expected from comments in the gcode wiki) and the resume.g gets interleaved into the main gcode stream after the resume happens, along with odd error messages about bad commands which indicate it has broken the reading of the gcode too.
The only way to get the above system to function well is with the contents of pause.g and resume.g commented out, and things are quicker with M25. I'd guess the length of the increase would likely be very build gcode dependent putting more emphasis on the parsing of gcode.
I think the bug report on needing to ensure trigger files (and any additional macros that they may call) are run in their entirety before running back to the build gcode needs to be investigated:
https://forum.duet3d.com/topic/22338/bug-ways-to-ensure-gcode-within-trigger-is-uninturupted