Professional Documents
Culture Documents
(http://robdobson.com/)
%
! (HTTP://ROBDOBSON.COM) SINGLE-ARM ROBOT
# (HTTP://ROBDOBSON.COM/2016/04/NON-VESTING-SHARE-OPTIONS/) $
(HTTP://ROBDOBSON.COM/2016/03/AUTO-REMINDER-WATCH/)
Looking for an open-source design to get started with I found one on Thingiverse
(http://www.thingiverse.com/thing:124149) which didnt look too complicated although, at the
time, nobody seemed to have made one. I got to work printing out the parts which took a couple
of days on my Ultimaker Original.
(http://robdobson.com/wp-content/uploads/2016/03/Scara-Arm-Testing2.jpg)
(http://robdobson.com/wp-
content/uploads/2016/03/47b37b70ae986bd9469e70a983e7e39c_preview_featured.jpg)
I then had some trouble with the belts used to drive the arms. I wasnt able to find 160 teeth belts
cheaply in the UK so I bought some 158 teeth ones. They were, unsurprisingly, too tight so I had to
re-print the motor mount pieces with the holes moved.
I also found that the 320 teeth belt (which I did manage to source) was too tight. In this case I
solved the problem by re-creating a 60 tooth gear to replace the 62 tooth one in the original
design. I found a great SCAD template for this here (http://www.thingiverse.com/thing:16627)
and modified it accordingly.
Control Electronics
To control the steppers I used a pair of driver modules like this
(https://www.pololu.com/product/1182) which have a micro-stepping ability
(http://motion.schneider-electric.com/technology-blog/stepper-motor-basics-half-and-micro-
stepping/). This allows a conventional stepper motor (with 1.8 degrees of movement per step) to
be driven in increments of slightly over 0.1 degrees (actually 1.8/16 degrees).
For the controller I wanted to try out a MicroPython PyBoard (https://micropython.org/) I had
recently bought together with an LCD display and touch keypad (https://micropython.org/doc/tut-
lcd-skin). It didnt take much time to get to grips with and I can heartily recommend this as an
alternative to writing C++ for every little project.
Test Program
Python
1 import pyb
2 import mpr121
3
4 # Pins used to control the stepper motor drivers
5 lowerArmStep = pyb.Pin('Y9', pyb.Pin.OUT_PP)
6 lowerArmDirn = pyb.Pin('Y10', pyb.Pin.OUT_PP)
7 upperArmStep = pyb.Pin('Y11', pyb.Pin.OUT_PP)
8 upperArmDirn = pyb.Pin('Y12', pyb.Pin.OUT_PP)
9
10 # Using a library provided by MicroPython for the keyboard
11 keybd = mpr121.MPR121(pyb.I2C(1, pyb.I2C.MASTER))
12 keybd.debounce(3,3)
13 for electr in range(4):
14 keybd.threshold(electr, 50, 30)
15
16 # Width and length of pulses for microstepping
17 pulseWidthUsecs = 1
18 betweenPulsesUsecs = 500
19
20 # Degrees per step calculation
21 upperDegreesToMove = 15
22 # Stepper motors move 1.8 degrees per full step
23 # In microstepping mode so 16 microsteps per step
24 # Motor shaft pulley has 20 teeth
25 # Upper arm pulley has 62 teeth
26 upperDegreesPerStep = (1.8/16)*(20/62)
27 upperStepsPerMove = upperDegreesToMove/upperDegreesPerStep
28
29 # Lower arm calculation as above
30 lowerDegreesToMove = 90
31 lowerDegreesPerStep = (1.8/16)*(20/62)
32 lowerStepsPerMove = lowerDegreesToMove/lowerDegreesPerStep
33
34 # Loop getting a key press and performing actions
35 while(True):
36 if (keybd.elec_voltage(1) < 220): # X Key
37 lowerArmDirn.value(0)
38 for i in range(lowerStepsPerMove):
39 lowerArmStep.value(1)
40 pyb.udelay(pulseWidthUsecs)
41 lowerArmStep.value(0)
42 pyb.udelay(betweenPulsesUsecs)
43 elif (keybd.elec_voltage(0) < 220): # Y Key
44 lowerArmDirn.value(1)
45 for i in range(lowerStepsPerMove):
46 lowerArmStep.value(1)
47 pyb.udelay(pulseWidthUsecs)
48 lowerArmStep.value(0)
49 pyb.udelay(betweenPulsesUsecs)
Circle Intersections
The next thing to do was to work out how to move to a specified position in Cartesian coordinates.
I started to work out the geometry and quickly realised that I essentially had two intersecting
circles, one centred on the point I wanted to reach and the other centred on the origin of the robot
i.e. the position of its shoulder.
Python
1 from math import cos, sin, pi, sqrt, atan2, asin, acos
2 d2r = pi/180
3
4 def circle_intersection(circle1, circle2):
5 '''
6 @summary: calculates intersection points of two circles
7 @param circle1: tuple(x,y,radius)
8 @param circle2: tuple(x,y,radius)
9 @result: tuple of intersection points (which are (x,y) tuple)
10 '''
11 # return self.circle_intersection_sympy(circle1,circle2)
12 x1,y1,r1 = circle1
13 x2,y2,r2 = circle2
14 # http://stackoverflow.com/a/3349134/798588
15 dx,dy = x2-x1,y2-y1
16 d = sqrt(dx*dx+dy*dy)
Moving to an XY Position
The only challenge then was to perform a couple of simple trigonometric calculations (to calculate
the required angles at the two joints) and drive the stepper motors to the desired positions.
A significant aspect of this is that there should be no cumulative error. When a stepper motor
moves it can only move in increments of a little over 0.1 degrees (using microstepping as described
above). If a particular angle requires a movement of, say, 10.03 degrees then the number of steps
will be rounded to approximate this angle. If this rounding is performed repeatedly there will be
an increasing error in the angular position. To avoid this I remember the location of the elbow
and the number of steps each arm segment has performed since being at the origin position
which I assume is straight out initially. Then everything is calculated from this origin position.
A further piece of minor trickery is the section of code which actually moves the motors. This uses
a variant of Bresenhams Line Algorithm
(https://en.wikipedia.org/wiki/Bresenham%27s_line_algorithm) which handles a situation where
one variable increments on each loop and the other only periodically the great advantage of this
approach is that it can be done with integer arithmetic if required although this particular
MicroPython implementation has floating point.
This is actually the final code with an additional fix which is described below.
Python
1 def drawLine(x1, y1, x2, y2):
2 lineLen = sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2))
3 lineSegmentCount = int(lineLen)
(http://robdobson.com/wp-content/uploads/2016/03/20160331-Straight-Line-Attempt.png)
The line (marked with the red arrows) started ok it was drawing from top-left to bottom-right
and is reasonably straight for about 2/3 of its length. But the code then detected that it needed to
change from a forehand swipe to a backhand swipe and rotated the arms accordingly.
However, as can be seen, the continuation of the line is not where it should be the discontinuity
between the two lower red arrows.
Eventually I realised that when changing the number of teeth on the pulley (which transfers the
motion from the lower arm motor to the lower arm itself) I had unbalanced the two intermediate
pulleys in an unexpected way. I actually had considered that this change might affect the ratio on
the lower arm but had decided that the same intermediate pulley is used by both the motor drive
belt and lower arm pulley. So actually there is no such change as the two cancel each other out (i.e.
there is a 20:60 ratio on the first belt and a 60:62 ratio on the second so the overall effect is just
20:62 as it was originally). But what I hadnt thought about is that when the upper arm moves (and
the lower arm motor stays still) there is an effective turning of only the second stage of the drive
belt mechanism. So when the upper arm moves through 90 degrees (for instance) there is a
consequential movement of the lower arm by:
Sharethis:
Twitter (http://robdobson.com/2016/03/single-arm-robot/?share=twitter&nb=1)
Email (http://robdobson.com/2016/03/single-arm-robot/?share=email&nb=1)
LinkedIn (http://robdobson.com/2016/03/single-arm-robot/?share=linkedin&nb=1)
Google (http://robdobson.com/2016/03/single-arm-robot/?share=google-plus-1&nb=1)
Pinterest (http://robdobson.com/2016/03/single-arm-robot/?share=pinterest&nb=1)
Comments
7
REPLY
(
(H TTP://ROBDOBSON.COM / 2 0 1 6 / 0 3 /SIN G L E-A RM - ROBOT/ ?R EP LYTOCOM = 3 7 1 1 4 # R ESP OND)
Swift
13 JANUARY 2017 AT 4:51 PM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-ARM-
ROBOT/#COMMENT-37114)
ZhangZQ
2 APRIL 2016 AT 3:57 PM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-ARM-
ROBOT/#COMMENT-26613)
Hi, I also built such arm, and I also found the belt is very tight, so I
modified the gear from 62 to 60 teeth, And then I want to drive it using
Marlin, but it cant run the straight line. Did you try marlin?
R EP LY
(
(H TT P ://ROBDOBSON .COM / 2 0 1 6 / 0 3 / SIN G L E-A R M -ROBOT/ ?
R EP LYTOCOM = 2 7 3 6 1 # R ESPON D)
Javier
6 JUNE 2016 AT 10:53 AM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-ARM-
ROBOT/#COMMENT-27361)
POST
AU THOR
rob
(http://robdobson.com)
24 JUNE 2016 AT 3:29 AM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-
ARM-ROBOT/#COMMENT-27426)
REPLY
(
(H TTP://ROBDOBSON.COM / 2 0 1 6 / 0 3 /SIN G L E-A RM - ROBOT/ ?R EP LYTOCOM = 2 6 5 8 3 # R ESP OND)
Rupert
31 MARCH 2016 AT 7:29 PM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-ARM-
ROBOT/#COMMENT-26583)
rob
31 MARCH 2016 AT 11:48 PM
(HTTP://ROBDOBSON.COM/2016/03/SINGLE-ARM-
ROBOT/#COMMENT-26587)
Leave a Reply
Your email address will not be published. Required fields are marked *
Comment
Name*
)
Website
+
Submit
, Search
Recent Posts
MK14 MEETS 7BOT (HTTP://ROBDOBSON.COM/2016/10/MK14-MEETS-7BOT/)
HTTP://WWW./ (HTTP://WWW./)
Archives
OCTOBER 2016 (HTTP://ROBDOBSON.COM/2016/10/)
Categories
GETITMADE (HTTP://ROBDOBSON.COM/CATEGORY/GETITMADE/)
STARTUPS (HTTP://ROBDOBSON.COM/CATEGORY/STARTUPS/)
Meta
LOG IN (HTTP://ROBDOBSON.COM/WP-LOGIN.PHP)
WORDPRESS.ORG (HTTPS://WORDPRESS.ORG/)