MultiTareas en paralelo (sin Delay)

Hola, soy nuevo en Arduino. :slight_smile: Estoy siguiendo muchos tutoriales y tengo una duda que no puedo encontrar resolver. Espero me pueda ayudar:

Para ponerles un ejemplo facil, piense en una fontana de agua, o aguas danzantes o como le llamen en su pa铆s. Chorros de agua que tienen una secuencia y que en ocasiones son al mismo tiempo, por tanto no sirve la funci贸n delay.

Para hacerlo simple pongamos el ejemplo de 3 pines configurados como salida para 3 chorros de agua.
Al presionar un boton (configurado a 1 de los pines como imput) comienza el show.

Todo el codigo de configuraci贸n inicial ya lo tengo resulto, solo no se como trabajar el concepto de MILLIS. :confused:

Hay posibilidad de alguna forma de configurar que al apretar el boton del pin input el "reloj de millis" tome el valor de cero? En en base a eso ir jugando con los HIGH y LOW de los pines de salida?
Por ejemplo, llamemos a los PINES AGUA1 AGUA2 AGUA3 y que la secuencia sea:

En el segundo 0 Comienza AGUA1 por 20 segundos
A SU VEZ
En el segundo 5 Comienza AGUA2 por 5 segundos
A SU VEZ
En el segundo 10 Comienza AGUA3 por 20 segundos
Y queda todo en LOW en espera a que se aprete el boton de nuevo para dar comienzo a un nuevo show.

Alguien me podr铆a tirar esa linea de c贸digo? :slight_smile: :slight_smile: :slight_smile: :slight_smile: :slight_smile:

Muy agradecido de antemano.

Buenas,

Por lo poco que s茅 (soy tambi茅n novato en esto), millis no se puede poner a cero a menos que resetees la placa arduino.

En tu caso, yo lo que har铆a es usar una variable adicional para tener el tiempo actual. Algo as铆:

#define PIN_BOTON 2
unsigned long tiempo; /
unsigned long t_ref;
// (a completar con tu c贸digo)

void setup() {
聽 // (...)
聽 pinMode (PIN_BOTON, INPUT);
聽 t_ref = millis();聽  // inicializamos la variable "tiempo de referencia"
聽 // (...) 
}
void loop() {
聽 tiempo = millis() - t_ref; // usamos la variable "tiempo" relativa a t_ref
聽 if (digitalRead(PIN_BOTON)){
聽 聽 t_ref = millis();聽  // en el momento en que pulsamos el bot贸n, la referencia 
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // de tiempo es la actual, por lo que la variable "tiempo" 
聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 聽 // valdr谩 0 en ese instante

聽 // ( a completar con lo que quieras hacer en tu c贸digo)
聽 }
}

De novato a novato, seguramente habr谩n formas m谩s limpias de hacerlo que como yo te lo he puesto.
Hay un hilo muy bueno bueno de victorjam en la secci贸n Documentaci贸n sobre el uso de millis() donde da bastantes consejos y buenas pr谩cticas.

Saludos,

Me pitaban los oidos y hoy me siento generoso:

/*
 * Enunciado: En el segundo 0 comienza agua1 por 20 segundos, a los 5 segundos
 * empieza agua 2 por 5 segundos y a los 10 segundos comienza agua3 por 20
 * segundos.
 *
 * Cuando apretemos el bot贸n se ha de guardar el valor de millis en t y se ha 
 * de poner en marcha el circuito. Transcurrido t+5 se debe encender agua2.
 * En t+10 se debe encender agua3 y apagar agua2 (ya han transcurrido los 5
 * segundos de su funcionamiento. En t+20 ser谩 cuando ha de apagarse agua1.
 * Y en t+30 se debe apagar agua3 y detener la secuencia.
 *
 * Se pueder usar millis() > t+X para comparar tiempo, pero tendr谩 problemas
 * cuando millis se desborde. en cambio si haces millis()-t > X no habr谩 
 * problemas y veras que es lo mismo.
 * 
 */

// https://forum.arduino.cc/index.php?topic=655306.0
// Libreria del bot贸n.
#include <BotonSimple.h>

// Pins de salida.
#define agua1 3
#define agua2 4
#define agua3 5

BotonSimple boton(2);聽 // El bot贸n estar谩 en el pin 2.
bool enMarcha = false; // La variable enMarcha indica el estado.
unsigned long t;聽 聽 聽  // La variable de tiempo.

void setup() {
聽 pinMode(agua1, OUTPUT),
聽 pinMode(agua2, OUTPUT);
聽 pinMode(agua3, OUTPUT);
}

void loop() {
聽 // Actualizamos el estado del bot贸n
聽 boton.actualizar();
聽 // Este es el segundo 0, cuando apretas el bot贸n.
聽 // guardas el valor de millis y se pone en marcha agua1 y la secuencia.
聽 if ( boton.leer() == SOLTANDOLO ) {
聽 聽 t = millis();
聽 聽 enMarcha = true;
聽 聽 digitalWrite(agua1, HIGH);
聽 }

聽 // Solo si estamos en marcha ejecutamos la secuencia.
聽 if ( enMarcha ) {
聽 聽 // Nota: si observas comparo desde los valores mayores de secuencia y
聽 聽 // usando else. Si no lo hiciera asi, afectar铆a a la secuencia y por ejemplo
聽 聽 // agua2 se volveria loco al pasar los 10 segundos.
聽 聽 if (聽 millis() - t > 30000 ) {
聽 聽 聽 // Han pasado los 30 segs. con lo que hay que apagar agua3 y detener la
聽 聽 聽 // secuencia.
聽 聽 聽 digitalWrite(agua3, LOW);
聽 聽 聽 enMarcha = false;
聽 聽 }
聽 聽 else
聽 聽 if (聽 millis() - t > 20000 ) {
聽 聽 聽 // Han pasado los 20 segs, desde que apretamos el boton asi que hay que
聽 聽 聽 // apagar agua1.
聽 聽 聽 digitalWrite(agua1, LOW);
聽 聽 }
聽 聽 else
聽 聽 if ( millis() - t > 10000 ) {
聽 聽 聽 // A los 10 segs. debe ponerse en marcha agua3 y como agua2 se encendio a
聽 聽 聽 // los 5 y debe apagarse a los 5, en 10 debe pararse.
聽 聽 聽 digitalWrite(agua3, HIGH);
聽 聽 聽 digitalWrite(agua2, LOW);
聽 聽 }
聽 聽 else
聽 聽 if ( millis() - t > 5000 ) {
聽 聽 聽 // Debe encencersea agua2.
聽 聽 聽 digitalWrite(agua2, HIGH);
聽 聽 }
聽 }
}

Muchas gracias por sus aportes!

Se me ocurre otra forma de plantearlo pero no se si es valida en el lenguje de Arduino.
Se trata de establecer un valor m铆nimo y un m谩ximo en una misma linea de c贸digo para que el pin este abierto, de los contrario eta cerrado. Mi ejemplo simple seria:


if (2000 < millis() < 10000 ) { 聽 //Si el valor de milli es mayor a 2" y menor 10"
聽 聽 
聽 聽 聽digitalWrite(PINX, HIGH); 聽 聽//Encencer el PinX
}

else 
聽 聽 digitalWrite(PINX, LOW); 聽 聽 //Si no esta dentro de ese tiempo arriba enunciado, el pin queda cerrado.

Es valida esta forma de escribirlo?

En C++ (Arduino) no se puede hacer esa comparaci贸n que has puesto:

if ( a < b < c ) {
}

Si bien no da error de compilaci贸n lo que hace es analizar la expresi贸n booleana a<b y el resultado que sera true/false lo compara con < c. Me parece que el 煤nico lenguaje que acepta esa comparaci贸n es python.

Tampoco te ser铆a muy util, ya que si comparas con millis te verias obligado a reiniciar millis, que aunque se puede hacer no es algo que se deba hacer.

Bueno voy avanzando de a poco con sus ayudas y cosas que sigo leyendo.
Cuando en mi ultimo ejemplo puse millis para tomar el valor, fue para simplificar el ejemplo.
Llevado a la realidad lo har铆a como arriba lo plantearon, llevando el valor a 0 con la resta de la variable.

Por si alguien mas con la misma duda viene leyendo esto, acabo de ver otra forma mas de plantearlo:

//**********************************

//Definimos la variables y el puerto asignado
int AGUA1=1;
int AGUA2=2;
int AGUA3=3;


// Configuramos los pines como salida
void setup() {
聽 pinMode(1,OUTPUT);
聽 pinMode(2,OUTPUT);
聽 pinMode(3,OUTPUT);
聽 
 //Definimos que todas las variables arranquen cerradas
 digitalWrite(AGUA1, LOW);
 digitalWrite(AGUA2, LOW);
 digitalWrite(AGUA3, LOW);
 

if(millis()>0 && millis()<20000) {
聽 digitalWrite(AGUA1, HIGH);
}

if(millis()>5000 && millis()<10000) {
聽 digitalWrite(AGUA2, HIGH);
}

if(millis()>10000 && millis()<30000) {
聽 digitalWrite(AGUA3, HIGH);
}


//**********************************

Se que faltan partes en el c贸digo, pero es para citar el ejemplo.
Esta bien pensarlo de esa forma, en la que defino un m谩ximo y un m铆nimo para que este en HIGH
y fuera de eso volver a LOW. O tengo que poner un else que lo hago volver a LOW ?

Por favor edita el c贸digo poniendolo entre etiquetas code. En las NORMAS viene como.

驴Usando el setup? Vale, pero requiere reiniciar el arduino. Y sigo sin enteder el por qu茅, si quieres que hago algo mas lo vas a tener dificil.