Posts by Koppel
-
-
Three interesting things I found out, trying to implement this:
- I have to define all the elements in the geometric operand, apart from Status and Turn.
- Using only MyPoint:{X 5} gives an error
- Must be MyPoint:{X 5,Y 0,Z 0,A 0,B 0,C 0}
- The order of the geometric operand is important.
- POS:FRAME outputs a FRAME
- Expert Programming manual says:
If the left-hand operand has the data type POS, type matching takes place. The position specified by the POS structure is transformed into a frame. That means the system determines the tool frame for this position. - This caused my position with the operand to move to the opposite direction because my tool is inverted.
So MyPoint:{X 200,Y 0,Z 0,A 0,B 0,C 0} did not add 200mm but subtracted
{X 200,Y 0,Z 0,A 0,B 0,C 0}:MyPoint added the 200mm to the original X component of MyPoint - Because if the robot wants to grab something from a table, the coordinate systems of the tool and the position match up. If I dont invert the tool, the robot flange wants to be inside the table. So I have to invert one of them... the point or the tool. There is a lot of points but only one tool... naturally I inverted the tool. I want the Z to point upwards for the things the robot needs to grab.
- When I used the IF statement I lost my approximation "C_PTP" for the
first point inside(EDIT: the point just before) the IF statement. Any cure for that?
- I have to define all the elements in the geometric operand, apart from Status and Turn.
-
Mentat, your approach seems convenient for many trays.
Let me work through this
You have a function "GetTrayBaseData" that returns the tray number with predefined offset
You change the base before the prefefined points... with some SWITCH / CASE statements or IF statements.
You need to change the base back to the original after these points.
How do you feel about just modifying the point with a geometric operator ":"
PTP TrayLeftUp:{X 5,Y 0,Z 0,A 0,B 0,C 0}
I could then still use an IF statementCode
Display MoreIF $IN[123]==TRUE THEN PTP TrayLeftUp:{X 5} PTP TrayLeftDown:{X 5} GripperClose() PTP TrayLeftDown2:{X 5} PTP TrayUp:{X 5} ELSE PTP TrayLeftUp PTP TrayLeftDown GripperClose() PTP TrayLeftDown2 PTP TrayUp ENDIF
I think its cleaner and easier to understand when I just have two variations.
Also I am a bit scared to change the BASE and change it back again. I could manually jump around in the program during testing and forget to switch back the base.
If I would have many more trays, handling them all with offsets in one area would definitely be more professional.
-
Hi,
I have used some defined positions in my program
...
PTP TrayLeftUp
PTP TrayLeftDown
GripperClose()
PTP TrayLeftDown2PTP TrayUp
...
And now some other tray has slightly different (+5mm in one direction) coordinates ( and need to make the program work with both depending if some input "TrayType2" for example is true or not.What is the most elegant way to solve this.
I could create completely new points for the new tray and use a CASE statement for the different cases - one using the old group of points, and the other using the new ones. But that seems messy.
I could change the base before these points with an IF statement... and then change the base right back after these points.
Code
Display MoreIF $IN[123]==TRUE THEN BAS(#BASE,2) ENDIF PTP TrayLeftUp PTP TrayLeftDown GripperClose() PTP TrayLeftDown2 PTP TrayUp IF $IN[123]==TRUE THEN BAS(#BASE,1) ENDIF
But how would the pro-s do it?
-
In my experience you have to go really slow if you work with rigid objects. The robot takes distance to brake. Imagine moving your hand really fast while holding a brick. Even if there is a child running by, you cannot stop your hand immediately. If you only sense the child being in the way by the extra force required to move your hand... the child was already hit hard, and only then will you think about slowing down your hand.
I remember panicmode telling me, its like parking a car blindfolded and detecting a wall when the engine load gets higher... its kinda too late.
Much better to have some interrupt triggered by a spring-loaded gripper... so you have much more time to stop and go back higher.
Fine tuning the holding torque parameters was a pain... -
Hi,
KSS version 8.6To make use of the timers in the area Display>Variable>Timer I have to use a system variable in KRL:
$TIMER_STOP[1]=FALSE
$TIMER[1]=0
$TIMER_STOP[1]=TRUE
But for the counters there is no such thing. How do I make a counter value show up in there?
EDIT: Found a thread from 2014 where "panic mode" gives an answer
how to use system counter in KRC2?
"variable shown in Variable monitor as COUNTER is actually I[]"
And he also suggests to use Display>Variable>Single for the purpose of monitoring a value.
There seems to be a way to monitor custom groups of variables
Display > Variable > Overview
Set up Variable Overview - Configmon
I will look into the subject and write a summary to help future generations.
Thank you,
-
A while ago I had the same requirement - to create a palletizing program.
You really have to learn raw KRL to do this. So no In-line forms.
I am using a PLC that runs a program when needed... so that might not be what you need.
Declare variables in a DAT file.
DECL GLOBAL INT RobotMove = 1
DECL GLOBAL INT BoxLayer = 1
In the SRC file declare two positions:
DECL POS InBoxUp, InBoxDown
And in the program section you can add "1" after every time the program was running.
RobotMove = RobotMove +1
IF RobotMove == 4 THEN
BoxLayer = BoxLayer + 1
ENDIF
IF RobotMove == 4 THENRobotMove = 1
ENDIF
So both of them keep going up... the RobotMove will go 1...2...3...4......1...2...3....4
And the BoxLayer will go to infinity unless you also reset it at some point. 1...2....3.....4.....5.....6
You can calculate individual components of a coordinate for different cases.
Or if you just have a single case then you don't need the SWITCH CASE statements.SWITCH RobotMove
CASE 1, 2, 3 ;
InBoxUp.x=257
InBoxUp.y=223-(RobotMove-1)*83
InBoxUp.z=(BoxLayer-1)*100
InBoxUp.A=90
InBoxUp.B=180
InBoxUp.C=0
ENDSWITCH
And after the switch statement you can order the robot to go to this point... and that point will have new coordinates every time the program is run.
PTP InBoxUpIn my case the box coordinates are relative to the base of the box... so I just adjust the base to be in the right place and the individual pieces are placed to the correct positions inside the box.
-
Hi,
KSS: 8.5
Controller: KR C4 Compact
Robot: KR10 R1100-2
In my program I use
BAS (#VEL_PTP, 40)
... to limit the speed.
But this has a negative side effect of limiting the allready lowered speed in T1 mode by another factor when I run through my program.So basically I end up with:
250mm/s * My limit 40% * TouchPad limit 100% = 100mm/s
I have also limited the ACC_PTP; VEL_CP and ACC_CP using the BAS function. Running through my program in T1 mode to see that everything is OK is super slow.Is there a clever trick where I still get the 250mm/s in T1 mode regardless of the speed limits I have set in the program... other than commenting out the speed limit. Beacause this results in me forgetting to re-enable the speed limits and things are too fast.
Thank you,
-
- Thanks for pointing out that the KRL array starts with 1. I used the numbers just as an example.
- Yes, I can access robot I/O-s after I have mapped them in Work Visual.
- I can do the declaration in a global DAT file... but can I also do a value assignment inside the same DAT file?
The expert programming manual says "Only value assignments with “=” are allowed in data lists."
Seems like I could do that.
-
Overlooked this when previously setting up, this is it! Possibly using the global ack block instead of the one specifically for DB30000 may fix it?
Any ideas how to enable the safe communication without having to acknowledge this on the robot TouchPad.
Every cold start requires the global safety acknowledgement... ACK_GL from the PLC.
And then again an acknowledge from the KUKA TouchPad. (going to T1 mode, acknowledge, home the robot again, go back to EXT mode)
This cannot be the way the system designers planned it to be used. There must be a way where the safe communications is automatically correctly set up without the need to do anything manually. -
KSS 8.5
KR C4 compact controller as a profinet slave
I have created counters for a palletizing program (row / column / layer) and would like to see the current values on a Siemens HMI.
I guess I should do a signal declaration. Write the variable to an output range and then map this range in Work Visual.
But then its only used in one program, and its outputting "00000000" if the program is not running, right?
If I wanted to for example control the program override speed from an HMI do I:
Whats the correct way?
-
I have seen a strategy where the robot program writes a new value to a variable like "i_am_in_section"
And then before every point in your program you write:
PTP P1
TRIGGER WHEN DISTANCE=1 DELAY=0 DO i_am_in_section=73PTP P2
TRIGGER WHEN DISTANCE=1 DELAY=0 DO i_am_in_section=74
PTP P3
And when you create your homing program you do it like:
IF i_am_in_section ==74 THENPTP P2
...
Or better use SWITCH CASE statements... its a bit cleaner.
But Mentat suggested that you may be able to just do a relative move upwards like 400 mm and then its straight to home from there.
You know best how many movements are nessessary to get home safely.Usually up high is pretty safe.
-
Is it possible to just increase the over-torque sensitivity of the robot so it will fault sooner before it causes damage in the event of a crash?
Yes.
System integrator manual.
Get it form here: Kuka Downloads (software, cad...)
Page 196.6.11.6.2 Robot program: avoiding damage in the event of collisions
Code
Display More... 1 DECL TorqLimitParam myParams ... 2 FOR i = 1 to 6 3 myParams.lower = $holding_torque[i] - 500 4 myParams.upper = $holding_torque[i] + 500 5 myParams.monitor = #off 6 myParams.max_lag = 0.1 7 SET_TORQUE_LIMITS(i, myParams) 8 ENDFOR 9 $acc.cp = my_low_acceleration 10 $vel.cp = my_low_velocity 11 LIN P7 12 LIN P8 13 LIN P9 14 FOR i = 1 to 6 15 myParams.lower = -1E10 16 myParams.upper = 1E10 17 myParams.monitor = #on 18 SET_TORQUE_LIMITS(i, myParams) 19 ENDFOR 20 $acc.cp = my_high_acceleration 21 $vel.cp = my_high_velocity 22 LIN P10 ...
So all the 6 axes are given a limit from -500 Nm to +500 Nm compared to the holding torque. You can only choose a single axis if you want.
The holding torque is dependent on the load and the position of the arms. If it is stretched out, a larger moment applied and if the arm is close to the robot base, a lower moment is required to keep it in place. So set your load correctly - the weight of the tool and the carrying load.On a KR10 robot I used +40Nm on just the 3rd axis and it worked fine. I knew what direction the additional load was coming from... So on a smaller robot the 500 Nm is a big number.
Also... you have to move slowly... the monitoring function will give an error if you move faster then the speedlimit in T1 mode... so don't move faster than that.If the robot takes 20 degrees of motion to stop from full speed then it does not matter what your torque limits are... it will cause a lot of damage.
-
Ok... so this approach will not work for actual use. So there is no way I can use the torque monitoring to sense an obstacle and continue with the program.... or are there other less fatal functions that would work in my case.
I have vacuum cups attached to an extended pneumatic cylinder.
To me the torque monitoring seems more secure than using a signal from vacuum sensor (touching cardboard would result in a higher vacuum) or overpowering my tiny pneumatic cylinder and pushing it out of its extended position and sensing that.
Adding additional sensors to my gripper takes space on the gripper that I don't have.
-
I now did my searching using the example provided in the System Integrators manual...
Instead of a sensor input I used $STOPMESS as the trigger with very sensitive torque values.
I set my A3 axis TorqueLimit to +/- 40 Nm compared to holding torque.CodeDECL TorqLimitParam myParams ... myParams.lower = $holding_torque[3] - 40 ;Nm myParams.upper = $holding_torque[3] + 40 ;Nm myParams.monitor = #off myParams.max_lag = 0.1 SET_TORQUE_LIMITS(3, myParams)
And this is causing the $STOPMESS which is causing the interrupt... Works fine in T1 mode...
BUT... in EXT mode it gives me the same warnings when the interrupt is triggered but the program will not continue even if I send $CONF_MESS signal.
It tells me "ACTIVE status required" meaning I must switch off the EXT mode, home the robot in T1 mode and try again.
panic_mode hinted that its like parking a car blindfolded and sensing hitting something but it should be possible. I am moving down very slowly with an extended pneumatic cylinder that acts like a shock absorber... so to me it seems like a good solution. The robot cannot even crush an empty cardboard box with my settings.
How can I get it to work in EXT mode without user intervention? -
KSS 8.4 for System Integrators.
Page 424.I modified it a bit to match my variables but the issue is that I got no response from the robot on the touchpad when the interrupt was triggered.
But thank you very much, panic mode.
The break was missing in the sub program and as soon as I added this the interrupt worked.On the real program I enable and disable the interrupt only during the search and I use only the correct interrupt number, not all of them.
-
I looked at the system integrators manual and examples for searching parts where location is unknown.
I was expecting the interrupt to jump to the UP1() local program immediately when the input is triggered... or create an error message that informs me about my mistake. Instead nothing happens and I cannot understand my mistake.
So you are saying that I have to place a BRAKE command in the UP1() sub program and then the Interrupt would have an effect?
I know about the risks in my sample code... I just wanted to post minimum number of lines where my error is quickly spotted.
-
I cannot get an interrupt to become active.
I can see from Display > Digital Inputs that the trigger Input 16 is really coming on... and it really is OFF in the beginning.
I use the simplest textbook example.Code
Display MoreDEF InterruptTest ( ) INTERRUPT DECL 10 WHEN $IN[16]==TRUE DO UP1() INTERRUPT ON BAS (#INITMOV,0 ) PTP xHome LIN CardboardSearchStart LIN CardboardSearchStop PTP xHome END ;------------------------ DEF UP1() PTP $POS_INT ;Turn vacuum on LIN CardboardSearchStart END
I test it in T1 mode... and the program acts like the interrupt doesn't exist... not stopping, no message...
What is a real copy-paste sample KRL code that definitely works. -
Is it also possible to program the searching of a part without using external sensors?
I mean, the robot is able to identify if it hits something... the motor torque goes up. But is this useable? Maybe my parts are crushed long before the motor torque senses an obstacle.I would also like to approach pile of cardboard and sense when I am able to grab one sheet.
Since I use vacuum cups I can turn on the vaccuum generator at the start of the seach, approach the parts slowly and when getting a trigger from the vacuum sensor I could stop the search.
The original post requires the movement to be in two stages... a fast search to get close and then switch to a slower approach for the pick up. I might get away with going slow all the way.
-
Robot tells you that? Or work visual?
It must have been WorkVisual because my global point delcarations work fine on the physical robot.
Does WorkVisual not check if the points are declared in some other DAT file !?