
The Narrative

Schematics+Diagrams

How the system thinks?
Arduino Board

Bill of Materials

Arduino Code
#include <Stepper.h>
const int pirSensors[3] = {3, 4, 5};
const int leftLimit = 6;
const int rightLimit = 7;
const int stepsPerRevolution = 2048;
Stepper motor(stepsPerRevolution, 9, 10, 11, 12);
const float sensorPositions[3] = {
0.25, 0.50, 0.75
};
const int motorSpeed = 15;
const long maxSteps = 30000;
long totalSteps = 0;
long currentPosition = 0;
long targetPosition = 0;
bool calibrated = false;
bool leftPressed() {
return digitalRead(leftLimit) == HIGH;
}
bool rightPressed() {
return digitalRead(rightLimit) == HIGH;
}
bool pirDetected(int pin) {
return digitalRead(pin) == HIGH;
}
bool calibrate() {
Serial.println(“Starting calibration.”);
long count = 0;
while (leftPressed()) {
if (rightPressed() || count++ >= maxSteps) {
Serial.println(“Calibration failed, Left limit not found.”);
return false;
}
motor.step(1);
}
count = 0;
while (!leftPressed()) {
if (count++ >= maxSteps) {
Serial.println(“Calibration failed, Error clearing left limit.”);
return false;
}
motor.step(-1);
}
currentPosition = 0;
Serial.println(“Left limit found. Moving right to measure track.”);
count = 0;
while (!rightPressed()) {
if (count++ >= maxSteps) {
Serial.println(“Calibration failed, Right limit not found.”);
return false;
}
motor.step(1);
}
if (count < 100) {
Serial.println(“Calibration failed, Track too short.”);
return false;
}
totalSteps = count;
currentPosition = totalSteps;
targetPosition = currentPosition;
Serial.print(“Calibration complete! Total steps: “);
Serial.println(totalSteps);
return true;
}
bool getTarget(long &target) {
int activeSensors = 0;
float positionSum = 0;
Serial.print(“PIR States: [ “);
for (int i = 0; i < 3; i++) {
int state = digitalRead(pirSensors[i]);
Serial.print(state);
Serial.print(” “);
if (state == HIGH) {
positionSum += sensorPositions[i];
activeSensors++;
}
}
Serial.println(“]”);
if (activeSensors == 0) return false;
target = (long)(
(positionSum / activeSensors) * totalSteps
);
target = constrain(target, 0L, totalSteps);
return true;
}
void moveCurtain() {
int stepsMoved = 0;
while (currentPosition != targetPosition && stepsMoved < 25) {
int direction = (targetPosition > currentPosition) ? 1 : -1;
if (direction < 0 && leftPressed()) {
currentPosition = 0;
Serial.println(“Hit Left Limit Switch!”);
break;
}
if (direction > 0 && rightPressed()) {
currentPosition = totalSteps;
Serial.println(“Hit Right Limit Switch!”);
break;
}
motor.step(direction);
currentPosition += direction;
stepsMoved++;
}
if (currentPosition != targetPosition) {
Serial.print(“Moving. Current: “);
Serial.print(currentPosition);
Serial.print(” | Target: “);
Serial.println(targetPosition);
}
}
void setup() {
Serial.begin(9600);
delay(500);
Serial.println(“System Booting”);
for (int i = 0; i < 3; i++) {
pinMode(pirSensors[i], INPUT);
}
pinMode(leftLimit, INPUT_PULLUP);
pinMode(rightLimit, INPUT_PULLUP);
motor.setSpeed(motorSpeed);
delay(1000);
calibrated = calibrate();
}
void loop() {
if (!calibrated) return;
long newTarget;
if (getTarget(newTarget)) {
targetPosition = newTarget;
Serial.print(“New Target Calculated: “);
Serial.println(targetPosition);
}
moveCurtain();
delay(100);
}
Future Development
