first draft of submission
This commit is contained in:
@@ -1,9 +1,8 @@
|
||||
---
|
||||
author: Akbar Rahman (20386125)
|
||||
date: \today
|
||||
title: Change Me
|
||||
tags: [ change_me ]
|
||||
uuid: Change Me
|
||||
title: MMME3085---Lab 2 Coursework
|
||||
tags: [ mmme, mmme3086 ]
|
||||
documentclass: article
|
||||
geometry:
|
||||
- margin=1in
|
||||
@@ -15,4 +14,146 @@ geometry:
|
||||
\tableofcontents
|
||||
\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()
|
||||
```
|
||||
|
||||
Reference in New Issue
Block a user