Sitting against the sun is a public bench at a park. This project is a prototype version of the installation piece. This installation is designed to enhance the outdoor seating experience by intuitively responding to sunlight and protecting users from direct exposure to strong sunlight. Through an integrated sensor and motor system, the bench continuously adjusts its orientation based on the angle of the sunlight. When the sun hits the bench, the mechanism initiates a gradual rotation to turn the seat away from direct sunlight, allowing users to enjoy the space comfortably without the glare and heat often associated with outdoor seating.
I used 6 photoresistors to indicate the direction of sunlight.
When IR obstacle sensor detects the motor turns forward for a second. When it’s not detecting anything, it stops turning.
#include <Stepper.h>
// Define the number of steps per revolution for your stepper motor
const int stepsPerRevolution = 2048; // Adjust based on your motor specs
const float stepsPerDegree = stepsPerRevolution / 360.0; // Steps per degree
// Create an instance of the Stepper class (Pins for ULN2003 driver: IN1, IN2, IN3, IN4)
Stepper myStepper(stepsPerRevolution, 8, 10, 9, 11);
// Pin definitions for the photoresistors
const int photoResistor1 = A0; // 6 o'clock
const int photoResistor2 = A1; // 8 o'clock
const int photoResistor3 = A2; // 10 o'clock
const int photoResistor4 = A3; // 12 o'clock
const int photoResistor5 = A4; // 2 o'clock
const int photoResistor6 = A5; // 4 o'clock
// Light threshold for detecting darkness
const int lightThreshold = 250; // Adjust based on environment (350 - classroom, 550 - studio, 920 - sunlight)
// Variables to hold the current angle and target angles for each photoresistor
int currentAngle = 0; // Initial motor position in degrees
const int targetAngles[] = {0, 60, 120, 180, 240, 300}; // Target angles for each photoresistor (clock positions)
// Debouncing variables
unsigned long lastMoveTime = 0; // Time since last move
const unsigned long debounceDelay = 500; // Debounce delay in milliseconds (adjust as needed)
void setup() {
Serial.begin(9600);
myStepper.setSpeed(15); // Set motor speed (RPM)
}
void loop() {
// Read the analog values from each photoresistor
int lightLevels[6];
lightLevels[0] = analogRead(photoResistor1);
lightLevels[1] = analogRead(photoResistor2);
lightLevels[2] = analogRead(photoResistor3);
lightLevels[3] = analogRead(photoResistor4);
lightLevels[4] = analogRead(photoResistor5);
lightLevels[5] = analogRead(photoResistor6);
// Find the first photoresistor that doesn't detect enough light
for (int i = 0; i < 6; i++) {
if (lightLevels[i] < lightThreshold) {
// Print which photoresistor is not receiving light
Serial.print("Photoresistor at ");
switch (i) {
case 0: Serial.print("senseA0 (1)"); break;
case 1: Serial.print("senseA1 (2)"); break;
case 2: Serial.print("senseA2 (3)"); break;
case 3: Serial.print("senseA3 (4)"); break;
case 4: Serial.print("senseA4 (5)"); break;
case 5: Serial.print("senseA5 (6)"); break;
}
Serial.print(" not receiving enough light (Value: ");
Serial.print(lightLevels[i]);
Serial.println(")");
// Check debounce: only move if enough time has passed since the last move
if (millis() - lastMoveTime > debounceDelay) {
moveToAngle(targetAngles[i]); // Move motor to target angle
lastMoveTime = millis(); // Update last move time
}
break; // Stop after the first detected photoresistor in darkness
}
}
// Short delay for system stability
delay(100);
}
// Function to move the stepper motor to a specified angle
void moveToAngle(int targetAngle) {
// Calculate the angle difference
int angleDifference = targetAngle - currentAngle;
// Normalize the angle difference to be within -180 to 180 degrees
if (angleDifference < -180) {
angleDifference += 360;
} else if (angleDifference > 180) {
angleDifference -= 360;
}
// Determine the number of steps to move
int stepsToMove = angleDifference * stepsPerDegree;
// Move the motor in the calculated direction if there is a movement needed
if (stepsToMove != 0) {
Serial.print("Moving to ");
Serial.print(targetAngle);
Serial.print(" degrees. ");
Serial.print(stepsToMove);
Serial.println(" steps.");
myStepper.step(stepsToMove); // Move the motor
currentAngle = targetAngle; // Update the current angle
// Normalize current angle to keep it within 0-360 degrees
if (currentAngle >= 360) {
currentAngle -= 360;
} else if (currentAngle < 0) {
currentAngle += 360;
}
} else {
Serial.println("Already at target angle.");
}
delay(1000); // Delay for stabilization
}