Compare commits

..

3 Commits

Author SHA1 Message Date
d18f125995 first draft of submission 2023-12-04 17:56:13 +00:00
d68eb0fa95 update gitignore 2023-12-04 17:55:41 +00:00
e188f0f2f4 update c mac steppers to take args and remove windows.h 2023-12-04 17:54:36 +00:00
7 changed files with 318 additions and 86 deletions

1
.gitignore vendored
View File

@@ -1 +1,2 @@
out out
plots

View File

@@ -0,0 +1,51 @@
Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)
0.000, 4.583, 21.000, 1, 218.218
0.189, 5.304, 3.828, 2, 188.528
0.347, 6.359, 6.711, 3, 157.245
0.480, 7.531, 8.822, 4, 132.785
0.596, 8.653, 9.711, 5, 115.565
0.700, 9.688, 10.023, 6, 103.223
0.794, 10.640, 10.135, 7, 93.982
0.881, 11.523, 10.175, 8, 86.781
0.962, 12.348, 10.186, 9, 80.984
1.039, 13.124, 10.185, 10, 76.195
1.112, 13.859, 10.180, 11, 72.157
1.181, 14.558, 10.172, 12, 68.693
1.247, 15.225, 10.164, 13, 65.681
1.311, 15.865, 10.156, 14, 63.031
1.372, 16.481, 10.148, 15, 60.676
1.431, 17.075, 10.141, 16, 58.566
1.488, 17.649, 10.134, 17, 56.660
1.543, 18.205, 10.128, 18, 54.929
1.597, 18.745, 10.122, 19, 53.346
1.649, 19.270, 10.117, 20, 51.893
1.700, 19.782, 10.112, 21, 50.552
1.751, 19.782, 0.000, 22, 50.552
1.802, 19.782, 0.000, 23, 50.552
1.853, 19.782, 0.000, 24, 50.552
1.904, 19.782, 0.000, 25, 50.552
1.955, 19.782, 0.000, 26, 50.552
2.006, 19.782, 0.000, 27, 50.552
2.057, 19.782, 0.000, 28, 50.552
2.108, 19.782, 0.000, 29, 50.552
2.159, 19.782, 0.000, 30, 50.552
2.210, 19.782, 0.000, 31, 50.552
2.262, 19.270, -9.853, 32, 51.894
2.316, 18.745, -9.845, 33, 53.347
2.371, 18.205, -9.835, 34, 54.930
2.428, 17.648, -9.823, 35, 56.663
2.487, 17.074, -9.810, 36, 58.570
2.548, 16.479, -9.795, 37, 60.682
2.612, 15.863, -9.778, 38, 63.040
2.678, 15.222, -9.757, 39, 65.695
2.747, 14.553, -9.732, 40, 68.714
2.820, 13.853, -9.702, 41, 72.188
2.897, 13.116, -9.665, 42, 76.244
2.979, 12.336, -9.618, 43, 81.062
3.066, 11.506, -9.556, 44, 86.914
3.161, 10.613, -9.473, 45, 94.224
3.265, 9.643, -9.355, 46, 103.703
3.382, 8.572, -9.178, 47, 116.655
3.518, 7.365, -8.889, 48, 135.770
3.686, 5.962, -8.365, 49, 167.717
3.905, 4.583, -6.323, 50, 218.218
1 Time (s) Speed (steps/s) Accel (steps/s^2) Posit'n (steps) Step time (ticks)
2 0.000 4.583 21.000 1 218.218
3 0.189 5.304 3.828 2 188.528
4 0.347 6.359 6.711 3 157.245
5 0.480 7.531 8.822 4 132.785
6 0.596 8.653 9.711 5 115.565
7 0.700 9.688 10.023 6 103.223
8 0.794 10.640 10.135 7 93.982
9 0.881 11.523 10.175 8 86.781
10 0.962 12.348 10.186 9 80.984
11 1.039 13.124 10.185 10 76.195
12 1.112 13.859 10.180 11 72.157
13 1.181 14.558 10.172 12 68.693
14 1.247 15.225 10.164 13 65.681
15 1.311 15.865 10.156 14 63.031
16 1.372 16.481 10.148 15 60.676
17 1.431 17.075 10.141 16 58.566
18 1.488 17.649 10.134 17 56.660
19 1.543 18.205 10.128 18 54.929
20 1.597 18.745 10.122 19 53.346
21 1.649 19.270 10.117 20 51.893
22 1.700 19.782 10.112 21 50.552
23 1.751 19.782 0.000 22 50.552
24 1.802 19.782 0.000 23 50.552
25 1.853 19.782 0.000 24 50.552
26 1.904 19.782 0.000 25 50.552
27 1.955 19.782 0.000 26 50.552
28 2.006 19.782 0.000 27 50.552
29 2.057 19.782 0.000 28 50.552
30 2.108 19.782 0.000 29 50.552
31 2.159 19.782 0.000 30 50.552
32 2.210 19.782 0.000 31 50.552
33 2.262 19.270 -9.853 32 51.894
34 2.316 18.745 -9.845 33 53.347
35 2.371 18.205 -9.835 34 54.930
36 2.428 17.648 -9.823 35 56.663
37 2.487 17.074 -9.810 36 58.570
38 2.548 16.479 -9.795 37 60.682
39 2.612 15.863 -9.778 38 63.040
40 2.678 15.222 -9.757 39 65.695
41 2.747 14.553 -9.732 40 68.714
42 2.820 13.853 -9.702 41 72.188
43 2.897 13.116 -9.665 42 76.244
44 2.979 12.336 -9.618 43 81.062
45 3.066 11.506 -9.556 44 86.914
46 3.161 10.613 -9.473 45 94.224
47 3.265 9.643 -9.355 46 103.703
48 3.382 8.572 -9.178 47 116.655
49 3.518 7.365 -8.889 48 135.770
50 3.686 5.962 -8.365 49 167.717
51 3.905 4.583 -6.323 50 218.218

View File

@@ -0,0 +1,51 @@
Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)
0.000, 1.000, 1.000, 1, 1000.000
0.953, 1.050, 0.052, 2, 952.500
1.858, 1.105, 0.061, 3, 905.000
2.716, 1.166, 0.071, 4, 857.500
3.526, 1.235, 0.084, 5, 810.000
4.289, 1.311, 0.101, 6, 762.500
5.004, 1.399, 0.122, 7, 715.000
5.672, 1.498, 0.149, 8, 667.500
6.292, 1.613, 0.185, 9, 620.000
6.865, 1.747, 0.234, 10, 572.500
7.390, 1.905, 0.301, 11, 525.000
7.868, 2.094, 0.397, 12, 477.500
8.298, 2.326, 0.538, 13, 430.000
8.681, 2.614, 0.755, 14, 382.500
9.016, 2.985, 1.107, 15, 335.000
9.304, 3.478, 1.715, 16, 287.500
9.544, 4.167, 2.868, 17, 240.000
9.737, 5.195, 5.341, 18, 192.500
9.882, 6.897, 11.736, 19, 145.000
9.980, 10.256, 34.460, 20, 97.500
10.030, 20.000, 194.872, 21, 50.000
10.080, 20.000, 0.000, 22, 50.000
10.130, 20.000, 0.000, 23, 50.000
10.180, 20.000, 0.000, 24, 50.000
10.230, 20.000, 0.000, 25, 50.000
10.280, 20.000, 0.000, 26, 50.000
10.330, 20.000, 0.000, 27, 50.000
10.380, 20.000, 0.000, 28, 50.000
10.430, 20.000, 0.000, 29, 50.000
10.480, 20.000, 0.000, 30, 50.000
10.578, 10.256, -99.934, 31, 97.500
10.723, 6.897, -23.171, 32, 145.000
10.916, 5.195, -8.840, 33, 192.500
11.156, 4.167, -4.284, 34, 240.000
11.444, 3.478, -2.394, 35, 287.500
11.779, 2.985, -1.472, 36, 335.000
12.162, 2.614, -0.969, 37, 382.500
12.592, 2.326, -0.672, 38, 430.000
13.070, 2.094, -0.484, 39, 477.500
13.595, 1.905, -0.361, 40, 525.000
14.168, 1.747, -0.276, 41, 572.500
14.788, 1.613, -0.216, 42, 620.000
15.456, 1.498, -0.172, 43, 667.500
16.171, 1.399, -0.139, 44, 715.000
16.934, 1.311, -0.114, 45, 762.500
17.744, 1.235, -0.095, 46, 810.000
18.602, 1.166, -0.080, 47, 857.500
19.507, 1.105, -0.068, 48, 905.000
20.460, 1.050, -0.058, 49, 952.500
21.460, 1.000, -0.050, 50, 1000.000
1 Time (s) Speed (steps/s) Accel (steps/s^2) Posit'n (steps) Step time (ticks)
2 0.000 1.000 1.000 1 1000.000
3 0.953 1.050 0.052 2 952.500
4 1.858 1.105 0.061 3 905.000
5 2.716 1.166 0.071 4 857.500
6 3.526 1.235 0.084 5 810.000
7 4.289 1.311 0.101 6 762.500
8 5.004 1.399 0.122 7 715.000
9 5.672 1.498 0.149 8 667.500
10 6.292 1.613 0.185 9 620.000
11 6.865 1.747 0.234 10 572.500
12 7.390 1.905 0.301 11 525.000
13 7.868 2.094 0.397 12 477.500
14 8.298 2.326 0.538 13 430.000
15 8.681 2.614 0.755 14 382.500
16 9.016 2.985 1.107 15 335.000
17 9.304 3.478 1.715 16 287.500
18 9.544 4.167 2.868 17 240.000
19 9.737 5.195 5.341 18 192.500
20 9.882 6.897 11.736 19 145.000
21 9.980 10.256 34.460 20 97.500
22 10.030 20.000 194.872 21 50.000
23 10.080 20.000 0.000 22 50.000
24 10.130 20.000 0.000 23 50.000
25 10.180 20.000 0.000 24 50.000
26 10.230 20.000 0.000 25 50.000
27 10.280 20.000 0.000 26 50.000
28 10.330 20.000 0.000 27 50.000
29 10.380 20.000 0.000 28 50.000
30 10.430 20.000 0.000 29 50.000
31 10.480 20.000 0.000 30 50.000
32 10.578 10.256 -99.934 31 97.500
33 10.723 6.897 -23.171 32 145.000
34 10.916 5.195 -8.840 33 192.500
35 11.156 4.167 -4.284 34 240.000
36 11.444 3.478 -2.394 35 287.500
37 11.779 2.985 -1.472 36 335.000
38 12.162 2.614 -0.969 37 382.500
39 12.592 2.326 -0.672 38 430.000
40 13.070 2.094 -0.484 39 477.500
41 13.595 1.905 -0.361 40 525.000
42 14.168 1.747 -0.276 41 572.500
43 14.788 1.613 -0.216 42 620.000
44 15.456 1.498 -0.172 43 667.500
45 16.171 1.399 -0.139 44 715.000
46 16.934 1.311 -0.114 45 762.500
47 17.744 1.235 -0.095 46 810.000
48 18.602 1.166 -0.080 47 857.500
49 19.507 1.105 -0.068 48 905.000
50 20.460 1.050 -0.058 49 952.500
51 21.460 1.000 -0.050 50 1000.000

View File

@@ -1,7 +1,6 @@
// Leib Ramp Stepper program with millis function adapted for MacOS // Leib Ramp Stepper program with millis function adapted for MacOS
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <windows.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
@@ -52,57 +51,52 @@ const float minSpeed = 1.0;
const float maxPermissSpeed = 20.0; const float maxPermissSpeed = 20.0;
const float maxAccel = 10.0; const float maxAccel = 10.0;
int main() int main(int argc, char *argv[1])
{ {
unsigned long currentMillis = millis(); unsigned long currentMillis = millis();
prevStepTime = 0; prevStepTime = 0;
long positionToMoveTo; long positionToMoveTo;
while(true) sscanf(argv[1], "%ld", &positionToMoveTo);
printf(" Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)\n");
goToPosition(positionToMoveTo);
/* -------------------------------------------------------------- */
/* Start of pre-computation code - only executed once per profile */
// STEP 1
// Define number of steps in acceleration phase using Equation (3)
accelSteps = (long)(( maxPermissSpeed * maxPermissSpeed - minSpeed * minSpeed) / ( 2.0 * (float)maxAccel)); // Equation 4 but need to consider initial speed
stepsToGo = computeStepsToGo();
maxSpeed = maxPermissSpeed;
if (2 * accelSteps > stepsToGo)
{ {
printf("Enter position to move to in profile (or 999 to terminate)\n"); // STEP 2
scanf("%ld", &positionToMoveTo); // Define maximum speed in profile and number of steps in acceleration phase
if (positionToMoveTo==999) break; // Use Equations (4) and (5)
printf(" Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)\n"); maxSpeed = sqrt(minSpeed * minSpeed + stepsToGo * maxAccel); // Modified version of eq. 5
accelSteps = (long)(stepsToGo / 2);
}
goToPosition(positionToMoveTo); // STEPS 3 and 5
// Calculate initial value of and p1 and R Set p = p1
p1 = (float)ticksPerSec / sqrt( minSpeed * minSpeed + 2 * maxAccel); // Eq 17 incorporating initial velocity
p = p1;
R = (float) maxAccel / ((float)ticksPerSec * (float)ticksPerSec); // Eq 19
ps = ((float)ticksPerSec) / maxSpeed; // STEP 4 Eq 7 in paper
/* -------------------------------------------------------------- */ /* End of pre-computation code */
/* Start of pre-computation code - only executed once per profile */ /* -------------------------------------------------------------- */
// STEP 1 millisAtStart = millis(); /* Needed only to tabulate speed vs. time */
// Define number of steps in acceleration phase using Equation (3)
accelSteps = (long)(( maxPermissSpeed * maxPermissSpeed - minSpeed * minSpeed) / ( 2.0 * (float)maxAccel)); // Equation 4 but need to consider initial speed /* Timed loop for stepping, and associated coding */
stepsToGo = computeStepsToGo(); while(stepsToGo > 0)
maxSpeed = maxPermissSpeed; {
if (2 * accelSteps > stepsToGo) currentMillis = millis();
if (currentMillis - prevStepTime >= p)
{ {
// STEP 2 moveOneStep();
// Define maximum speed in profile and number of steps in acceleration phase prevStepTime = currentMillis;
// Use Equations (4) and (5) computeNewSpeed();
maxSpeed = sqrt(minSpeed * minSpeed + stepsToGo * maxAccel); // Modified version of eq. 5
accelSteps = (long)(stepsToGo / 2);
}
// STEPS 3 and 5
// Calculate initial value of and p1 and R Set p = p1
p1 = (float)ticksPerSec / sqrt( minSpeed * minSpeed + 2 * maxAccel); // Eq 17 incorporating initial velocity
p = p1;
R = (float) maxAccel / ((float)ticksPerSec * (float)ticksPerSec); // Eq 19
ps = ((float)ticksPerSec) / maxSpeed; // STEP 4 Eq 7 in paper
/* End of pre-computation code */
/* -------------------------------------------------------------- */
millisAtStart = millis(); /* Needed only to tabulate speed vs. time */
/* Timed loop for stepping, and associated coding */
while(stepsToGo > 0)
{
currentMillis = millis();
if (currentMillis - prevStepTime >= p)
{
moveOneStep();
prevStepTime = currentMillis;
computeNewSpeed();
}
} }
} }
return 0; return 0;

View File

@@ -2,7 +2,6 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <windows.h>
#include <math.h> #include <math.h>
#include <time.h> #include <time.h>
@@ -48,50 +47,45 @@ const float minSpeed = 1.0; // in steps/s
const float maxPermissSpeed = 20.0; // in steps/s const float maxPermissSpeed = 20.0; // in steps/s
const float maxAccel = 10.0; // in steps/s^2 const float maxAccel = 10.0; // in steps/s^2
int main() int main(int argc, char *argv[])
{ {
unsigned long currentMillis = millis(); unsigned long currentMillis = millis();
prevStepTime = 0; prevStepTime = 0;
long positionToMoveTo; long positionToMoveTo;
while(true) sscanf(argv[1], "%ld", &positionToMoveTo);
printf(" Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)\n");
goToPosition(positionToMoveTo);
/* -------------------------------------------------------------- */
/* Start of pre-computation code - only executed once per profile */
float maxInterval = ((float)ticksPerSec) / minSpeed;
ps = ((float)ticksPerSec) / maxPermissSpeed;
deltaP = (maxInterval - ps) / accelSteps;
stepsToGo = computeStepsToGo();
maxSpeed = maxPermissSpeed;
if (2 * accelSteps > stepsToGo)
{ {
printf("Enter position to move to in profile (or 999 to terminate)\n"); accelSteps = (long)(stepsToGo / 2);
scanf("%ld", &positionToMoveTo); }
if (positionToMoveTo==999) break;
printf(" Time (s), Speed (steps/s), Accel (steps/s^2), Posit'n (steps), Step time (ticks)\n");
goToPosition(positionToMoveTo); p = maxInterval;
/* -------------------------------------------------------------- */ ps = ((float)ticksPerSec) / maxSpeed;
/* Start of pre-computation code - only executed once per profile */ /* End of pre-computation code */
/* -------------------------------------------------------------- */
millisAtStart = millis(); /* Needed only to tabulate speed vs. time */
float maxInterval = ((float)ticksPerSec) / minSpeed; /* Timed loop for stepping */
ps = ((float)ticksPerSec) / maxPermissSpeed; while(stepsToGo > 0)
deltaP = (maxInterval - ps) / accelSteps; {
stepsToGo = computeStepsToGo(); currentMillis = millis();
maxSpeed = maxPermissSpeed; if (currentMillis - prevStepTime >= p)
if (2 * accelSteps > stepsToGo)
{ {
accelSteps = (long)(stepsToGo / 2); moveOneStep();
} prevStepTime = currentMillis;
computeNewSpeed();
p = maxInterval;
ps = ((float)ticksPerSec) / maxSpeed;
/* End of pre-computation code */
/* -------------------------------------------------------------- */
millisAtStart = millis(); /* Needed only to tabulate speed vs. time */
/* Timed loop for stepping */
while(stepsToGo > 0)
{
currentMillis = millis();
if (currentMillis - prevStepTime >= p)
{
moveOneStep();
prevStepTime = currentMillis;
computeNewSpeed();
}
} }
} }
return 0; return 0;

View File

@@ -1,9 +1,8 @@
--- ---
author: Akbar Rahman (20386125) author: Akbar Rahman (20386125)
date: \today date: \today
title: Change Me title: MMME3085---Lab 2 Coursework
tags: [ change_me ] tags: [ mmme, mmme3086 ]
uuid: Change Me
documentclass: article documentclass: article
geometry: geometry:
- margin=1in - margin=1in
@@ -15,4 +14,146 @@ geometry:
\tableofcontents \tableofcontents
\newpage \newpage
# Header # Question 1
As you increase the proportional gain, you increase the responsiveness of the motor to error,
but it is easy to go too high and cause the motor to oscillate around the target position.
This is because the motor current is set proportional to the error.
This means that if the motor is spinning too quickly, the proportional control will not slow
down the motor in time to avoid overshoot.
Additionally, if the target position is set too close to the motor, the proportional control
maybe not push enough current to motor to actually get it spinning in some cases.
# Question 2
When derivative control is added at low levels (0.02) it reduces the oscillations.
This is because derivative control only considers the rate of change of of the error
and therefore tries to bring the rate of change to zero.
# Question 3
There are two if statements in the loop function as the controller will work best and be able to respond
to changes faster if the control functions are run more frequently.
The faster the better.
However, the Arduino does not really need to print to serial every time as it is only used to ensure
the Arduino is running properly.
If `prevMillisControl` and `prevMillisPrint` was replaced with just one variable, the `printLoop` function
would never run as the variable would have been updated to equal `currentMillis` before the print loop's
if statement will check its condition.
# Question 4
First the library is `include`d on line 4:
```c
#include <PID_V1.h>
```
Then a PID object is created using the `myPID` function on line 48.
This object holds all the properties of the PID controller including values of $K_p$, $K_i$, and $K_d$,
as well as a pointers to variables with the current motor position, speed, and set point.
```c
PID myPID(&encoderPosnMeasured, &percentSpeed, &positionSetPoint, Kp, Ki, Kd, DIRECT);
```
Some initialisation is run in `setup` on lines 89 and 90:
```c
myPID.SetOutputLimits(-100,100);
myPID.SetMode(AUTOMATIC);
```
Then the main control loop starts.
The `loop` function runs the `controlLoop` function every 20 milliseconds (as defined by
`controlInterval`) on line 101.
The `controlLoop` function retrieves the current motor position and stores it in the variable
that the PID controller has a pointer to.
`myPID.Compute()` is then called to recompute the motor speed required to get to the set point
and this is stored in the `percentSpeed` variable as the controller has a pointer to it.
This new speed is passed to the `driveMotorPercent` function to update the motor's speed.
# Question 5
The mathematically complex operations in `loop()` as it is run infrequently.
This is because it is inside an if statement with condition `convertNewNumber()`, which
returns `false` if there is no new data to convert (i.e. if there has not been any serial input
since the last loop).
Essentially, the complex operations only run once per serial input, meaning it is run very infrequently
compared to how many times the loop runs.
# Question 6
Complex operations in `computeNewSpeed()` have been avoided because this function runs very frequently
(on the order of microseconds).
Therefore it is important that the function does not consume too many processor cycles,
else the Arduino will be able to do little else.
# Question 7
If the stepper motor is run too quickly, steps will be skipped and it will not accelerate or
accelerate slowly.
It also makes a different noise to normal operation.
This is because the pole pairs of the motor will be activated too soon if attempting to spin
the motor too fast.
If they are activated too soon, they will not have the desired effect of speeding up the rotation
of the shaft, as the magnets of the motor will not be aligned as needed.
This is also why the steppers use a ramp function, so that the shaft has time accelerate to the
desired speed without skipping steps.
# Question 8
```{ .matplotlib caption="A plot of velocity and acceleration for SimplisticRampStepper" dpi=150 }
import numpy as np
import matplotlib.pyplot as plt
TIME = 'Time_s'
SPEED = 'Speed_stepss'
ACCEL = 'Accel_stepss2'
POS = 'Positn_steps'
STEP = 'Step_time_ticks'
data = np.genfromtxt("csv/SimplisticRampStepper_out_50.csv",
delimiter=",", names=True, dtype=float)
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(data[TIME], data[SPEED], label='Speed [steps/s]', color='tab:blue')
ax2.plot(data[TIME], data[ACCEL], label='Acceleration [steps/s^2]', color='tab:red')
ax1.set_ylabel('Speed [steps/s]')
ax2.set_ylabel('Acceleration [steps/s^2]')
ax1.set_xlabel("Time [s]")
fig.tight_layout()
```
```{ .matplotlib caption="A plot of velocity and acceleration for LeibRampStepper" dpi=150 }
import numpy as np
import matplotlib.pyplot as plt
TIME = 'Time_s'
SPEED = 'Speed_stepss'
ACCEL = 'Accel_stepss2'
POS = 'Positn_steps'
STEP = 'Step_time_ticks'
data = np.genfromtxt("csv/LeibRampStepper_out_50.csv",
delimiter=",", names=True, dtype=float)
fig, ax1 = plt.subplots()
ax2 = ax1.twinx()
ax1.plot(data[TIME], data[SPEED], label='Speed [steps/s]', color='tab:blue')
ax2.plot(data[TIME], data[ACCEL], label='Acceleration [steps/s^2]', color='tab:red')
ax1.set_ylabel('Speed [steps/s]')
ax2.set_ylabel('Acceleration [steps/s^2]')
ax1.set_xlabel("Time [s]")
fig.tight_layout()
```

View File

@@ -1 +1 @@
SUBMISSION_FILENAME=changeme.pdf SUBMISSION_FILENAME=mmme3086_lab2_coursework_akbar_alvi_rahman_20386125.pdf