-
Notifications
You must be signed in to change notification settings - Fork 89
/
meArm.cpp
159 lines (139 loc) · 4.17 KB
/
meArm.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* meArm library York Hack Space May 2014
* A simple control library for Phenoptix' meArm
* Usage:
* meArm arm;
* arm.begin(1, 10, 9, 6);
* arm.openGripper();
* arm.gotoPoint(-80, 100, 140);
* arm.closeGripper();
* arm.gotoPoint(70, 200, 10);
* arm.openGripper();
*/
#include <Arduino.h>
#include "ik.h"
#include "meArm.h"
#include <Servo.h>
bool setup_servo (ServoInfo& svo, const int n_min, const int n_max,
const float a_min, const float a_max)
{
float n_range = n_max - n_min;
float a_range = a_max - a_min;
// Must have a non-zero angle range
if(a_range == 0) return false;
// Calculate gain and zero
svo.gain = n_range / a_range;
svo.zero = n_min - svo.gain * a_min;
// Set limits
svo.n_min = n_min;
svo.n_max = n_max;
return true;
}
int angle2pwm (const ServoInfo& svo, const float angle)
{
float pwm = 0.5f + svo.zero + svo.gain * angle;
return int(pwm);
}
//Full constructor with calibration data
meArm::meArm(int sweepMinBase, int sweepMaxBase, float angleMinBase, float angleMaxBase,
int sweepMinShoulder, int sweepMaxShoulder, float angleMinShoulder, float angleMaxShoulder,
int sweepMinElbow, int sweepMaxElbow, float angleMinElbow, float angleMaxElbow,
int sweepMinGripper, int sweepMaxGripper, float angleMinGripper, float angleMaxGripper) {
//calroutine();
setup_servo(_svoBase, sweepMinBase, sweepMaxBase, angleMinBase, angleMaxBase);
setup_servo(_svoShoulder, sweepMinShoulder, sweepMaxShoulder, angleMinShoulder, angleMaxShoulder);
setup_servo(_svoElbow, sweepMinElbow, sweepMaxElbow, angleMinElbow, angleMaxElbow);
setup_servo(_svoGripper, sweepMinGripper, sweepMaxGripper, angleMinGripper, angleMaxGripper);
}
void meArm::begin(int pinBase, int pinShoulder, int pinElbow, int pinGripper) {
_pinBase = pinBase;
_pinShoulder = pinShoulder;
_pinElbow = pinElbow;
_pinGripper = pinGripper;
_base.attach(_pinBase);
_shoulder.attach(_pinShoulder);
_elbow.attach(_pinElbow);
_gripper.attach(_pinGripper);
//goDirectlyTo(0, 100, 50);
goDirectlyToCylinder(0, 100, 50);
openGripper();
}
void meArm::end() {
_base.detach();
_shoulder.detach();
_elbow.detach();
_gripper.detach();
}
//Set servos to reach a certain point directly without caring how we get there
void meArm::goDirectlyTo(float x, float y, float z) {
float radBase,radShoulder,radElbow;
if (solve(x, y, z, radBase, radShoulder, radElbow)) {
_base.write(angle2pwm(_svoBase,radBase));
_shoulder.write(angle2pwm(_svoShoulder,radShoulder));
_elbow.write(angle2pwm(_svoElbow,radElbow));
_x = x; _y = y; _z = z;
}
}
//Travel smoothly from current point to another point
void meArm::gotoPoint(float x, float y, float z) {
//Starting points - current pos
float x0 = _x;
float y0 = _y;
float z0 = _z;
float dist = sqrt((x0-x)*(x0-x)+(y0-y)*(y0-y)+(z0-z)*(z0-z));
int step = 10;
for (int i = 0; i<dist; i+= step) {
goDirectlyTo(x0 + (x-x0)*i/dist, y0 + (y-y0) * i/dist, z0 + (z-z0) * i/dist);
delay(50);
}
goDirectlyTo(x, y, z);
delay(50);
}
//Get x and y from theta and r
void meArm::polarToCartesian(float theta, float r, float& x, float& y){
_r = r;
_t = theta;
x = r*sin(theta);
y = r*cos(theta);
}
//Same as above but for cylindrical polar coodrinates
void meArm::gotoPointCylinder(float theta, float r, float z){
float x, y;
polarToCartesian(theta, r, x, y);
gotoPoint(x,y,z);
}
void meArm::goDirectlyToCylinder(float theta, float r, float z){
float x, y;
polarToCartesian(theta, r, x, y);
goDirectlyTo(x,y,z);
}
//Check to see if possible
bool meArm::isReachable(float x, float y, float z) {
float radBase,radShoulder,radElbow;
return (solve(x, y, z, radBase, radShoulder, radElbow));
}
//Grab something
void meArm::openGripper() {
_gripper.write(angle2pwm(_svoGripper,pi/2));
delay(300);
}
//Let go of something
void meArm::closeGripper() {
_gripper.write(angle2pwm(_svoGripper,0));
delay(300);
}
//Current x, y and z
float meArm::getX() {
return _x;
}
float meArm::getY() {
return _y;
}
float meArm::getZ() {
return _z;
}
float meArm::getR() {
return _r;
}
float meArm::getTheta() {
return _t;
}