commit 93da0895593a66f902cbf9d23c5e354de9991665
parent 87f7d354c44ea1f57efafc929b8aa5d05f56ba57
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Sun, 7 Dec 2025 17:36:45 +0000
completed testing
Diffstat:
5 files changed, 67 insertions(+), 40 deletions(-)
diff --git a/CS12020/robot/calibrate/helper.h b/CS12020/robot/calibrate/helper.h
@@ -17,7 +17,7 @@
#define LDRB A1
#define LDRC A0
-uint8_t SERVOA_ZERO = 84;
+uint8_t SERVOA_ZERO = 83;
uint8_t SERVOB_ZERO = 85;
uint8_t SPEEDA = 10;
uint8_t SPEEDB = 10;
@@ -124,4 +124,4 @@ bool
isButtonBPressed() {
return !digitalRead(BUTTONB);
}
-#endif
-\ No newline at end of file
+#endif
diff --git a/CS12020/robot/line/Makefile b/CS12020/robot/line/Makefile
@@ -1,10 +1,10 @@
all: compile upload
upload: compile
- arduino-cli upload --fqbn arduino:avr:uno . -p /dev/ttyACM0
+ arduino-cli upload --fqbn arduino:avr:uno . -p /dev/ttyACM1
compile: line.ino
arduino-cli compile --fqbn arduino:avr:uno .
monitor:
- arduino-cli monitor -p /dev/ttyACM0 --fqbn arduino:avr:uno
+ arduino-cli monitor -p /dev/ttyACM1 --fqbn arduino:avr:uno
diff --git a/CS12020/robot/line/helper.h b/CS12020/robot/line/helper.h
@@ -81,11 +81,14 @@ SEprintf(const char *fmt, ...) {
bool
isObstacle() {
+ int readings = 0;
tone(IRTRANSMITTER, IRFREQ);
delay(5);
- bool ret = (digitalRead(IRRECEVIER) == LOW);
+ for (int i = 0; i < 100; i++) {
+ if (digitalRead(IRRECEVIER) == LOW) readings++;
+ }
noTone(IRTRANSMITTER);
- return ret;
+ return (readings >= 80);
}
bool
@@ -124,4 +127,4 @@ bool
isButtonBPressed() {
return !digitalRead(BUTTONB);
}
-#endif
-\ No newline at end of file
+#endif
diff --git a/CS12020/robot/line/line.ino b/CS12020/robot/line/line.ino
@@ -5,7 +5,7 @@
#include "reading.h"
-#define DEBUG
+#define DEBUG_OFF
#ifdef DEBUG
#define DBG(expr) expr;
@@ -17,12 +17,12 @@
#define TESTREADINGS 10
typedef struct state {
- bool left, mid, right; /* is on black */
- int rawleft, rawmid, rawright; /* raw readings from LDRS */
- enum DIRECTIONS prevDir; /* enum to store which direction we moved in last, used to error correct */
- long timeStamp; /* barcode timestamp, used to see how long it has been since we went over a barcode */
- long lastmove, lastturn; /* time the last stepmove call was made, used to turn the motor off when we stop calling the functions */
- long gstate, ystate, rstate; /*used to store the time values of the LEDs to turn them off when needed */
+ bool left, mid, right; /* is on black */
+ int rawleft, rawmid, rawright; /* raw readings from LDRS */
+ enum DIRECTIONS prevDir; /* enum to store which direction we moved in last, used to error correct */
+ long timeStamp; /* barcode timestamp, used to see how long it has been since we went over a barcode */
+ long lastmove, lastturn; /* time the last stepmove call was made, used to turn the motor off when we stop calling the functions */
+ long gstate, ystate, rstate; /*used to store the time values of the LEDs to turn them off when needed */
} state;
const char *colors[] = {"white", "black"};
@@ -36,7 +36,16 @@ const char *colors[] = {"white", "black"};
for (int i = 0; i < 2; i++) {
SEprintf("Please turn on the lights, and place the robot on a %s surface (press button A to continue)\n", colors[i]);
waitButton(BUTTONA, HIGH);
- readSensorsMean(TESTREADINGS);
+ reading r = readSensorsMean(TESTREADINGS);
+ if (strcmp(colors[i], "black") == 0) {
+ EEPROM.put(6, (uint16_t)r.left + 100);
+ EEPROM.put(10,(uint16_t)r.mid + 100);
+ EEPROM.put(14, (uint16_t)r.right + 100);
+ } else {
+ EEPROM.put(4, (uint16_t)r.left);
+ EEPROM.put(8,(uint16_t)r.mid);
+ EEPROM.put(12, (uint16_t)r.right);
+ }
SEprintf("Test complete, please turn off the lights (press button A to continue)\n");
waitButton(BUTTONA, HIGH);
@@ -75,14 +84,13 @@ const char *colors[] = {"white", "black"};
SEprintf("Testing IR sensor, please place an object infront of the IR sensor\n");
delay(5000);
for (int i = 0; i < 10; i++) {
- if (!isObstacle())
- SEprintf("Did not detect object\n");
- else {
+ if (isObstacle()) {
SEprintf("Detected object\n");
seen++;
- }
+ } else
+ SEprintf("Did not detect object\n");
- delay(READING_INTERVAL);
+ delay(1000);
}
if (seen < 8)
SEprintf("Only saw the object %d times, test failed\n", seen);
@@ -182,6 +190,7 @@ getState()
updateFlash(&s);
updateMotor(&s);
+
return &s;
}
@@ -260,10 +269,10 @@ move(state *s)
/* large adjustments */
else if (s->right) {
- s->prevDir = LFT;
+ s->prevDir = RGT;
stepTurn(RGT, s);
} else if (s->left) {
- s->prevDir = RGT;
+ s->prevDir = LFT;
stepTurn(LFT, s);
/* drive straight, nominal */
@@ -287,23 +296,18 @@ setup()
delay(3000);
setupRobot();
- /* read the calibrated values that should be in EEPROM, these values will be made by the calibrate program */
- EEPROM.get(6, LDRA_SWITCH);
- EEPROM.get(10, LDRB_SWITCH);
- EEPROM.get(14, LDRC_SWITCH);
-
/* servo speed values */
EEPROM.get(0, SERVOA_ZERO);
EEPROM.get(1, SPEEDA);
EEPROM.get(2, SERVOB_ZERO);
EEPROM.get(3, SPEEDB);
+ SEprintf("A zero: %d\nB zero: %d\nA speed: %d\nB speed: %d\n", SERVOA_ZERO, SERVOB_ZERO, SPEEDA, SPEEDB);
/* because this is static, I can modify these values to set defaults */
state *s = getState();
s->prevDir = BWD;
s->timeStamp = 0;
-
/* test all the sensors and motors */
DBG({
testLDR();
@@ -321,6 +325,10 @@ setup()
SEprintf("finished testing\n");
});
+ /* read the calibrated values that should be in EEPROM, these values will be made by the tests above program */
+ EEPROM.get(6, LDRA_SWITCH);
+ EEPROM.get(10, LDRB_SWITCH);
+ EEPROM.get(14, LDRC_SWITCH);
}
void
@@ -345,4 +353,4 @@ loop()
/* normal movement */
else move(s);
-}
-\ No newline at end of file
+}
diff --git a/CS12020/robot/report/writeup/writeup.tex b/CS12020/robot/report/writeup/writeup.tex
@@ -28,12 +28,12 @@
\section{How does the robot work?}
I designed my system around the idea of repeatedly polling the sensors, and adjusting the motors based on the input, I made functions called \lstinline{stepMove} and \lstinline{stepTurn} which each moved or turned the robot a small amount. These function ran in a very short amount of time, allowing them to be called as often as possible, letting me read the sensors more often. This aloud me to make my robot react to changes, such as going off course or touching the barcode, a lot faster than if I halted the program while the robot moved. Thanks to this I didn't have to worry about distances or angles in my code, as I could tell the robot to keep moving until something happened.
-The sensors were polled by a function called \lstinline{getState}, which would be called as often as possible and updated the readings of the sensors in the robot, and updated the state of the motors depending on how long they had be turned on for. My step function worked by storing a time stamp of when they were called (using \lstinline{millis}), then every time the get state function was called, I could see if it had been over 19 milliseconds since the motors had been told to move, if it had been, I could turn them off. The reason I did this was to avoid the need to turn the motors off in my behavior functions and line following functions, as having that in them, would have made them more complex than they needed to be.
+The sensors were polled by a function called \lstinline{getState}, which would be called as often as possible and updated the readings of the sensors in the robot, and updated the state of the motors depending on how long they had be turned on for. My step function worked by storing a time stamp of when they were called (using \lstinline{millis}), then every time the get state function was called, I could see if it had been over 19 milliseconds since the motors had been told to move, if it had been, I could turn them off. The reason I did this was to avoid the need to turn the motors off in my behaviour functions and line following functions, as having that in them, would have made them more complex than they needed to be.
-These functions were used to create a line following function, 2 behavior functions and a barcode detection function. They are all called from the Arduino's loop function, allowing them to be called as often as possible.
+These functions were used to create a line following function, 2 behaviour functions and a barcode detection function. They are all called from the Arduino's loop function, allowing them to be called as often as possible.
\subsection{What went well?}
-I was very happy with the robots attraction and avoidance behaviors, they both worked very well, and were reliable. The LED state functioned as expected, flashing repeatedly, this worked in a similar way to the motors, checking when the last call was made to flash the LED, allowing the code to spend more time on the sensors readings than the state of the LED.
+I was very happy with the robots attraction and avoidance behaviours, they both worked very well, and were reliable. The LED state functioned as expected, flashing repeatedly, this worked in a similar way to the motors, checking when the last call was made to flash the LED, allowing the code to spend more time on the sensors readings than the state of the LED.
I was also happy with my use of a state \lstinline{struct} to hold all of the robots internal values, thanks to this my robot used almost no global variables. I declared it as \lstinline{static} inside of the \lstinline{getState} function, this meant that I could reassign the state variable in my \lstinline{loop} function, while not losing data, such as LED flash state.
@@ -263,7 +263,7 @@ This code makes use of function pointers, this is to avoid over indenting the co
\end{minipage}
\noindent\begin{minipage}{\textwidth}
- The avoidance and attraction behaviors are both very similar, just having inverted directions, they work by comparing the raw values of the LDRs, meaning they should work in many light conditions.
+ The avoidance and attraction behaviours are both very similar, just having inverted directions, they work by comparing the raw values of the LDRs, meaning they should work in many light conditions.
\begin{verbatim}
void
@@ -377,7 +377,7 @@ The EEPROM was fairly easy to implement, my code only relied on the black calibr
void
setup()
{
- /* let the user attach the battery, attaching the battery while code is running caused strange behavior */
+ /* let the user attach the battery, attaching the battery while code is running caused strange behaviour */
delay(3000);
setupRobot();
@@ -398,8 +398,8 @@ setup()
\section{Testing}
\begin{table}[H]
- \resizebox{\textwidth}{!}{
- \begin{tabular}{|| l | p{0.6\textwidth} | r ||}
+ \resizebox{\linewidth}{!}{
+ \begin{tabular}{|| l | p{0.6\linewidth} | p{0.4\linewidth} ||}
\hline
\textbf{Test} & \textbf{Method} & \textbf{Result} \\
\hline
@@ -428,10 +428,29 @@ setup()
I made a function called \lstinline{testLDRS} that asks the user to place the robot on different colours and in different lighting conditions, then takes many readings, the user can then compares these to expected values for the input. &
Pass \\
\hline
+ \hline
+ Object avoidance &
+ To test the object avoidance, I simply used the robot repeatedly, in a variety of lighting conditions, and confirmed that the robot stops and that the orange LED turns on. I ran this test 10 times, with the object \~10cm away from the robot. &
+ 8 / 10 Passed. 2 times resulted in robot entering attraction behaviour due to detecting shadow from object \\
+ \hline
+ Line following &
+ To test the line following, I placed the robot on the start of the line, and turned it on, I then saw if the robot was able to follow a straight black line. I repeated this 10 times. &
+ 7 / 10 Passed. The robot sometimes has issues when travelling over barcodes if it doesn't go straight on, as this causes it to act as if it is on the line diagonally. \\
+ \hline
+ Barcode reading &
+ To test the barcode reading, I let the robot run over the 2 types of barcode 10 times each, and recorded how many times it was able to determine the correct type of barcode. For this test I repeated it if the robot failed to follow the line, as this was to test if the robot could read the barcode, not follow the line. &
+ 9 / 10 Passed for long barcode.
+ 8 / 10 Passed for short barcode.
+ All the times this test failed, was because the robot was detecting the other kind of barcode, this is most likely due to the reading being based on time since last line, causing a slow travel to detect as the long barcode, and vice versa. \\
+ \hline
+ Light attraction and avoidance &
+ To test the light attraction and avoidance, I modified my program to put the robot straight into these modes, I then used my phones flashlight to see if the robot did the expected behaviour. I repeated this 10 times for each behaviour and assessed it based on how well it worked. &
+ All 10 times were consistent for each behaviour, however I found while the robot was turning that it wasn't very smooth, I am not sure why this is, as turning in the line following behaviour was smooth, this did not effect its ability to move towards or away from the light. \\
+ \hline
\end{tabular}
}
\end{table}
While testing my robot, I found a few issues of note. For example, while testing the IR sensor, it was always seeing something, even when nothing was present in front of it. I found this was because it was pointing inwards slightly, after turning it to face outwards, it started working as expected. I also found issues while testing with the LDRs, my testing program was receiving somewhat random offsets. I realised this was because I had not assigned the starting values to 0, so I was reading memory garbage.
-\End{document}
+\end{document}