Inseguitore Solare Astronomico

L’inseguitore solare astronomico è un progetto pensato per orientare un pannello solare nella direzione del sole in qualsiasi punto del nostro pianeta esso sia installato, attraverso calcoli astronomici che, utilizzando i valori dei Latitudine e Longitudine oltre che Data e Ora, possano determinare la sua posizione relativa rispetto ai pannelli, in modo tale da garantire una produzione elevata.

La fase iniziale si è basata sulla ricerca in quanto è necessario effettuare calcoli astronomici di precisione per ottenere i valori di Altezza Solare ed Azimut di interesse. Per determinare la posizione
del sole analiticamente, infatti, occorre stabilire il numero di gradi di elevazione rispetto alla superficie terrestre (Altezza Solare) e l’angolo tra il piano verticale passante per l’astro e quello orizzontale passante per il punto di osservazione, con riferimento a nord (Azimut).

L’inseguitore solare non presenta un solo Pannello Solare, ma 2, di identico tipo.
Uno rivolto direttamente verso il sole ed un secondo che raccoglie la luce solare concentrata da una parabola riflettente. In questo modo oltre ad una maggiore produzione di energia ci è possibile anche valutare la differenza tra produzione diretta ed a concentrazione.

L’APPROCCIO ASTRONOMICO

Il funzionamento dell’Inseguitore Solare Astronomico si basa sugli studi astronomici che permettono, in un preciso momento ed in un punto geografico preciso della Terra, di calcolare l’altezza del Sole all’orizzonte (Altezza Solare) ed il suo angolo con il Nord sul piano equatoriale (Azimut).

Le coordinate del luogo (Latitudine e Longitudine) in cui l’inseguitore è installato, oltre a data e ora, sono determinati dal modulo GPS GY-NEO6MV2, e passati all’Arduino Mega 2560 che esguirà i calcoli e controllerà i motori.

La parte di programma sviluppato in C++ con Arduino IDE che realizza questi calcoli è il seguente:

// Calcoli Astronomici per determinare l'Azimut e Altezza Solare

//GPS Virtuale
// -------------------------
String Latitudine = "44.4359"; // Latitudine Castelnovo Monti
String Longitudine = "10.4026";// Longitudine Castelnovo Monti
String Dir_Lat = "N"; 
String Dir_Lon = "E"; 
String Altitudine = "700.5"; 
String Hour = "6"; // ORA SOLARE
String Minute = "13"; 
String Second = "27"; 
String Day = "31"; 
String Month = "1"; 
String Year = "2023";
String Data, Ora;

// AltezzaSolare e Azimut
// -------------------------
//float Lon_meridiano = 15.0; //0.26179939 meridiano di riferimento 15°0'0" (Etna) || DA INDIVIDUARE per l località considerata
int Lon_meridiano;
float tempo = 0.0;
float tempo_luogo = 0.0;
float mezzogiorno_luogo;
float EqT = 0.0;
float angoloOrario = 0.0; //angolo orario Rad
float declinazione = 0.0; //declinazione Rad
float altezzaSolare = 0.0; //altezza solare Rad
float azimut = 0.0; //azimut solare Rad
int pro;
float inRad;
float Y;
// Offset hours from gps time (UTC)
int ora_legale = 1; // da settare!!!!

// il GPS considera già l'offset!
const int offset = 1;   // Central European Time (rispetto a Greenweck)

// -----------------------------------------------
// Funzioni --------------------------------------
// -----------------------------------------------

//GPS
//-------------------------------------------------
void lettura_GPS() {
  Serial.print("Data = ");Serial.print(Day);Serial.print("/");Serial.print(Month);Serial.print("/");Serial.println(Year);
  Serial.print("Orario = ");Serial.print(Hour);Serial.print(":");Serial.print(Minute);Serial.print(":");Serial.println(Second);
  Serial.print("Latitudine = ");Serial.print(Latitudine);
  Serial.print(" ");Serial.println(Dir_Lat);
  // correggo Longitudine
  float LonF = Longitudine.toFloat();
  if(Dir_Lon == "W") Longitudine = "-" + Longitudine;
  if(Dir_Lon == "E" && Longitudine.toFloat() > 180) Longitudine = "-" + String(360 - LonF);
  Serial.print("Longitudine = ");Serial.print(Longitudine);
  Serial.print(" ");Serial.println(Dir_Lon);
  Serial.print("Altitudine = ");Serial.println(Altitudine);Serial.println("");
}
int longitudineMeridianoFuso(String Longitudine){
  float deltaLongitudine = Longitudine.toFloat() - int(Longitudine.toFloat()/15)*15;
  if(deltaLongitudine < 7.5 && deltaLongitudine > -7.5) Lon_meridiano = int(Longitudine.toFloat()/15)*15;
  else if(deltaLongitudine > 7.5) Lon_meridiano = int(Longitudine.toFloat()/15)*15 + 15;
  else if(deltaLongitudine < -7.5) Lon_meridiano = int(Longitudine.toFloat()/15)*15 - 15;
  else Lon_meridiano = 0;
  return Lon_meridiano;
}
// Calcolo Altezza Solare e Azimut
//-------------------------------------------------
int progressivo(){
  //calcolo del numero progressivo corrispondente al giorno dell’anno
  pro = 0;
  int anno = 1900 + Year.toInt();
  int mese = Month.toInt();
  int giorno = Day.toInt();
  int bise = bisestile(anno);
  if (mese==1){pro=giorno;}
  if (mese==2){pro=0*30+1*31+giorno;}
  if (mese==3){pro=0*30+1*31+giorno+bise;}
  if (mese==4){pro=0*30+2*31+giorno+bise;}
  if (mese==5){pro=1*30+2*31+giorno+bise;}
  if (mese==6){pro=1*30+3*31+giorno+bise;}
  if (mese==7){pro=2*30+3*31+giorno+bise;}
  if (mese==8){pro=2*30+4*31+giorno+bise;}
  if (mese==9){pro=2*30+5*31+giorno+bise;}
  if (mese==10){pro=3*30+5*31+giorno+bise;}
  if (mese==11){pro=3*30+6*31+giorno+bise;}
  if (mese==12){pro=4*30+6*31+giorno+bise;}
  return pro;
}
int bisestile(int a){
  //funzione per scoprire se l’anno in corso è bisestile
  int bis = 28;
  if(a%4==0){
    if(a%100==0){
      if(a%400==0) bis = 29;
      else bis = 28;
    }
    else bis = 29;
  }
  else bis = 28;
  return bis;
}
void posizione_Sole(){
  /*
   * 24 Fusi orari, ognuno composto da 15 Meridiani a distanza di 1° tra uno e l'altro
   * 
   * Equazione del tempo: EqT = 229,18(0,000075+0,001868cos@-0,032077sin@-0,014615cos2@-0,040849sin2@)
   * dove @ = (2PI/365)*(N-1)
   * 
   * Latitudine: LAT
   * Longitudine: LON
   * Angolo Orario: AO  = 15*(h_conv + ((EqT-4*(longitudineMeridianoFuso-LON))/60))-180
   * Declinazione Solare: DS = 0.006918-0.399912cos(@)+0.070257sin(@)-0.006758cos(2@)-0.002697cos(3@)+0.00148sin(3@) 
   * 
   * sin(AS) = sin(LAT)sin(DS)+cos(LAT)cos(DS)cos(AO)
   * cos(Az) = (cos(AO)cos(DS)sin(LAT)-sin(DS)cos(LAT))/cos(AS)
   * 
   * dove:
   * g = 360°/365 con angoli espressi in ° o 2pi/365 con angoli espressi in Rad
   * N = giorno progressivo dell'anno
   * @ = (2PI/365)*(N-1)
  */
  float Hour_f;
  if(Month.toInt() >= 4 && Month.toInt() <=10) Hour_f = Hour.toFloat() + ora_legale; //-----------SOLO QUANDO C'E' L'ORA LEGALE!!!!
  else Hour_f = Hour.toFloat();
  
  tempo = Hour_f + (Minute.toFloat()/60) + (Second.toFloat()/3600);
  inRad = (2*PI/360); 
  Y = (2*PI/365)*(progressivo()-1);
  EqT = 229.18*(0.000075+0.001868*cos(Y)-0.032077*sin(Y)-0.014615*cos(2*Y)-0.040849*sin(2*Y));
  tempo_luogo = tempo -((EqT-4*(longitudineMeridianoFuso(Longitudine)-Longitudine.toFloat()))/60);
  mezzogiorno_luogo = 12.00 -((EqT-4*(longitudineMeridianoFuso(Longitudine)-Longitudine.toFloat()))/60);
  angoloOrario = 15*(tempo + ((EqT-4*(longitudineMeridianoFuso(Longitudine)-Longitudine.toFloat()))/60))-180; //angolo orario °
  declinazione = (0.006918-0.399912*cos(Y)+0.070257*sin(Y)-0.006758*cos(2*Y)-0.002697*cos(3*Y)+0.00148*sin(3*Y))*(365/(2*PI)); //declinazione Deg
  altezzaSolare = asin((sin(Latitudine.toFloat()*inRad)*sin(declinazione*inRad))+(cos(Latitudine.toFloat()*inRad)*cos(declinazione*inRad)*cos(angoloOrario*inRad)))/inRad; //altezza solare
  azimut = (acos(((cos(angoloOrario*inRad)*cos(declinazione*inRad)*sin(Latitudine.toFloat()*inRad))-(sin(declinazione*inRad)*cos(Latitudine.toFloat()*inRad)))/cos(altezzaSolare*inRad))/inRad); //azimut Rad
  if(tempo < mezzogiorno_luogo) azimut = 180 - azimut;
  else azimut = 180 + azimut;
  
  Serial.println("Posizione Sole:"); Serial.println("----------------------------------------"); 
  Serial.print("Ora = "); Serial.print(tempo); Serial.println(" (Hd)");
  Serial.print("Ora_luogo = "); Serial.print(tempo_luogo); Serial.println(" (Hd)");
  Serial.print("Mezzogiorno_luogo = "); Serial.print(mezzogiorno_luogo); Serial.println(" (Hd)");
  Serial.print("Longitudine_meridiano_fuso = "); Serial.print(longitudineMeridianoFuso(Longitudine)); Serial.println(" Gradi");
  Serial.print("Equazione_Tempo = "); Serial.print(EqT); Serial.println(" (Md)");
  Serial.print("Angolo_Orario = "); Serial.print(angoloOrario); Serial.println(" Gradi");
  Serial.print("Declinazione = "); Serial.print(declinazione); Serial.println(" Gradi");
  
  Serial.print("Altezza_Solare = "); Serial.print(altezzaSolare); Serial.println(" Gradi");
  Serial.print("Azimut = "); Serial.print(azimut); Serial.println(" Gradi");
  Serial.println("----------------------------------------");Serial.println("");
}

void setup() {
  
  //init seriale hardware
  Serial.begin(9600);

  Serial.println("INSEGUITORE SOLARE ASTRONOMICO SIM");
  Serial.println("----------------------------------");
  Serial.println("");
}

void loop() {
  // Calcolo Coord Solari
  posizione_Sole();
  
  while(1);
}

Una volta determinate le coordinate solari il sistema le confronta con i valori di Inclinazione determinata con l’Accelerometro ADXL335 utilizzato come inclinometro, e l’Azimut misurato con la Bussola Elettronica CMP12. Se questi valori non coincidono, i motori dei 2 assi X e Y lungo i quali l’inseguitore può muoversi si movimentano riportando il sistema ai valori determinati, cioè rivolto verso il sole.

MODULO IoT

Una volta determinate Altezza Solare e Azimut, e posizionato i pannelli solari nella direzione del sole, il sistema memorizza i propri dati inviandoli, attraverso applicazioni PHP che fungono da API (), ad un Database posizionato su un server web.

L’invio dei dati è possibile attraverso l’utilizzo del Modulo GSM SIM900, che attraverso una SIM dati permette all’inseguitore di connettersi alla rete e di potersi quindi collegarsi al Database.

Questi dati sono quindi visualizzati da una pagina internet che funge da monitoraggio dei valori Geografici, Ambientali e di produzione Energetica.

E’ stata anche realizzata una App sviluppata in C# che permette di visualizzare l’andamento della produzione nelle 24 ore, sia in forma di dati che graficamente, e di fare impostazioni manuali sul sistema.

ELEMENTI PRINCIPALI CHE COSTITUISCONO L’INSEGUITORE SOLARE

Microcontrollore Arduino

La gestione dell’inseguitore è affidata ad un microcontrollore a 8 bit Arduino Mega 2560 con processore ATmega2560 16MHz il quale dispone di 54 pin di Input/Output digitali di cui 15 utilizzabili come uscite PWM (Pulse Width Modulation) e 16 ingressi analogici. Per la comunicazione con altri dispositivi è dotato di 4 pin seriali hardware, oltre alla possibilità di utilizzare una comunicazione I2C (abbreviazione di Inter Integrated Circuit) e SPI. I²C (pr. i-quadro-ci o i-due-ci), è un sistema di comunicazione seriale bifilare utilizzato tra circuiti integrati. Il classico bus I²C è composto da almeno un componente master ed uno slave (risp. letteralmente “capo, padrone” e “sottoposto, schiavo”). La situazione più frequente vede un singolo master e più slave; possono tuttavia essere usate architetture multimaster e multislave in sistemi più complessi. Il bus è stato sviluppato dalla Philips nel 1982 e, dopo la realizzazione di centinaia di componenti e sistemi negli anni ’80, nel 1992 è stata prodotta la prima versione del protocollo che ha subìto diversi aggiornamenti ed ha generato bus simili, uno dei quali per motivi squisitamente commerciali, di brevetto Intel, nel 1995. Di fatto i due standard si assomigliano in molti aspetti quali l’arbitraggio del bus (cioè la scelta nel caso di più possibili master di quale dispositivo debba assumere questa funzione di controllo del bus), l’alta impedenza in condizione di rilascio bus, il sistema di indirizzamento ed il protocollo ACK/NACK (vi sono però differenze da tenere presenti). Serial Peripheral Interface (SPI) è un protocollo dati seriale sincrono utilizzato dai microcontrollori per comunicare rapidamente con uno o più dispositivi periferici su brevi distanze. Inoltre, sono disponibili una connessione USB e un jack di alimentazione. L’oscillatore interno che si occupa di gestire il funzionamento è a cristallo da 16 MHz. Per quanto riguarda la memoria sono a disposizione 4096 byte di EEPROM che non viene cancellata allo spegnimento della scheda. La tensione di Input/Output vale 5 V mentre la tensione di ingresso nominale può variare da 7 V a 12 V

Arduino MEGA 2560

Ricevitore GPS

La ricezione dei dati geografici del luogo in cui l’inseguitore solare si trova è compito del modulo GPS
GY-NEO6MV2 dotato di un’apposita antenna. Per un corretto funzionamento è necessario fornire un’alimentazione compresa tra 3 V e 5 V. I piedini dedicati all’elaborazione dei dati sono un trasmettitore (Tx) e un ricevitore (Rx) da collegare ad Arduino.

Ricevitore GPS

Bussola Elettronica CPSS12

Un modulo dedicato all’implementazione di una bussola elettronica CMPS12 fornisce il valore in gradi relativo alla posizione orizzontale dell’inseguitore solare da confrontare con il calcolo dell’azimut per verificare un posizionamento corretto.

Bussola CMPS12

Inclinometro ADXL335

Un modulo che funge da inclinometro GY-61 ADXL335 rileva l’inclinazione del pannello solare affinché sia possibile confrontare tale valore espresso in gradi con l’altezza solare calcolata verificando, così, la correttezza del posizionamento. La tensione di alimentazione può variare da 3 V a 5 V e i piedini da connettere ad Arduino su cui il sensore fornisce i dati corrispondono agli assi x, y, z; l’inclinazione viene determinata a partire dai valori degli assi x e y.

Inclinometro ADXL335

Modulo GSM SIM900

Un modulo GSM SIM900 con antenna si occupa di caricare i dati riguardanti altezza solare e azimut su un database per poi costruire un grafico grazie all’applicazione C# e del download di valori relativi al luogo in cui si desidera installare l’inseguitore solare. La tensione di alimentazione del modulo può giungere sino a 12 V e i piedini che ne determinano il funzionamento sono un trasmettitore (Tx) e un ricevitore (Rx) da collegare ad Arduino.

Modulo GSM SIM900

Controller Motori Ponte H L298

La gestione dei motori è regolata da un ponte H pilotato da un segnale PWM generato da Arduino. La PWM è una forma di modulazione digitale che permette di ottenere una tensione variabile che dipende dal duty cycle (rapporto tra la durata dell’impulso positivo e quello dell’intero periodo) ed è impiegata per controllare la velocità dei due motori collegati al dispositivo. Inoltre è possibile comandare l’inversione della polarità dei motori in corrente continua mediante un sistema di interruttori interni, settando ad un valore alto o basso il pin a cui questa funzione del ponte è collegata, senza ricorrere ad un’inversione manuale dei poli.

Controller Motori con Ponte H L298

La presenza di 4 fine corsa consente al software di interrompere il movimento dei motori quando sono premuti per evitare guasti nel caso in cui la rotazione e l’inclinazione del pannello risulti eccessiva.

PIEDINATURA DEI COLLEGAMENTI:

Pin A0 inclinometro: asse x
Pin A1inclinometro: asse y
Pin A2inclinometro: asse z
Pin A8tensione pannello a concentrazione
Pin A9tensione pannello diretto
Pin 43accensione modulo GSM da software
Pin 11direzione_1 motore azimut
Pin 12direzione_2 motore azimut
Pin 10velocità motore azimut
Pin 6direzione_1 motore altezza solare
Pin 5direzione_2 motore altezza solare
Pin 9velocità motore altezza solare
Pin 50modulo GSM (TX)
Pin 53modulo GSM (RX)
Pin 2fine corsa altezza solare minima
Pin 3fine corsa altezza solare massima
Pin 16modulo GPS (RX della scheda)
Pin 17modulo GPS (TX della scheda)
Pin 18fine corsa azimut verso E
Pin 19fine corsa azimut verso W
Pin 20bussola (SDA)
Pin 21bussola (SCL)

Ogni componente è dotato di un piedino di alimentazione (VCC) piedino che funge da massa (GND).

PROGRAMMA ARDUINO COMPLETO


/* Programma Inseguitore Solare Astronomico:
* Realizza i Calcoli Astronomici per determinare l'Azimut e Altezza Solare
* Confronta i valori calcolati con quelli letti dai sensori (Inclinometro e Bussola)
* Movimenta gli assi per portare i Pannelli Solari in direzione del Sole
* Invia al Database sul Server Web i valori Geografici, Ambientali e di produzione
*/

#include 
#include 
#include 

Stepper stepperAltezza(48, 7, 8); //motore altezza solare
Stepper stepperAzimut(48, 9, 10); //motore azimut
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

int contatore = 0;
//contatore della funzione safeMode()
int byteGPS=-1;
//variabile della funzione sincronizzaGps
char linea[100] = "";
//variabile della funzione sincronizzaGps
char comandoGPR[7] = "$GPRMC";
//variabile della funzione sincronizzaGps
int cont=0;
//variabile della funzione sincronizzaGps
int bien=0;
//variabile della funzione sincronizzaGps
int conta=0;
//variabile della funzione sincronizzaGps
int indices[13];
//variabile della funzione sincronizzaGps
int posizioneAltezza[2];
//posizione attuale [1] , posizione precedente [0]
int posizioneAzimut[2];
//posizione attuale [1] , posizione precedente [0]
int fcInizioAltezza = LOW;
//fine corsa iniziale altezza pin 6
int fcInizioAzimut = LOW;
//fine corsa iniziale azimut pin 13
int fcFineAltezza = LOW;
//fine corsa finale altezza pin 6
int fcFineAzimut = LOW;
//fine corsa finale azimut pin 13
int avanti = 0;
//pulsante avanti nero
int indietro = 0;
//pulsanti indietro rosso / conferma introduzione coordinate
int ore = -1;int minuti = -1;int secondi = -1; //inizializzazione tempo
int giorno = 0;int mese = 0;int anno = 0;
//inizializzazione data
int lag = -1;int lam = -1;int las = -1;
//inizializzazione latitudine ° ' "
int logg = -1;int lom = -1;int los = -1;
//inizializzazione longitudine ° ' "
float latitudine = -1.0;
//inizializzazione variabile della latitudine
float longitudine = -1.0;
//inizializzazione variabile della longitudine
float meridiano = 15.0;
//0.26179939 meridiano di riferimento 15°0'0" (Etna)
boolean semaforoCoordinate = true;
boolean semaforoGps = true;
int soglia = 40;
//limite vento: 10m/s corrispondono a 40
int wind = 0;
//inizializza la variabile che contiene il valore del vento
int altezzaMin = 0;
//inizializza posizione in gradi della minima altezza
int altezzaMax = 90;
//inizializza altezza massima
int azimutEst = 135;
//inizializza l’angolo azimutale iniziale
int azimutOvest = -135;
//inizializza l’angolo azimutale finale
int altezzaOstacolo1 = 0;
//inizializza l’altezza dell’ostacolo1
int azimutOstacolo1 = 135;
//inizializza l’azimut dell’ostacolo1
int altezzaOstacolo2 = 0;
//inizializza l’altezza dell’ostacolo2
int azimutOstacolo2 = -135; ;
//inizializza l’azimut dell’ostacolo2
float tempo = 0.0;
float equazioneTempo = 0.0;
float deltaLongitudine = 0.0;
float mezzogiorno = 0.0;
//sull'orologio dell'osservatore; considero l'ora solare
float angoloOrario = 0.0;
//angolo orario
float declinazione = 0.0;
//declinazione
float altezzaSolare = 0.0;
//altezza solare
float azimut = 0.0;
//azimut

void setup(){
  Serial.begin(4800);
  //inizializza la serila a 4800 per comunicare con il GPS
  stepperAltezza.setSpeed(10);
  stepperAzimut.setSpeed(10);
  lcd.begin(2, 16);
  for (int i=0;i<100;i++){
  linea[i]=' ';}
  posizioneAltezza[0]=altezzaMin;
  posizioneAzimut[0]=azimutEst;
  posizioneAltezza[1]=altezzaMin;
  posizioneAzimut[1]=azimutEst;
}

void loop(){
  if (!safeMode()){
    int selettore = analogRead(3);
    if (selettore <= 128){
      //richiama la funzione automatico
      if ((giorno > 0)&&(mese > 0)&&(anno > 0)&&(ore >= 0)&&(minuti >= 0)&&(secondi >= 0)&&(lag >=
      0)&&(lam >= 0)&&(las >= 0)&&(logg >= 0)&&(lom >= 0)&&(los >= 0)&&(DateTime.available())){
        semaforoCoordinate = true;
        semaforoGps = true;
        automatico();
      }
      else {
        lcd.setCursor(0, 0);
        lcd.print("dati non validi!");
        lcd.setCursor(0, 1);
        lcd.print(" sincronizzare ");
        delay(100);
        semaforoGps = true;
        semaforoCoordinate = true;
      }
    }
    if ((selettore > 128)&&(selettore <= 298)) {
      // richiama la funzione manuale
      lcd.setCursor(0, 0);
      lcd.print(" funzionamento ");
      lcd.setCursor(0, 1);
      lcd.print(" manuale ");
      delay(100);
      avanti = analogRead(2); // leggo lo stato del pulsante avanti
      indietro = analogRead(1); // leggo lo stato del pulsante indietro
      if ((avanti >=512)&&(indietro >=512)) reset();
      else manuale();
    }
    if ((selettore > 298)&&(selettore <= 426)) {
      // richiama la funzione pc
      lcd.setCursor(0, 0);
      lcd.print("sincronizzazione");
      lcd.setCursor(0, 1);
      lcd.print(" manuale ");
      //delay(2000);
      if (semaforoCoordinate == true){
        digitaCoordinate();
      }
    }
    if ((selettore > 426)&&(selettore <= 768)) {
      // richiama la funzione gps
      lcd.setCursor(0, 0);
      lcd.print("sincronizzazione");
      lcd.setCursor(0, 1);
      lcd.print(" con GPS ");
      sincronizzaGps();
    }
    if (selettore > 768) {
      // richiama la funzione ostacoli
      lcd.setCursor(0, 0);
      lcd.print(" inserimento ");
      lcd.setCursor(0, 1);
      lcd.print(" ostacoli ");
      ostacoli();
    }
  }
}

boolean safeMode(){
  //funzione salvataggio
  int result = false;
  wind = analogRead(4);
  //ingresso analogico del segnale presenza vento
  if (wind > soglia){
    int fcwind = digitalRead(6);
    if (fcwind == LOW) {
      stepperAltezza.step(-1);
      contatore++;
    }
    result = true;
    lcd.setCursor(0, 0); lcd.print(" vento forte ");
    lcd.setCursor(0, 1); lcd.print(" safety mode ");
  }
  else {
    if (contatore > 0){
      contatore--;
      stepperAltezza.step(+1);
      result = true;
      lcd.setCursor(0, 0);
      lcd.print(" vento nornale ");
      lcd.setCursor(0, 1);
      lcd.print(" return back ");
    }
    else {result = false;}
  }
  return result;
}

void sincronizzaGps(){
  //funzione sincronizza con GPS
  while (Serial.available() && (semaforoGps == true)){
    byteGPS=Serial.read();
    linea[conta]=byteGPS;
    // If there is serial port data, it is put in the buffer
    conta++;
    if (byteGPS==13){
      // If the received byte is = to 13, end of transmission
      cont=0;
      bien=0;
      for (int i=1;i<7;i++){
      // Verifies if the received command starts with $GPR
        if (linea[i]==comandoGPR[i-1]){
          bien++;
        }
      }
      if(bien==6){
        // If yes, continue and process the data
        for (int i=0;i<100;i++){
          if (linea[i]==','){
            // check for the position of the "," separator
            indices[cont]=i;
            cont++;
          }
          if (linea[i]=='*'){
            // ... and the "*"
            indices[12]=i;
            cont++;
          }
        }
        int ver = indices[1];
        if (linea[ver+1]=='V'){
          //dati validi
          lcd.setCursor(0, 0);
          lcd.print(" dati validi ");
          lcd.setCursor(0, 1);
          lcd.print("OK!");
          delay(1000);
          int j=indices[0];
          char c=linea[j+1]; ore = 10*(c-'0');c=linea[j+2];
          ore = ore + (c-'0')+1;
          c=linea[j+3];
          minuti = 10*(c-'0');c=linea[j+4]; minuti = minuti + (c-'0');
          c=linea[j+5];
          secondi = 10*(c-'0');c=linea[j+6]; secondi = secondi + (c-'0');
          j=indices[2];
          c=linea[j+1];
          lag = 10*(c-'0');c=linea[j+2];
          lag = lag + (c-'0');
          c=linea[j+3];
          lam = 10*(c-'0');c=linea[j+4];
          lam = lam + (c-'0');
          c=linea[j+6];
          las = 10*(c-'0');c=linea[j+7];
          las = las + (c-'0');
          las = round(las*0.6);
          j=indices[4];
          c=linea[j+1];logg = 100*(c-'0');c=linea[j+2];logg = logg + (10*(c-'0'));c=linea[j+3];logg = logg + (c-'0');
          c=linea[j+4];
          lom = 10*(c-'0');c=linea[j+5];
          lom = lom + (c-'0');
          c=linea[j+7]
          ;los = 10*(c-'0');c=linea[j+8];
          los = los + (c-'0');
          los = round(los*0.6);
          j=indices[8];
          c=linea[j+1];
          giorno = 10*(c-'0');c=linea[j+2]; giorno = giorno + (c-'0');
          c=linea[j+3];
          mese = 10*(c-'0');c=linea[j+4];
          mese = mese + (c-'0');
          c=linea[j+5];
          anno = 10*(c-'0');c=linea[j+6];
          anno = anno + (c-'0');
          semaforoGps = false;
          time_t sincro = DateTime.makeTime(secondi, minuti, ore, giorno, mese, anno );
          DateTime.sync(sincro);
          latitudine = lag + (lam/60.0) + (las/3600.0);latitudine = radianti(latitudine);
          longitudine = logg + (lom/60.0) + (los/3600.0);//longitudine = radianti(longitudine);
          reset();
        }
      }
      conta=0;
      // Reset the buffer
      for (int i=0;i<100;i++){
        linea[i]=' ';
      }
    }
  }
}

void manuale(){
  //funzione manuale
  lcd.setCursor(0, 0); lcd.print(" funzionamento ");
  lcd.setCursor(0, 1); lcd.print(" manuale ");
  int motore = analogRead(0);
  if (motore <= 512){
    //seleziona motore altezza
    avanti = analogRead(2);
    // leggo lo stato del pulsante avanti
    indietro = analogRead(1);
    // leggo lo stato del pulsante indietro
    if (avanti >=512){
      //richiesta avanti
      if ((posizioneAltezza[1]+1) <= altezzaMax){
        //vedo se la richiesta è corretta
        fcFineAltezza = digitalRead(6);
        if (fcFineAltezza == LOW){
          stepperAltezza.step(+1);
          delay(10);
          posizioneAltezza[0]=posizioneAltezza[1];
          posizioneAltezza[1]=posizioneAltezza[1]+1;
        }
        else {
          lcd.setCursor(0, 0);
          lcd.print("errore posizione");
          lcd.setCursor(0, 1);
          lcd.print(" resettare ");
          reset();
        }
          // segnala errore
      }
      /*else {lcd.setCursor(0, 0);
        lcd.print("errore posizione");
        lcd.setCursor(0, 1);
        lcd.print(" resettare ");
        reset();}*/
        // segnala errore
    }
    if (indietro >=512){
      //richiesta indietro
      if ((posizioneAltezza[1]-1) >= altezzaMin){
        fcInizioAltezza = digitalRead(6);
        if (fcInizioAltezza == LOW){
          stepperAltezza.step(-1);
          delay(10);
          posizioneAltezza[0]=posizioneAltezza[1];
          posizioneAltezza[1]=posizioneAltezza[1]-1;
        }
        else {
          lcd.setCursor(0, 0);
          lcd.print("errore posizione");
          lcd.setCursor(0, 1);
          lcd.print(" resettare ");
          reset();
        }
        // segnala errore
      }/*else {lcd.setCursor(0, 0);
      lcd.print("errore posizione");
      lcd.setCursor(0, 1);
      lcd.print(" resettare ");
      reset();}*/
      // segnala errore
    }
  }
  else {
    //seleziona motore azimut
    avanti = analogRead(2);
    // leggo lo stato del pulsante avanti
    indietro = analogRead(1);
    // leggo lo stato del pulsante indietro
    if (avanti >=512){
      //richiesta avanti
      if ((posizioneAzimut[1]-1) >= azimutOvest){ //>-135 corretto con >=-135
        fcFineAzimut = digitalRead(13);
        if (fcFineAzimut == LOW){
          stepperAzimut.step(-1);
          delay(10);
          posizioneAzimut[0]=posizioneAzimut[1];
          posizioneAzimut[1]=posizioneAzimut[1]-1;
        }
        else {
          lcd.setCursor(0, 0);
          lcd.print("errore posizione");
          lcd.setCursor(0, 1);
          lcd.print(" resettare ");
          reset();
        }
        // segnala errore
      }
      /*else {lcd.setCursor(0, 0);
      lcd.print("errore posizione");
      lcd.setCursor(0, 1);
      lcd.print(" resettare ");
      reset();}*/
      // segnala errore
    }
    if (indietro >=512){
      //richiesta indietro
      if ((posizioneAzimut[1]+1) <= azimutEst){
        fcInizioAzimut = digitalRead(13);
        if (fcInizioAzimut == LOW){
          stepperAzimut.step(+1);
          delay(10);
          posizioneAzimut[0]=posizioneAzimut[1];
          posizioneAzimut[1]=posizioneAzimut[1]+1;
        }
        else {
          lcd.setCursor(0, 0);
          lcd.print("errore posizione");
          lcd.setCursor(0, 1);
          lcd.print(" resettare ");
          reset();
        }
        // segnala errore
      }
        /*else {lcd.setCursor(0, 0);
        lcd.print("errore posizione");
        lcd.setCursor(0, 1);
        lcd.print(" resettare ");
        reset();}*/
        // segnala errore
    }
  }
}
void reset(){
  //funzione reset
  lcd.setCursor(0, 0); lcd.print(" reset in corso ");
  lcd.setCursor(0, 1); lcd.print("wait");
  fcInizioAltezza = digitalRead(6);
  //fine corsa iniziale motore altezza
  while (fcInizioAltezza != HIGH){
    wind = analogRead(4);
    if (wind > soglia){break;}
    stepperAltezza.step(-1);
    delay(100);
    fcInizioAltezza = digitalRead(6);
  }
  int alCount = 1;
  while (alCount <= altezzaMin){
    wind = analogRead(4);
    if (wind > soglia) break;
    stepperAltezza.step(+1);
    delay(100);
    alCount++;
  }
  fcInizioAzimut = digitalRead(13);
  //fine corsa iniziale motore azimut
  while (fcInizioAzimut != HIGH){
    wind = analogRead(4);
    if (wind > soglia) break;
    stepperAzimut.step(+1);
    delay(100);
    fcInizioAzimut = digitalRead(13);
  }
  int azCount = 1;
  while (azCount <= (135 - azimutEst)){
    wind = analogRead(4);
    if (wind > soglia) break;
    stepperAzimut.step(-1);
    delay(100);
    azCount++;
  }
  posizioneAltezza[0]=altezzaMin;
  //reset posizione iniziale
  posizioneAzimut[0]=azimutEst;
  //reset posizione iniziale
  posizioneAltezza[1]=altezzaMin;
  //reset posizione attuale
  posizioneAzimut[1]=azimutEst;
  //reset posizione attuale
  lcd.clear();
}

void automatico(){
  //funzionamento automatico
  unsigned long prevtime = DateTime.now();
  while( prevtime == DateTime.now() );
  //attende un secondo
  DateTime.available();
  lcd.setCursor(0, 1); lcd.print(" : : ");
  lcd.setCursor(0, 1); stampaData(DateTime.Hour);
  lcd.setCursor(3, 1); stampaData(DateTime.Minute);
  lcd.setCursor(6, 1); stampaData(DateTime.Second);
  if ((DateTime.Hour==22)&&(DateTime.Minute==00)&&(DateTime.Second==00)){
    reset();
    lcd.setCursor(0, 0); lcd.print(" good nigth ");
    lcd.setCursor(0, 1); lcd.print(" see tomorrow ");
    delay(3000);
    lcd.setCursor(0, 0); lcd.print("");
    lcd.setCursor(0, 1); lcd.print("");
  }
  else {
    if (DateTime.Second==0){
      tempo = float(DateTime.Hour) + (float(DateTime.Minute)/60) + (float(DateTime.Second)/3600);
      equazioneTempo = -(9.87*sin(2*2*PI*(progressivo()-81)/365.0)-7.67*sin(2*PI*(progressivo()-1)/365.0));
      deltaLongitudine = meridiano - longitudine;
      mezzogiorno = 12.00 + (equazioneTempo/60.0) + (4/60.0)*(deltaLongitudine);
      //mezzogiorno del
      luogo
      angoloOrario = (mezzogiorno - tempo)*(2*PI)*15/360;
      //angolo orario
      declinazione = 0.4092797*sin((2*PI)*(284+progressivo())/365);
      //declinazione
      altezzaSolare =
      arcsin(sin(latitudine)*sin(declinazione)+cos(latitudine)*cos(declinazione)*cos(angoloOrario));
      //altezza solare
      azimut = arcsin(cos(declinazione)*sin(angoloOrario)/cos(altezzaSolare));
      //azimut
      if ((azimutOvest < gradi(azimut))&&(gradi(azimut) azimutOstacolo1){
          if ((gradi(altezzaSolare) > altezzaOstacolo1)&&(gradi(altezzaSolare) > altezzaMin)){
            posizione();
          } 
          else {
            lcd.setCursor(0, 0);
            lcd.print("altezza > ");
            lcd.setCursor(0, 1);
            lcd.print("altezzaOstacolo1");
          }
        }
        if (gradi(azimut) < azimutOstacolo2){
          if ((gradi(altezzaSolare) > altezzaOstacolo2)&&(gradi(altezzaSolare) > altezzaMin)){
            posizione();
          } 
          else {
            lcd.setCursor(0, 0);
            lcd.print("altezza > ");
            lcd.setCursor(0, 1);
            lcd.print("altezzaOstacolo2");
          }
        }
        if ((gradi(azimut)azimutOstacolo2)){
          if (gradi(altezzaSolare) > altezzaMin){
            posizione();
          } 
          else {
            lcd.setCursor(0, 0);
            lcd.print("altezza > ");
            lcd.setCursor(0, 1);
            lcd.print("altezza minima ");
          }
        }
      } 
      else {
        lcd.setCursor(0, 0);
        lcd.print("azimut fuori ");
        lcd.setCursor(0, 1);
        lcd.print("dai limiti ");
      }
    }
  }
}
void digitaCoordinate(){
  //funzione inserimento manuale coordinate
  indietro = analogRead(1);
  // leggo lo stato del pulsante indietro
  lcd.setCursor(0, 0); lcd.print("dd | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (giorno == 0){giorno = 1;}
  giorno = ciclo(giorno,31,1,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("mm | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (mese == 0){mese = 1;}
  mese = ciclo(mese,12,1,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("yy | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (anno == 0){anno = 9;}
  anno = ciclo(anno,29,9,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("hh | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (ore == -1){ore = 0;}
  ore = ciclo(ore,23,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("mm | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (minuti == -1){minuti = 0;}
  minuti = ciclo(minuti,59,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("ss | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (secondi == -1){secondi = 0;}
  secondi = ciclo(secondi,59,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("la°| FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (lag == -1){lag = 0;}
  lag = ciclo(lag,89,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("la' | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (lam == -1){lam = 0;}
  lam = ciclo(lam,59,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("la''| FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (las == -1){las = 0;}
  las = ciclo(las,59,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("lo° | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (logg == -1){logg = 0;}
  logg = ciclo(logg,359,0,3,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("lo' | FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (lom == -1){lom = 0;}
  lom = ciclo(lom,59,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("lo''| FW | NEXT");
  lcd.setCursor(0, 1); lcd.print(" |black| red ");
  if (los == -1){los = 0;}
  los = ciclo(los,59,0,0,0);
  reset();
  time_t sincro = DateTime.makeTime(secondi, minuti, ore, giorno, mese, anno );
  DateTime.sync(sincro);
  latitudine = lag + (lam/60.0) + (las/3600.0);latitudine = 2*PI*latitudine/360;
  longitudine = logg + (lom/60.0) + (los/3600.0);//longitudine = 2*PI*longitudine/360;
  semaforoCoordinate = false;
}

void ostacoli(){
  //funzione inserimento coordinate ostacoli
  indietro = analogRead(1);
  // leggo lo stato del pulsante indietro
  lcd.setCursor(0, 0); lcd.print("altezza minima ");
  lcd.setCursor(0, 1); lcd.print(" ");
  altezzaMin = ciclo(altezzaMin,90,0,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("azimut est ");
  lcd.setCursor(0, 1); lcd.print(" ");
  azimutEst = ciclo(azimutEst,0,135,3,1);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("azimut ovest ");
  lcd.setCursor(0, 1); lcd.print(" ");
  azimutOvest = ciclo(azimutOvest,0,-135,33,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("altezza ostac.1 ");
  lcd.setCursor(0, 1); lcd.print(" ");
  altezzaOstacolo1 = ciclo(altezzaOstacolo1,90,1,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("azimut ostac.1 ");
  lcd.setCursor(0, 1); lcd.print(" ");
  azimutOstacolo1 = ciclo(azimutOstacolo1,0,135,3,1);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("altezza ostac.2 ");
  lcd.setCursor(0, 1); lcd.print(" ");
  altezzaOstacolo2 = ciclo(altezzaOstacolo2,90,1,0,0);
  indietro = 0;
  lcd.setCursor(0, 0); lcd.print("azimut ostac.2 ");
  lcd.setCursor(0, 1); lcd.print(" ");
  azimutOstacolo2 = ciclo(azimutOstacolo2,0,-135,33,0);
  indietro = 0;
}
int progressivo(){
  //calcolo del numero progressivo corrispondente al giorno dell’anno
  int pro = 0;
  int anno = 1900 + int(DateTime.Year);
  int mese = int(DateTime.Month);
  int giorno = int(DateTime.Day);
  int bise = bisestile(anno);
  if (mese==1){pro=giorno;}
  if (mese==2){pro=0*30+1*31+giorno;}
  if (mese==3){pro=0*30+1*31+giorno+bise;}
  if (mese==4){pro=0*30+2*31+giorno+bise;}
  if (mese==5){pro=1*30+2*31+giorno+bise;}
  if (mese==6){pro=1*30+3*31+giorno+bise;}
  if (mese==7){pro=2*30+3*31+giorno+bise;}
  if (mese==8){pro=2*30+4*31+giorno+bise;}
  if (mese==9){pro=2*30+5*31+giorno+bise;}
  if (mese==10){pro=3*30+5*31+giorno+bise;}
  if (mese==11){pro=3*30+6*31+giorno+bise;}
  if (mese==12){pro=4*30+6*31+giorno+bise;}
  return pro;
}

int bisestile(int a){
  //funzione per scoprire se l’anno in corso è bisestile
  int bis = 28;
  if(a%4==0){
    if(a%100==0){
      if(a%400==0) bis = 29;
      else bis = 28;
    }
    else bis = 29;
  }
  else bis = 28;
  return bis;
}

int gradi( float x){
  //trasforma i radianti in gradi
  int gra = round(x*360.0/(2*PI));
  return gra;
}

float radianti( float x){
  //trasforma I gradi in radianti
  float rad = 2*PI*x/360.0;
  return rad;
}

float arcsin(float x){
  //funzione arcsin()
  float rad = 2 *arctan(x/(1+sqrt(1-pow(x,2))));
  return rad;
}

float arctan(float x){
  //funzione arctan()
  float rad = 0.0;
  for (int i = 0 ; i <= 200 ; i=i+1 ){
  rad = rad + (pow(-1,i)*pow(x,2*i+1))/(2*i+1);} // con |x|<1
  return rad;
}

void stampaValore(int x){
  //stampa sul display LCD
  if (x < 10){
  lcd.setCursor(0, 1);
  lcd.print("0");
  lcd.setCursor(1, 1);
  lcd.print(x);
  }else {lcd.setCursor(0, 1);
  lcd.print(x);}
}

void stampaValore3(int x){
  //stampa sul display LCD
  if (x < 10){
    lcd.setCursor(0, 1);
    lcd.print("00");
    lcd.setCursor(2, 1);
    lcd.print(x);
  }
  else {
    if ((x >=10)&&(x < 100)){
      lcd.setCursor(0, 1);
      lcd.print("0");
      lcd.setCursor(1, 1);
      lcd.print(x);
    }
    else{
      lcd.setCursor(0, 1);
      lcd.print(x);
    }
  }
}

void stampaValore33(int x){
  //stampa sul display LCD
  x=-x;
  if (x < 10){
    lcd.setCursor(0, 1);
    lcd.print("-00");
    lcd.setCursor(3, 1);
    lcd.print(x);
  }
  else {
    if ((x >=10)&&(x < 100)){
      lcd.setCursor(0, 1);
      lcd.print("-0");
      lcd.setCursor(2, 1);
      lcd.print(x);
      }else{lcd.setCursor(0, 1);
      lcd.print(-x);
    }
  }
}

void stampaData(byte digits){
  if(digits < 10)
  lcd.print('0');
  lcd.print(digits,DEC);
}

int ciclo(int a, int b, int c, int d, int e){
  //funzione utilizzata dal caso d’uso inserisci coordinate
  while (indietro <= 512){
    //se non è stato premuto il tasto di conferma
    wind = analogRead(4);
    if (wind > soglia){break;}
    if (d == 0){stampaValore(a);}
    if (d == 3){stampaValore3(a);}
    if (d == 33){stampaValore33(a);}
    delay(200);
    // ritardo per la pressione del tasto
    avanti = analogRead(2); // leggo lo stato del pulsante avanti
    if (avanti >= 512){
      if (e == 0){a++;
        if (a > b){a = c;}
      }
      if (e == 1){
        a--;
        if (a < b){a = c;}
      }
    }
    indietro = analogRead(1);
  }
  return a;
}

void posizione(){
  //funzione utilizzata dal caso d’uso funzionamento automatico
  lcd.setCursor(0, 0); lcd.print(" ");
  lcd.setCursor(0, 0); lcd.print("Alt");
  lcd.setCursor(4, 0); lcd.print(gradi(altezzaSolare));
  lcd.setCursor(8, 0); lcd.print("Azi");
  lcd.setCursor(12, 0); lcd.print(gradi(azimut));
  if (posizioneAltezza[1] != gradi(altezzaSolare)){ //la posizione attuale è diversa da quella precedente
    int passi = gradi(altezzaSolare) - posizioneAltezza[1];
    if (passi>0){ //devo incrementare la posizione
      fcFineAltezza = digitalRead(6);
      boolean uscitaRegolare = true;
      while ((fcFineAltezza == LOW) && (passi > 0)){ //il finecorsa non è premuto oppure ho fatto tutti i
        passi richiesti
        stepperAltezza.step(+1);
        fcFineAltezza = digitalRead(6);
        passi--;
        posizioneAltezza[0] = posizioneAltezza[1]; //registro la posizione attuale dell'altezza solare
        posizioneAltezza[1] = posizioneAltezza[1]+1;
        if ((fcFineAltezza == HIGH) && (passi > 0)) uscitaRegolare = false;
        delay(100);
      }
      if (uscitaRegolare == false) {
        invioSMS();
        reset();
      }//segnala l'errore che il sistema comanda il movimento ma il generatore è già arrivato a finecorsa
    } 
    else {
      if (passi<0){ //devo decrementare la posizione
        fcInizioAltezza = digitalRead(6);
        boolean uscitaRegolare = true;
        while ((fcInizioAltezza == LOW) && (passi < 0)){ //il finecorsa non è premuto oppure ho fatto tutti i
          passi richiesti
          stepperAltezza.step(-1);
          fcInizioAltezza = digitalRead(6);
          passi++;
          posizioneAltezza[0] = posizioneAltezza[1]; //registro la posizione attuale dell'altezza solare
          posizioneAltezza[1] = posizioneAltezza[1]-1;
          if ((fcInizioAltezza == HIGH) && (passi > 0)) uscitaRegolare = false;
          delay(100);
        }
        if (uscitaRegolare == false) {
          invioSMS();
          reset();
        }
      }
    } //segnala l'errore che il sistema comanda il movimento ma il generatore è già arrivato a
    finecorsa
  }
  if (posizioneAzimut[1] != gradi(azimut)){
    int passi = posizioneAzimut[1] - gradi(azimut);
    if (passi>0){ //devo incrementare la posizione
      fcFineAzimut = digitalRead(13);
      boolean uscitaRegolare = true;
      while ((fcFineAzimut == LOW) && (passi > 0)){ //il finecorsa non è premuto oppure ho fatto tutti i
        passi richiesti
        stepperAzimut.step(-1);
        fcFineAzimut = digitalRead(6);
        passi--;
        posizioneAzimut[0] = posizioneAzimut[1]; //registro la posizione attuale dell'altezza solare
        posizioneAzimut[1] = posizioneAzimut[1]-1;
        if ((fcFineAzimut == HIGH) && (passi > 0)) uscitaRegolare = false;
        delay(100);
      }
      if (uscitaRegolare == false) {
        invioSMS();
        reset();
      }//segnala l'errore che il sistema comanda il movimento ma il generatore è già arrivato a finecorsa
    }
    else{
      if (passi<0){ //devo decrementare la posizione
        fcInizioAzimut = digitalRead(13);
        boolean uscitaRegolare = true;
        while ((fcInizioAzimut == LOW) && (passi < 0)){ //il finecorsa non è premuto oppure ho fatto tutti i
          passi richiesti
          stepperAzimut.step(+1);
          fcInizioAzimut = digitalRead(6);
          passi++;
          posizioneAzimut[0] = posizioneAzimut[1]; //registro la posizione attuale dell'altezza solare
          posizioneAzimut[1] = posizioneAzimut[1]+1;
          if ((fcFineAzimut == HIGH) && (passi > 0)) uscitaRegolare = false;
          delay(100);
        }
        if (uscitaRegolare == false) {
          invioSMS();
          reset();
        }//segnala l'errore che il sistema comanda il movimento ma il generatore è già arrivato a finecorsa
      }
    }
  }
}

Progetto realizzato dagli studenti: Luigi Negri e Nicola Sassi – AS 2021-22