forked from MoebiusTech/MecanumRobot-ArduinoMega2560
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMecanumRobotPS2Control.ino
232 lines (199 loc) · 7.5 KB
/
MecanumRobotPS2Control.ino
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
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
// NOTE: requires the Encoder library.
// 1) open Tools -> Manage Libraries...
// 2) install "Encoder" by Paul Stoffregen v1.4.1
#include <Encoder.h>
// NOTE: Requires the PS2X_lib installed.
// 1) open Sketch -> Include Library -> Add .ZIP Library
// 2) select "PS2X_lib.zip"
#include <PS2X_lib.h>
//PS2
#define PS2_DAT 52 //14
#define PS2_CMD 51 //15
#define PS2_SEL 53 //16
#define PS2_CLK 50 //17
// #define pressures true
#define pressures false
#define rumble true
//#define rumble false
PS2X ps2x; // create PS2 Controller Class
int error = 0;
byte type = 0;
byte vibrate = 0;
void (* resetFunc) (void) = 0;
// --- SPD Motor ---
class SPDMotor {
public:
SPDMotor( int encoderA, int encoderB, bool encoderReversed, int motorPWM, int motorDir1, int motorDir2 );
/// Set the PWM speed and direction pins.
/// pwm = 0, stop (no active control)
/// pwm = 1 to 255, proportion of CCW rotation
/// pwm = -1 to -255, proportion of CW rotation
void speed( int pwm );
/// Activate a SHORT BRAKE mode, which shorts the motor drive EM, clamping motion.
void hardStop();
/// Get the current speed.
int getSpeed();
/// Get the current rotation position from the encoder.
long getEncoderPosition();
private:
Encoder *_encoder;
bool _encoderReversed;
int _motorPWM, _motorDir1, _motorDir2;
// Current speed setting.
int _speed;
};
SPDMotor::SPDMotor( int encoderA, int encoderB, bool encoderReversed, int motorPWM, int motorDir1, int motorDir2 ) {
_encoder = new Encoder(encoderA, encoderB);
_encoderReversed = encoderReversed;
_motorPWM = motorPWM;
pinMode( _motorPWM, OUTPUT );
_motorDir1 = motorDir1;
pinMode( _motorDir1, OUTPUT );
_motorDir2 = motorDir2;
pinMode( _motorDir2, OUTPUT );
}
/// Set the PWM speed and direction pins.
/// pwm = 0, stop (no active control)
/// pwm = 1 to 255, proportion of CCW rotation
/// pwm = -1 to -255, proportion of CW rotation
void SPDMotor::speed( int speedPWM ) {
_speed = speedPWM;
if( speedPWM == 0 ) {
digitalWrite(_motorDir1,LOW);
digitalWrite(_motorDir2,LOW);
analogWrite( _motorPWM, 255);
} else if( speedPWM > 0 ) {
digitalWrite(_motorDir1, LOW );
digitalWrite(_motorDir2, HIGH );
analogWrite( _motorPWM, speedPWM < 255 ? speedPWM : 255);
} else if( speedPWM < 0 ) {
digitalWrite(_motorDir1, HIGH );
digitalWrite(_motorDir2, LOW );
analogWrite( _motorPWM, (-speedPWM) < 255 ? (-speedPWM): 255);
}
}
/// Activate a SHORT BRAKE mode, which shorts the motor drive EM, clamping motion.
void SPDMotor::hardStop() {
_speed = 0;
digitalWrite(_motorDir1,HIGH);
digitalWrite(_motorDir2,HIGH);
analogWrite( _motorPWM, 0);
}
/// Get the current speed.
int SPDMotor::getSpeed() {
return _speed;
}
/// Get the current rotation position from the encoder.
long SPDMotor::getEncoderPosition() {
long position = _encoder->read();
return _encoderReversed ? -position : position;
}
SPDMotor *motorLF = new SPDMotor(18, 31, true, 12, 34, 35); // <- Encoder reversed to make +position measurement be forward.
SPDMotor *motorRF = new SPDMotor(19, 38, false, 8, 36, 37); // <- NOTE: Motor Dir pins reversed for opposite operation
SPDMotor *motorLR = new SPDMotor( 3, 49, true, 9, 43, 42); // <- Encoder reversed to make +position measurement be forward.
SPDMotor *motorRR = new SPDMotor( 2, 23, false, 5, 27, 26); // <- NOTE: Motor Dir pins reversed for opposite operation
void setup()
{
Serial.begin(9600);
delay(300) ;//added delay to give wireless ps2 module some time to startup, before configuring it
//CHANGES for v1.6 HERE!!! **************PAY ATTENTION*************
//setup pins and settings: GamePad(clock, command, attention, data, Pressures?, Rumble?) check for error
error = ps2x.config_gamepad(PS2_CLK, PS2_CMD, PS2_SEL, PS2_DAT, pressures, rumble);
if (error == 0) {
Serial.println("Found Controller, configuration successful ");
Serial.println();
Serial.println("SPDMotor control by Aaron Hilton of Steampunk Digital");
Serial.println("=====================================================");
Serial.println("Holding L1 or R1 will activate analog joystick control.");
Serial.println("Left analog stick for forward/back and turning.");
Serial.println("Right analog stick for sideways movement.");
Serial.println("Hold both L1 and R1 for full-speed.");
}
else if (error == 1)
{
Serial.println("No controller found, check PS2 receiver is inserted the correct way around.");
resetFunc();
}
else if (error == 2)
Serial.println("Controller found but not accepting commands.");
else if (error == 3)
Serial.println("Controller refusing to enter Pressures mode, may not support it. ");
type = ps2x.readType();
switch (type) {
case 0:
Serial.println("Unknown Controller type found ");
break;
case 1:
Serial.println("DualShock Controller found ");
break;
case 2:
Serial.println("GuitarHero Controller found ");
break;
case 3:
Serial.println("Wireless Sony DualShock Controller found ");
break;
}
}
void loop() {
if (error == 1) //skip loop if no controller found
return;
if (type == 2) { //Guitar Hero Controller
return;
}
else { //DualShock Controller
static long oldSumPosition = 0;
long sumPosition = motorLF->getEncoderPosition() + motorRF->getEncoderPosition() + motorLR->getEncoderPosition() + motorRR->getEncoderPosition();
long deltaPosition = sumPosition - oldSumPosition;
oldSumPosition = sumPosition;
Serial.print("∆pos: ");
Serial.print(deltaPosition);
long posVibrate = abs(deltaPosition);
posVibrate = posVibrate > 255 ? 255 : 0;
vibrate = (byte)posVibrate;
ps2x.read_gamepad(false, vibrate); //read controller and set large motor to spin at 'vibrate' speed
if (ps2x.Button(PSB_L1) || ps2x.Button(PSB_R1)) {
int LY = ps2x.Analog(PSS_LY);
int LX = ps2x.Analog(PSS_LX);
int RX = ps2x.Analog(PSS_RX);
float forwardNormalized = (float)(-LY + 128)/127.f;
forwardNormalized = constrain( forwardNormalized, -1.f, 1.f );
float multiplier = (ps2x.Button(PSB_L1) && ps2x.Button(PSB_R1)) ? 255.f : 80.f;
int forward = (int)(pow(forwardNormalized, 2.0) * multiplier);
// Preserve the direction of movement.
if( forwardNormalized < 0 ) {
forward = -forward;
}
int right = -RX + 127;
int ccwTurn = (LX - 127)/2;
Serial.print( " fwd:" );
Serial.print( forward );
Serial.print( " r:" );
Serial.print( right );
Serial.print( " ∆°:" );
Serial.print( ccwTurn );
Serial.print( " LF:" );
Serial.print( motorLF->getEncoderPosition() );
Serial.print( " RF:" );
Serial.print( motorRF->getEncoderPosition() );
Serial.print( " LR:" );
Serial.print( motorLR->getEncoderPosition() );
Serial.print( " RR:" );
Serial.println( motorRR->getEncoderPosition() );
motorLF->speed(forward + ccwTurn - right); motorRF->speed(forward - ccwTurn + right);
motorLR->speed(forward - ccwTurn - right); motorRR->speed(forward + ccwTurn + right);
} else {
// If there's motor power, try to hard-stop briefly.
if( motorLF->getSpeed() != 0
|| motorRF->getSpeed() != 0
|| motorLR->getSpeed() != 0
|| motorRR->getSpeed() != 0 )
{
motorLF->hardStop(); motorRF->hardStop();
motorLR->hardStop(); motorRR->hardStop();
delay(500);
motorLF->speed(0); motorRF->speed(0);
motorLR->speed(0); motorRR->speed(0);
}
}
}
}