Mike's 6-Axis Articulated Robot

Each integer consumes 1/3 of a line of code, so adding 30 integers means you lose the ability to use 10 lines of code from the 8000.
What is it using for programming memory? I remember one prof I worked with hacking his TRS-80, adding wires and piggyback SRAM chips, to greatly increase the program memory. By that time the TRS-80 was already an antiquated beast, but it was his form of amusement.
 
To make the most of the limited program sizes in the robot controller it is advantageous to use subroutines when possible. In short, subroutines are blocks of code that can be executed by a single line of code (e.g. SUB 31). Subroutines can have as much code as needed and can call other subroutines (known as nesting) up to 16 layers deep.

Subroutines can be very simple such as the following example to open a gripper:

Code:
SUBROUTINE 32
0010 VON 6
0020 VOFF 5
0030 TIM 50
0040 END

Or they can be as complicated as needed. There are no parameters that can be passed into the subroutine from the subroutine call, but the subroutine can read and write global variables just like the main program. For example the main program might write the value 10.0 to Floating Point variable 1

Code:
0010 S F0001=10.0

and the subroutine might copy that to Floating Point variable 2

Code:
SUBROUTINE 33
0010 S F0002=F0001
0020 END

The power of this global variable access comes when you get into indirect addressing. Indirect addressing allows you to access the data in a variable based on the value of a different variable. In the simple example below, The value from Floating Point variable 2 is copied into Floating Point variable 1, and then later Floating Point variable 3 is copied into Floating Point variable 1, but they use the same subroutine

Code:
PROGRAM 1
0010 S I0001=2
0020 SUB 1
0030 S I0001=3
0040 SUB 1
0050 END

SUBROUTINE 1
0010 S F0001=I0001.F
0020 END

In the example above, the integer variable "I0001" contains the value of index of the floating point array to be copied. In a traditional programming sense, I0001 is a pointer to the F000x variable.

Initially I0001 is set equal to 2. When the subroutine call is executed, the indirect reference "I0001.F" is resolved to "F0002" (floating point variable with the index equal to the value of I0001). Later in the program, the main routine redefines I0001=3, so the next execution of the subroutine, the indirect reference "I0001.F" is resolved to "F0003".

Based on these principles, I rewrote the previous program into a subroutine based program:

Code:
PROGRAM 31
0010 S I0028=50  //Rapid Speed
0020 S I0029=20  //Reduced Speed
0030 TOOL 5  //Setup tool offset
0040 SUB 32
0050 ISP I0028  //Set speed
0060 MV E,J0100  //PTP move to safe location in the air
---------------------------------------------------First Place----------------
0070 S I0030=102
0080 S I0032=104
0090 SUB 30
---------------------------------------------------Second Place----------------
0100 S I0030=106
0110 S I0032=108
0120 SUB 30
---------------------------------------------------Third Place----------------
0130 S I0030=110
0140 S I0032=112
0150 SUB 30
---------------------------------------------------First Return----------------
0160 S I0030=104
0170 S I0032=102
0180 SUB 30
---------------------------------------------------Second Return----------------
0190 S I0030=108
0200 S I0032=106
0210 SUB 30
---------------------------------------------------Third Return----------------
0220 S I0030=112
0230 S I0032=110
0240 SUB 30
---------------------------------------------------End of Program----------------
0250 MV E,J0100 //PTP move to safe location in the air
0260 END  //END of program


----------------------Pick & Place w/ Approach Points Subroutine--------------------------
//This subroutine completes a full pick and place action
//Approach positions are used for each pick and place location
//Robot moves to approach points at full speed defined by FLOAT 30
//Robot moves from approach points to pick/drop points at reduced speed defined by FLOAT 31
//Robot moves to pick point defined by INTEGER 30. Pick approach point must be stored in the position variable immediately preceding the pick point (e.g. P0101 = pick approach position, P0102 = pick position)
//INTEGER 31 is used for intermediate calculation of pick approach position
//Robot moves to drop point defined by INTEGER 32. Drop approach point must be stored in the position variable immediately preceding the drop point (e.g. P0103 = drop approach position, P0104 = drop position)
//INTEGER 33 is used for intermediate calculation of pick approach position

SUBROUTINE 30

0010 ISP I0028  //Set full speed from global rapid speed variable
0020 S P0100=I0030.P  //Copy the pick point from the Position variable registers "P" at index defined by the value of I0030 to the working pick position P0100
0030 S I0031=I0030-1  //Subtract 1 from the pick position pointer
0040 S P0099=I0031.P  //Copy the pick approach point from the Position variable registers "P" at index defined by the value of I0031 to the working pick approach position P0099
0050 MVS E,P0099  //Move linear to pick approach point
0060 ISP I0029  //Set full speed from global reduced speed variable
0070 MVS E,P0100  //Move linear to pick point
0080 SUB 31  //Call Close Gripper subroutine
0090 MVS E,P0099  //Move linear to pick approach point
0100 ISP I0028  //Set full speed from global rapid speed variable
0110 S P0100=I0032.P  //Copy the pick point from the Position variable registers "P" at index defined by the value of I0030 to the working pick position P0100
0120 S I0033=I0032-1  //Subtract 1 from the pick position pointer
0130 S P0099=I0033.P  //Copy the pick approach point from the Position variable registers "P" at index defined by the value of I0031 to the working pick approach position P0099
0140 MVS E,P0099  //Move linear to pick approach point
0150 ISP I0029  //Set full speed from global reduced speed variable
0160 MVS E,P0100  //Move linear to pick point
0170 SUB 32  //Call Open Gripper subroutine
0180 MVS E,P0099  //Move linear to pick approach point
0190 ISP I0028  //Set full speed from global rapid speed variable
0200 END


----------------------Close Gripper Subroutine--------------------------
//This subroutine completes a gripper close action

SUBROUTINE 31

0010 VON 5
0020 VOFF 6
0030 TIM 50
0040 END


----------------------Open Gripper Subroutine--------------------------
//This subroutine completes a gripper close action

SUBROUTINE 32

0010 VON 6
0020 VOFF 5
0030 TIM 50
0040 END


----------------------Variable definitions--------------------------

I0028 = Rapid Speed (default 50)
I0029 = Reduced Speed (default 20)

I0030 = Pick Point Pointer
I0031 = Internal Calculation (Pick Approach Pointer)
I0032 = Drop Point Pointer
I0033 = Internal Calculation (Drop Approach Pointer)

J0100 = Safe clearance position
P0099 = Internal Calculation (Pick/Drop Approach Position)
P0100 = Internal Calculation (Pick/Drop Position)
P0101 = Approach point to pick location 1
P0102 = Pick location 1
P0103 = Approach point to drop location 1
P0104 = Drop location 1
P0105 = Approach point to pick location 2
P0106 = Pick location 2
P0107 = Approach point to drop location 2
P0108 = Drop location 2
P0109 = Approach point to pick location 3
P0110 = Pick location 3
P0111 = Approach point to drop location 3
P0112 = Drop location 3

This reduced the total number of lines of code from 127 to 58 and each addition pick/place of a brick only adds 3 lines of code rather than 20.

A couple limitations of this is that you cannot complete indirect references or math outside of a "SETI" command line (lines starting with "S"). This means that the following line of code is invalid since you cannot resolve "I0030.P" to P.xxxx in the same line of code that you are trying to execute a move from.

Code:
0010 MVS E,I0030.P

You are also not allowed to complete more than one math operation per "SETI" command line, so the following is invalid since you are trying to add 3 values together:

Code:
0010 S I0001=I0002+I0003+2

This would be valid if written as:

Code:
0010 S I0001=I0002+I0003
0020 S I0001=I0001+2
 
Last edited:
What is it using for programming memory? I remember one prof I worked with hacking his TRS-80, adding wires and piggyback SRAM chips, to greatly increase the program memory. By that time the TRS-80 was already an antiquated beast, but it was his form of amusement.
Not real sure to be honest. I can try to study the mother board. The control does mention the option to mount optional memory to increase the total available storage by ~20%.
 
Looks great. I wonder if there is a way to dynamically load/replace some of the program memory. for instance if a subroutine could load a new block of code. Essentially a simple paging system. A long shot, I realize.
 
Looks great. I wonder if there is a way to dynamically load/replace some of the program memory. for instance if a subroutine could load a new block of code. Essentially a simple paging system. A long shot, I realize.

Nothing can call another main program, but your main program could pretty much only call subroutines (which could be written to look like their own main programs). Probably not exactly what you were suggesting.
 
Probably not exactly what you were suggesting
agreed. It would only be valuable if it can load from near-line / off-line memory as a way to increase the program & variable space.
 
Not real sure to be honest. I can try to study the mother board. The control does mention the option to mount optional memory to increase the total available storage by ~20%.
Not really an issue until you get around to writing really complex code. Just a random thought.
 
Morning all, I've been away from this site for quite a while as life has gotten quite busy in the last year (new house, new job, and baby on the way!), but I figured I'd give a quick sneak peek of a project I've been working on for about a month now...

This little setup will become our Halloween display this year! Robot will hand out candy by dropping baggies down a chute when a candy order button is pressed.

image310.jpg

The robot control is wired into this big enclosure which is 99% empty but I grabbed it before we threw it away at work. It has a 24V PSU, safety relay, and a couple terminal blocks inside. The display will be protected by a laser area scanner (safety rated) to prevent kids from running up to the running robot (plus multiple ESTOP buttons).

image311.jpg

Have quite a bit of work to go, but I'm getting there. mostly programming, teaching positions, building the chute supports, and decorating it. 7 days left...
 
Congratulations on life!! All great news!!!


And that Halloween project, sweet! Be sure to get a video of it working with the kids! So cool!
 
Back
Top