#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// LCD address 0x27, 16 columns, 2 rows
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Photodiode analog pins
const int leftSensorPin = A0;
const int rightSensorPin = A1;
const int upSensorPin = A2;
const int downSensorPin = A3;
// Stepper pins
const int dirPinH = 2;
const int stepPinH = 3;
const int dirPinV = 4;
const int stepPinV = 5;
const int stepDelay = 800; // microseconds
const int threshold = 50; // sensor difference threshold
void setup() {
pinMode(dirPinH, OUTPUT);
pinMode(stepPinH, OUTPUT);
pinMode(dirPinV, OUTPUT);
pinMode(stepPinV, OUTPUT);
lcd.init();
lcd.backlight();
lcd.print("Dual Axis Tracker");
delay(2000);
lcd.clear();
}
void loop() {
// Inverted readings: higher light = higher value
int leftVal = 1023 - analogRead(leftSensorPin);
int rightVal = 1023 - analogRead(rightSensorPin);
int upVal = 1023 - analogRead(upSensorPin);
int downVal = 1023 - analogRead(downSensorPin);
// Horizontal control (corrected direction)
if (abs(leftVal - rightVal) > threshold) {
if (leftVal > rightVal) {
moveStepper(dirPinH, stepPinH, false); // Move LEFT
} else {
moveStepper(dirPinH, stepPinH, true); // Move RIGHT
}
}
// Vertical control (corrected direction)
if (abs(upVal - downVal) > threshold) {
if (upVal > downVal) {
moveStepper(dirPinV, stepPinV, false); // Move UP
} else {
moveStepper(dirPinV, stepPinV, true); // Move DOWN
}
}
// Display sensor values
lcd.setCursor(0, 0);
lcd.print("L:");
lcd.print(leftVal);
lcd.print(" R:");
lcd.print(rightVal);
lcd.setCursor(0, 1);
lcd.print("U:");
lcd.print(upVal);
lcd.print(" D:");
lcd.print(downVal);
delay(200);
}
void moveStepper(int dirPin, int stepPin, bool direction) {
digitalWrite(dirPin, direction ? HIGH : LOW);
digitalWrite(stepPin, HIGH);
delayMicroseconds(stepDelay);
digitalWrite(stepPin, LOW);
delayMicroseconds(stepDelay);
}
X - AXIS
(HORIZONTAL)
Y - AXIS
(VERTICAL)
LEFT
RIGHT
UP
DOWN