Yet more conditional gcode help required



  • Here is the scenario. On my CoreXYUVAB, the XY gantry and UV gantry are coupled together with wires and bowden tubes which means that each one only has about 15mm of allowable movement in respect to the other, before nasty things happen. So I have to take great care using the jog buttons on DWC and in fact, they are pretty useless in my particular usage case.

    So, I've bought a simple joystick which has 4 microswitches. Let's call them NSE and W. I plan to connect each switch to an io pin and the usen trigger macros. So for example, "E" = left and is connected to io4.in and will run trigger 4 which will jog all 3 gantries by doing G1 X-n U-n A-n.

    I'd like to use a loop so that the gantries will continue to jog while the joystick is being held in that position. Something like

    echo "Joystick left
    while sensors.gpIn[4].value=0
    	G1 X-1 U-1 A-1 F6000; move
    	M400; wait for move to finish
    

    So question 1 - Will that work? That is to say, is it OK to poll the same pin that initially triggered the macro?

    Part 2. This joystick can also trigger two switches concurrently. So as well as NSE and W, I could also do 45 degree moves. i.e. If "E" is trigger 4, that macro could also poll the "N" and "S" switches and if either of those is also closed, then do G1 Xn Yn Un Vn An Bn (either + or - depending on which switch was closed). So the loop would get extended to include an

    if sensors.gpIn[6].value=0, then move YV and B as well else only move XU and A ( or some such).

    Obviously all 4 trigger macros would need to check the state of two other switches as well as the one which caused the trigger. i.e. "E" would also need to check the state of "N and "S" . The problem with that is, if I do a (say) NE move on the joystick, this will cause two trigger events - one for each switch. But the firmware states "Polling for further trigger conditions is suspended until the trigger macro file has been completed", so I guess as long as each macro checks all the switch combinations, then it ought to work. i.e. if E also checks N and S, and N also checks E and W then if the joystick is moved to the NE position, it won't matter which trigger occurs first as the outcome will be the same (either macro will do a 45 degree move).

    Does that make sense? Will it work?



  • Maybe something to do in daemon.g file? This way, you don't need to use trigger events, and you can poll all you want...


  • administrators

    I think the best option may be to use a single trigger macro that responds to all 4 switches, that reads all 4 switches directly from the object model and makes appropriate movements, until none of the 4 switches is triggered.



  • @fma said in Yet more conditional gcode help required:

    Maybe something to do in daemon.g file? This way, you don't need to use trigger events, and you can poll all you want...

    That's something I hadn't considered. But I'd need to restrict any movement to only happen when NOT printing. This will be possible using the R2 parameter in M581. Can the same thing be achieved with daemon.g?



  • @dc42 said in Yet more conditional gcode help required:

    I think the best option may be to use a single trigger macro that responds to all 4 switches, that reads all 4 switches directly from the object model and makes appropriate movements, until none of the 4 switches is triggered.

    Ahh. That sounds a better option. I wasn't aware that a trigger could be initiated with any one of multiple pins. Can you point me to the command I'd need to use.


  • administrators

    See https://duet3d.dozuki.com/Wiki/Gcode#Section_M581_RepRapFirmware_3_01RC2_and_later. The P parameter accepts multiple GpIn pin numbers.



  • OK, I think I've sussed it but would appreciate a sanity check.

    Config.g now has this......

    M950 J5 C"^0.io5.in" ; main board(0) io5, joystick left 
    M950 J6 C"^0.io6.in" ; main board(0) io6, joystick right
    M950 J7 C"^0.io7.in" ; main board(0) io7, joystick forward 
    M950 J8 C"^0.io8.in" ; main board(0) io8, joystick backwards
    M581 P5:6:7:8 T5 R0 S0 ;Run trigger5 macro - (joystick left,right, forward or backwards)
    ; *** Note to self - change R0 to R2 after upgrading to firmware 3.2 ** 
    

    .....and the macro looks like this.....

    ; ******Trigger 5 - Joystick left,right, forward or backwards ********
    ; IO Pin to switch connections J5=left, J6=Right, J7=Forward, J8=Backward
    
    
    G91; Set relative
    M400; wait for any moves to finish
    G1 F6000 ; set feedrate to 100mm/sec
    while sensors.gpIn[5].value=0 | sensors.gpIn[6].value=0 | sensors.gpIn[7].value=0 | sensors.gpIn[8].value=0
    	if sensors.gpIn[5].value=0 ; joystick left
    		G1 X-1 U-1 A-1
    	elif sensors.gpIn[6].value=0 ; joystick right	
    		G1 X1 U1 A1
    	elif sensors.gpIn[7].value=0 ; joystick forwards	
    		G1 Y-1 V-1 B-1
    	elif sensors.gpIn[8].value=0 ; joystick backwards	
    		G1 Y1 V1 B1
    	elif sensors.gpIn[5].value=0 & sensors.gpIn[7]; joystick left and forward	
    		G1 X-1 U-1 A-1 Y-1 V-1 B-1
    	elif sensors.gpIn[5].value=0 & sensors.gpIn[8]; joystick left and backwards	
    		G1 X-1 U-1 A-1 Y1 V1 B1
    	elif sensors.gpIn[6].value=0 & sensors.gpIn[7]; joystick right and forward	
    		G1 X1 U1 A1 Y-1 V-1 B-1
    	elif sensors.gpIn[6].value=0 & sensors.gpIn[8]; joystick right and backward	
    		G1 X1 U1 A1 Y1 V1 B1
    

    I'm not sure about the "while". What I'm trying to say is while any one of those 4 pins is being pulled low by a switch do the following.

    After that, I've used 8 "if" or "elif" statements to define what happens with the various switch combinations that are possible. Is that the way to do it?



  • @deckingman You'll probably need to move the dual input directions in front of the uni-input directions.
    Otherwise they won't execute using elif because each combination move will have previously equated to true in the single input section.



  • @OwenD said in Yet more conditional gcode help required:

    @deckingman You'll probably need to move the dual input directions in front of the uni-input directions.
    Otherwise they won't execute using elif because each combination move will have previously equated to true in the single input section.

    Ahh - good point. Does the rest of it look reasonable?



  • @deckingman said in Yet more conditional gcode help required:

    Ahh - good point. Does the rest of it look reasonable?

    Looks reasonably sane.
    You may need an M400 in each elif.
    I'm not sure what the cycle time will be so you might experience an accumulation of moves by the time you take your hand off the joystick



  • @OwenD said in Yet more conditional gcode help required:

    @deckingman said in Yet more conditional gcode help required:

    Ahh - good point. Does the rest of it look reasonable?

    Looks reasonably sane.

    That's unusual for me - I spend most of my time doing crazy stuff 🙂

    You may need an M400 in each elif.

    Good point - I'll plaster a few more M400s around

    I'm not sure what the cycle time will be so you might experience an accumulation of moves by the time you take your hand off the joystick

    Yes I had considered that - hence the 1mm "nudge move" length to start with. Guess I could either shorten that to (say) 0.1mm and/or scatter a few G4 commands around.



  • One suggestion: At the first 4 if statements I would add an "AND" with the negated statements of the last 4 if statements. Otherwise when you push the joystick to left forward the ifs "left", "forward" and "left forward" will be executed.

    Or wait I think what I just read is only the case if using if instead of elif ...


  • administrators

    That's the right approach, however the if..elif statements are not right. Try something like this:

        if sensors.gpIn[5].value=0           ; if left button down
            if sensors.gpIn[7].value=0       ; if joystick left and forward	
    	    G1 ...
    	elif sensors.gpIn[8].value=0     ; if joystick left and backwards	
    	    G1 ...
            else                             ; just left
    	    G1 ... 
        elif sensors.gpIn[6].value=0         ; right button down
    	if sensors.gpIn[7].value=0       ; joystick right and forwards	
    	    G1 ...
            elif sensors.gpIn[8].value=0     ; joystick right and backwards	
    	    G1 ...
            else                             ; just right
    	    G1 X1 U1 A1
        elif sensors.gpIn[7].value=0         ; if just forwards
    	G1 ...
        elif sensors.gpIn[8].value=0         ; if just backwards
    	G1 ...
    

    You could also add an "else break" at the end, then you wouldn't need to test all the buttons in the while-part.



  • @dc42 Thanks. That looks good. From my very limited knowledge, I can see that would be "conflict free" compared to what I had.

    @all. Thanks for the input everyone - much appreciated. It'll be a couple of days or so before I get time to get the hardware and wiring sorted. Then I'll either report back with a successful outcome, or I'll be asking for more help........



  • @dc42 said in Yet more conditional gcode help required:

    That's the right approach, however the if..elif statements are not right. Try something like this:

    You could also add an "else break" at the end, then you wouldn't need to test all the buttons in the while-part.

    If he removes the while test of all pins, wouldn't the macro only trigger once (when a switch signal rose/fell)
    Or do you just mean use "while true" instead (hence the break statement )
    I'm always reluctant to use potentially infinite loops.


  • administrators

    Yes I meant use "while true". Or if you don't like infinite loops, "while iterations < 1000" or similar.



  • @dc42 Thanks for clarification.
    I might have locked up a few machines over the years with my clumsy work when using loops.
    I realise it's a valid method for those that think things through more than me before they press "executive" edit: "execute" (Stupid iPhone!!!) 😆



  • Err, in view of the above and as a further sanity check on my understanding, here is the full macro that I intend to start with ........

    G91; Set relative
    M400; wait for any moves to finish
    G1 F6000 ; set feedrate to 100mm/sec
    
    while sensors.gpIn[5].value=0 | sensors.gpIn[6].value=0 | sensors.gpIn[7].value=0 | sensors.gpIn[8].value=0
    	
    	if sensors.gpIn[5].value=0; joystick left 	
    		
    		if sensors.gpIn[7].value=0 ; joystick left and forwards 
    			M400 
    			G1 X-1 U-1 A-1 Y-1 V-1 B-1
    			
    		elif sensors.gpIn[8]; joystick left and backwards	
    			M400
    			G1 X-1 U-1 A-1 Y1 V1 B1
    		
    		else ; joystick left only
    			M400
    			G1 X-1 U-1 A-1
    			
    	elif sensors.gpIn[6].value=0; joystick right 	
    		
    		if sensors.gpIn[7].value=0 ; joystick right and forwards 
    			M400
    			G1 X1 U1 A1 Y-1 V-1 B-1
    		
    			
    		elif sensors.gpIn[8]; joystick right and backward	
    			M400
    			G1 X1 U1 A1 Y1 V1 B1
    			
    		else ; joystick right only
    			M400
    			G1 X1 U1 A1
    	
    	elif sensors.gpIn[7].value=0 ; joystick forwards only	
    		M400
    		G1 Y-1 V-1 B-1
    		
    	elif sensors.gpIn[8].value=0 ; joystick backward only
    		M400
    		G1 Y1 V1 B1
    		
    	else break
    

    Is that about right?



  • To clarify my comments.

    A "while" statement will loop if the condition test is true.
    In your case by testing all those inputs.

    If you put

    while true
      G1 X1
    

    Then you have an endless loop as true always equals true, so you're going to crash.
    Therefore you must ensure that you put a test in somewhere the calls "break" to get you out of the loop.

    In the suggested code above that test is satisfied when none of the IF statements resolve to true, so break is called.



  • OK, so that's all wired up and working. It does what I hoped it would and it respects the axis limits too (of course it does - I never doubted it would 🙂 ).

    But I'd like to add an embellishment if possible. I've used 1mm as a movement length which is great for reasonably precise positioning but naturally, it's a bit slow if I want to travel the full 400mm or so of axis travel. Increasing the step size to (say) 5mm is about right but then I lose precision. So what I'd like to do is a bit like how one sets the time on some digital clocks. That is to say, the longer one holds the button, the faster the time changes.

    So I'd like to alter the code so that if I hold the joystick in one position, it will move in 1mm increments but after (say) 5 iterations, the move length will increase to (say) 5mm). Ideally I'd like to do something a bit more sophisticated still, like keep increasing the move length the longer the joystick is held in one position but I'll settle for just a binary change after say 5 iterations of the same move.

    Here is the code that I have now (without the errors that I had in some of the elif commands when I last posted it 🙂 )

    G91; Set relative
    M400; wait for any moves to finish
    G1 F6000 ; set feedrate to 100mm/sec
    M118 S"Trigger 5 - Joystick"
    while sensors.gpIn[5].value=0 | sensors.gpIn[6].value=0 | sensors.gpIn[7].value=0 | sensors.gpIn[8].value=0
    	
    	if sensors.gpIn[5].value=0; joystick left 	
    		
    		if sensors.gpIn[7].value=0 ; joystick left and forwards 
    			M400 
    			G1 X-1 U-1 A-1 Y-1 V-1 B-1
    			echo "Left and forward"
    			
    		elif sensors.gpIn[8].value=0; joystick left and backwards	
    			M400
    			G1 X-1 U-1 A-1 Y1 V1 B1
    			echo "Left and backwards"
    			
    		else ; joystick left only
    			M400
    			G1 X-1 U-1 A-1
    			echo "Left"
    			
    	elif sensors.gpIn[6].value=0; joystick right 	
    		
    		if sensors.gpIn[7].value=0 ; joystick right and forwards 
    			M400
    			G1 X1 U1 A1 Y-1 V-1 B-1
    			echo "Right and forward"
    			
    		elif sensors.gpIn[8].value=0; joystick right and backward	
    			M400
    			G1 X1 U1 A1 Y1 V1 B1
    			echo "Right and backwards"
    			
    		else ; joystick right only
    			M400
    			G1 X1 U1 A1
    			echo "Right"
    	
    	elif sensors.gpIn[7].value=0 ; joystick forwards only	
    		M400
    		G1 Y-1 V-1 B-1
    		echo "Forward"
    		
    	elif sensors.gpIn[8].value=0 ; joystick backward only
    		M400
    		G1 Y1 V1 B1
    		echo "Backwards"
    		
    	else break
    

  • administrators

    You could use the built-in 'iterations' variable to adjust the movement amount and/or speed.



  • @dc42 said in Yet more conditional gcode help required:

    You could use the built-in 'iterations' variable to adjust the movement amount and/or speed.

    Thanks. Would I be right in assuming the "iterations" is a counter which increments by 1 every time the while loop runs?

    Scratch that - found it.



  • That's all working now although the code is a bit "clunky".

    I'm guessing that once variables are introduced, I ought to be able to do something like ....

    MoveAmount= 0.5+(iterations/5) 
    G1 X MoveAmount..............
    

    .......or some such. Anyway, this is what I've ended up with which may not be elegant but works.

    
    G91; Set relative
    M400; wait for any moves to finish
    G1 F3000 ; set feedrate to 100mm/sec
    M118 S"Trigger 5 - Joystick"
    while sensors.gpIn[5].value=0 | sensors.gpIn[6].value=0 | sensors.gpIn[7].value=0 | sensors.gpIn[8].value=0
    	
    	if sensors.gpIn[5].value=0; joystick left 	
    		
    		if sensors.gpIn[7].value=0 ; joystick left and forwards 
    			M400 
    			if iterations<3
    				G1 X-0.5 U-0.5 A-0.5 Y-0.5 V-0.5 B-0.5
    			elif iterations<5
    				G1 X-1 U-1 A-1 Y-1 V-1 B-1
    			elif iterations<7
    				G1 X-2 U-2 A-2 Y-2 V-2 B-2
    			elif iterations<9
    				G1 X-5 U-5 A-5 Y-5 V-5 B-5	
    			elif iterations<11
    				G1 X-10 U-10 A-10 Y-10 V-10 B-10
    			else 
    				G1 X-20 U-20 A-20 Y-20 V-20 B-20	
    			
    			
    		elif sensors.gpIn[8].value=0; joystick left and backwards	
    			M400
    			if iterations<3
    				G1 X-0.5 U-0.5 A-0.5 Y0.5 V0.5 B0.5
    			elif iterations<5
    				G1 X-1 U-1 A-1 Y1 V1 B1
    			elif iterations<7
    				G1 X-2 U-2 A-2 Y2 V2 B2
    			elif iterations<9
    				G1 X-5 U-5 A-5 Y5 V5 B5	
    			elif iterations<11
    				G1 X-10 U-10 A-10 Y10 V10 B10
    			else 
    				G1 X-20 U-20 A-20 Y20 V20 B20
    			
    			
    		else ; joystick left only
    			M400
    			if iterations<3
    				G1 X-0.5 U-0.5 A-0.5 
    			elif iterations<5
    				G1 X-1 U-1 A-1 
    			elif iterations<7
    				G1 X-2 U-2 A-2 
    			elif iterations<9
    				G1 X-5 U-5 A-5 
    			elif iterations<11
    				G1 X-10 U-10 A-10 
    			else 
    				G1 X-20 U-20 A-20
    			
    						
    	elif sensors.gpIn[6].value=0; joystick right 	
    		
    		if sensors.gpIn[7].value=0 ; joystick right and forwards 
    			M400
    			if iterations<3
    				G1 X0.5 U0.5 A0.5 Y-0.5 V-0.5 B-0.5
    			elif iterations<5
    				G1 X1 U1 A1 Y-1 V-1 B-1
    			elif iterations<7
    				G1 X2 U2 A2 Y-2 V-2 B-2
    			elif iterations<9
    				G1 X5 U5 A5 Y-5 V-5 B-5	
    			elif iterations<11
    				G1 X10 U10 A10 Y-10 V-10 B-10
    			else 
    				G1 X20 U20 A20 Y-20 V-20 B-20
    			
    			
    		elif sensors.gpIn[8].value=0; joystick right and backward	
    			M400
    			if iterations<3
    				G1 X0.5 U0.5 A0.5 Y0.5 V0.5 B0.5
    			elif iterations<5
    				G1 X1 U1 A1 Y1 V1 B1
    			elif iterations<7
    				G1 X2 U2 A2 Y2 V2 B2
    			elif iterations<9
    				G1 X5 U5 A5 Y5 V5 B5	
    			elif iterations<11
    				G1 X10 U10 A10 Y10 V10 B10
    			else 
    				G1 X20 U20 A20 Y20 V20 B20
    			
    			
    		else ; joystick right only
    			M400
    			if iterations<3
    				G1 X0.5 U0.5 A0.5
    			elif iterations<5
    				G1 X1 U1 A1 
    			elif iterations<7
    				G1 X2 U2 A2 
    			elif iterations<9
    				G1 X5 U5 A5 
    			elif iterations<11
    				G1 X10 U10 A10 
    			else 
    				G1 X20 U20 A20 
    			
    	
    	elif sensors.gpIn[7].value=0 ; joystick forwards only	
    		M400
    		if iterations<3
    				G1 Y-0.5 V-0.5 B-0.5
    			elif iterations<5
    				G1 Y-1 V-1 B-1
    			elif iterations<7
    				G1 Y-2 V-2 B-2
    			elif iterations<9
    				G1 Y-5 V-5 B-5	
    			elif iterations<11
    				G1 Y-10 V-10 B-10
    			else 
    				G1 Y-20 V-20 B-20
    				
    	elif sensors.gpIn[8].value=0 ; joystick backward only
    		M400
    		if iterations<3
    				G1 Y0.5 V0.5 B0.5
    			elif iterations<5
    				G1 Y1 V1 B1
    			elif iterations<7
    				G1 Y2 V2 B2
    			elif iterations<9
    				G1 Y5 V5 B5	
    			elif iterations<11
    				G1 Y10 V10 B10
    			else 
    				G1 Y20 V20 B20
    		
    		
    	else break
    	
    

  • administrators

    Another way is to use your original code but replace all the XYUVABC coordinates in the G1 commands by calculated values, something like this:

    G1 X{0.5+0.1 * iterations} Y{-(0.5+0.1 * iterations)} ...



  • @dc42 said in Yet more conditional gcode help required:

    Another way is to use your original code but replace all the XYUVABC coordinates in the G1 commands by calculated values, something like this:

    G1 X{0.5+0.1 * iterations} Y{-(0.5+0.1 * iterations)} ...

    Ahhh - that looks good! I tried something similar but it didn't work - because I used plain braces rather than curly ones. I'll give that a go..............


Log in to reply