//solar Tracking and Power management system developed by Pavanakumar K Hegde
#include <Servo.h>
#include <LiquidCrystal_I2C.h>
#include <Wire.h>
#include <DHT.h>
#include <EthernetENC.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 = HIGH;
int buttonState2 = HIGH;
int prevButtonState1 = HIGH;
int prevButtonState2 = HIGH;
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
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;
int max1=0, max2=0, max3=0;
int ser1 = 90, ser2=150;
const int ldrPin = A0; // LDR sensor pin
const int fun_buttonPin = 13; // Pin for the functional push button
const float GAMMA = 0.7;
const float RL10 = 50;
unsigned long previousMillis = 0;
const long interval = 3600000; // 1 hour in milliseconds
// Initialize Ethernet settings
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 1, 177);
EthernetServer server(80);
DHT dht(DHTPIN, DHTTYPE);
LiquidCrystal_I2C lcd(0x27, 20, 4);
// 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
void setup() {
// Initialize Ethernet
Ethernet.begin(mac, ip);
server.begin();
// Initialize Serial
Serial.begin(9600);
// Initialize the LCD
lcd.init();
// Turn on the backlight
lcd.backlight();
// Start the DHT sensor
dht.begin();
// Clear the LCD
lcd.clear();
printWelcomeMessage();
delay(500);
//lcd.noBacklight();
//delay(500);
// 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(11, INPUT_PULLUP); // Button to change auto/manual mode
pinMode(fun_buttonPin, INPUT_PULLUP); // Display Reading Button
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(7); // New servo motor
servo_finalDirection_rightleft.attach(8); // New servo motor
servo_updown.write(ser2);
servo_rightleft.write(ser1);
servo_finalDirection_updown.write(ser2);
servo_finalDirection_rightleft.write(ser1);
// Initial intensity scanning
scanMaxIntensity();//calling function
}
void loop() {
buttonState1 = digitalRead(11);
buttonState2 = digitalRead(12);
if (buttonState1 != prevButtonState1 && buttonState1 == LOW) {
delay(50); // Debounce delay
if (digitalRead(11) == LOW) { // Confirm the button is still pressed
mode = !mode;
updateModeDisplay();//calling function
}
}
prevButtonState1 = buttonState1;//update statement
if (buttonState2 != prevButtonState2 && buttonState2 == LOW) {
delay(50); // Debounce delay
if (digitalRead(12) == LOW) { // Confirm the button is still pressed
axe = !axe;
updateAxeDisplay();//calling function
}
}
prevButtonState2 = buttonState2;//update statement
if (mode == 1) {
manualsolartracker();//calling function
} else {
automaticsolartracker();//calling function
}
}
////////////////////////////////////////////////////Functions///////////////////////////////////////////////////////////////////////
void updateModeDisplay() {
lcd.backlight();
lcd.clear();
if (mode == 1) {
lcd.setCursor(0, 1);
lcd.print(" Manual Mode");
} else {
lcd.setCursor(0, 1);
lcd.print(" Auto Mode");
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void updateAxeDisplay() {
lcd.backlight();
lcd.clear();
if (axe == 0) {
lcd.setCursor(0, 1);
lcd.print(" Axis: Right-Left");
} else {
lcd.setCursor(0, 1);
lcd.print(" Axis: Up-Down");
}
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void manualsolartracker() {
if (axe == 0) { // Control right-left movement
servo_finalDirection_rightleft.write(map(analogRead(A5), 0, 1023, 0, 180));
servo_rightleft.write(map(analogRead(A5), 0, 1023, 0, 180));
} else { // Control up-down movement
servo_finalDirection_updown.write(map(analogRead(A5), 0, 1023, 30, 150));
servo_updown.write(map(analogRead(A5), 0, 1023, 30, 150));
}
State();//calling function
datatrans();//calling function
//getclock();//calling function
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void automaticsolartracker() {
// Capture analog values of each LDR
int topr = analogRead(ldrtopr);
int topl = analogRead(ldrtopl);
int botr = analogRead(ldrbotr);
int botl = analogRead(ldrbotl);
// Compute averages
int top_avg = (topr + topl) / 2;
int bot_avg = (botr + botl) / 2;
int left_avg = (topl + botl) / 2;
int right_avg = (topr + botr) / 2;
// Compute the difference between averages
int vertical_diff = top_avg - bot_avg;
int horizontal_diff = left_avg - right_avg;
// Threshold for movement (adjust this value for sensitivity)
int threshold = 30;
int current_angle_updown = servo_finalDirection_updown.read();
int current_angle_rightleft = servo_finalDirection_rightleft.read();
// Up-down movement of solar tracker
if (abs(vertical_diff) > threshold) {
if (vertical_diff > 0 ){
if(30<current_angle_updown < 150) {
current_angle_updown -= 5;
}
}
else if (vertical_diff < 0 ){
if(30< current_angle_updown < 150) {
current_angle_updown += 5;
}
}
servo_updown.write(current_angle_updown);
servo_finalDirection_updown.write(current_angle_updown);
}
// Left-right movement of solar tracker
if (abs(horizontal_diff) > threshold) {
if (horizontal_diff > 0){
if(0<current_angle_rightleft< 180) {
current_angle_rightleft -= 5;
}
}
else if (horizontal_diff < 0){
if(0 < current_angle_rightleft < 180) {
current_angle_rightleft += 5;
}
}
servo_rightleft.write(current_angle_rightleft);
servo_finalDirection_rightleft.write(current_angle_rightleft);
}
// Optional: Print values for debugging
//Serial.println(topr); Serial.println(topl); Serial.println(botr); Serial.println(botl);
//Serial.println(top_avg); Serial.println(bot_avg); Serial.println(left_avg); Serial.println(right_avg);
//Serial.println(vertical_diff); Serial.println(horizontal_diff);
delay(500); // Add a delay to reduce the frequency of updates
State();//calling function
datatrans();//calling function
getclock();//calling function
delay(500); // Add a delay to reduce the frequency of updates
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
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();
delay(500);
//lcd.noBacklight();
break;
case 2:
printVisibility();
delay(300);
//lcd.noBacklight();
break;
case 3:
printWelcomeMessage();
delay(300);
//lcd.noBacklight();
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(" Sky is ");
if (lux > 50) {
lcd.print("clear");
delay(2000);
} else {
lcd.print("Not Clear");
delay(2000);
}
lcd.clear(); // Clear previous message
lcd.setCursor(0, 0);
lcd.print(" Lux: ");
lcd.print(lux);
lcd.setCursor(0, 1);
lcd.print(" Thank You.....");
lcd.setCursor(0, 2);
lcd.print(" CSIR-NAL &");
lcd.setCursor(0, 3);
lcd.print("Mangalore University");
delay(2000);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void printWelcomeMessage() {
lcd.setCursor(0, 1);
lcd.print(" CSIR - NAL ");
delay(3000);
lcd.clear(); // Clear previous message
lcd.setCursor(0, 1);
lcd.print("MANGALORE UNIVERSITY"); //Mangalore University
delay(3000);
lcd.clear(); // Clear previous message
lcd.setCursor(0, 1);
lcd.print(" I S P S");
delay(3000);
lcd.clear(); // Clear previous message
lcd.setCursor(0, 1);
lcd.print(" INTELLIGENT");
lcd.setCursor(0, 2);
lcd.print("SOLAR POWER STATION");
delay(2000);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void datatrans(){
float humidity = dht.readHumidity();
float temperature = dht.readTemperature();
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));
Serial.print("Welcome to CSIR NAL. It is Solar Tracking and power management system");
Serial.print("Temp: ");
Serial.print(temperature);
Serial.print("C, Humidity: ");
Serial.print(humidity);
Serial.print("%, Lux: ");
Serial.println(lux);
// Send data via Ethernet
EthernetClient client = server.available();
if (client) {
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close");
client.println();
client.print("Temp: ");
client.print(temperature);
client.print("C, Humidity: ");
client.print(humidity);
client.print("%, Lux: ");
client.println(lux);
client.stop();
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void getclock(){
// Check if 1 hour has passed to perform intensity scanning
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
scanMaxIntensity();//calling function
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void scanMaxIntensity() {
int maxIntensity = 0;
int bestAngleX = 0;
int bestAngleY = 0;
// Scan all angles
for (int x = 0; x <= 180; x += 30) {
for (int y = 30; y <= 150; y += 10) {
servo_rightleft.write(x);
servo_updown.write(y);
delay(1000); // Wait for servo to reach position
int intensity = readLightIntensity();//calling function
if (intensity > maxIntensity) {
maxIntensity = intensity;
bestAngleX = x;
bestAngleY = y;
}
}
}
// Move servos to position with maximum intensity
servo_rightleft.write(bestAngleX);
servo_updown.write(bestAngleY);
servo_finalDirection_updown.write(bestAngleY);
servo_finalDirection_rightleft.write(bestAngleX);
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int readLightIntensity() {
// 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
// Combine readings (you may use a different method if needed)
int intensity = (topr+topl+botr+botl)/4;
return intensity;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////