Posts by Shellmer

    It's not all about the experience you have or what you have learn't in school, but about how much you want to improve and learn...


    Having a previous base of programmation helps a lot in this world, but I've seen much people that with effort, becomes a great robotics, even without previous kwnoledge on the matter.

    Knowing how a PLC works helps as well to diagnose much problems, and I always recommend people who are interested to learn a few things about that.


    The major part I've learnt was by searching throught the system variables, reading manuals and solving problems, nobody gets here with all learned.

    When I started as robotic, even as I have received formation on the matter, the first thing I learn't was that I had no idea in reality...


    This forum and people who are here also helps a lot, so many headaches avoided by doing a quick search, here and there, and when you discover some tricks you will become more confident about what can and cannot be done.



    I've also coded some applications to analyze fanuc programs from an .ls backup, but it's a nightmare to parse all data and types of instructions.... I find sometimes new modifiers I haven't contemplated and need to do corrections.

    I hope there was a way to do a quick search on the fanuc program for registers being used without the need to analyze all the program by hand, as I haven't found a way I needed to do it myself.


    Maybe on the future I will publish it, but it's still in development and there are several bugs to address.

    Socket messaging is out of the question for me, parsing IOSTATE.DG would be the last resort. For finding out the main problems of a robotic cell during production without exaggerating with mget>parse loop what interval would you recommend?

    The last solution sounds verry good and less messy. I guess you are talking about a background program that continuously running. Unfortunately I don`t have any idea about how it would look.

    Reading the IOSTATE.DG would be the best way, because if you write the IO info every second on a file inside the MD, I don't think the SD card or whathever fanuc uses internally to store the files would survive the constant write cycles over a year.


    If you want to do it the other way writting ony the variables you want on a file, you will need to do it with Karel... there is not other way to do it since the TP instruction set is not ennough to do that.

    You will need to get info from the signals you want, parse them to text and overwrite (or append) the lines from that file every 1sec per example.

    You can do it with a background program you can call with the "RUN" instruction or launching it on the hotstart through the "Config" menu.


    I do not remember if it's possible to access the ramdisk through FTP... if it's possible, then you can do it with Karel but writting the file inside the ramdisk so no damage is done to the memory card...


    This is not a good method, best way would be to send the information to the PLC and then read it using something like an OPC server from the PLC DB... if you do not want to use socket messages, and you also don't want to use a PLC, I don't know any other method.

    One thing you may be able to do is to send the IO status from some signals through socket communication, but as far as I know, to do that you need the socket message option (R648) in order to send data that way.


    See this thread: Socket Messaging with C #


    I currently use a similar way to transfer data from the robot to an external PC, but you must parse the data and send it on various bytes, then on the server side decode that information again and reconstruct the data you have just sent.

    You can find usseful info about how to setup this on the "Karel reference manual"



    Another possible way, but I don't know if will work, is trying to access the IOSTATE.DG file using the FTP, but I think it will be a bit messy to just download that file every second and parse it.

    You may be able also to write a file inside the MD directory using Karel with the status of signals you are interested, download and parse it.

    Axis error codes are in Hexadecimal, if you decode it by converting to binary, each bit is and axis, so if you have an error of "G:1, A:10" it is the axis 5 who is causing the problem, if code is "12" axis 2 and 5 are giving the problem.


    There are more than one type of singularity, not only from the axis 4/6, you can also have singularity on the axis 2/3 when very streched, and on axis 1/6 if the axis 6 interface is pointing up per example.

    Any axis alignment is a singularity.


    Singularities should be avoided when possible, one way is to use a tool interface that has around 15 degrees of inclination (or more) to the flange, this problem should be avoided when possible when designing the tools from your applications.


    If you pass near singuilarity but the point is a fly-point, you shouls first try to use a J movement.

    If a linear movement is required, you can try to use the "Wjoint" modifier on the movement, but take care since the path will not be completelly ninear and robot will deviate in order to avod the singularity. Do not use this modifier if point coordinates are being calculated since it will not be reliable due to config changes, only on fixed points.


    Also, singularities and L movements are not the best friends, since a L movement is done with the shortest path and axis configuration is not used, you can reach axis limits very easily. You should avoid to do the complete path with L movements, at least try to use one or 2 to "unwind" the axis so limits are not reached.

    I don't understand something on that logic you wrote:


    You are getting the rest from the operation $FAST_CLOCK MOD 3000, that will give a value betwheen 2999-0.

    Then you are dividing by 1000 with the DIV operator, that will result on a value betwheen 2-0.


    If you equal a register to a flag, 0 value will be false, and 1 or some other positive number will be true.

    I understand this and the logic part seems correct, you will have 1/3 of this time the flag at false and 2/3 on true.


    But... since every tick is 4ms, the value obtained on the MOD operation will increase to 3000 on exactly 12 seconds. So if fast clock increases every 4ms one unit you will have that flag on true 8 seconds, and on false 4 seconds.

    Is this correct?? The remark from that flag says "2sec on 1sec off"... and to do that you should MOD by 750 instead of 3000.


    Also, you can get rid of one register if you want, you can replace the "R[10] register on the second line and use the FAST_CLOCK variable directly.

    Searching the board you have said I do not see any fuse, maybe they are inside the black box near the orange connector where the safety signals are wired. There must be fuses on some place, at least on all controllers I have seen, even on RJ3 controllers there are fuses placed on the safety board but in different locations on the board.


    If with one pendant it works the fuses will not be the issue, Skooter may be right, but it seems to me strange to exist pendants with single and dual channel deadman... even with 2 or 4 switches I would expect to work the same way, using 2 signals in order to detect faults, but with more switches in parallel so the deadman is easier to handle.


    Deadmans usually work by providing 2 signals, usually inverted and the two must be engaged at the same time with very little time difference. If some switch is in bad state and signals are not syncronized an alarm is raised. I haven't seen the inside of a fanuc pendant yet, only abb ones while repairing them.

    I don't know about the wiring... but have you reset that alarm through the alarm screen the first time it happens?


    There is a button called "RES 1CH" on the alarm screen. Click on it, confirm and press shift+reset yo see if error dissapears.


    Sometimes when the deadman is pressed incorrectly controller gives that error, the alarm also fires if wiring is damaged, but will not dissapear if you do not reset the error manually.


    It also fires if some security channel like the "fence" or "emgstop" is not changing the dual-channel signal at the same time, or if a fuse from the safety board if blown.


    If you are using 2 different pendants and one of them for sure is ok because its brand new, check the fuses from the safety board, it's likelly a problem on the controller side.

    Its another good way to implement it.

    The idea is to avoid triggering several times the same condition, and to do that its needed a register to track time.


    Problem with fast clock and bglogic is that you cant ensure you will catch only one tick of the fastclock on every bglogic loop, so you cant use a = operator on conditionals.

    Instead it should be used one register and an >= or <= so the condition is executed one time even if you miss 4... 8 or 12ms.


    Since fast_clock is likelly tied to a hardware timer on the real controller his value will be incremented even if the cpu is at full load, and a bglogic task is not something that cpu should priorize and can take more time to be executed than the dcs check... or the motion planner, so you can miss ticks of fastclock.



    I suppose the first thing I would try before using that other approach would be an IF ($FAST_CLOCK MOD 12000 = 0) ... but due to the nature of this timer it will not work as you cant ensure you will catch that tick change.

    Relating to something I just wrote on another post, you may be able to store the current time of the robot writting on bglogic the time into a register.


    Assuming the variable $FAST_CLOCK is reset after a powerup (i dont have a controller here to check if it works that way), you can check if robot controller was restarted by checking if the new value is lower than the last one stored to know if robot was powered down. This should be running on bglogic:


    Code
    1: IF ($FAST_CLOCK < R[10]), JMP LBL[100] ; jump to the code where a flag is set indicating powerdown
    2: JMP LBL[200] ; jump to end and update register
    3: ;
    4: LBL[100] ;
    5: F[5]=ON ;
    6: ;
    7: LBL[200] ;
    8: R[10]=$FAST_CLOCK ; store the current time
    9: LBL[999]

    You should reset the flag manually each time the condition triggers.

    To know the exact time robot is started again I suppose it can be done by using karel, there may be some finction to get the full date and time of the controller, if so you can store it every time thst flag is set.


    If you try this, let me know if it works or if that variable is reset after every powerup.

    Another different aproach is to temporize the signal change as it's done on microcontrollers in order to not use software delays. Example:


    Code
    1: IF ($FAST_CLOCK >= R[10]), JMP LBL[100] ; jump to the code where pulse is generated
    2: JMP LBL[999] ; jump to end if condition not met
    3: ;
    4: LBL[100] ;
    5: F[30:2s ON 1s OFF]=PULSE,2.0sec ;
    6: R[10]=$FAST_CLOCK ; store the current time
    7: R[10]=R[10] + (3000 DIV 4) ; with this we store on R10 the current time + the time that must pass to trigger the next pulse
    8: LBL[999]

    With this method you will be using a register to track the time elapsed since the last time pulse was sent... if you want to generate more pulses with different periods you must use more registers.


    When $FAST_CLOCK surpasses the time stored on that register it will execute the pulse instruction and store on the register the next time to trigger another pulse, this ensures you are executing this code only one time every 3 seconds.

    On your aproach you are checking if the result value of the MOD instruction is betwheen 0-2899, this will run the PULSE instruction several times while the condition is met and may generate an incorrect behaviour...


    If 1 unit on fast_clock is increased every 4ms, you must DIV the time value you add by 4 as in the example.

    Also, if fastclock works that way it makes sense that the value you have on R[11] take 12 seconds to reach 3000, if it takes 4ms to increase the fastclock 1 unit then to reach 3000 it must pass 3000*4ms=12 seconds.



    FAST_CLOCK assuming its stored on a 32bit unsigned integer should overflow after 198 days... so take care with that if you use values from that variable. I suppose fastclock is reset after every powerup to 0.

    If you want to do a pulse, maybe you can also try to set and reset the signal directly instead of using the pulse instruction.

    You can do it through 2 conditionals or using a flag to do a flip-flop logic, inverting the signal each time the condition is met.


    As roboguide is executing a virtual machine with the robot software, the timers are likelly software emulated, and timers that are software emulated usually are slower...

    This problem often happen on microcontrollers if hardware timers are not used because code can take different time to execute on every program loop, and if a register is incremented based on software that "timer" is unreliable.

    That is the most probable cause if you see that it works ok on a real controller.

    Adding info about this:

    If you want to use the new instructions, do not mix "S" and "Normal" instructions (Example: SLIN and LIN instructions on the same trajectory)

    It seems each set of instruction uses a different motion planner, and if you mix the normal and new instructions it will be forced a fine point.


    I had that issue with a robot that was stopping even with C_DIS and no logic betwheen points, until I changed all instructions to the normal ones.

    I also tested it using only "S" instructions and it works ok, problem only happens when you mix the two instruction sets.

    I'm a bit rusty on Kuka... but maybe if you declare that 8 points globally, you can then edit the Z coordinate of all points before performing the movement.

    Not inside the point itself, but overwritting the Z value of every position before executing the movement.


    Putting a variable inside the declaration of the local point will likelly result on a syntax error, also you are not incrementing zAx so that loop will run forever.

    You should be able to access data on the point by putting $xPointName1.x or something similar, like when you access the variables through the smartpad.

    Remote TCP is a TCP that is fixed in space and do not move with the robot.

    Think about a robot with spot weld that handles a workpiece and move it to a external spot welder, the remote tcp will be on the fixed cap of the spotgun and will never move.


    On abb robots you can embark a workobject(frame) with reference to the 6th axis interface and you use a "tool" that is fixed on the space.


    Fanuc doesn't have that, so you declare a "tool" on the gripper that in reality will be a "frame" and declare the frame on the spot gun location (the fixed tool)

    Then if you go to the TP module you have the welding path, go to details and active the remote tcp option, the robot will convert his point coordinates and calculate them from the "moving frame" to the fixed tool. Coordinates will be represented as XYZ RxRyRz instead of XYZWPR.


    This also applies to external gluing guns. The reason to do that is that for example with spot welding you can move the workpiece along the direction of the external tool to compensate cap wear. Also if you reorient with remote tcp you will be reorienting the workpiece around the external tool, no matter where the "tool" from the robot is declared.



    Also some manufacturers have a frame declared on the product 3D origin, with this all gluing or welding coordinates will be represented on the 3D coordinates, its usseful to check if a soldering point is positioned like in the design.


    It's a little confuse at first to understand it.

    Also a tool declared this way should not be used to handle parts(only when soldering, gluing, etc) since if you have a tool declared 3m away from the 6th axis interface, robot will move slower than if you use a tool that is located on a pilot from the gripper.

    If you have the original mastercount values I would try to restore them, if robot has not lost power to the encoders and motors or encoders have not been replaced its better to use the factory original mastering data than to master each axis manually again. This data is always provided with the robot and its usually stored on paper inside the controller cabinet.


    Being a secondhand robot it will likelly not be the case but its easy to check if it works or not.

    I work a lot with vision equipment and it makes a big diference when a robot is well calibrated, I needed to restore calibration on various controllers and is night and day difference when you need to pick parts with different rotations.

    Assumption was based on the program content and that tool is pointing down.

    But it doesn't matter, if you are using cartesian coordinates then you want to rotate 90 degrees around Z, its ok.


    Speed issue can be because movements are blending toguether due to use of cnt like HawkEye says.

    You have a movement with 1000mm/s and before it reaches that destination you change the speed to 5deg/sec, but robot do not decelerate instantly and may be going faster than 5deg/sec when passing near the first point to the second one.


    Have you tried to put a fine point on both points and see how much time it takes to do the full rotation without the cnt?. Only as a way to check if the robot is doing what its expected when provided that speed command.

    First thing I see wrong is that you are using a L movement to move "lineary" to a position that I assume you are storing on "Joint position" coordinates.

    This, as far as I know will not work correctly and robot will go to the first position without respecting a linear path... I had issues with this on one robot that was not working correctly when going lineary to a point until I discovered it was saved as "joint coordinates" instead of castesian ones.


    Second thing is that you are also using another L movement after switching the axis 6 to 90 degrees.

    It should be a J movement if you want the robot to respect the speed you are commanding with the 5deg/sec speed.... if not it will interpolate the TCP path and you do not want that. If you are only moving the 6th axis back and forth you do not need a linear movement and with a J movement axis 6 will turn freely with the other axis standing still.


    Third thing... when you modify PR on the program directly, motion planner calculates a path, then you are modifying the 6th axis position while in movement.

    I think motion planner do not look ahead the same way with "PR" as with "P" points, and it may do a fine point instead because of this.

    I never do that anymore so I can't be sure of that but I remember having problems regarding this matter while calculating points middle-movement.


    If you calculate all points and store them in PR before the movements, then execute the trajectory it will work ok, but as far as I know if you edit PR while on movement the program pointer will stop briefly on every PR assignment before the next move path is calculated.... it may not be much time, but on some cases it will pause a bit.


    If you can, you should use an additional PR just to be sure.

    I always use to release the handbroken when changing uframe/utool numbers on the tp, because sometimes (not on every robot) if not done, the robot moves incorrectly on an axis even moving in uframe.


    Not sure the reason this happens, but it happened me various times.

    One thing to note is that fanuc axis 6 interface has 2 holes to fix the tool, have you checked if tool reorients correctly?

    Maybe you have the suction cup interface incorrectly mounted (inverted), also some mechanical units have that 2 holes rotated around 20 degrees (I think the M10iA with the 4th axis painted in black).



    To do this type of TCP measures I usually use a pointer fixed on the machine I work and then I measure the TCP as accurate I can putting another pointer but screwing it on the pneumatic racor hole. Then I only update the XYZ coordinates, original orientations from the offline TCP program are maintained.



    Make sure the robot is well calibrated before trying to make a TCP... if robot is not calibrated correctly is next to impossible to reorient correctly and robot may behave incorrectly on all linear movements.

    No problem, this forum has helped me when I started at robot programming a lot, I still learn things with the questions and responses from all people who is here.

    So it's time to return a little bit of knowledge.


    Another thing I recommend you is to try to keep all simple on the robot program.... if you can split a Karel routine into little subroutines and handle all logic and karel calls on a TP program, it is better to do that.

    That way you can debug your program better, also it makes maintaining the code easier to all people who comes next (but make sure to add remarks of what do every input parammeter if you can)


    At least for me there is no benefit in obfuscating the code of the robot. People will get angry at you when they ask who programmed the robot if they can't see anything.

    Having the program in a "black box" with karel is awful... but yeah, it "ensures" that they will call you to do any modification, but the most probable scenario is that they call you one time, and with the next cell they will not call you anymore.


    I hoped they provided a way to optionally "unlock" the karel files when compiling in order to allow to see the content and program pointer, but I think it will never happen since there are options for all sort of things, even for loading/saving programs on ascii format, that should be a free option like the majority of other robot brands.

    Just ensure to save the .kl files somewhere since the .pc files can't be decompiled and when you need to make a change if you do not have the sources you are screwed.