Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1702 - 1
/* AL5D robotic arm manual control using USB mouse. Servo controller by Renbotics with some pins swapped, USB Host Shield by Circuits At Home */
2
#include <ServoShield.h>
3
#include <Spi.h>
4
#include <Max3421e.h>
5
#include <Usb.h>
6
 
7
#define DEVADDR 1
8
#define CONFVALUE 1
9
 
10
 
11
 
12
 
13
/* Arm dimensions( mm ) */
14
#define BASE_HGT 67.31      //base hight 2.65"
15
#define HUMERUS 146.05      //shoulder-to-elbow "bone" 5.75"
16
#define ULNA 187.325        //elbow-to-wrist "bone" 7.375"
17
#define GRIPPER 100.00      //gripper (incl.heavy duty wrist rotate mechanism) length 3.94"
18
 
19
#define ftl(x) ((x)>=0?(long)((x)+0.5):(long)((x)-0.5))  //float to long conversion
20
 
21
/* Servo names/numbers */
22
/* Base servo HS-485HB */
23
#define BAS_SERVO 0
24
/* Shoulder Servo HS-5745-MG */
25
#define SHL_SERVO 1
26
/* Elbow Servo HS-5745-MG */
27
#define ELB_SERVO 2
28
/* Wrist servo HS-645MG */
29
#define WRI_SERVO 3
30
/* Wrist rotate servo HS-485HB */
31
#define WRO_SERVO 4
32
/* Gripper servo HS-422 */
33
#define GRI_SERVO 5
34
 
35
//#define ARM_PARK set_arm( -50, 140, 100, 0 )  //arm parking position
36
 
37
/* pre-calculations */
38
float hum_sq = HUMERUS*HUMERUS;
39
float uln_sq = ULNA*ULNA;
40
 
41
void setup();
42
void loop();
43
 
44
ServoShield servos;                       //ServoShield object
45
MAX3421E Max;
46
USB Usb;
47
//ServoShield servos;                       //ServoShield object
48
 
49
/* Arm data structure */
50
struct {
51
  float x_coord;            // X coordinate of the gripper tip
52
  float y_coord;            // Y coordinate of the gripper tip
53
  float z_coord;            //Z coordinate of the gripper tip
54
  float gripper_angle;      //gripper angle
55
  int16_t gripper_servo;   //gripper servo pulse duration
56
  int16_t wrist_rotate;    //wrist rotate servo pulse duration
57
} armdata;
58
 
59
void setup()
60
{
61
  /* set servo end points */
62
  servos.setbounds( BAS_SERVO, 900, 2100 );
63
  servos.setbounds( SHL_SERVO, 1000, 2100 );
64
  servos.setbounds( ELB_SERVO, 900, 2100 );
65
  servos.setbounds( WRI_SERVO, 600, 2400 );
66
  servos.setbounds( WRO_SERVO, 600, 2400 );
67
  servos.setbounds( GRI_SERVO, 890, 2100 );
68
  /**/
69
//  servo_park();
70
  arm_park();
71
 
72
  servos.start();                         //Start the servo shield
73
  Max.powerOn();
74
  Serial.begin( 115200 );
75
  Serial.println("Start");
76
  delay( 500 );
77
  //ARM_PARK;
78
}
79
 
80
void loop()
81
{
82
byte rcode;
83
    //delay( 10 );
84
    set_arm( armdata.x_coord, armdata.y_coord, armdata.z_coord, armdata.gripper_angle );
85
    servos.setposition( WRO_SERVO, armdata.wrist_rotate );
86
    servos.setposition( GRI_SERVO, armdata.gripper_servo );
87
   //ARM_PARK;
88
 // circle();
89
    Max.Task();
90
    Usb.Task();
91
    if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING ) {
92
        mouse_init();
93
    }//if( Usb.getUsbTaskState() == USB_STATE_CONFIGURING...
94
    if( Usb.getUsbTaskState() == USB_STATE_RUNNING ) {  //poll the keyboard
95
        rcode = mouse_poll();
96
        if( rcode ) {
97
          Serial.print("Mouse Poll Error: ");
98
          Serial.println( rcode, HEX );
99
        }//if( rcode...
100
    }//if( Usb.getUsbTaskState() == USB_STATE_RUNNING...
101
    //Serial.println( armdata.gripper_servo, DEC );
102
}
103
 
104
/* Initialize mouse */
105
void mouse_init( void )
106
{
107
 byte rcode = 0;  //return code
108
  /**/
109
  Usb.setDevTableEntry( 1, Usb.getDevTableEntry( 0,0 ) );              //copy device 0 endpoint information to device 1
110
  /* Configure device */
111
  rcode = Usb.setConf( DEVADDR, 0, CONFVALUE );
112
  if( rcode ) {
113
    Serial.print("Error configuring mouse. Return code : ");
114
    Serial.println( rcode, HEX );
115
    while(1);  //stop
116
  }//if( rcode...
117
  Usb.setUsbTaskState( USB_STATE_RUNNING );
118
  return;
119
}
120
 
121
/* Poll mouse using Get Report and fill arm data structure */
122
byte mouse_poll( void )
123
{
124
  byte rcode;
125
  char buf[ 4 ];                //mouse buffer
126
  static uint16_t delay = 500;  //delay before park
127
 
128
    /* poll mouse */
129
    rcode = Usb.getReport( DEVADDR, 0, 4, 0, 1, 0, buf );
130
    if( rcode ) {  //error
131
      return( rcode );
132
    }
133
    // todo: add arm limit check
134
    armdata.x_coord += ( buf[ 1 ] * -0.1 );
135
    armdata.y_coord += ( buf[ 2 ] * -0.1 );
136
    switch( buf[ 0 ] ) {  //read buttons
137
      case 0x00:            //no buttons pressed
138
        armdata.z_coord += ( buf[ 3 ] * -2 ) ;
139
        break;
140
      case 0x01:            //button 1 pressed. Wheel sets gripper angle
141
        armdata.gripper_servo += ( buf[ 3 ] * -20 );
142
          /* check gripper boundaries */
143
        if( armdata.gripper_servo < 1000 ) {
144
          armdata.gripper_servo = 1000;
145
        }
146
        if( armdata.gripper_servo > 2100 ) {
147
          armdata.gripper_servo = 2100;
148
        }
149
        break;
150
      case 0x02:           //button 2 pressed. Wheel sets wrist rotate
151
        armdata.wrist_rotate += ( buf[ 3 ] * -10 );
152
        /* check wrist rotate boundaries */
153
        if( armdata.wrist_rotate < 600 ) {
154
          armdata.wrist_rotate = 600;
155
        }
156
        if( armdata.wrist_rotate > 2400 ) {
157
          armdata.wrist_rotate = 2400;
158
        }
159
        break;
160
      case 0x04:          //wheel button pressed. Wheel controls gripper
161
        armdata.gripper_angle += ( buf[ 3 ] * -1 );
162
        /* check gripper angle boundaries */
163
        if( armdata.gripper_angle < -90 ) {
164
          armdata.gripper_angle = -90;
165
        }
166
        if( armdata.gripper_angle > 90 ) {
167
          armdata.gripper_angle = 90;
168
        }
169
        break;
170
      case 0x07:          //all 3 buttons pressed. Park the arm
171
        arm_park();
172
        break;
173
    }//switch( buf[ 0 ...
174
    Serial.println( armdata.wrist_rotate, DEC );
175
}
176
 
177
 
178
/* arm positioning routine utilizing inverse kinematics */
179
/* z is height, y is distance from base center out, x is side to side. y,z can only be positive */
180
//void set_arm( uint16_t x, uint16_t y, uint16_t z, uint16_t grip_angle )
181
void set_arm( float x, float y, float z, float grip_angle_d )
182
{
183
  float grip_angle_r = radians( grip_angle_d );    //grip angle in radians for use in calculations
184
  /* Base angle and radial distance from x,y coordinates */
185
  float bas_angle_r = atan2( x, y );
186
  float rdist = sqrt(( x * x ) + ( y * y ));
187
  /* rdist is y coordinate for the arm */
188
  y = rdist;
189
  /* Grip offsets calculated based on grip angle */
190
  float grip_off_z = ( sin( grip_angle_r )) * GRIPPER;
191
  float grip_off_y = ( cos( grip_angle_r )) * GRIPPER;
192
  /* Wrist position */
193
  float wrist_z = ( z - grip_off_z ) - BASE_HGT;
194
  float wrist_y = y - grip_off_y;
195
  /* Shoulder to wrist distance ( AKA sw ) */
196
  float s_w = ( wrist_z * wrist_z ) + ( wrist_y * wrist_y );
197
  float s_w_sqrt = sqrt( s_w );
198
  /* s_w angle to ground */
199
  //float a1 = atan2( wrist_y, wrist_z );
200
  float a1 = atan2( wrist_z, wrist_y );
201
  /* s_w angle to humerus */
202
  float a2 = acos((( hum_sq - uln_sq ) + s_w ) / ( 2 * HUMERUS * s_w_sqrt ));
203
  /* shoulder angle */
204
  float shl_angle_r = a1 + a2;
205
  float shl_angle_d = degrees( shl_angle_r );
206
  /* elbow angle */
207
  float elb_angle_r = acos(( hum_sq + uln_sq - s_w ) / ( 2 * HUMERUS * ULNA ));
208
  float elb_angle_d = degrees( elb_angle_r );
209
  float elb_angle_dn = -( 180.0 - elb_angle_d );
210
  /* wrist angle */
211
  float wri_angle_d = ( grip_angle_d - elb_angle_dn ) - shl_angle_d;
212
 
213
  /* Servo pulses */
214
  float bas_servopulse = 1500.0 - (( degrees( bas_angle_r )) * 11.11 );
215
  float shl_servopulse = 1500.0 + (( shl_angle_d - 90.0 ) * 6.6 );
216
  float elb_servopulse = 1500.0 -  (( elb_angle_d - 90.0 ) * 6.6 );
217
  float wri_servopulse = 1500 + ( wri_angle_d  * 11.1 );
218
 
219
  /* Set servos */
220
  servos.setposition( BAS_SERVO, ftl( bas_servopulse ));
221
  servos.setposition( WRI_SERVO, ftl( wri_servopulse ));
222
  servos.setposition( SHL_SERVO, ftl( shl_servopulse ));
223
  servos.setposition( ELB_SERVO, ftl( elb_servopulse ));
224
 
225
}
226
 
227
/* moves the arm to parking position */
228
void arm_park()
229
{
230
  set_arm( armdata.x_coord = -50, armdata.y_coord = 140, armdata.z_coord = 100, armdata.gripper_angle = 0 );
231
  servos.setposition( WRO_SERVO, armdata.wrist_rotate = 600 );
232
  servos.setposition( GRI_SERVO, armdata.gripper_servo = 900 );
233
}
234
 
235
/* move servos to parking position */
236
void servo_park()
237
{
238
  servos.setposition( BAS_SERVO, 1715 );
239
  servos.setposition( SHL_SERVO, 2100 );
240
  servos.setposition( ELB_SERVO, 2100 );
241
  servos.setposition( WRI_SERVO, 1800 );
242
  servos.setposition( WRO_SERVO, 600 );
243
  servos.setposition( GRI_SERVO, 900 );
244
  return;
245
}
246
 
247
void zero_x()
248
{
249
  for( double yaxis = 150.0; yaxis < 356.0; yaxis += 1 ) {
250
    set_arm( 0, yaxis, 127.0, 0 );
251
    delay( 10 );
252
  }
253
  for( double yaxis = 356.0; yaxis > 150.0; yaxis -= 1 ) {
254
    set_arm( 0, yaxis, 127.0, 0 );
255
    delay( 10 );
256
  }
257
}
258
 
259
/* moves arm in a straight line */
260
void line()
261
{
262
    for( double xaxis = -100.0; xaxis < 100.0; xaxis += 0.5 ) {
263
      set_arm( xaxis, 250, 100, 0 );
264
      delay( 10 );
265
    }
266
    for( float xaxis = 100.0; xaxis > -100.0; xaxis -= 0.5 ) {
267
      set_arm( xaxis, 250, 100, 0 );
268
      delay( 10 );
269
    }
270
}
271
 
272
void circle()
273
{
274
  #define RADIUS 80.0
275
  //float angle = 0;
276
  float zaxis,yaxis;
277
  for( float angle = 0.0; angle < 360.0; angle += 1.0 ) {
278
      yaxis = RADIUS * sin( radians( angle )) + 200;
279
      zaxis = RADIUS * cos( radians( angle )) + 200;
280
      set_arm( 0, yaxis, zaxis, 0 );
281
      delay( 1 );
282
  }
283
}
284