Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5

Program Event or Function Call for 3D Printing Extruder Control

#1
Dear Community,

I'm trying to use RoboDK and a Kuka with KRC4 controller for 3D printing and I'm hoping to control both the Robot and the Extruder through RoboDK using the "Run on Robot" function.

My idea is to have three very similar function calls "SetRPM", "Extruder" and "MCode". SetRPM giving the F Value, Extruder the E Value of the G1 commands and MCode all the M commands of the G Code. The functions would then use TCP/IP over Ethernet to send these values as text string to a controller board for the extruder before sending the corresponding move to the robot and then continuing with the program.

I'm hoping that this way the error between the moves and extrusions is limited to one move at a time and therefore very small to avoid either the robot or extruder running faster than the other.
So far I have modified the post processor so it adds the lines SetRPM(ExtruderSpeed) and Extruder(PRINT_E_New) with the parameters in the brackets being the values for F and E. When I generate a program for the functions are being passed on to the robot program as you can see in the code example below at the end of the post.

My question is now, if I run this program through RoboDK on the robot can I use these lines to call functions or program events that will then send the corresponding code through a ethernet connection to the controlboard of the extruder? If so, do you know of any similar code snippets I could adapt the code from?

I have seen a lot of posts in the forum regarding 3D printing but none with this issue, is there perhaps a easier solution that I'm not aware of?

Best regards
Patrick


Code:
LIN {X 301.500,Y 498.500,Z 15.000,A 180.000,B 0.000,C -180.000} C_DIS
MCode(83)()
MCode(83)
$VEL.CP = 0.02500
SetRPM(0.000)
Extruder(-6.500)
LIN {X 301.500,Y 498.500,Z 15.000,A 180.000,B 0.000,C -180.000} C_DIS
MCode(107)()
MCode(107)
$VEL.CP = 0.06000
LIN {X 301.500,Y 498.500,Z 0.300,A 180.000,B 0.000,C 180.000} C_DIS
$VEL.CP = 0.02500
LIN {X 301.500,Y 498.500,Z 0.300,A 180.000,B 0.000,C 180.000} C_DIS
$VEL.CP = 0.03000
SetRPM(6000.000)
Extruder(73.713)
LIN {X 301.500,Y 301.500,Z 0.300,A 180.000,B 0.000,C -180.000} C_DIS
#2
Hi Patrick,

The post processor and the driver are different (having a working post processor does not mean the driver will work).

The best way to make this work with the driver is to trigger a program with a number. For example:
Extruder(73)
will pass the program id 73. However, this was designed to make it work for more simple calls (program ID). Example:
Program 1
This will pass the program_id number 1. You can pass a floating point number (32 bit precision, more information here).

Note that it is not possible to trigger programs by name using this method. You are also limited to 1 value. We can improve it to pass 2 or 3 values if you need.

Once you pass the program id (as an integer or a decimal value) you need to implement your actions in the driver (SRC file). I attached the sample implementation code and comments in the driver file.

Code:
;----- Run program COM_VALUE1 ---------
; (to trigger from RoboDK: use robot.RunCodeCustom("program id", INSTRUCTION_CALL_PROGRAM)
program_id = COM_VALUE1
SWITCH program_id
CASE 1
; -- run program 1 --
; Drill()
; -------------------
CASE 2
; -- run program 2 --
; Cut()
; -------------------
ENDSWITCH


Albert
#3
Hi Albert,

thank you for the reply this actually helps a lot! I've been trying to modify the scripts in RDK and the Postprocessor when what I needed was the Robot driver. I looked in the directory where the drivers are and found that the kuka driver "apikuka" is a .exe file that i can't modify but there is a apikukaiiwa.py. 
From a quick look it seems that the driver is for a robot with 7 degrees of freedom, I'll try to get it working with our 6 DoF robot, but could you provide the apikuka.exe as .py file?

I would approach the problem by adding another elif like the one below:

Code:
   elif n_cmd_values >= nDOFs_MIN and cmd_line.startswith("MOVL"):
       UpdateStatus(ROBOTCOM_WORKING)
       # Activate the monitor feedback
       ROBOT_MOVING = True
       # Execute a linear move. RoboDK provides j1,j2,...,j6,j7,x,y,z,w,p,r
       if ROBOT.SendCmd(MSG_MOVEL, cmd_values):
           # Wait for command to be executed
           if ROBOT.recv_acknowledge():
               # Notify that we are done with this command
               UpdateStatus(ROBOTCOM_READY)


and change it so if the code starts with "Call Extruder" it establishes a connection by telnet to the extruder, sends the Gcode command and closes the connection.

Best regards
Patrick
#4
Hi Patrick,

After reading the second message I realized that you would like to communicate to the extruder using the computer (not the robot). Correct?

In this case the integration may be easier as you can program the socket communication protocol using Python. Otherwise, you may need to purchase KUKA Ethernet/XML option to do so with a KUKA KRC controller.

To react on a program call (such as Extruder) in a custom way you can create an Extruder script like the one attached. You can collect arguments using sys.argv as shown here:

Code:
E_Value = None
# Check if we are running this program inside another program and passing arguments
import sys
if len(sys.argv) > 1:
   E_Value = float(sys.argv[1])

Let me know if this is not what you are looking for.

Albert


Attached Files
.py   Extruder.py (Size: 1.79 KB / Downloads: 861)
#5
Albert that's brilliant! It works! You saved my day :D

I just noticed the attached file when I went to post this, I went with Telnet instead but the segment to quit if in Simulation mode is neat, I'll add that and post some details on the scripts I end up using once I'm through testing in case someone else has the same issues.

Thank you!
#6
Hello PatrickC,

I am also trying to implement extrusion via a python script in RoboDK for online programming of our Fanuc 6 axis robot. Did you come up with a solution after all? Myself, I was trying to use the Printrun library (from the Pronterface project) to send some G-code commands over to the extruder, but I can't make it work.

Could you share some details about the scripts that you developped? Any help would be highly appreciated.

Thanks a lot!

JF
#7
Are you using a custom made extruder?

If so, I recommend you to just send raw strings or binary data to update the extruder speed. You can implement your own protocol to just send the necessary information to the extruder.
#8
Hi Albert. I am using an Arduino controler with the Marlin Firmware to drive the extruder. I would like to interpret the RoboDK's Extruder(x.xxx) function to send my own G-code to the Marlin Firmware.
#9
(02-14-2020, 02:37 PM)JFCh Wrote: Hi Albert. I am using an Arduino controler with the Marlin Firmware to drive the extruder. I would like to interpret the RoboDK's Extruder(x.xxx) function to send my own G-code to the Marlin Firmware.

Hi JF,

sorry about not replying sooner. To be fair I was printing. My extruder is controlled by a duet2 so it can recieve gcode through http get requests. that makes it pretty straight forward. You can adapt the speed using a pre-processor to insert a function call after each robot speed change, then calling a funtion that works the same as the extruder call but transforms the mm/s from robodk to the mm/min in gcode and corrects for the crosssection of the extruded line compared to your filament crosssection.
Below you'll find the code, you'll have to use the ip's of your respective boards.

Extruder
Code:
e_value = None
from robolink import * #nur fuer Nutzung in RoboDK
RDK = Robolink()
# Check if we are running this program inside another program and passing arguments
import sys
if len(sys.argv) > 1:
   e_value = float(sys.argv[1])
   code = 'G1 E' + str(e_value)
   #print(message) #for test purposes
   RDK.ShowMessage(code, popup=False)  # for test purpose set to True for popup, set to false or comment out for use to avoid blocking
   if RDK.RunMode() == RUNMODE_SIMULATE:
       quit()

   import requests
   params = {"gcode": code }
   r = requests.get("http://192.168.2.114/rr_status?type=1")
   
   # print(r.json()) # for test purpose
   r = requests.get("http://192.168.2.114/rr_gcode", params=params)  # this works!
   # r = requests.get("http://192.168.0.100/rr_gcode?gcode=G1 Z100")  # this works!
   #print(r.json())
Speed
Code:
f_value = None
from robolink import * #nur fuer Nutzung in RoboDK
RDK = Robolink()
# Check if we are running this program inside another program and passing arguments
import sys
if len(sys.argv) > 1:
   e_value = float(sys.argv[1])
   f_transform=f_value * 60 * 1.5676 # mm/s in mm/min und adaptation for line crossection Q to fed filament Q/pi*(2.85/2)²
   code = 'G1 F' + str(f_transform)
   #print(message) #for test purposes
   RDK.ShowMessage(code, popup=False)  # for test purpose set to True for popup, set to false or comment out for use to avoid blocking
   if RDK.RunMode() == RUNMODE_SIMULATE:
       quit()

   import requests
   params = {"gcode": code }
   r = requests.get("http://192.168.2.114/rr_status?type=1")
 
   #print(r.json()) # for test purpose
   r = requests.get("http://192.168.2.114/rr_gcode", params=params)  # this works!
   # r = requests.get("http://192.168.0.100/rr_gcode?gcode=G1 Z100")  # this also works!
   #print(r.json())

Pre-Processor:
Code:
from robolink import *    # API to communicate with RoboDK
from robodk import *      # basic matrix operations
RDK = Robolink()

# Ask the user to select a program:
prog = RDK.ItemUserPick("Select a Program to modify", ITEM_TYPE_PROGRAM)
if not prog.Valid():
   print("Operation cancelled or no programs available")
   quit()

# Ask the user to enter a function call that will be added after each movement:
print("Program selected: " + prog.Name())
ins_call = 'SetExtSpeed'
#mbox("Enter a program call to add after each movement", entry="SynchRobot")
if not ins_call:
   print("Operation cancelled")
   quit()

# Iterate through all the instructions in a program:
ins_id = 0
ins_count = prog.InstructionCount()
while ins_id < ins_count:
   # Retrieve instruction
   ins_nom, ins_type, move_type, isjointtarget, pose, joints = prog.Instruction(ins_id)
   if ins_type == INS_TYPE_CHANGESPEED:
       # Select the movement instruction as a reference
       prog.InstructionSelect(ins_id)
       value = prog.Instruction(ins_id)
       name = value[0]
       import re
       matches = re.findall("[+-]?\d+\.\d+", name)

       # Add a new program call
       prog.RunInstruction(ins_call + '('  + matches[0] + ')', INSTRUCTION_CALL_PROGRAM)
       
       # Advance one additional instruction as we just added another instruction
       ins_id = ins_id + 1
       ins_count = ins_count + 1
       
   ins_id = ins_id + 1
#10
Hello PatrickC,

It's been a while since I looked at the forum and I have missed your reply. Thank you very much for sharing the scripts with me. I will take a look and let you know the outcome.

Regards,

JF
  




Users browsing this thread:
2 Guest(s)