Muovere 2 motori simultaneamente

Ciao a tutti, come già accennato nelle presentazioni, sono abbastanza negato in elettronica, quindi conosco soltanto componenti semplici.
Detto questo, sto facendo un sistemino che alla pressione di un pulsante, due motori comandati da relè, eseguano una sequenza di operazioni, tipo vai avanti, torna indietro aziona l'altro motore. Ma il mio problema è capire se è possibile, far muovere in alcuni momenti i due motori insieme. Al momento sono riuscito a fargli fare delle operazioni, ma uno alla volta.
Di seguito lo sketch

int StatoBottone = 0;

void setup()
{
 pinMode(2, INPUT);
 pinMode(13, OUTPUT);
 pinMode(12, OUTPUT);
 pinMode(11, OUTPUT);
 pinMode(10, OUTPUT);
 pinMode(9, OUTPUT);
}

void loop()
{
 // leggi lo stato del bottone
 StatoBottone = digitalRead(2);
 // controlla il bottone_se premuto significa
 // stato=HIGH
 if (StatoBottone == HIGH) {
   delay(10);
   digitalWrite(13, HIGH); //accende il led di funzionamento
   digitalWrite(12, LOW);
   delay(15000);
   digitalWrite(12, HIGH); //Alza il carrello
   delay(500);
   digitalWrite(11, LOW); //Scarica il carrello
   delay(8000);
   digitalWrite(11, HIGH); 
   delay(500);
   digitalWrite(10, LOW); //Rimette il carrello in posizione
   delay(8000);
   digitalWrite(10, HIGH); 
   delay(500);
   digitalWrite(11, LOW);
   delay(2000);
   digitalWrite(11, HIGH);
   delay(500);
   digitalWrite(10, LOW);
   delay(2000);
   digitalWrite(10, HIGH);
   delay(500);
   digitalWrite(9, LOW); //Abbassa il carrello
   delay(15000);
   digitalWrite(9, HIGH);
   delay(500);
   digitalWrite(11, LOW);
   delay(500);
   digitalWrite(11, HIGH);
   delay(500);
   digitalWrite(10, LOW);
   delay(500);
   digitalWrite(10, HIGH);
   delay(500);
   digitalWrite(11, LOW);
   delay(500);
   digitalWrite(11, HIGH);
   delay(500);
   digitalWrite(10, LOW);
   delay(500);
   digitalWrite(10, HIGH);
   delay(500);
     } else {
   digitalWrite(13, LOW);
   digitalWrite(12, HIGH);
   digitalWrite(11, HIGH);
   digitalWrite(10, HIGH);
   digitalWrite(9, HIGH);
 }
}

Grazie a chi mi aiuterà.

Alessandro

>workale: ti ricordo che in conformità al regolamento (che, ti consiglio di rileggere TUTTO con molta attenzione), punto 7, devi editare il tuo post (quindi NON scrivendo un nuovo post, ma utilizzando il bottone More -> Modify che si trova in basso a destra del tuo post) e racchiudere il codice all'interno dei tag CODE (... sono quelli che in edit inserisce il bottone con icona fatta così: </>, tutto a sinistra).

In pratica, tutto il tuo codice dovrà trovarsi racchiuso tra due tag: [code] _il _tuo_ codice_ [/code] così da non venire interpretato e non dare adito alla formazione di caratteri indesiderati o cattiva formattazione del testo. Grazie.

Guglielmo

P.S.: Ti ricordo che, purtroppo, fino a quando non avrai sistemato il codice come richiesto, nessuno ti potrà rispondere, quindi ti consiglio di farlo al più presto. :wink:

Chiedo perdono.

La funzione delay() è "bloccante" per cui, ogni volta che la chiami, il tutto si ferma e NON puoi fare altro.

Se si devono fare più cose, senza fermare il programma, occorre uasre una tecnica totalmente differente (... in parole povere devi riscrivere TOTALMENTE il programma).

Ti consiglio di studiarti come si usa la funzione millis(), prima QUI, poi QUI e QUI e QUI e tutti gli articoli che sono in QUESTA pagina ... vedrai che ti sarà tutto più chiaro :wink:

Guglielmo

Grazie, ho dato un primo sguardo e sembra che Delay accodi ogni azione per un tot, mentre il comando Millis usa un temporizzatore dal momento dell'accensione e quindi si possono richiamare i comandi nei vari momenti, anche nello stesso, giusto?

... non proprio, delay() è una funzione che FERMA il programma, millis() è una funzione che ritorna un "numero" e non ferma nulla ... poi a te usare bene quel "numero" come è ampiamente spiegato in quei link (... a cui, purtroppo, NON basta dare un occhiata, ma tocca studiarli con molta attenzione ::slight_smile:).

Guglielmo

OK, studio :smiley:

workale:
comando Millis usa un temporizzatore dal momento dell'accensione e quindi si possono richiamare i comandi nei vari momenti, anche nello stesso, giusto?

L'idea di un tempo sempre crescente a partire dall'accensione è giusta solo in parte. Intanto non è detto che il conteggio parta da zero nell'esatto momento di accensione, può iniziare anche dopo qualche secondo (quando il bootloader avvia il programma utente), e poi è un valore sempre crescente solo fino a 2 alla 32esima ms, dopo di che ritorna a zero.

Quindi si deve evitare da subito di pensarlo come un valore sempre crescente, un tipico errore è quello di impostare un tempo di arrivo a millis()+N millisecondi.

Si deve invece sempre ragionare per "tempo trascorso" a partire da un momento X iniziale in cui ci eravamo salvati il valore di millis().

trascorso = millis() - inizio

Facendo così non si ha mai alcun errore di passaggio per lo zero, e a dire il vero non ha neppure importanza il valore di millis all'accensione, potrebbe benissimo partire da un valore qualsiasi perché tanto a noi interessa solo la differenza tra due momenti.

Su un Arduino con oscillatore ceramico la funzione millis (come la delay che si basa sullo stesso oscillatore/timer) nel migliore dei casi ha un errore di circa cinque secondi all'ora, possono essere tanti o pochi a seconda delle esigenze, ma bisogna tenerne conto. Con un oscillatore al quarzo la precisione sarebbe invece molto migliore.

Tutte le variabili che hanno a che fare con millis devono essere a 32bit senza segno, quindi di tipo unsigned long oppure uint32_t.

Detto questo, in generale un programma che fa uso di millis, e che deve passare attraverso diverse fasi di funzionamento, può essere composto da tante righe del tipo:

if ((fase == ...)   &&   (trascorso > 5000)) { ... }

dove 'fase' è una variabile che identifica la situazione/stato attuale. In questo modo cambiando la variabile di fase si "abilitano" o "disabilitano" le condizioni.

Con questa impostazione ogni delay viene sostituito da una fase testata da un if, e ogni ritardo è realizzato permanendo in quella fase per tutto il tempo che serve, tanto il controllo della condizione dura pochi microsecondi, e le operazioni da eseguire si eseguono solo una volta quando la condizione diventa vera.

Questo lascia tutto il tempo di testare altre condizioni su altre variabili di fase che servono a realizzare altri compiti virtualmente in parallelo.

Grazie per i consigli che cercherò di applicare, ma devo studiare parecchio, con il delay mi sembrava tutto molto semplice, mentre ora la situazione si complica, almeno per un novizio come me, ma è la soluzione migliore per quello che vorrei fare.