#include <TimeLib.h> //https://github.com/PaulStoffregen/Time
#include <EEPROM.h>
// Suntracker addon with actuator, for solarTrolley
// open source suntracker project for higher performance solarpanels
// Arduino IDE 1.18 This version is a standalone version of the webbased solartracker
// You need to make some kind of data view mode trough serial/usb or embed some code for at display if you will used the polulo current chip data
// Author: http://techmind.dk michael pedersen
// Project home: http://techmind.dk/tag/suntracker/
// Start Date: 24. feb 2019
// License: coyright
// Version: 08b
// Update: 01
//***********************************************************************
//Define solartracker ports, valiables and static
//Digital ports
// 0 , 1 recerved for serial com
//const byte interruptPin = 2; // interrupt Data pin from actuator position encoder
const int motorController_IN3_OUT3 = 3; // HIGH = go WEST
const int motorController_IN4_OUT4 = 4; // HIGH = go EAST
//D in/out 5 NC/free
const int dipSwitchWest = 6;
const int ledAlive = 7;
const int dipSwitchEast = 8;
const int ledCheck = 9;
//Analog ports
int solarVoltSensor = 0;
//int free = 1;
int lightSensorEast = 2; //LDR
int lightSensorWest = 3; //LDR
int solarCurrentSensor = 4;
int actuatorCurrentSensor = 5;
//Variables
long lowCounter = 0;
int waitMinutesToNextTrackUpdate = 1; //This value is in minutes 1 equal one minut 5 eual 5 minuttes. In my application it is Set to 3 or 5 minutes
bool testModeSet = 0;
bool onWayHomeToWest = 0;
bool east = 0;
bool west = 1;
bool acuatorCurrentExceeded; //1 = ok, 0 = overcurrent, Physical Limit, stop actuator
bool dipSwitchWestState = 0;
bool dipSwitchEastState = 0;
int optoPositionTheValue = 0;
int solarCurrentValue = 0;
int actuatorCurrentSensorValue; // Stop actuator +-15 from 520
int lightSensorEastValue;
int lightSensorWestValue;
int addrE2 = 0; //eeprom start adress
byte suntrackerPositionFromE2;
//volatile int state = LOW; // The input state toggle
//Declare metodes
void goHomeWest(); //go all the way back to west start position
void goHomeEast(); //go all the way back to west start position
void goToWest();
void goToEast();
void stopActuator();
void testMode();
//********************
//Initialize and setup
//********************
void setup(){
Serial.begin(9600);
Serial.println("Hello world, i am suntracker and alive ;) ");
//Initialize Solartracker ports and variables
pinMode(ledAlive, OUTPUT);
pinMode(ledCheck, OUTPUT);
pinMode(dipSwitchWest, INPUT);
pinMode(dipSwitchEast, INPUT);
// Initialize Motor controller ports
pinMode(motorController_IN3_OUT3, OUTPUT); //
pinMode(motorController_IN4_OUT4, OUTPUT); //
// Initialize, make sure actuator is stopped
stopActuator();
digitalWrite(ledCheck, HIGH);
//Attach the interrupt to the input pin and monitor for ANY Change
//attachInterrupt(digitalPinToInterrupt(interruptPin), stateChange, CHANGE);
//Set lowcounter
time_t t = now(); // store the current time in time variable t
minute(t); // returns the minute for the given time t
lowCounter =minute(t);
// set test mode
testModeSet = LOW; //set to HIGH to enter test mode
onWayHomeToWest = LOW;
blinkGreenLEDFast();
digitalWrite(ledAlive, LOW);
acuatorCurrentExceeded = HIGH;
}
//**********************************
// The loop where everything happens
//**********************************
void loop(){ //Main state maschine
Serial.println(optoPositionTheValue);
if (!testModeSet)
{ // Run normal
blinkGreenLEDSlow();
Serial.println("Run mode");
checkDualDipswitchPress(); // Enter testmode, press both endstop dipswitches at the same time
checkSuntrackerCurrentPosition();
gotoNextSuntrackerPosition();
time_t t = now();
Serial.println(second(t));
}
else
{ // Go into Testmode
blinkRedLEDFast();
Serial.println("Test mode");
testMode();
digitalWrite(ledAlive, LOW);
checkDualDipswitchPress(); // Leave testmode, press both endstop dipswitches at the same time
}
}
void gotoNextSuntrackerPosition()
{
// *** Start test light level east / west
lightSensorEastValue = analogRead(lightSensorEast);
lightSensorWestValue = analogRead(lightSensorWest);
Serial.print(lightSensorEastValue);
Serial.print(".....");
Serial.println(lightSensorWestValue);
checkActuatorPhysicalLimit();
Serial.print(dipSwitchEastState);
Serial.print(".....");
Serial.println(dipSwitchWestState);
//Check where to turn the suntracker to, to optain most light fotons
if (lightSensorWestValue > lightSensorEastValue)
{
time_t t = now();
if ((lowCounter+waitMinutesToNextTrackUpdate) == (minute(t)))
{
goToWest();
Serial.println("Moving West");
}
}
else if (lightSensorWestValue < lightSensorEastValue)
{
time_t t = now();
if ((lowCounter+waitMinutesToNextTrackUpdate) == (minute(t)))
{
goToEast();
Serial.println("Moving east");
}
}
else if (lightSensorWestValue = lightSensorEastValue)
{
//LDR east and West equal, so stop actuator and copy minutes here and now til lowCounter, the wait offset data, not a counter, sorry
stopActuator();
time_t t = now();
lowCounter =minute(t);
}
}
void checkActuatorPhysicalLimit()
{
dipSwitchEastState = digitalRead(dipSwitchEast); // read dipswitch East 0 = pressed = end stop
dipSwitchWestState = digitalRead(dipSwitchWest); // read dipswitch west 0 = pressed = end stop
}
void checkDualDipswitchPress() // Toggle testmode flag
{
// Both dipswitches pressed enter testmode
dipSwitchEastState = digitalRead(dipSwitchEast); // read dipswitch west 0 = pressed = end stop
if (!dipSwitchEastState)
{
dipSwitchWestState = digitalRead(dipSwitchWest); // read dipswitch west 0 = pressed = end stop
if (!dipSwitchWestState)
{
testModeSet = !testModeSet;
}
}
}
void goToWest()
{
digitalWrite(ledCheck, HIGH);
checkActuatorPhysicalLimit();
actuatorCurrentCheck();
if (acuatorCurrentExceeded)
{
if (dipSwitchWestState)
{
digitalWrite(motorController_IN3_OUT3, HIGH);
digitalWrite(motorController_IN4_OUT4, LOW);
}
else
{
stopActuator();
}
}
else
{
stopActuator();
}
}
void goToEast()
{
checkActuatorPhysicalLimit();
actuatorCurrentCheck();
if (acuatorCurrentExceeded)
{
if (dipSwitchEastState)
{
digitalWrite(ledCheck, HIGH);
digitalWrite(motorController_IN3_OUT3, LOW);
digitalWrite(motorController_IN4_OUT4, HIGH);
}
else
{
stopActuator();
}
}
else
{
stopActuator();
}
}
void actuatorCurrentCheck()
{
actuatorCurrentSensorValue = analogRead(actuatorCurrentSensor);
Serial.println(actuatorCurrentSensorValue);
if (actuatorCurrentSensorValue > 540)
{
acuatorCurrentExceeded = LOW;
Serial.println("acuator Current Exceeded!!");
}
else if (actuatorCurrentSensorValue < 495)
{
acuatorCurrentExceeded = LOW;
Serial.println("acuator Current Exceeded!!");
}
}
void stopActuator()
{
digitalWrite(motorController_IN3_OUT3, LOW);
digitalWrite(motorController_IN4_OUT4, LOW);
digitalWrite(ledCheck, LOW);
}
void checkSuntrackerCurrentPosition()
{
suntrackerPositionFromE2 = EEPROM.read(addrE2);//write EEPROM.write(addr, val);
//optoPositionThePhotoTransistor interrupt data pin in
//optoPositionTheValue
}
void testMode()
{
stopActuator();
acuatorCurrentExceeded = HIGH;
}
void blinkGreenLEDFast()
{
// Blink, Great solar tracker is alive
digitalWrite(ledAlive, HIGH);
delay(100);
digitalWrite(ledAlive, LOW);
delay(100);
}
void blinkGreenLEDSlow()
{
// Blink, Great solar tracker is alive
digitalWrite(ledAlive, HIGH);
delay(300);
digitalWrite(ledAlive, LOW);
delay(300);
}
void blinkRedLEDSlow()
{
// Blink, Great solar tracker is alive
digitalWrite(ledCheck, HIGH);
delay(300);
digitalWrite(ledCheck, LOW);
delay(300);
}
void blinkRedLEDFast()
{
// Blink, Great solar tracker is alive
digitalWrite(ledCheck, HIGH);
delay(100);
digitalWrite(ledCheck, LOW);
delay(100);
}
Leave a comment