#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <DHT.h>
#define DHTPIN 6 // Pin connected to the DHT sensor
#define DHTTYPE DHT22 // DHT 22
// Initialize variables
int mode = 0;
int axe = 0;
int buttonState1 = 0;
int buttonState2 = 0;
int prevButtonState1 = 1;
int prevButtonState2 = 1;
const int ldrPin = A0; // LDR sensor pin
const int fun_buttonPin = 13; // Pin for the functional push button
int fun_buttonState = HIGH; // Variable to store the button state
int fun_lastButtonState = HIGH; // Variable to store the last button state
int functionState = 0; // Variable to store the current equipment state
// LDR Characteristics
const float GAMMA = 0.7;
const float RL10 = 50;
int ldrtopr = A1; // top-right LDR
int ldrtopl = A2; // top-left LDR
int ldrbotr = A3; // bottom-right LDR
int ldrbotl = A4; // bottom-left LDR
int topl = 0;
int topr = 0;
int botl = 0;
int botr = 0;
// Declare servos
Servo servo_updown;
Servo servo_rightleft;
Servo servo_finalDirection_updown; // New servo motor for final direction in auto mode
Servo servo_finalDirection_rightleft; // New servo motor for final direction in auto mode
int threshold_value = 10; // Measurement sensitivity
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);
void setup() {
// Initialize the LCD
lcd.init();
// Turn on the backlight
lcd.backlight();
// Start the DHT sensor
dht.begin();
// Clear the LCD
lcd.clear();
printWelcomeMessage();
delay(4000);
lcd.clear();
// Initialize serial communication
pinMode(ldrPin, INPUT);
// Set pin modes with internal pull-ups
pinMode(13, INPUT_PULLUP); // Mode switch Button
pinMode(12, INPUT_PULLUP); // Axis switch
pinMode(A5, INPUT); // Potentiometer for right-left movement and for up-down movement
// Attach servos
servo_updown.attach(9); // Servo motor up-down movement
servo_rightleft.attach(10); // Servo motor right-left movement
servo_finalDirection_updown.attach(8); // New servo motor
servo_finalDirection_rightleft.attach(7); // New servo motor
pinMode(fun_buttonPin, INPUT_PULLUP); // Set button pin as input with pull-up resistor
}
void loop() {
if (buttonState1 != prevButtonState1) {
ButtonState();
}
else{
lcd.noBacklight();
lcd.clear();
}
State();
}
void ButtonState(){
char Mode[16];
buttonState1 = digitalRead(13);
if (buttonState1 ==LOW && prevButtonState1 == HIGH) {
lcd.backlight();
delay(50); // Debounce delay
if (digitalRead(13) == LOW) {// Confirm the button is still pressed
// Change mode
mode = !mode;
}
}
if (mode == 0) {
strcpy(Mode, " Manual Mode");
Serial.println(Mode); // Send Mode "Manual" to serial port
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Mode);
manualsolartracker();
} else { // mode automatic
strcpy(Mode, " Auto Mode");
Serial.println(Mode);
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(Mode);
automaticsolartracker(); // Send Mode "Automatic" to serial port
}
prevButtonState1 = buttonState1;
}
void automaticsolartracker() {
// Capture analog values of each LDR
topr = analogRead(ldrtopr); // Capturing analog value of top right LDR
topl = analogRead(ldrtopl); // Capturing analog value of top left LDR
botr = analogRead(ldrbotr); // Capturing analog value of bot right LDR
botl = analogRead(ldrbotl); // Capturing analog value of bot left LDR
// calculating average
int avgtop = (topr + topl) / 2; // average of top LDRs
int avgbot = (botr + botl) / 2; // average of bottom LDRs
int avgleft = (topl + botl) / 2; // average of left LDRs
int avgright = (topr + botr) / 2; // average of right LDRs
// Get the difference
int diffelev = avgtop - avgbot; // Get the difference average between LDRs top and LDRs bot
int diffazi = avgright - avgleft; // Get the difference average between LDRs right and LDRs left
// left-right movement of solar tracker
if (abs(diffazi) >= threshold_value) { // Change position only if light difference is bigger then the threshold_value
if (diffazi > 0) {
if (servo_rightleft.read() < 180) {
servo_rightleft.write(servo_rightleft.read() + 2);
servo_finalDirection_rightleft.write(servo_rightleft.read() + 2);
}
} else {
if (servo_rightleft.read() > 0) {
servo_rightleft.write(servo_rightleft.read() - 2);
servo_finalDirection_rightleft.write(servo_rightleft.read() - 2);
}
}
}
// up-down movement of solar tracker
if (abs(diffelev) >= threshold_value) { // Change position only if light difference is bigger then the threshold_value
if (diffelev > 0) {
if (servo_updown.read() < 180) {
servo_updown.write(servo_updown.read() - 2);
servo_finalDirection_updown.write(servo_updown.read() - 2);
}
} else {
if (servo_updown.read() > 0) {
servo_updown.write(servo_updown.read() + 2);
servo_finalDirection_updown.write(servo_updown.read() + 2);
}
}
}
}
void manualsolartracker() {
buttonState2 = digitalRead(12);
if (buttonState2 != prevButtonState2 && buttonState2 == LOW) {
delay(50); // Debounce delay
if (buttonState2 == LOW) {
// Change axis and light up the correct indicator
axe = !axe;
}
}
prevButtonState2 = buttonState2;
if (axe == 0) { // Control right-left movement
servo_finalDirection_rightleft.write(map(analogRead(A5), 0, 1023, 0, 180));
} else { // Control up-down movement
servo_finalDirection_updown.write(map(analogRead(A5), 0, 1023, 0, 180));
}
}
void State() {
fun_buttonState = digitalRead(fun_buttonPin); // Read the state of the button
if (fun_buttonState == LOW && fun_lastButtonState == HIGH) {
lcd.backlight();
delay(50); // Debounce delay
functionState++;
if (functionState > 3) {
functionState = 1; // Reset to 1 after the last equipment
}
updatefunctionState();
}
fun_lastButtonState = fun_buttonState; // Update the last button state
}
void updatefunctionState() {
// Turn off all previous print
lcd.clear();
// Turn on the current equipment based on the state
switch (functionState) {
case 1:
printDHTData();
break;
case 2:
printVisibility();
break;
case 3:
printWelcomeMessage();
break;
}
}
void printDHTData() {
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
// Check if any reads failed and exit early (to try again).
if (isnan(humidity) || isnan(temperature)) {
lcd.setCursor(0, 1);
lcd.print("Failed to read from");
lcd.setCursor(0, 2);
lcd.print("DHT sensor!");
delay(1000);
return;
}
// Display temperature and humidity on LCD
lcd.setCursor(0, 1);
lcd.print("Temp: ");
lcd.print(temperature);
lcd.print("C");
lcd.setCursor(0, 2);
lcd.print("Humidity: ");
lcd.print(humidity);
lcd.print("%");
delay(1000);
}
void printVisibility() {
lcd.setCursor(0, 1);
lcd.print("Checking Visibility"); // Initial message on LCD
lcd.setCursor(0, 2);
lcd.print(" Loading....");
lcd.setCursor(0, 3);
lcd.print(" please wait");
delay(1000); // Delay for stability
int analogValue = analogRead(ldrPin);
float voltage = analogValue / 1024.0 * 5;
float resistance = 2000 * voltage / (1 - voltage / 5);
float lux = pow(RL10 * 1e3 * pow(10, GAMMA) / resistance, (1 / GAMMA));
lcd.setCursor(0, 3);
lcd.print(" "); // Clear previous message
lcd.setCursor(0, 2);
lcd.print("Visibility:");
if (lux > 50) {
lcd.print("clear");
delay(1000);
} else {
lcd.print("Not Clear");
delay(1000);
}
lcd.clear(); // Clear previous message
lcd.setCursor(0, 1);
lcd.print("Lux: ");
lcd.print(lux);
lcd.setCursor(0,2);
lcd.print("Thank You.....");
delay(1000);
lcd.clear();
}
void printWelcomeMessage() {
lcd.setCursor(0, 0);
lcd.print("Welcome to CSIR NAL");
lcd.setCursor(0, 1);
lcd.print("It is Solar Tracking");
lcd.setCursor(0, 2);
lcd.print("and power management");
lcd.setCursor(0, 3);
lcd.print("system");
delay(2000);
}