-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFRC_Testbed_2.ino
322 lines (226 loc) · 6.73 KB
/
FRC_Testbed_2.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
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
/*
FRC Motor Controller Testbed
Written by Samuel Moore (Alumni Team 1714)
This project serves as a prototyping platform to test many
different FRC mechanisms. It can run up to four motors and
one pneumatic solenoid simultaniously, all without the
user having to write any code for their mechanisms. Each
motor is controlled via a potentiometer, and their speeds
are displayed on an I2C LiquidCrystal display.
*/
// Required libraries
#include <Wire.h> // Library for I2C communication
#include <LiquidCrystal_I2C.h> // Library for LCD
#include <Servo.h> // Library for motors
/*
Motor object declaration
NOTE: FRC motor controllers require a 50Hz PWM signal.
This can be set manualy, but I've found it easier
to set the motor controller PWM signals as Servo
objects, as most servos also use a 50Hz PWM signal.
*/
Servo motor1;
Servo motor2;
Servo motor3;
Servo motor4;
// Display object declaration
LiquidCrystal_I2C lcd = LiquidCrystal_I2C(0x27, 16, 2);
// Motor pins
const int motor1Pin = 11;
const int motor2Pin = 6;
const int motor3Pin = 5;
const int motor4Pin = 3;
// Potentiometer pins
const int potent1Pin = A0;
const int potent2Pin = A1;
const int potent3Pin = A2;
const int potent4Pin = A3;
/*
Centered variables
These are global variables that represent the state of each potentiometer
true = the potentiometer is in the center position
false = the potentiometer is not in the center position
*/
bool centered1 = false;
bool centered2 = false;
bool centered3 = false;
bool centered4 = false;
/*
Potentiometer centered value
This is the value that the potentiometer should output when in the centered position
*/
const int midValue = 1500;
// potentiometer deadzone value
int deadzone = 25;
// whether or not to force all potentiometers to be centered on startup before motors can be used
bool forceCenter = true;
// run once on startup
void setup() {
// setup serial
Serial.begin(9600);
// setup display
lcd.init();
lcd.backlight();
// set motor pins
pinMode(potent1Pin, INPUT);
pinMode(potent2Pin, INPUT);
pinMode(potent3Pin, INPUT);
pinMode(potent4Pin, INPUT);
// attach motor pins to motor objects
motor1.attach(motor1Pin);
motor2.attach(motor2Pin);
motor3.attach(motor3Pin);
motor4.attach(motor4Pin);
// force potentiometers to all be centered before moving motors
if (forceCenter == true) {
centerStartup();
}
}
// run periodically
void loop() {
// get motor speeds
int motor1Speed = getSpeed(0);
int motor2Speed = getSpeed(1);
int motor3Speed = getSpeed(2);
int motor4Speed = getSpeed(3);
// display motor speeds
displaySpeed(motor1Speed, motor2Speed, motor3Speed, motor4Speed);
// run motors at inputed speeds
drive(motor1Speed, motor2Speed, motor3Speed, motor4Speed);
}
/*
This function will read a potentiometer and map it between the motor controller PWM range with the deadband.
Inputs:
potentPin (int)
The pin number of the potentiometer
Outputs:
motorSpeed (int)
The Pulse Width Modulation (PWM) value cooresponding to the potentiometer value
*/
int getSpeed(int potentPin) {
// map potentiometer value in PWM range
int calibratedSpeed = map(analogRead(potentPin), 0, 1023, 1000, 2000);
// apply deadband
if (calibratedSpeed >= midValue - deadzone && calibratedSpeed <= midValue + deadzone) {
calibratedSpeed = midValue;
}
return calibratedSpeed;
}
/*
This function will drive all four motors at a desired speed.
Inputs:
motor1Speed (int)
PWM value sent to motor 1
motor2Speed (int)
PWM value sent to motor 2
motor3Speed (int)
PWM value sent to motor 3
motor4Speed (int)
PWM value sent to motor 4
Outputs:
none (void)
*/
void drive(int motor1Speed, int motor2Speed, int motor3Speed, int motor4Speed) {
// drive motors
motor1.writeMicroseconds(motor1Speed);
motor2.writeMicroseconds(motor2Speed);
motor3.writeMicroseconds(motor3Speed);
motor4.writeMicroseconds(motor4Speed);
// delay to keep stable PWM signal
//delay(100);
}
/*
This function will check to see if a potentiometer is in the center value.
Inputs:
potentPin (int)
The pin number of the potentiometer
Outputs:
centered (bool)
true = potentiometer is centered
false = potentiometer is not centered
*/
bool centeredCheck(int potentPin) {
// get potentiometer value
int speedCheck = getSpeed(potentPin);
// return if potentiometer is centered
return (speedCheck >= midValue - deadzone && speedCheck <= midValue + deadzone);
}
/*
This function will display the inputed PWM signal value sent to each motor.
Inputs:
motor1Speed (int)
PWM value sent to motor 1
motor2Speed (int)
PWM value sent to motor 2
motor3Speed (int)
PWM value sent to motor 3
motor4Speed (int)
PWM value sent to motor 4
Outputs:
none (void)
*/
void displaySpeed(int motor1Speed, int motor2Speed, int motor3Speed, int motor4Speed) {
// Map the values from 1000-2000 to -100 to 100
int mappedValue1 = map(motor1Speed, 1000, 2000, -100, 100);
int mappedValue2 = map(motor2Speed, 1000, 2000, -100, 100);
int mappedValue3 = map(motor3Speed, 1000, 2000, -100, 100);
int mappedValue4 = map(motor4Speed, 1000, 2000, -100, 100);
// Display value 1 in the first quadrant (top-left)
lcd.setCursor(0, 0);
lcd.print("M1: ");
lcd.setCursor(4, 0);
lcd.print(mappedValue1);
// Display value 2 in the second quadrant (top-right)
lcd.setCursor(8, 0);
lcd.print("M2: ");
lcd.setCursor(12, 0);
lcd.print(mappedValue2);
// Display value 3 in the third quadrant (bottom-left)
lcd.setCursor(0, 1);
lcd.print("M3: ");
lcd.setCursor(4, 1);
lcd.print(mappedValue3);
// Display value 4 in the fourth quadrant (bottom-right)
lcd.setCursor(8, 1);
lcd.print("M4: ");
lcd.setCursor(12, 1);
lcd.print(mappedValue4);
}
/*
This function will instruct the user to center a specific potentiometer.
Inputs:
potentPin (int)
The pin number of the potentiometer
Outputs:
none (void)
*/
void displayInstruction(int potentPin) {
lcd.setCursor(5, 0);
lcd.print("CENTER");
lcd.setCursor(0, 1);
lcd.print("POTENTIOMETER " + String(potentPin));
}
/* This function will instruct the user to center each potentiometer until all potentiometers are in the centered position.
Inputs:
none
Outputs:
none (void)
*/
void centerStartup() {
while (centeredCheck(0) == false) {
displayInstruction(1);
}
lcd.clear();
while (centeredCheck(1) == false) {
displayInstruction(2);
}
lcd.clear();
while (centeredCheck(2) == false) {
displayInstruction(3);
}
lcd.clear();
while (centeredCheck(3) == false) {
displayInstruction(4);
}
lcd.clear();
}