Salve a tutti,
forse sono stupido io ma proprio non capisco… sto provando questo sketch che poi dovrà essere implementato in un altro un po’ più complesso (ma non di molto) e non riesco a capire come funziona. questo è lo sketch:
int apriCancelloR = 5;
unsigned long tAttuale;
int ritardo;
int tLimite = 30000;
void setup()
{
delay(250);
//inizializzo la porta seriale
Serial.begin(9600);
Serial.println("prova millis");
pinMode(apriCancelloR, INPUT_PULLUP);
tAttuale = millis();
}
void loop()
{
do
{
ritardo = digitalRead(apriCancelloR);
tAttuale = millis();
Serial.println(tAttuale);
}
while (ritardo == HIGH || tAttuale < tLimite);
if (ritardo == LOW)
{
Serial.println("apro il cancello");
unsigned long tAttuale;
}
else
{
Serial.println("il cancello resta chiuso");
unsigned long tAttuale;
Serial.println(tAttuale);
}
}
per come avevo capito io il funzionamento doveva essere il seguente.
dichiaro le variabili,
le inizializzo nel setup(),
nel loop eseguo il ciclo do while fino a che una delle due condizioni non si avveri,
se premo il bottone esco dal do while
quindi se il bottone è stato premuto apro il cancello e resetto la variabile
oppure non apro il cancello ma la variabile la azzero lo stesso per ricominciare il loop da capo.
E’ corretto il mio ragionamento?
Mmm … in quel programma c’è qualche problema, ed il primo che vedo è :
do {
ritardo = digitalRead(apriCancelloR);
tAttuale = millis();
Serial.println(tAttuale);
}
while (ritardo == HIGH || tAttuale < tLimite);
la parte che non va è “tAttuale < tLimite” visto che tAttuale, che prende il valore di millis() cresce sempre e quindi, appena diventa superiore a tLimite tu la dentro non ci entri più.
Se vuoi implementare un meccanismo di “TimeOut” lo devi implementare, come sempre, con delle “differenze” e non con dei valori fissi …
… nota l’operatore negazione che inverte il valore di quel confronto … se non si è superato il tempo limite, avresti FALSE che, negato, diventa TRUE, quando il valore limite sarà superato, quella espressione diventerà TRUE e, grazie alla negazione, verrà trasformata in FALSE e si uscirà dal while …
O … almeno spero fosse questo il comportamento che volevi ottenere …
ok l'ho tolto ma continua a non funzionare secondo come io mi aspetto che funzioni....
mi spiego meglio... ora senza il ; credo entri nel while (ma devo verificare togliendo la print iniziale, però se premo il bottone non esce dal while e comunque sia non azzera la variabile tAttuale...
30003
apro il cancello
30003
0
apro il cancello
30003
0
apro il cancello
30003
0
apro il cancello
30003
0
30127
30134
30141
non è uscito per tempo limite raggiunto e malgrado lo "0" che si vede tAttuale non viene resettata, va avanti
Ok ...
... e se vuoi stare lontano dai guai ... NON usare mai millis() come la stavi usando, ma sempre con una tecnica di "differenza tra valori" ... ti metti al riparo sia dal problema che stavi incontrando, sia dal problema che ... dopo poco più di 49 gg. millis() si azzera e riparte
questo è lo sketch con la modifica che mi hai suggerito
int apriCancelloR = 5;
unsigned long tAttuale;
int ritardo;
int tLimite = 30000;
void setup()
{
delay(250);
//inizializza lo shield con il mac e l'ip
//inizializza la porta seriale
Serial.begin(9600);
Serial.println("prova millis");
pinMode(apriCancelloR, INPUT_PULLUP);
}
void loop()
{
tAttuale = millis();
do {
ritardo = digitalRead(apriCancelloR);
Serial.println(tAttuale);
}
while ((ritardo == HIGH) || ( ! ( millis() - tAttuale > tLimite)));
if (ritardo == LOW)
{
Serial.println("apro il cancello");
unsigned long tAttuale;
}
else
{
Serial.println("il cancello resta chiuso");
unsigned long tAttuale;
Serial.println(tAttuale);
}
}
e adesso il monitor seriale mi continua a stampare "249" come se tAttuale non si incrementasse più... mi correggo non visualizza la variabile che si incrementa ma appena ho premuto il bottone...
249
249
apro il cancello
1532223
1532223
1532223
il problema è che adesso nel ciclo while non ci entra più, e l'altro problema è che doveva uscire dal ciclo per aver raggiunto il limite e stampare sul monitor "il cancello resta chiuso", invece è uscito solo quando ho premuto il bottone e se premo il bottone nuovamente non succede proprio niente.
Se volete vi spiego meglio quello che questo sketck di prova dovrà fare quando sarà "in produzione" presso un agriturismo così magari mi aiutate a capire meglio il problema e riesco, con il vostro aiuto, a trovare una soluzione.
int apriCancelloR = 5;
unsigned long tAttuale;
int ritardo;
int tLimite = 3000;
void setup()
{
delay(250);
//inizializza lo shield con il mac e l'ip
//inizializza la porta seriale
Serial.begin(9600);
Serial.println("prova millis");
pinMode(apriCancelloR, INPUT_PULLUP);
tAttuale = millis();
}
void loop()
{
// Serial.println(tAttuale);
do {
ritardo = digitalRead(apriCancelloR);
if ( millis() - tAttuale > tLimite)
{
Serial.println(tAttuale);
tAttuale = millis();
break;
}
}
while (ritardo == HIGH);
if (ritardo == LOW)
{
Serial.println("apro il cancello");
}
else
{
Serial.println("il cancello resta chiuso");
Serial.println(tAttuale);
}
}
Questo pezzo di sketch in particolare serve in un agriturismo per un’apertura del cancello “ritardata”.
In pratica gli ospiti che hanno terminato il loro soggiorno in questo agriturismo fanno il check-out, montano in macchina e se ne vanno, la strada da percorrere per arrivare dalla tenuta al cancello è sterrata e presenta salite e discese ed in media ci si mettono dai 6 ai 10 minuti per arrivare al cancello.
Attualmente i proprietari quando fanno il check-out di un cliente e lo salutano, si mettono davanti al PC che visualizza il cancello (sia lato esterno che interno) ad aspettare che il cliente arrivi al cancello per premere il pulsante di apertura e permettere l’uscita.
Mi hanno chiesto di risolvere il problema ed io ho pensato ad arduino.
In pratica succederà questo:
il cliente fa il check-out, il proprietario preme un’icona di consenso sul suo desktop che manda, via web browser (avevo detto che gli arduino sono 3, tutti equipaggiati con ethernet shield W5100? ) il seguente messaggio: “http://192.168.0.46/rapr/” l’arduino al cancello recepisce il messaggio “rapr” e parte questo ciclo:
if (msg.indexOf("rapr") > 0)
{
int ritardo;
do
{
ritardo = digitalRead(apriCancelloR);
if ( millis() - tAttuale > tLimite)
{
tAttuale = millis();
break;
}
}
while (ritardo == HIGH);
if (ritardo == LOW)
{
pc_client.print("<p>apertura cancello ritardata</p>");
digitalWrite(apriCancello, HIGH);
delay(1000);
digitalWrite(apriCancello, LOW);
}
quindi il cliente ha 10 minuti di tempo(da quando il proprietario ha premuto l’icona del consenso) per arrivare al cancello e premere un pulsante che apre il cancello. Passati i 10 minuti (ho impostato tLimite a 600000) il pulsante non funziona più ed il cliente deve suonare il campanello per farsi aprire (non state a sindacare, i proprietari vogliono così ed io attacco l’asino dove vuole il padrone).
E questo è tutto… per stasera
Se volete posto lo sketch completo così mi date un opinione…
Se l'ospite si ferma a guarda un fiore resta intrapolato.
Metterei un campanello all'interno del cancello che il cliente deve premere.
Puó suonare un campanello in casa e il propretario apre il cancello oppure il propretario alla partena del ospite attiva per x minuti il pulsante interno che in quel tempo funge da apricancello automatico.
Ciao Uwe
Dubbio ...
... faccio il check-out, prendo la macchina e mi avvio, il proprietario pigia il bottone e scattano i 10 min.
Dopo 5 minuti, arriva un altro e fa check-out anche lui, prende la macchina e si avvia ... e il padrone che fa ? Preme di nuovo il pulsante ? E cosa avviene al tempo ?
Perché a me mancano ancora 5 minuti per arrivare al cancello, mentre al secondo ne mancano 10 ...
... hai previsto questa cosa ???
@uwe
ci sono due pulsanti all'interno del cancello, uno che apre il cancello previo consenso, e l'altro è il campanello che sarà premuto in caso di scadenza dei 10 minuti
@guglielmo
no questa cosa al momento non è prevista
prima c'era solo il campanello e adesso i proprietari hanno voluto in questo modo