/*
Creato da Pimpi 26/03/2024
- spostato la dichiarazione di "stato = 0" dal loop alla condizione "if (value1 < range && value2 < range)"
- V1.91 stampa del valore di "pausa del movimento" (quando i valori sono all'interno del range il timer si resetta al tempo di attesa)
- V1.90 pausa tra movimenti automatici con variabile "pausa_movimento"
- V1.82 aggiustato con timer non bloccanti le stampe a monitor in tutte le condizioni
- V1.81 timer non bloccante su stampa a monitor dei valori (per evitare lo scorrimento dati troppo rapido) - aggiustato la fase di movimento manuale
- V1.80 eliminato la funzione di posizione home (in caso di vento)
- V1.72 lampeggio del led per condizione di nuvolo - rinominato "RED_LED con LED"
- V1.71 ridefinito le variabili "diff con stato" e "offset con range"
- V1.70 calcolo del valore correzione con funzione map (DA PROVARE)
- V1.68 abbassato il valore nuvolo (prima era 400)
- V1.67 inversione dei pulsanti per il comando manuale - attivata la correzione tra 300 e 400
- V1.66 rinominato la variabile i con est per chiarire la funzione
- V1.65 abbassato i valori di correzione della posizione pannello
- V1.64 valore di correzione in base allo luce rilevata
- V1.63 aggiunto la variabile nuvolo per evitare movimenti con il calare della luce (alla sera il pannello andava sempre verso est)
- V1.62 aggihnto variabile di correzione sensori ldr1/ldr2 (pannello/luce + per spostare verso ovest )
- V1.61 inserito nel comando automatico il valore se somma < buio -200 (per non muovere in caso di posizione Est)
- V1.60 variabile (i) per evitare di tenere sempre alto il relè dopo la funzione est
- V1.51 pausa dopo il posizonamento automatico per evitare scatti di movimenti
- V1.50 riposizionamento verso est dopo il tramonto con variabile buio
- V1.41 sostituito error con offset per differenza dei sensori
- V1.40 void home in caso di vento (ELIMINATO)
- V1.24 invertito il ciclo man con automatico nell'interruttore 1=automatico 0=manuale
- V1.23 con ciclo while evito il doppio comando manuale (necessaria la funzione break per uscire dal ciclo while)
- V1.22 verificato e sistemato il selettore man/auto con resistenza
- V1.21 ingresso micro home
- V1.20 interruttore per stato man/auto - comando manuale con pulsanti - led rosso per stato manuale
- V1.11 utilizzo della funzione switch per la gestione dei relè
- V1.10 aggiustamento e riposo con tolleranza di intervento impostato in variabile
TODO:
- creare lo schema elettrico
INFO:
- valore max senza luce di ldr1 + ldr2 =2000
- stepDown per aimentazione 12v - 5,5v
- alimentazione arduino nano su vpin - gnd
- ECO-WORTHY pannello 12V 25W monocristallino IP65
- ECO-WORTHY 2 Batterie al Litio LiFePO4 12V 8Ah
- attuatore lineare per inseguimento solare con alimentazione da batteria 12v 150mm 150N 4mm/s
- interruttore per ciclo man/auto
- led blu per attivazione comandi manuali e lampeggio per segnalare la funzione nuvoloso (in funzione automatico il pannello non si muove)
- 2 pulsanti per comando manuale (posizione pannello)
- 2 sensori di luce LDR
- variabile di tolleranza tra sensori LDR (range)
- variabile buio per posizionamento a Est
- variabile per calibrazione della differenza lettra tra i sensori (correzione)
https://srituhobby.com
*/
// SETTAGGIO HARDWARE
#define LED 13 // led blu per indicare lo stato manuale
#define MAN_AUTO 5 // interruttore per stato man/auto
#define BUTTON_CLOSE 6 // comando manuale di chiusura attuatore (tasto giallo)
#define BUTTON_OPEN 7 // comando manuale di apertura attuatore (tasto blu)
#define LDR1 A1 // ingresso sensore ldr1
#define LDR2 A0 // ingresso sensore ldr2
#define RELAY_OPEN 3 // attuatore lineare (apertura)
#define RELAY_CLOSE 4 // attuatore lineare (chiusura)
// IMPOSTAZOINI
#define range 40 // era 40 range dei 2 sensori ldr oltre il quale avviene la modifica automatico della posizione (valore originale 10)
#define offset_correzione 200 // soglia massima di correzione (utilizzato dalla funzione map)
#define buio 15000 // somma dei valori dei due sensori per determinare il buio (prima era 1100)
#define nuvolo 7000 // se sopra al valore non muove se trova differenza tra i sensori(PRIMA ERA 550)
#define pausa_movimento 0.1 // minuti di pasua tra cicli
#define pausa_stampa 2000 // ms per visualizzazione delle stampe a monitor
// VARIABILI
int correzione = 0; // modulazione per calibrazione dei sensori ldr1/ldr2 ( con funzione map + per muovere il pannello verso ovest valore originale 0)
int est = 0; // per riconoscere la posizione del pannello a est
int stato = 0; // per la gestione automatica dei movimenti del pannollo solare
unsigned long t0; // per la pausa tra movimenti in automatici
unsigned long t1; // per la stampa a monitor in caso di comando automatico
unsigned long t2; // per la stampa a monitor in caso di comando manuele
unsigned long t3; // per la stampa a monitor in caso di comando automatico
unsigned long t4; // per la stampa a monitor in caso di nuvolo
unsigned long t5; // per la stampa a monitor in caso posizione a est
unsigned long t6; // per la stampa del tempo di pausa
void setup() {
pinMode(LED, OUTPUT);
pinMode(BUTTON_CLOSE, INPUT);
pinMode(BUTTON_OPEN, INPUT);
pinMode(MAN_AUTO, INPUT);
pinMode(RELAY_OPEN, OUTPUT);
pinMode(RELAY_CLOSE, OUTPUT);
Serial.begin(9600);
riposo();
}
void loop() {
int ldr1 = 500;
int ldr2 = analogRead(LDR2) + correzione;
int value1 = ldr1 - ldr2;
int value2 = ldr2 - ldr1;
int Somma = ldr1 + ldr2;
delay(100);
// CALIBRAZIONE DELLA POSIZIONE PANNELLO (V 1.64)
correzione = map(Somma, 0, 400, 0, offset_correzione);
if (Somma >= 400) {
correzione = offset_correzione;
}
// POSIZIONAMENTO AUTOMATICO DI INSEGUIMENTO SOLARE
if (value1 >= range && Somma < nuvolo && millis() - t0 >= (pausa_movimento * 60000)) { // nuvolo - per evitare di partire con poca luce e dopo riposizionamento a Est
stato = 1;
}
if (value2 >= range && Somma < nuvolo && millis() - t0 >= (pausa_movimento * 60000)) { // nuvolo - per evitare di partire con poca luce e dopo riposizionamento a Est
stato = 2;
}
// TEMPO DI RITARDO PER IL COMANDO DI MOVIMENTO - RESET IN CASO DI VALORI IN RANGE (per evitare movimenti continui)
if (value1 < range && value2 < range) {
t0 = millis();
stato = 0;
}
if (millis() - t0 < (pausa_movimento * 60000)) {
if (millis() - t6 >= pausa_stampa) {
Serial.print("Pausa del movimento = ");
Serial.println(((pausa_movimento * 60000) - (millis() - t0)) / 1000);
t6 = millis();
}
}
// STAMPA DEI VALORI SU MONITOR SERIALE
if (millis() - t1 >= pausa_stampa) {
Serial.print("ldr1 ");
Serial.println(ldr1);
Serial.print("ldr2 ");
Serial.println(ldr2);
Serial.print("Differenza = ");
Serial.println(value1);
Serial.print("Somma = ");
Serial.println(Somma);
Serial.print("Correzione = ");
Serial.println(correzione);
Serial.print("est = ");
Serial.println(est);
Serial.println("");
t1 = millis();
}
// COMANDI AUTOMATICI ATTIVI
if (digitalRead(MAN_AUTO)) {
if (millis() - t3 >= pausa_stampa && Somma < nuvolo) {
Serial.println("comando automatico attivo");
t3 = millis();
}
digitalWrite(LED, LOW);
// POSIZIONE EST DOPO IL TRAMONTO
if (Somma > buio && est == 0) {
Pos_est();
} else if (Somma > buio && est == 1) {
if (millis() - t5 >= pausa_stampa) {
Serial.println("Posizione a Est per mancanza di sole");
t5 = millis();
}
}
// LAMPEGGIO DEL LED PER SEGNALARE LA CONDIZIONE DI NUVOLO
if (Somma > nuvolo && Somma < buio) {
if (millis() - t4 >= pausa_stampa) {
Serial.println("Comandi automatici bloccati per mancanza di sole");
t4 = millis();
}
digitalWrite(LED, HIGH);
delay(500);
digitalWrite(LED, LOW);
}
switch (stato) {
case 1:
close();
break;
case 2:
open();
break;
default:
riposo();
break;
}
} else {
// COMANDI MANUALI ATTIVI
if (millis() - t2 >= pausa_stampa) {
Serial.println("Comandi manuali attivi");
t2 = millis();
}
digitalWrite(LED, HIGH);
// APERTURA MANUALE
if (digitalRead(BUTTON_OPEN)) {
Serial.println("");
Serial.println("Comando di apertura ");
while (digitalRead(BUTTON_OPEN)) {
open();
delay(100);
}
Serial.println("");
Serial.println("Attuatore a riposo ");
riposo();
delay(1000);
}
// CHIUSURA MANUALE
if (digitalRead(BUTTON_CLOSE)) {
Serial.println("");
Serial.println("Comando di chiusura ");
while (digitalRead(BUTTON_CLOSE)) {
close();
delay(100);
}
Serial.println("");
Serial.println("Attuatore a riposo ");
riposo();
delay(1000);
}
}
}
void open() {
digitalWrite(RELAY_OPEN, HIGH);
digitalWrite(RELAY_CLOSE, LOW);
est = 0;
}
void close() {
digitalWrite(RELAY_OPEN, LOW);
digitalWrite(RELAY_CLOSE, HIGH);
est = 0;
}
void riposo() {
digitalWrite(RELAY_OPEN, LOW);
digitalWrite(RELAY_CLOSE, LOW);
delay(500);
}
void Pos_est() {
close();
Serial.println("Posizione Est");
delay(40000);
riposo();
est = 1;
}