Ascensore con arduino

Ciao a tutti :slight_smile:
per il mio esame di maturità pensavo di progettare un ascensore intelligente tramite arduino, qualche buon anima mi può verificare il programma facendomi notare eventuali (anzi probabili) errori / incongruenze? Sono alla prima esperienza di programmazione :fearful:
grazie in anticipo

#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>

//VARIABILI//
int PA = 0; //Piano attuale
int PC = 0; // Piano chiamato
int val1 = 0; // Valore finecorsa piano 0
int val2 = 0; // Valore finecorsa piano 1
int val3 = 0; // Valore finecorsa piano 2
int val4 = 0; // Valore finecorsa piano 3
int val5 = 0; // Valore tasto al piano 0
int val6 = 0; // Valore tasto al piano 1
int val7 = 0; // Valore tasto al piano 2
int val8 = 0; // Valore tasto al piano 3

//TASTI//
int TP0 = 2; // Tasto piano 0
int TP1 = 3; // Tasto piano 1
int TP2 = 4; // Tasto piano 2
int TP3 = 5; // Tasto piano 3

// FINECORSA//
int FP0 = 6; // Finecorsa piano 0
int FP1 = 7; // Finecorsa piano 1
int FP2 = 8; // Finecorsa piano 2
int FP3 = 9; // Finecorsa piano 3

//MOTORE ASCENSORE//
int MASU = 10; // Motore ascensore SU
int MAGIU = 11; // Motore ascensore GIU
// MOTORE PORTE//
int MPA = 12; // Motore porte aperte
int MPC = 13; // Motore porte chiuse

String readString; //string
boolean LEDON = false; //LED status flag

//CONFIGURAZIONE PIN//
void setup()
{
pinMode (MASU, OUTPUT);
pinMode (MAGIU, OUTPUT);
pinMode (MPA, OUTPUT);
pinMode (MPC, OUTPUT);
pinMode(TP0, INPUT);
pinMode(TP1, INPUT);
pinMode(TP2, INPUT);
pinMode(TP3, INPUT);
pinMode(FP0, INPUT);
pinMode(FP1, INPUT);
pinMode(FP2, INPUT);
pinMode(FP3, INPUT);
Serial.begin(9600);
}

//PROGRAMMA//
void loop( )
{

//CONTROLLO PIANO ATTUALE//
finecorsa:
val1 = digitalRead(FP0);
val2 = digitalRead(FP1);
val3 = digitalRead(FP2);
val4 = digitalRead(FP3);

if (val1 == HIGH) // Controllo del finecorsa del Piano 0
{
PA = 0 ; // Si è il piano terra
goto pulsanti;
}
else if (val2 == HIGH) // Controllo del finecorsa del Piano 1
{
PA = 1 ; // Si è il primo piano
goto pulsanti;          
}
else if (val3 == HIGH) // Controllo del finecorsa del Piano 2
{
PA = 2 ; // Si è il secondo piano
goto pulsanti;
}
else if (val4 == HIGH) // Controllo del finecorsa del Piano 2
{
PA = 2 ; // Si è il terzo piano
goto pulsanti;
}

//CONTROLLO PULSANTI//
pulsanti:
val5 = digitalRead(TP0);
val6 = digitalRead(TP1);
val7 = digitalRead(TP2);
val8 = digitalRead(TP3);

if (val5 == HIGH) // Controlla se il piano da cui è stato chiamato l'ascensore è il Piano 0
{
PC = 0; // Si è stato chiamato dal Piano 0
goto motorecabina;
}
else if (val6 == HIGH) // Controlla se il piano da cui è stato chiamato l'ascensore è il Piano 1
{
PC = 1; // Si è stato chiamato dal Piano 1
goto motorecabina;
}
else if (val7 == HIGH) // Controlla se il piano da cui è stato chiamato l'ascensore è il Piano 2
{
PC = 2; // Si è stato chiamato dal Piano 2
goto motorecabina;
}
else if (val8 == HIGH) // Controlla se il piano da cui è stato chiamato l'ascensore è il Piano 3
{
PC = 3; // Si è stato chiamato dal Piano 3
goto motorecabina;
}

goto pulsanti;

// MOTORE ASCENSORE//
motorecabina:
if (PC > PA) // La cabina è sotto la destinazione
{
digitalWrite(MASU, HIGH);
digitalWrite(MAGIU, LOW);
PA++;
goto destinazione;
}
else if (PC < PA) // La cabina è sopra la destinazione
{
digitalWrite(MASU, LOW);
digitalWrite(MAGIU, HIGH);
PA--;
goto destinazione;
}

//CONTROLLO DESTINAZIONE//
destinazione:
if (PC == PA) //Controlla se la destinazione è stata raggiunta
{
goto motoreporte;
}
else if (PC != PA) //Controlla se la destinazione non è stata raggiunta      
{
goto motorecabina;
}

// MOTORE PORTE//
motoreporte:
delay(3000); 
digitalWrite(MPA, HIGH);
digitalWrite(MPC, LOW);
delay(5000); 
digitalWrite(MPA, LOW);
digitalWrite(MPC, LOW);
goto finecorsa;

}

Funzionamento:

  1. I finecorsa rilevano il piano in cui la cabina si trova al momento della chiamata
  2. Viene effettuato un controllo dei tasti, se nessun tasto è premuto ritorna a ricontrollare il ciclo, se un tasto è premuto si va al motore della cabina
  3. Vengono distinti due casi, che portano comunque al controllo della destinazione
  4. Se la destinazione coincide allora si va al motore delle porte, se non coincide si ritorna al motore della cabina
  5. Si aspettano tot secondi e le porte si aprono (quindi si parte dal presupposto che le porte siano chiuse) e dopo tot secondi si fermano e le porte rimangono aperte fino ad un eventuale chiamata

ciao, prima di tutto è gradita una presentazione nell'apposito topic e la lettura del regolamento prima di proporre quesiti.

a colpo d'occhio, inizierei a eliminare tutti "goto". non è proprio un errore, ma sono da evitare il più possibile, perchè possono causare malfunzionamenti del programma.

Grazie, mi sono appena presentato :) Comunque avevo letto da qualche parte che il goto non era la migliore cosa... Per caso in questo forum italiano c'è una discussione in cui vengono spiegate chiaramente le varie strutture? Non ho molta dimestichezza con l'inglese e nella pagina "reference" ci capisco poco =(

Cerca in internet un manualetto (pdf) in italiano fatto dalla professoressa Marsella. E' una buona guida. "Programmare Arduino - Marsella" c'e' anche "Applicazioni con Arduino - Marsella"

Se mostrerai il codice, sarà bene, oltre a levare tutti i goto!!:

  • indentare per bene il codice
  • usare una const byte al posto di int per dichiarare i pin
  • pensare di manipolare direttamente le porte tramite i registri dedicati per evitare una sfilza di una dozzina di pinMode ad inizio sketch che sono bruttini da vedere
  • volendo, potresti anche eliminare i delay in fondo al codice e sostituirli con cicli fatti con la lettura di millis
  • non vedo sistemi di debounce sui pulsanti, potresti avere letture multiple
  • nel controllo della posizione dell’ascensore, c’è un else inutile: metti un if(PC==PA) e poi un else if (PC!=PA). E’ ovvio che se PC non è uguale a PA, sia diverso quindi il secondo if dopo l’else non serve

Poi non so se c’è altro, ho dato una rapida occhiata ma col codice non indentato e con tutti quei goto è impossibile seguirne il flusso :sweat_smile: :sweat_smile:

Togliamo i goto piano-piano.

  1. nella prima catena di if-elseif, con val da 1 a 4 quel “goto pulsanti;” non serve.
  2. nella seconda catena di if-elseif con val da 5 a 8, il “goto motorecabina;” togliolo ma aggiungi un else con dentro quel “goto pulsanti;”
else if (val8 == HIGH) // Controlla se il piano da cui è stato chiamato l'ascensore è il Piano 3
{ PC = 3; // Si è stato chiamato dal Piano 3
}
else
{ goto pulsanti;
}

Non è ancora al meglio ma almeno abbiamo tolto un pò di goto. Questo pezzo sarà da mettere dentro a un ciclo do-while
3. anche l’if dopo a “motorecabina:” contiene 2 “goto destinazione;” che non servono
4. il goto finale è inutile, la loop() quando finisce viene di nuovo eseguita dall’inizio.

In generale credo che un programma per gestire un ascensore sarebbe gestito meglio attraverso delle variabili di stato. macchina-a-stati-finiti-e-arduino

Per la gestione dei compiti usando millis() invece che delay() ( da sito di @Leo72 ) programmiamo-i-compiti-con-millis

Solo un'appunto, che non riguarda il software ...

Joninho: ... si parte dal presupposto che le porte siano chiuse ...

Se stai facendolo per una tesi, non presupporre nulla ... si parla, anche se in via teorica, di un'apparato (ascensore, quindi per persone) in cui un malfunzionamento potrebbe avere esiti letali (cadute, porte aperte senza cabina, cabina che si muove mentre passa la persona, ecc) ...

Un professore non ci mette nulla a "strinarti i baffi", come si dice da noi, se per la tesi gli presenti un progetto che non incorpora almeno TUTTI i possibili sistemi di sicurezza, piu uno, trattandosi di potenziale realizzazione pericolosa ... non importa se e' un modellino, e' l'utilizzo di principio che viene considerato ... quindi finecorsa di posizione per la cabina, ai piani, per le porte, magari fotocellula sulla soglia della cabina che impedisce il movimento se qualcuno sta entrando/uscendo, ecc. ecc. ecc.

Meglio farsi criticare per averci messo una sicurezza in piu che si poteva anche evitare, che far bocciare tutto il progetto perche' ne manca una che ci doveva essere ... ;)

Sono perfettamente d'accordo con Etemenanki