uni

Thing1's amazing uni repo
Log | Files | Refs

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:
ACS12020/robot/calibrate/Makefile | 10++++++++++
MCS12020/robot/calibrate/calibrate.ino | 15+++++++++++++++
ACS12020/robot/calibrate/helper.h | 158+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
ACS12020/robot/line/2 | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MCS12020/robot/line/helper.h | 43+++++++++++++++++++++++++++++++++++++++----
MCS12020/robot/line/line.ino | 63++++++++++++++++++++++++++++++++++++---------------------------
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); }