commit b22cd9412c2a552b39bd8559c016b82d111ee4c5
parent 0a22b16a61820cb73642b36734b2b28582a89df8
Author: thing1 <thing1@seacrossedlovers.xyz>
Date: Tue, 25 Nov 2025 16:54:19 +0000
made a calibrator for the robot, and let the robot read the eeprom for the values :)
Diffstat:
6 files changed, 392 insertions(+), 31 deletions(-)
diff --git a/CS12020/robot/calibrate/Makefile b/CS12020/robot/calibrate/Makefile
@@ -0,0 +1,10 @@
+all: compile upload
+
+upload: compile
+ arduino-cli upload --fqbn arduino:avr:uno . -p /dev/ttyACM0
+
+compile: calibrate.ino
+ arduino-cli compile --fqbn arduino:avr:uno .
+
+monitor:
+ arduino-cli monitor -p /dev/ttyACM0
diff --git a/CS12020/robot/calibrate/calibrate.ino b/CS12020/robot/calibrate/calibrate.ino
@@ -1,7 +1,22 @@
+#include <EEPROM.h>
+#include <stdint.h>
+#include "helper.h"
void
setup() {
+ Serial.begin(9600);
+ SEprintf("expecting to be on black\n");
+ delay(3000);
+ while (isLDRBright(LDRA)) LDRA_SWITCH++;
+ while (isLDRBright(LDRB)) LDRB_SWITCH++;
+ while (isLDRBright(LDRC)) LDRC_SWITCH++;
+
+ SEprintf("%d, %d, %d", LDRA_SWITCH + 100, LDRB_SWITCH + 100, LDRC_SWITCH + 100);
+
+ writeuint16(LDRA_SWITCH + 100, 6);
+ writeuint16(LDRB_SWITCH + 100, 10);
+ writeuint16(LDRB_SWITCH + 100, 14);
}
void
diff --git a/CS12020/robot/calibrate/helper.h b/CS12020/robot/calibrate/helper.h
@@ -0,0 +1,158 @@
+#include <Servo.h>
+#include <stdint.h>
+#include <EEPROM.h>
+
+#define GREEN_LED 7
+#define YELLOW_LED 12
+#define RED_LED 13
+
+#define BUTTONA 4
+#define BUTTONB 2
+
+#define SERVOA_PIN 6
+#define SERVOB_PIN 5
+
+#define LDRA A2
+#define LDRB A1
+#define LDRC A0
+
+#define SERVOA_ZERO 96
+#define SERVOB_ZERO 96
+#define ANALOG_MAX 1023
+
+#define IRTRANSMITTER 3
+#define IRRECEVIER 2
+
+#define IRFREQ 38000
+
+uint16_t LDRA_SWITCH = 0;
+uint16_t LDRB_SWITCH = 0;
+uint16_t LDRC_SWITCH = 0;
+
+#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
+
+enum DIRECTIONS {
+ FWD = 1,
+ BWD = -1,
+ LFT = -2,
+ RGT = 2
+};
+
+Servo servoA;
+Servo servoB;
+
+void
+setupRobot() {
+ Serial.begin(9600);
+ pinMode(GREEN_LED, OUTPUT);
+ pinMode(YELLOW_LED, OUTPUT);
+ pinMode(RED_LED, OUTPUT);
+ pinMode(BUTTONA, INPUT);
+ pinMode(BUTTONB, INPUT);
+ pinMode(SERVOA_PIN, OUTPUT);
+ pinMode(SERVOB_PIN, OUTPUT);
+ pinMode(LDRA, INPUT);
+ pinMode(LDRB, INPUT);
+ pinMode(LDRC, INPUT);
+ pinMode(IRTRANSMITTER, OUTPUT);
+ pinMode(IRRECEVIER, INPUT);
+ servoA.attach(SERVOA_PIN);
+ servoB.attach(SERVOB_PIN);
+ servoA.write(SERVOA_ZERO);
+ servoB.write(SERVOB_ZERO);
+}
+
+void
+writeuint16(uint16_t num, int start) {
+ uint8_t n[2] = {0};
+ memcpy(n, &num, 2);
+
+ EEPROM.update(start, n[0]);
+ EEPROM.update(start + 1, n[1]);
+}
+
+uint16_t
+readuint16(int start) {
+ uint8_t n[2] = {0};
+ uint16_t num = 0;
+
+ n[0] = EEPROM.read(start);
+ n[1] = EEPROM.read(start + 1);
+
+ memcpy(&num, n, 2);
+ return num;
+}
+
+void
+SEprintf(const char *fmt, ...) {
+ static char sbuf[64] = { 0 };
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(sbuf, 64, fmt, ap);
+ va_end(ap);
+
+ Serial.print(sbuf);
+}
+
+
+bool
+isObstacle() {
+ tone(IRTRANSMITTER, IRFREQ);
+ bool ret = (digitalRead(IRRECEVIER) == LOW);
+ noTone(IRTRANSMITTER);
+ return ret;
+}
+
+bool
+isLDRBright(int pin) {
+ int v = analogRead(pin);
+ switch (pin) {
+ case LDRA:
+ return (v > LDRA_SWITCH);
+ case LDRB:
+ return (v > LDRB_SWITCH);
+ case LDRC:
+ return (v > LDRC_SWITCH);
+ }
+}
+
+void
+setLEDs(int g, int y, int r) {
+ digitalWrite(GREEN_LED, g);
+ digitalWrite(YELLOW_LED, y);
+ digitalWrite(RED_LED, r);
+}
+
+void
+waitButton(int pin, int state) {
+ while (digitalRead(pin) == state) ;
+}
+
+void
+stepMove(int dir) {
+ servoA.write(SERVOA_ZERO + (6 * dir));
+ servoB.write(SERVOB_ZERO - (6 * dir));
+ delay(10);
+ servoA.write(SERVOA_ZERO);
+ servoB.write(SERVOB_ZERO);
+}
+
+void
+stepTurn(int dir) {
+ servoA.write(SERVOA_ZERO + (10 * dir));
+ servoB.write(SERVOB_ZERO - (10 * -dir));
+ delay(10);
+ servoA.write(SERVOA_ZERO);
+ servoB.write(SERVOB_ZERO);
+}
+
+bool
+isButtonAPressed() {
+ return !digitalRead(BUTTONA);
+}
+
+bool
+isButtonBPressed() {
+ return !digitalRead(BUTTONB);
+}
diff --git a/CS12020/robot/line/2 b/CS12020/robot/line/2
@@ -0,0 +1,134 @@
+#include "helper.h"
+
+#define DEBUG
+
+#ifdef DEBUG
+#define DBG(expr) expr;
+#else
+#define DBG(expr)
+#endif
+
+typedef struct state {
+ bool left, mid, right;
+ int rawleft, rawmid, rawright;
+ short prevDir;
+ long timeStamp;
+} state;
+
+state *
+getState() {
+ static state s;
+ s.left = !isLDRBright(LDRA);
+ s.mid = !isLDRBright(LDRB);
+ s.right = !isLDRBright(LDRC);
+ s.rawleft = analogRead(LDRA);
+ s.rawmid =
+ s.rawright =
+
+ setLEDs(s.left, s.mid, s.right);
+ return &s;
+}
+
+void
+stepAvoidanceBehave(state *s) {
+ DBG({Serial.println("avoid");});
+}
+
+
+void
+stepAttractionBehave(state *s) {
+ DBG({Serial.println("avoid");});
+
+ /*
+ if (s->rawleft > s->rawright + 300)
+ stepTurn(LFT);
+
+ else if (s->rawright > s->rawleft + 300)
+ stepTurn(RGT);
+ else
+ stepMove(FWD);
+ */
+}
+
+void
+runBehave(void (*stepBehave)(state *)) {
+ while (true) {
+ state *s = getState();
+ stepBehave(s);
+ }
+}
+
+void
+checkBarcode(state *s) {
+ long t = millis();
+ if (s->timeStamp > 500) {
+ /* long barcode */
+ if ((t - s->timeStamp) > 3000)
+ runBehave(&stepAvoidanceBehave);
+
+ /* short barcode */
+ else if ((t - s->timeStamp) > 800)
+ runBehave(&stepAttractionBehave);
+ }
+ s->timeStamp = t;
+}
+
+void
+move(state *s) {
+ /* small adjustments */
+ if (s->right && s->mid)
+ stepTurn(LFT);
+ else if (s->left && s->mid)
+ stepTurn(RGT);
+ /* large adjustments */
+ else if (s->right) {
+ s->prevDir = LFT;
+ stepTurn(RGT);
+ } else if (s->left) {
+ s->prevDir = RGT;
+ stepTurn(LFT);
+ /* drive straight, nominal */
+ } else if (s->mid) {
+ for (int i = 0; i < 20; i++)
+ stepMove(FWD);
+ } else {
+ /* try to recover from not being on the line by moving in the prevDir */
+ while (!s->mid) {
+ getState();
+ stepTurn(s->prevDir);
+ }
+ }
+}
+
+void
+setup() {
+ delay(3000);
+ setupRobot();
+
+ /* because this is static, I can modify these values to set defaults */
+ state *s = getState();
+ s->prevDir = BWD;
+ s->timeStamp = 0;
+
+ LDRA_SWITCH = readuint16(6);
+ LDRB_SWITCH = readuint16(10);
+ LDRC_SWITCH = readuint16(14);
+}
+
+void
+loop() {
+ state *s = getState();
+
+ /* do nothing while there is an obstacle */
+ while (isObstacle())
+ return;
+
+ if (s->right && s->left && s->mid) {
+ checkBarcode(s);
+ /* run through the barcode */
+ for (int i = 0; i < 20; i++)
+ stepMove(FWD);
+ }
+ /* don't do any turns when on a the barcode, go straight */
+ else move(s);
+}
diff --git a/CS12020/robot/line/helper.h b/CS12020/robot/line/helper.h
@@ -1,4 +1,6 @@
#include <Servo.h>
+#include <stdint.h>
+#include <EEPROM.h>
#define GREEN_LED 7
#define YELLOW_LED 12
@@ -23,9 +25,9 @@
#define IRFREQ 38000
-#define LDRA_SWITCH (ANALOG_MAX / 2) + 100
-#define LDRB_SWITCH (ANALOG_MAX / 2) + 100
-#define LDRC_SWITCH (ANALOG_MAX / 2) + 50
+uint16_t LDRA_SWITCH = 0;
+uint16_t LDRB_SWITCH = 0;
+uint16_t LDRC_SWITCH = 0;
#define SIZE(arr) (sizeof(arr) / sizeof(arr[0]))
@@ -60,11 +62,44 @@ setupRobot() {
servoB.write(SERVOB_ZERO);
}
+void
+writeuint16(uint16_t num, int start) {
+ uint8_t n[2] = {0};
+ memcpy(n, &num, 2);
+
+ EEPROM.update(start, n[0]);
+ EEPROM.update(start + 1, n[1]);
+}
+
+uint16_t
+readuint16(int start) {
+ uint8_t n[2] = {0};
+ uint16_t num = 0;
+
+ n[0] = EEPROM.read(start);
+ n[1] = EEPROM.read(start + 1);
+
+ memcpy(&num, n, 2);
+ return num;
+}
+
+void
+SEprintf(const char *fmt, ...) {
+ static char sbuf[64] = { 0 };
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(sbuf, 64, fmt, ap);
+ va_end(ap);
+
+ Serial.print(sbuf);
+}
+
bool
isObstacle() {
tone(IRTRANSMITTER, IRFREQ);
- bool ret = (digitalRead(IRRECEVIER) == LOW);
+ bool ret = (digitalRead(IRRECEVIER) == LOW);
noTone(IRTRANSMITTER);
return ret;
}
diff --git a/CS12020/robot/line/line.ino b/CS12020/robot/line/line.ino
@@ -2,27 +2,29 @@
#define DEBUG
-#ifdef DEBUG
+#ifdef DEBUG
#define DBG(expr) expr;
#else
#define DBG(expr)
#endif
-
typedef struct state {
bool left, mid, right;
+ int rawleft, rawmid, rawright;
short prevDir;
long timeStamp;
} state;
state *
getState() {
- static state s = {
- .left = !isLDRBright(LDRA),
- .mid = !isLDRBright(LDRB),
- .right = !isLDRBright(LDRC),
- };
-
+ static state s;
+ s.left = !isLDRBright(LDRA);
+ s.mid = !isLDRBright(LDRB);
+ s.right = !isLDRBright(LDRC);
+ s.rawleft = analogRead(LDRA);
+ s.rawmid = analogRead(LDRB);
+ s.rawright = analogRead(LDRC);
+
setLEDs(s.left, s.mid, s.right);
return &s;
}
@@ -30,26 +32,27 @@ getState() {
void
stepAvoidanceBehave(state *s) {
DBG({Serial.println("avoid");});
- if (s->mid > s->left - 300 && s->mid > s->right - 300)
- stepMove(BWD);
- stepTurn((s->left > s->right) ? RGT : LFT);
- getState();
}
+
void
stepAttractionBehave(state *s) {
- if (s->mid > s->left - 300 && s->mid > s->right - 300)
+ DBG({Serial.println("avoid");});
+
+ if (s->rawleft > s->rawright + 300)
+ stepTurn(LFT);
+ else if (s->rawright > s->rawleft + 300)
+ stepTurn(RGT);
+ else
stepMove(FWD);
- stepTurn((s->left < s->right) ? RGT : LFT);
- getState();
}
void
runBehave(void (*stepBehave)(state *)) {
- do {
+ while (true) {
state *s = getState();
stepBehave(s);
- } while (true);
+ }
}
void
@@ -57,11 +60,11 @@ checkBarcode(state *s) {
long t = millis();
if (s->timeStamp > 500) {
/* long barcode */
- if ((t - s->timeStamp) > 3000)
+ if ((t - s->timeStamp) > 3000)
runBehave(&stepAvoidanceBehave);
-
+
/* short barcode */
- else if ((t - s->timeStamp) > 800)
+ else if ((t - s->timeStamp) > 800)
runBehave(&stepAttractionBehave);
}
s->timeStamp = t;
@@ -70,13 +73,13 @@ checkBarcode(state *s) {
void
move(state *s) {
/* small adjustments */
- if (s->right && s->mid)
+ if (s->right && s->mid)
stepTurn(LFT);
else if (s->left && s->mid)
stepTurn(RGT);
/* large adjustments */
else if (s->right) {
- s->prevDir = LFT;
+ s->prevDir = LFT;
stepTurn(RGT);
} else if (s->left) {
s->prevDir = RGT;
@@ -98,25 +101,31 @@ void
setup() {
delay(3000);
setupRobot();
+
/* because this is static, I can modify these values to set defaults */
- state *s = getState();
+ state *s = getState();
s->prevDir = BWD;
s->timeStamp = 0;
+
+ LDRA_SWITCH = readuint16(6);
+ LDRB_SWITCH = readuint16(10);
+ LDRC_SWITCH = readuint16(14);
}
void
-loop() {
+loop() {
state *s = getState();
/* do nothing while there is an obstacle */
while (isObstacle())
- return;
- if (s->right && s->left && s->mid) {
+ return;
+
+ if (s->right && s->left && s->mid) {
checkBarcode(s);
/* run through the barcode */
for (int i = 0; i < 20; i++)
stepMove(FWD);
- }
+ }
/* don't do any turns when on a the barcode, go straight */
else move(s);
}