Bene
sono contento che tu abbia trovato la tua strada................
Bene
sono contento che tu abbia trovato la tua strada................
Grazie docsavage
Ma in realtà devo ancora risolvere il problema di bloccare il delay in qualsiasi momento ripremendo il pulsante per 1 secondo.
Ho letto che posso sfruttare sempre la variabile millis per bloccare il conteggio sostituendola con il delay ma gli esempi che sto trovando si sviluppano sempre con piu pulsanti e non rientra nel mio caso le soluzioni che trovo.
Ci sono idee?
Ma a parte il tempo, che si mette a posto....
Hai provato ad accendere apri, e a spegnerlo
Ad accendere chiudi, e a spegnerlo?
Te la butto li al volo ... ordine di controllo ed esclusioni reciproche ...
esempio, il tuo STOP e' 1000, ma lo controlli per primo, quindi sara' sempre vero per qualsiasi intervallo superiore a 1000 ...
Seconda cosa, puoi sostituire i delay con un ciclo if in cui controlli il valore di una variabile in rapporto a millis() ... se servono tempi diversi, serve una variabile diversa per ogni tempo ... se gli eventi di tempo da controllare iniziano in momenti diversi, serve una diversa variabile per memorizzarci il valore di millis() nel momento in cui ognuno di quegli specifici eventi inizia ... detta banalmente, se devo controllare due diversi intervalli di 1000, pero' il primo inizia 500 dopo il secondo, mi servira', ad esempio, una variabile, chiamiamola tempo1, in cui memorizzare il valore di millis() nell'istante in cui inizia il primo evento, ed una seconda variabile, chiamiamola tempo2, in cui memorizzare di nuovo il valore di millis() nell'istante in cui inizia il secondo evento ... e cosi via ... ![]()
quella parte funziona,
la parte che dovrò gestire ora è la seguente...
apro prima una parentesi
Il motore della tenda ha già i suoi finecorsa di apertura e chiusura, per cui si fermerebbe in automatico, ma non voglio che i relè di apertura e chiusura rimangano accesi, quindi pochi secondi dopo che la tenda si è fermata in automatico (ho calcolato che ad aprirsi e chiudersi impiega 1 minuto e 45, di conseguenza ho impostato il delay a 2 minuti) il relè a 2 minuti di deve disattivare.
Se in qualsiasi momento devo fermare il movimento questo non può avvenire perche il pulsante non mi viene letto finche non passano quei 2 minuti.
non so se mi sono spiegato bene...
digitalWrite(CHIUDI, LOW); //assicuro che il relè di chiusura sia spento
delay(500);
digitalWrite(APRI, HIGH); //attivo l'apertura
delay(120000); //2min relè off
digitalWrite(APRI, LOW); // spengo il relè di apertura
Si, c'è casino con l'ordine delle if
Ma per culo, credo, la prima non ha la else...
E quindi in prima approssimazione va...
Anche se in realtà se accendesse il motore già acceso lo staccherebbe inutilmente per mezzo secondo
Sospettavo qualcosa, ecco il significato della mia domanda
DJTech84:
... il pulsante non mi viene letto ...
Non ti viene letto proprio perche' usi delay anziche' il controllo con millis ... delay e' bloccante, cioe' mentre il micro aspetta, "aspetta" e basta, non fa assolutamente niente altro, tantomeno leggere i pulsanti ...
Ti do' un'aiutino (ma piccolo, altrimenti Guglielmo mi bacchetta :D)
"delay(120000)" ... puo anche essere scritto in questo modo
tempo1 = millis(); (da eseguire una sola volta, quando attivi il rele',
quindi andra' anche questo in un ciclo di controllo)
if (millis() - tempo1 >= 120000) digitalWrite(APRI, LOW);
(il rele' si spegnera' dopo 120000 millisecondi da quando hai impostato
tempo1, per questo lo devi fare una sola volta quando accendi il rele'
... inoltre in questo modo il programma non si blocchera', continuando
a leggere gli ingressi, quindi potra' sentire se premi il pulsante all'interno
dell'intervallo e fare altro in un'altro ciclo di controllo)
E' un po piu complesso del semplice delay, ma molto piu versatile e non blocca nulla ... ![]()
DJTech84:
Se in qualsiasi momento devo fermare il movimento questo non può avvenire perche il pulsante non mi viene letto finche non passano quei 2 minuti
Il tuo codice è lineare e monoprocesso, fai questo, poi questo poi quest'altro ecc. Come design non è strutturato per gestire più cose in parallelo dedicando ciclicamente solo pochi attimi a ciascuna, che è il modo che si cerca di suggerire, e in effetti usando quest'altra logica non ci sarebbe alcun problema a gestire cinque tende, ciascuna con i suoi pulsanti / tempi / relé indipendenti, con il loop principale che gira costantemente decine di migliaia di volte al secondo.
Ma comunque sono possibili almeno due "patch" senza modificare la logica già messa in piedi. Si rallenta il loop principale con un piccolo delay finale, ad esempio di 100ms in modo che venga eseguito solo dieci volte al secondo, si implementa un contatore che aumenta quando almeno uno dei due relé è acceso e si azzera quando sono spenti, e si aggiunge un if che quando il contatore supera un certo valore (3000 per cinque minuti) svolge la stessa funzione stop della pressione un secondo.
L'altro modo sarebbe usare millis() per contare il tempo, e il loop principale potrebbe girare alla velocità che gli pare. Bisognerebbe salvarsi il tempo attuale nel momento in cui un relé si attiva, si dovrebbe controllare se è trascorso un certo tempo (ed eventualmente comandare lo stop come prima), oppure non controllare più nulla se entrambi i relé sono spenti.
Si risolverebbe questo singolo caso, ma non si riuscirebbero ad implementare facilmente altre funzionalità perché i delay già presenti potrebbero interferire.
all'avvio di uno o dell'altro relè carica un tempo in una variabile
nella loop DOPO aver fatto tutto il resto (ovvero al posto di tutto il resto, se i pulsanti non sono premuti)
se motore1 o motore2
controlla il tempo
se passato
spegne tutti e due i motori, così non dobbiamo preoccuparci di quale era acceso
fine dei due se
piccolo trucco: gli output si possono leggere, questo evita di dover aggiungere delle variabili di appoggio
if (analogread(motore1)+analogread(motore2))
secondo me si riesce benissimo ad aggiungere anche altre possibilità
anche se per adesso non saprei quali
io vi ringrazio per la pazienza e il tempo che avete per darmi delle dritte, ma per oggi lascio stare, sto da ore dietro senza aver ricavato qualcosa di funzionale.
ci sono alcune informazioni che per quanto possano semplificare certe situazioni al momento per le conoscenze che ho non riesco ad associarle, per quanto semplice possa sembrar questo codice non ci sto riuscendo e sono rimasto fermo al codice che ho inserito nel post 19 di questa discussione.
ho riguardato gli esempi piu volte ma continuo a conteggiare male lo stato del pulsante, o non conteggia quanto mi deve rimanere acceso il relè.
domani è un altro giorno e proverò a perderci un altro po di tempo, fatto sta che domenica devo risistemare l'armadio vicino alla scatola di comando che va all'esterno e non sarà facilmente accessibile.
per ora grazie a tutti, vi aggiorno se tiro fuori qualcosa
posta quello che hai fatto finora..........
che vediamo
Grazie Doc alla fine sto ancora qui a leggere degli esempi e spulciando il forum mi sono imbattuto in un altro quesito: la questione overflow.
E' una tenda da sole, non penso che in inverno si muoverà. Arduino (nano o uno, adesso vedo quale userò) sarà operativo 24hsu24h.
ciò che sto provando a inserire e far funzionare è questo
riguarda il tenere on un relè per tot secondi e poi spegnerlo in automatico o se viene premuto dinuovo il pulsante mentre sta contando..
tempo1 = millis();
if (millis() - tempo1 >= 5000) digitalWrite(APRI, LOW);//al momento testo con 5 secondi lo stato ON
invece ciò che (anche se è un codice fatto in modo spartano) al momento mi gira è questo.
float DURATAPRESSIONE_milliSeconds = 0;
int CHIUSURA_milliSeconds = 2000;
int APERTURA_milliSeconds = 3000;
int STOP_milliSeconds = 1000;
int PULSANTE = 4;
int CHIUDI = 3;
int APRI = 2;
void setup(){
pinMode(PULSANTE, INPUT_PULLUP);
pinMode(CHIUDI, OUTPUT);
pinMode(APRI, OUTPUT);
}
void loop() {
while (digitalRead(PULSANTE) == LOW ){
delay(100); //if you want more resolution, lower this number
DURATAPRESSIONE_milliSeconds = DURATAPRESSIONE_milliSeconds + 100;
}
if (DURATAPRESSIONE_milliSeconds >= STOP_milliSeconds){
digitalWrite(CHIUDI, LOW);
digitalWrite(APRI, LOW);
}
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(CHIUDI, LOW);
delay(500);
digitalWrite(APRI, HIGH);
}
else if(DURATAPRESSIONE_milliSeconds >= CHIUSURA_milliSeconds){
digitalWrite(APRI, LOW);
delay(500);
digitalWrite(CHIUDI, HIGH);
}
DURATAPRESSIONE_milliSeconds = 500;
}
dichiara una variabile long int a nome tempo
dopo aver acceso sia uno che l'altro rele
metti tempo=millis()
dopo duratapressione_millisecon=500
prima della graffa chiusa
fai il test
if tempo+12000>millis()
e se superato fai:
le digitalwrite a LOW dei due rele
tempo=millis()
così va
vedrai
ciao docsavatage,
intendi cosi?
sto provando con i led al posto dei relè al momento, vedo illuminarsi per un nanosecondo il led collegato al pin3
float DURATAPRESSIONE_milliSeconds = 0;
int CHIUSURA_milliSeconds = 2000;
int APERTURA_milliSeconds = 3000;
int STOP_milliSeconds = 1000;
int PULSANTE = 4;
int CHIUDI = 3;
int APRI = 2;
long int tempo = 0;
void setup(){
pinMode(PULSANTE, INPUT_PULLUP);
pinMode(CHIUDI, OUTPUT);
pinMode(APRI, OUTPUT);
}
void loop() {
while (digitalRead(PULSANTE) == LOW ){
delay(100); //if you want more resolution, lower this number
DURATAPRESSIONE_milliSeconds = DURATAPRESSIONE_milliSeconds + 100;
}
if (DURATAPRESSIONE_milliSeconds >= STOP_milliSeconds){
digitalWrite(CHIUDI, LOW);
digitalWrite(APRI, LOW);
}
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(APRI, HIGH);
tempo=millis();
digitalWrite(APRI, LOW);
}
else if(DURATAPRESSIONE_milliSeconds >= CHIUSURA_milliSeconds){
digitalWrite(CHIUDI, HIGH);
tempo=millis();
digitalWrite(CHIUDI, LOW);
}
{DURATAPRESSIONE_milliSeconds = 500;
if (tempo+6000>millis());
}
}
per la variabile tempo è meglio se la dichiari come unsigned long che è uguale ai valori che restituisce millis().
Si
Ho commesso due errori...
Il tipo della variabile
E il segno di maggiore
E sono stati ricopiati pari pari
Ma dico io....
Capisco non avere l'idea...
Capisco incasinato una volta con un nome di variabile sbagliato
Ma qui stiamo parlando da giorni di un test di maggiore minore
Roba che a cervello acceso bastano 2 minuti
Qui qualcuno copia senza nemmeno cercare di capire cosa scrive
Adesso poi col copia-incolla non serve nemmeno scrivere....
Buongiorno Zef, ho cambiato la variabile e rispetto l'ultima versione già è cambiato qualcosa.
stamattina a mente fresca ho riscritto un po di cose in base ai vostri consigli...
in questa versione sembra essere piu stabile in quanto esegue cio che ho descritto a inizio forum.
ho l'inceppo che passati (al momento 6 secondi per i test) il relè non torna off
float DURATAPRESSIONE_milliSeconds = 0;
int CHIUSURA_milliSeconds = 2000;
int APERTURA_milliSeconds = 3000;
int STOP_milliSeconds = 1000;
unsigned long tempo1 = 0;
int PULSANTE = 4;
int CHIUDI = 2;
int APRI = 3;
void setup(){
pinMode(PULSANTE, INPUT_PULLUP);
pinMode(CHIUDI, OUTPUT);
pinMode(APRI, OUTPUT);
}
void loop() {
while (digitalRead(PULSANTE) == LOW ){
delay(100); //if you want more resolution, lower this number
DURATAPRESSIONE_milliSeconds = DURATAPRESSIONE_milliSeconds + 100;
}
if (DURATAPRESSIONE_milliSeconds >= STOP_milliSeconds){
digitalWrite(CHIUDI, LOW);
digitalWrite(APRI, LOW);
}
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(APRI, HIGH);
tempo1 = millis();
if (millis() - tempo1 >= 5000) digitalWrite(APRI, LOW);
}
else if(DURATAPRESSIONE_milliSeconds >= CHIUSURA_milliSeconds){
digitalWrite(CHIUDI, HIGH);
tempo1 = millis();
if (millis() - tempo1 >= 5000) digitalWrite(CHIUDI, LOW);
}
DURATAPRESSIONE_milliSeconds = 500;
if (tempo1+6000 > millis());
}
ho sbagliato a posizionare qualcosa anche ora? o manca qualcosa?
la variabile tempo è settata
allo scadere non esegue l'istruzione assegnata
if (millis() - tempo1 >= 5000) digitalWrite(CHIUDI, LOW);
Mi spiace, non posso dirti nulla di più di quello che ti ho già detto...
Gli if che controllano i tempi sono all'interno di altri if ... se l'if esterno non viene eseguito, non viene eseguito neppure quello interno ... Tralasciando il fatto che non userei un while con dentro un delay (i while sono ottimi per altri scopi), tu scrivi, ad esempio
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(APRI, HIGH);
tempo1 = millis();
if (millis() - tempo1 >= 5000) digitalWrite(APRI, LOW);
}
mentre invece dovresti scrivere
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(APRI, HIGH);
tempo1 = millis();
}
if (millis() - tempo1 >= 5000) digitalWrite(APRI, LOW);
se vuoi che l'if di controllo del tempo venga eseguito ... ![]()
Comunque non e' ancora completo, mancano diversi controlli, secondo me ... ![]()
EDIT: io ti suggerirei di strutturare il tutto per gradi, a sezioni ... prima la parte che legge il pulsante e ti restituisce il valore del tempo (o una variabile con stati diversi in base ai tempi, come preferisci) ... poi la parte che controlla i tempi ... e cosi via ... alla fine, volendo, potresti persino creare una funzione per ogni evento, e richiamarle a piacere dal loop solo se servono ... oppure usare una catena di if come in una semplice macchina a stati finiti ... in ogni modo, procedendo per blocchi, oltre a capire di piu cosa fanno, capisci anche dove c'e' qualcosa che non va, se capita ... ![]()
Grazie Etemenanki,
sono rimasto focalizzato sul ragionamento
millis conta dopo l'istruzione accendi relè emappena finiva il conteggio se erano passati i secondi andava in stop..
ora mi è piu chiaro su dove deve andare a leggere l'istruzione il controllo.
posto la soluzione.
float DURATAPRESSIONE_milliSeconds = 0;
int CHIUSURA_milliSeconds = 2000;
int APERTURA_milliSeconds = 3000;
int STOP_milliSeconds = 1000;
unsigned long tempo1 = 0;
int PULSANTE = 4;
int CHIUDI = 2;
int APRI = 3;
void setup(){
pinMode(PULSANTE, INPUT_PULLUP);
pinMode(CHIUDI, OUTPUT);
pinMode(APRI, OUTPUT);
}
void loop() {
while (digitalRead(PULSANTE) == LOW ){
delay(100); //if you want more resolution, lower this number
DURATAPRESSIONE_milliSeconds = DURATAPRESSIONE_milliSeconds + 100;
}
if (DURATAPRESSIONE_milliSeconds >= STOP_milliSeconds){
digitalWrite(CHIUDI, LOW);
digitalWrite(APRI, LOW);
}
if (DURATAPRESSIONE_milliSeconds >= APERTURA_milliSeconds){
digitalWrite(APRI, HIGH);
tempo1 = millis();
}
else if(DURATAPRESSIONE_milliSeconds >= CHIUSURA_milliSeconds){
digitalWrite(CHIUDI, HIGH);
tempo1 = millis();
}
DURATAPRESSIONE_milliSeconds = 500;
if (tempo1+6000 > millis());
if (millis() - tempo1 >= 5000) digitalWrite(CHIUDI, LOW);
if (millis() - tempo1 >= 5000) digitalWrite(APRI, LOW);
}
Docsavatage, ti ringrazio per aver partecipato al forum con le tue proposte ed eventuali critiche nell'ultimo tuo commento, che sono ben accette, la cosa che mi dispiace è anche tu appena hai conosciuto arduino non penso che eri un genio a prima botta, io sto ad un livello terra terra e dopo anni che ho avuto bisogno di dover realizzare un qualcosa che richiedeva un livello di conoscenza superiore con arduino mi sono fatto delle ricerche e ho cercato di capire come funzionasse il millis ho effettuato delle prove e non riuscendoci ho deciso di chiedere supporto qui.
Se ho chiesto supporto è perche avevo dubbi su come funzionasse una else ed if sviluppato in piu situazioni.
Se il post è stato attivo 3 giorni eventualmente era per un motivo che alla fine del tutto ha reso funzionante la mia richiesta grazie all'aiuto di tutti, tu compreso.
Non è una critica ma una replica al tuo ultimo commento.
ringrazio tutti per il supporto