Attivare due rele se si soddisfa la condizione

Ciao a tutti.
Vorrei chiedere il vostro aiuto per scrivere un codice poiche non sono capace.
Vorrei un codice che esegua le seguenti azioni.
all'accensione del Arduino se un pulsante 1 è premuto, deve attivarsi il rele 1. Dopo 2 secondi si attiva il rele 2. Quest ultimo deve rimanere eccitato per 3 secondi ma all'occorrenza spegnersi in anticipo se nel frattempo si preme un pulsante 2. questa procedura si ripete una sola volta ad ogni accensione dell'Arduino.
Grazie in anticipo a chiunque mi vorra aiutare con il codice oppure semplicemente mi segnala uno gia fatto in rete.

Ma la richiesta esattamente qual'é?
Mostra ciò che hai fatto fino ad ora.

Credo che la sua richiesta sia "scrivi il codice" e mandamelo.

NON credo proprio ... REGOLAMENTO, punto 16.1.

Guglielmo

Giusto o sbagliato che sia non voglio essere il primo ad infrangere il regolamento...
Il fatto è che ho 40 anni ed una famiglia di 5 persone da mantenere. Giustissimo non preparare i biscotti per i fannulloni. La richiesta nasce dalla mancanza di tempo e non di voglia. Anzi, quella non manca. Chi volesse puo dare qualche dritta altrimenti va bene cosi...

Capisco, ma quello che devi iniziare a pensare è una struttura del programma nella quale "memorizzi" lo stato attuale, chiamata "macchina a stati finiti". So che è una questione inizialmente "ostica" da comprendere, ma se vuoi programmare con Arduino (e non solo) sono concetti che è utile apprendere. In ogni caso devi cercare di scrivere tu qualcosa e poi noi possiamo darti una mano, altrimenti come ti è stato detto siamo in violazione del regolamento secondo il quale nel forum non si scrive codice "per conto terzi".

Per iniziare quindi a progettare la cosa devi "tradurre" quello che hai descritto sotto forma di parole, in stati, eventi ed azioni: ossia se sono in un certo "stato" e si verifica un certo "evento" allora fai una certa "azione" e passa ad un altro stato (o resta nello stesso).

Diciamo che all'accensione il programma parte dallo stato inziale che chiamiamo START:

START:
Evento: tasto 1 premuto -> attivo relè 1 e vado in ATTESA2

ATTESA2:
Evento: sono passati 2 secondi -> Attivo relè 2 e vado in ATTESA3

ATTESA3:
Evento: tasto 2 premuto -> Disattivo relè 2 e vado in FINE
Evento: sono passati 3 secondi -> Disattivo relè 2 e vado in FINE

FINE:
(non faccio più nulla).

Detto questo, la traduzione in codice Arduino si fa con una variabile intera (chiamata ad esmepio proprio "stato" diciamo) nella quale lo zero rappresenta START, 1 sarebbe ATTESA2, 2 sarebbe ATTESA3, e 3 sarebbe FINE. Inizi ad inserire nel codice le tue "descrizioni" sotto forma di commenti, dividendole in elementi più semplici, e poi inizi a scrivere.
Ti riporto solo parte di un codice di esempio già da me postato nel forum, dal quale potresti iniziare (prendilo "con le molle" non puoi ovviamente compilarlo ma devi iniziare tu a scrivere il resto del codice...:

// Stati:
#define S_START 0
#define S_ATTESA2 1
#define S_ATTESA3 2
#define S_FINE 3

// Variabile di stato
int stato = S_START;
...
void loop()
{
  switch (stato)
  {
    case S_START:
      // Evento: tasto 1 premuto -> attivo relè 1 e vado in ATTESA2
      // Esempio:
      if (pulsante1) {
        accendirele(1);
        stato = S_ATTESA2;
      }
      break;

    case S_ATTESA2:
      // Evento: sono passati 2 secondi -> Attivo relè 2 e vado in ATTESA3
      // Esempio:
      if (passati(2))  {
	    accenddirele(2);
        stato = S_ATTESA3;
      }
      break;

    case S_ATTESA3:
      // Evento: tasto 2 premuto -> Disattivo relè 2 e vado in FINE
      if (pulsante1) {
        spegnirele(2);
        stato = S_FINE;
      }	  
      // Evento: sono passati 3 secondi -> Disattivo relè 2 e vado in FINE
      if (passati(2))  {
        spegnirele(2);
        stato = S_FINE;
      }	  
      break;

    case S_FINE:
      // Non faccio più nulla
	  while(1) {};
}

Ciao.
Mettere nel "setup" la lettura del pulsante, la decisione if e l'attivazione dei relè, così verrà eseguita una sola volta al riavvio.
Saluti.

Buongiorno e grazie mille per l'interesse.
In rete ho trovato questo sketch, ho cancellato i riferimenti per non fare pubblicità ma se non è vietato li posso mettere. Lo sketch comanda 4 rele. Poi sono andato a trovare la regola del "if..else" che credo debba inserire ma non so dove e quando. Riporto l'esempio dopo lo sketch. E possibile eliminare 2 rele ed inserire la condizione "if"?

Sketch 4 rele recuperato in rete.

/*
  test_4_rele.ino
*/

//Impostazione dei pin a cui
//sono collegati i rele
int IN1 = 2;
int IN2 = 3;
int IN3 = 4;
int IN4 = 5;

#define ON   0
#define OFF  1

void setup()
{
  relay_init();//initialize the relay
}

void loop() {

  relay_SetStatus(ON, OFF, OFF, OFF); //Attiva RELE'_1
  delay(2000);//Pausa di 2s
  relay_SetStatus(OFF, ON, OFF, OFF); //Attiva RELE'_2
  delay(2000);//Pausa di 2s
  relay_SetStatus(OFF, OFF, ON, OFF); //Attiva RELE'_3
  delay(2000);//Pausa di 2s
  relay_SetStatus(OFF, OFF, OFF, ON); //Attiva RELE'_5
  delay(2000);//Pausa di 2s
}
void relay_init(void)//initializza i relè
{
  //Porta tutti i relè in OUTPUT
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  relay_SetStatus(OFF, OFF, OFF, OFF); //Porta tutti i relè a off
}
//Inposta lo stato dei relè
void relay_SetStatus( unsigned char status_1,  unsigned char status_2, unsigned char status_3, unsigned char status_4)
{
  digitalWrite(IN1, status_1);
  digitalWrite(IN2, status_2);
  digitalWrite(IN3, status_3);
  digitalWrite(IN4, status_4);
}

esempio uso "if...else"

if (x > 120) digitalWrite(LEDpin, HIGH);

if (x > 120)
digitalWrite(LEDpin, HIGH);

if (x > 120){ digitalWrite(LEDpin, HIGH); }

if (x > 120){
  digitalWrite(LEDpin1, HIGH);
  digitalWrite(LEDpin2, HIGH);
}                                 // all are correct

https://www.arduino.cc/reference/it/language/structure/control-structure/if/

Se fosse impegnativo... ho pensato di semplificarlo ulteriormente.
Attivare un rele dopo attesa di 2 secondi e disattivarlo in anticipo nel caso si premesse un pulsante.

@Jimmy : In conformità al REGOLAMENTO (che dovresti aver letto), fosse anche per una sola riga, il codice va racchiuso negli appositi tag ... :roll_eyes:

... cortesemente, quindi, edita il tuo post più sopra (quindi NON scrivendo un nuovo post, ma utilizzando il bottone a forma di piccola matita :pencil2: che si trova in basso del tuo post), seleziona la parte di codice e premi l'icona </> nella barra degli strumenti per contrassegnarla come codice.

Inoltre, così com'è, non è molto leggibile ... assicurati di averlo correttamente indentato nell'IDE prima di inserirlo (questo lo si fa premendo ctrlT su un PC o cmd T su un Mac all'intero del IDE). Grazie. :slight_smile:

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non sarà sistemato il codice come da regolamento, nel rispetto del citato regolamento nessuno ti risponderà (eventuali risposte verrebbero cancellate), quindi ti consiglio di fare il tutto al più presto. :wink:

Messo cosi pero lo vedo discriminatorio. Conosciamo la storia ma non eravamo li quando sono successi i fatti. Conosciamo la legge di Ohm, Lorentz, Newton ecc ma non siamo stati noi a scoprirli. Ci siamo limitati ad applicarli.
Nei forum Spesso e volentieri si danno consigli e soluzioni a gratis e senza condizioni riguardanti le conoscenze. Su questo forum per esempio http://www.ingegneri.info/forum/ si danno consigli e soluzioni che frutteranno in termini economici. Chi risponde è conscio che non vedra i frutti del suo lavoro intellettuale ma ciò non gli impedisce di farlo.
Cmq atteniamoci al regolamento.

Non capisco in questo momento a cosa ti riferisci ... :roll_eyes:

... se alla formattazione del codice, vai a leggere i motivi nel punto 17.2 così capisci perché è richiesta;

... se ti rifersci alla precedente questione del punto 16.1 ... serve proprio ad evitare di fare concorrenza sleale a professionisti del settore ... se ci si impegna e si studia, noi aiutiamo a fare (NON facciamo noi) quello che si vuole realizzare, altrimenti ... ci si rivolge ad un professionista, pagandolo, e si chiede di realizzare la propria idea. :wink:

Guglielmo

Ok ho scritto di mio pugno il seguente codice. Quando premo il pulsante il rele si accende poi si spegno con un certo ritardo. Vorrei pero inserire un pulsante che faccia spegne il rele se premuto.

int pinButton = 8;
int Relay = 2;
int stateRelay = LOW;
int stateButton;
int previous = LOW;
long time = 0;
long debounce = 500;
int stayON = 5000; //stay on for 5000 ms

void setup() {
  pinMode(pinButton, INPUT);
  pinMode(Relay, OUTPUT);
}

void loop() {
  stateButton = digitalRead(pinButton);  
  if(stateButton == HIGH && previous == LOW && millis() - time > debounce) {
    if(stateRelay == HIGH){
      digitalWrite(Relay, LOW);
    } else {
       digitalWrite(Relay, HIGH);
       delay(stayON);
       digitalWrite(Relay, LOW);
    }
    time = millis();
  }
  previous == stateButton;
}

Con quel delay(stayON); è impossibile! Devi fare la temporizzazione con millis().
P.s.: stateButton = Pulsante di stato; stessa cosa per gli altri nomi: piedino di stato e relè di stato.

Io faccio tante cose ma questo non fa parte di quelle cose.
In assenza di un aiuto concreto prenderò un timer e lavorerò con due relè.

Mio vicino Soc*** durante il servizio di leva faceva il marconista. In quanto tale, una volta alla settimana riceveva "lezioni" di Sambo da un istruttore. Ad ogni lezione Soc*** aveva un nuovo livido. Chiese quindi al istruttore: Compagno Istruttore, lei ci deve insegnare oppure picchiare? L'istruttore rispose: Fare sul serio è il modo migliore per imparare. La settimana successiva, subito dopo il riscaldamento l'istruttore contava le stelle (in pieno giorno) mentre Soc***, in cella d'isolamento contava i giorni che gli rimanevano da scontare. Era la prova che Soc*** aveva imparato il Sambo.
Oggi Soc*** fa il giardiniere in provincia di Milano.

A differenza di Sco***, io non riesco ad imparare con il "devi fare".

Ringrazio tutti quelli che a loro modo hanno cercato di aiutarmi.
Ciao alla prossima

PS. E' una storia triste ma con Soc*** ridiamo sempre quando lo ricordiamo.

Caro Jimmy,
questo forum è per imparare e chiedere aiuto su ciò che non si riesce a capire... Se vuoi imparare, anche poco per volta, siamo disponibili, e ti assicuro che ciò che vuoi fare non è assolutamente complicato. Devi, però, essere disponibile a imparare...

Per semplificare, puoi togliere l'antirimbalzo dal codice e mettere un condensatore in parallelo al pulsante. Considera anche che il pulsante necessita di una resistenza di pull-up, se è collegato verso massa, o di pull-down, se è collegato verso il positivo. Se lo metti verso massa, puoi usare la resistenza di pull-up interna.

Nota: PULSANTE e RELE sono scritti in maiuscolo per ricordare che sono costanti, cioè valori che non verranno cambiati nel corso del programma. Anche INPUT_PULLUP e OUTPUT, però, devono essere scritti in maiuscolo.

Nota 2: dopo la definizione delle macro con #define non va messo il punto e virgola, perché verrebbe legato al numero.

#define PULSANTE 8 // Definisco la macro PULSANTE con il numero 8.
#define RELE 2 // Definisco la macro RELE con il numero 2.

void setup() // Ciò che sta in questa funzione verrà eseguito solo al momento dell'accensione.
{
pinMode (PULSANTE, INPUT_PULLUP); // Imposto il pin PULSANTE come ingresso e attivo la resistenza di pull-up interna.
pinMode (RELE, OUTPUT); // Imposto il pin RELE come uscita. All'accensione assumerà stato basso (0V).
}

void loop() // Ciò che sta in questa funzione verrà eseguito ciclicamente dopo che è stato eseguito il setup().
{

}

Con queste premesse, credo sia l'unica soluzione che tu abbia a disposizione.

basandomi su questo esempio ho provato a fare questo sketch

// Stati:
#define S_START 0
#define S_ATTESA2 1
#define S_ATTESA3 2
#define S_FINE 3

// Variabile di stato
int stato = S_START;

void loop()
{
  switch (stato)
  {
    case S_START:
      // Evento: tasto 1 premuto -> attivo relè 1 e vado in ATTESA2
      // Esempio:
if (digitalRead(2) == 1) {
    digitalWrite(3, HIGH);  
        stato = S_ATTESA2;
      }
      break;

    case S_ATTESA2:
      // Evento: sono passati 2 secondi -> Attivo relè 2 e vado in ATTESA3
      // Esempio:
if (digitalRead(12) == 1) {
    digitalWrite(8, HIGH);     

        stato = S_ATTESA3;
      }
      break;

    case S_ATTESA3:
      // Evento: tasto 2 premuto -> Disattivo relè 2 e vado in FINE
      if (digitalRead(4) == 1) {
    digitalWrite(8, LOW);
      {

        stato = S_FINE;
      }   
      // Evento: sono passati 3 secondi -> Disattivo relè 2 e vado in FINE
if cosa scrivo qui?      

        stato = S_FINE;
      }   
      break;

    case S_FINE:
      // Non faccio più nulla
    while(1) {};
}
   

Come errore ricevo : In function 'void loop()':
42:4: error: expected '(' before 'cosa'
51:1: error: expected '}' at end of input
exit status 1
avete idea su cosa sia?

Sapete dirmi cosa devo scrivere al posto di "cosa scrivo qui?"

Il secondo errore dice che manca una parentesi di chiusura, ma è un errore apparente, l'errore reale è che alla riga 37 c'è una parentesi aperta di troppo.

Il primo errore invece segnala che la sintassi "if cosa scrivo" non è (ovviamente) un'istruzione valida. Li ci va un test sul tempo trascorso dal momento dell'attivazione dello stato, e ci sono diverse possibilità per farlo.

Visto che è stata impostata una macchina a stati la soluzione più rapida è memorizzare "l'ora di sistema" in una variabile 't_inizio_stato' ogni volta che lo stato attivo cambia, e il riconoscimento di questo cambiamento si può ottenere confrontando lo stato attuale con quello precedente (memorizzato in una variabile 'stato_precedente'), se diversi si aggiornano le variabili. Questa parte va scritta appena prima dello switch:

    if (stato != stato_precedente) 
    {
        stato_precedente = stato;
        t_inizio_stato = millis();
    }
    trascorso = millis() - t_inizio_stato;

E quindi in qualsiasi stato si può testare se è trascorso un certo tempo:

if (trascorso > 3000) ...

Bisognerà anche dichiarare le variabili necessarie all'inizio del programma:

int stato_precedente = ~stato;
unsigned long trascorso;
unsigned long t_inizio_stato;

NOTE:

Nel codice manca la funzione 'setup'.

Nel caso 'S_ATTESA2' il commento e il test realizzato con l'if non sono congruenti.

In un circuito reale i pulsanti collegati così non funzionerebbero, perché mancano le resistenze di pull-down verso GND per mantenere gli ingressi stabili a livello 0 quando i pulsanti non sono premuti.

Concordo con quanto scritto da altri qui e mi accodo consigliandoti (devi usare :smiling_imp:) di usare la combinazione di tasti CTRL-T che rende più leggibile e comprensibile il codice.

Ciao.

anche cosi mi da un errore

// Stati:
#define S_START 0
#define S_ATTESA2 1
#define S_ATTESA3 2
#define S_FINE 3

// Variabile di stato
int stato = S_START;
int stato_precedente = ~stato;
unsigned long trascorso;
unsigned long t_inizio_stato;
void loop()
{
  switch (stato)
  {
    case S_START:
      // Evento: tasto 1 premuto -> attivo relè 1 e vado in ATTESA2
      // Esempio:
if (digitalRead(2) == 1) {
    digitalWrite(3, HIGH);  
        stato = S_ATTESA2;
      }
      break;

    case S_ATTESA2:
      // Evento: sono passati 2 secondi -> Attivo relè 2 e vado in ATTESA3
      // Esempio:
if (digitalRead(12) == 1) {
    digitalWrite(8, HIGH);     

        stato = S_ATTESA3;
      }
      break;

    case S_ATTESA3:
      // Evento: tasto 2 premuto -> Disattivo relè 2 e vado in FINE
      if (digitalRead(4) == 1) {
    digitalWrite(8, LOW);
              stato = S_FINE;
      }   
      // Evento: sono passati 3 secondi -> Disattivo relè 2 e vado in FINE
if (stato != stato_precedente) 
    {
        stato_precedente = stato;
        t_inizio_stato = millis();
    }
    trascorso = millis() - t_inizio_stato;    

        stato = S_FINE;
      }   
      // Non faccio più nulla
    while(1) {};
}
   

Ho messo i resistori di pull down 10k