-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathStudentsRobot.cpp
232 lines (216 loc) · 7.32 KB
/
StudentsRobot.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
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
/*
* StudentsRobot.cpp
*
* Created on: Dec 28, 2018
* Author: hephaestus
* Author: Kevin Harrington
* Author: Matthew Bowers
*
*/
#include "StudentsRobot.h"
StudentsRobot::StudentsRobot(PIDMotor * motor1,
PIDMotor * motor2, PIDMotor * motor3) {
Serial.println("StudentsRobot::StudentsRobot constructor called here ");
this->motor1 = motor1;
this->motor2 = motor2;
this->motor3 = motor3;
// Set the PID Clock gating rate. The PID must be 10 times slower than the motors update rate
motor1->myPID.sampleRateMs = 1; //
motor2->myPID.sampleRateMs = 1; //
motor3->myPID.sampleRateMs = 1; // 10khz H-Bridge, 0.1ms update, 1 ms PID
// Set default P.I.D gains
motor1->myPID.setpid(0.1, 0.4, 30);
motor2->myPID.setpid(0.015, 0, 0);
motor3->myPID.setpid(0.015, 0, 0);
motor1->velocityPID.setpid(0.1, 0, 0);
motor2->velocityPID.setpid(0.1, 0, 0);
motor3->velocityPID.setpid(0.1, 0, 0);
// compute ratios and bounding
double motorToWheel = 3;
motor1->setOutputBoundingValues(-255, //the minimum value that the output takes (Full reverse)
255, //the maximum value the output takes (Full forward)
0, //the value of the output to stop moving
126, //a positive value subtracted from stop value to creep backward
126, //a positive value added to the stop value to creep forwards
100, // 100 Cent-Degrees per degree
876, // measured max degrees per second
150 // the speed in degrees per second that the motor spins when the hardware output is at creep forwards
);
motor2->setOutputBoundingValues(-255, //the minimum value that the output takes (Full reverse)
255, //the maximum value the output takes (Full forward)
0, //the value of the output to stop moving
44, //a positive value subtracted from stop value to creep backward
44, //a positive value added to the stop value to creep forwards
100, // 100 Cent-Degrees per degree
480, // measured max degrees per second
150 // the speed in degrees per second that the motor spins when the hardware output is at creep forwards
);
motor3->setOutputBoundingValues(-255, //the minimum value that the output takes (Full reverse)
255, //the maximum value the output takes (Full forward)
0, //the value of the output to stop moving
44, //a positive value subtracted from stop value to creep backward
44, //a positive value added to the stop value to creep forwards
100, // 100 Cent-Degrees per degree
1400, // measured max degrees per second
50 // the speed in degrees per second that the motor spins when the hardware output is at creep forwards
);
// Set up the line tracker
//pinMode(ANALOG_SENSE_ONE, ANALOG);
//pinMode(ANALOG_SENSE_TWO, ANALOG);
}
/**
* Separate from running the motor control,
* update the state machine for running the final project code here
*/
void StudentsRobot::updateStateMachine() {
long now = millis();
switch (status) {
case StartupRobot:
//Do this once at startup
status = StartRunning;
Serial.println("StudentsRobot::updateStateMachine StartupRobot here ");
break;
case StartRunning:
Serial.println("Start Running");
// Start an interpolation of the motors
// motor1->startInterpolationDegrees(1080, 6000, SIN);
// motor2->startInterpolationDegrees(1080, 6000, SIN);
// motor3->startInterpolationDegrees(1080, 6000, SIN);
status = sample_pid; // set the state machine to wait for the motors to finish
nextStatus = Running; // the next status to move to when the motors finish
startTime = now + 1000; // the motors should be done in 1000 ms
nextTime = startTime + 1000; // the next timer loop should be 1000ms after the motors stop
break;
case Running:
// Set up a non-blocking 1000 ms delay
status = WAIT_FOR_TIME;
nextTime = nextTime + 1000; // ensure no timer drift by incremeting the target
// After 1000 ms, come back to this state
nextStatus = Running;
break;
case sample_pid:
status = WAIT_FOR_TIME;
nextTime = nextTime + 50; // ensure no timer drift by incremeting the target
// After 1000 ms, come back to this state
// if(isLessThan3rev()){
// sampleAndStore();
// nextStatus = sample_pid;
// }else
nextStatus = Running;
break;
case WAIT_FOR_TIME:
// Check to see if enough time has elapsed
if (nextTime <= millis()) {
// if the time is up, move on to the next state
status = nextStatus;
}
break;
case WAIT_FOR_MOTORS_TO_FINNISH:
if (motor1->isInterpolationDone() && motor2->isInterpolationDone()
&& motor3->isInterpolationDone()) {
status = nextStatus;
}
break;
case Halting:
// save state and enter safe mode
Serial.println("Halting State machine");
//digitalWrite(H_BRIDGE_ENABLE, 0); // Disable and idle motors
motor3->stop();
motor2->stop();
motor1->stop();
status = Halt;
break;
case Halt:
// in safe mode
break;
}
}
/**
* This is run fast and should return fast
*
* You call the PIDMotor's loop function. This will update the whole motor control system
* This will read from the conceder and write to the motors and handle the hardware interface.
* Instead of allowing this to be called by the controller you may call these from a timer interrupt.
*/
void StudentsRobot::pidLoop() {
motor1->loop();
motor2->loop();
motor3->loop();
}
/**
* Approve
*
* @param buffer A buffer of floats containing nothing
*
* the is the event of the Approve button pressed in the GUI
*
* This function is called via coms.server() in:
* @see RobotControlCenter::fastLoop
*/
void StudentsRobot::Approve(float * buffer) {
// approve the procession to new state
Serial.println("StudentsRobot::Approve");
if (myCommandsStatus == Waiting_for_approval_to_pickup) {
myCommandsStatus = Waiting_for_approval_to_dropoff;
} else {
myCommandsStatus = Ready_for_new_task;
}
}
/**
* ClearFaults
*
* @param buffer A buffer of floats containing nothing
*
* this represents the event of the clear faults button press in the gui
*
* This function is called via coms.server() in:
* @see RobotControlCenter::fastLoop
*/
void StudentsRobot::ClearFaults(float * buffer) {
// clear the faults somehow
Serial.println("StudentsRobot::ClearFaults");
myCommandsStatus = Ready_for_new_task;
status = Running;
}
/**
* EStop
*
* @param buffer A buffer of floats containing nothing
*
* this represents the event of the EStop button press in the gui
*
* This is called whrn the estop in the GUI is pressed
* All motors shuld hault and lock in position
* Motors should not go idle and drop the plate
*
* This function is called via coms.server() in:
* @see RobotControlCenter::fastLoop
*/
void StudentsRobot::EStop(float * buffer) {
// Stop the robot immediatly
Serial.println("StudentsRobot::EStop");
myCommandsStatus = Fault_E_Stop_pressed;
status = Halting;
}
/**
* PickOrder
*
* @param buffer A buffer of floats containing the pick order data
*
* buffer[0] is the material, aluminum or plastic.
* buffer[1] is the drop off angle 25 or 45 degrees
* buffer[2] is the drop off position 1, or 2
*
* This function is called via coms.server() in:
* @see RobotControlCenter::fastLoop
*/
void StudentsRobot::PickOrder(float * buffer) {
float pickupMaterial = buffer[0];
float dropoffAngle = buffer[1];
float dropoffPosition = buffer[2];
Serial.println(
"StudentsRobot::PickOrder Recived from : " + String(pickupMaterial)
+ " " + String(dropoffAngle) + " "
+ String(dropoffPosition));
myCommandsStatus = Waiting_for_approval_to_pickup;
}