programar arduino por tareas pendientes o timers?

Hola
Estoy desde ayer dando vueltas a una programacion y la verdad es que estoy algo denso con ella.
estoy intentando hacer una programacion en base a tareas pendientes, me explico:

No consigo esbozar aunque sea en nemonicos, como hacer que el arduino chequee unas tareas (ocho en total) continuamente (bueno, esto si, leo una varible en el loop y ya esta), si se ha producido un evento asignar como tarea pendiente hasta que se cumpla, pero no siempre estara pendiente de la tarea de primer nivel, entre huecos tiene que chequear otras tareas y al cabo de 4 minutos volver a la principal hasta que se cumpla.

De momento estoy intentando hacerlo asi:
creo una variable llamada tarea de tipo byte (tarea = 0000 0000) y asigno el primer bit (que seria tarea de primer nivel) a '0' si no hay tarea tipo uno y si tiene que hacer esa tarea la pongo a '1' es decir (tarea = 0000 0001).

Asi el arduino chequea la varible "tarea" y ve que tiene pendiente alguno de los bits que ya no esta a cero (la tarea numero 1 de primer nivel (bitread(tarea, 1))), entonces pasa a ejecutarla, pero si no consigue ejecutarla en intervalos de 4 minutos y hasta un maximo de tres intentos, pasa a dejarla pendiente hasta la siguiente hora.

tambien se puede producir una tarea 5, es decir que queda pendiente realizar la cinco (tarea = 0001 0001) pero como esa es de segundo nivel, la primera que tiene que intentar es la uno.

En esos 4 minutos de intervalos de los tres intentos, tambien chequea las otras tareas de segundo nivel (tarea dos, tres, cuatro...), pero tiene que pasar a cumplir la tarea 1 cuando se cumplan los 4 minutos.

En el momento que ha finalizado la tarea 1, pone la variable a 0 para que sepa que esta liquidada (bitwrite (tarea, 1, 0)) y continua en ese bucle sin fin de chequearlas.

el concepto en delphi lo tengo claro y ademas asigno timers para dicha funcion, pero en arduino no consigo esbozar la estructura o el procedimiento basico, ni siquiera en tablas de decision, y ya digo... estoy un poco bloqueado.

¿ Podeis darme alguna orientacion o parecido, a "grosso modo" a lo que quiero hacer?

Gracias, sobre todo por leerlo. :slight_smile:

Añado por si queda un poco mas claro: Si la tarea "uno" es poner en marcha una bomba de agua para achicar y esta bomba solo puede conectarse a intervalos de 4 minutos, sino consigue achicar el agua, tiene que esperar una hora hasta que se enfrie y volver a ello hasta que haya quitado toda el agua.
Pero eso no quita que mientras compruebe si hay electricidad, si se ha calentado mucho, si hay bloqueo en otra cañeria etc.. etc... espero que haya quedado un poco mas claro.

Lo siento Heke, acepto tus gracias por leerlo...pero mis conocimientos no vas mas lejos! esto queda a años luz de mi !! suerte a ver si alguien puede ayudarte!!

No te preocupes Luis, se que es un "CACAO" .

Un saludo compañero.

Aunque una cosa, no se si sera de ayuda ya que no se mucho de programación en C/C++ de Arduino, pero leyendo lo que querías hacer se me ha ocurrido usar una estructura de la función switch / case de manera anidada, en plan, hago un primer case para chequear si hay algo en primer byte o y un case para el segundo y de ahí establezco una prioridad entre primer o segundo nivel. Aunque esta claro que solo con esta estructura pueden salir muchas posibilidades si se sigue separando posibilidades en estructura de arbol sacando varias ramas y en cada una de ellas al final esta una tarea, supongo que usando alguna que otra estructura por el medio (como do while, para que mientras esta en primer nivel con tareas no se meta ha analizar el segundo) supongo que algo se podría implementar. No se si estoy dando palos de ciego, o algo de lo que te he dicho te pueda servir...pero bueno me ha surgido la idea y digo voy a comentarsela xDD

Si no vale para nada borra mi comentario sin problema! Un saludo, y suerte de nuevo.

Y otra posibilidad así podría ser comprobar bit a bit si esta a "1", en plan compruebas haciéndole una mascara al bit de mas a la derecha para que solo se quede su valor, y comprobar si esta en alto, y si no esta comprobar el siguiente con su mascara propia.....así con todos, y si encuentras alguna tarea, reiniciar la comprobación en búsqueda de otra nueva....ya paro de poner ideas que se me posan por la cabeza... xD :blush:

Suena a procesos con tiempos de actualización muy largos, asi que no tiene pinta de tener que complicarte la vida con programación dificil.... aunque puede que no haya entendido bien los propositos de tu proyecto.

millis() es tu amigo!!

ejemplo:

if (millis() -tant_tarea1) >=t_tarea1)
{
if (contador_tarea1<3)
{
encender_bomba();
contador_tarea1++;
}else{
parar_bomba();
contador_tarea1=0;
t_tarea1=millis() + 1 hora;
t_ant_tarea1=millis();
}
}

if (millis() -tant_tarea2) >=t_tarea2)
{
chequeo_temperatura();
if (temperatura > t_alarma)
{
alarma();
}
tant_tarea2=millis();
}

if (millis() -tant_tarea3) >=t_tarea3)
{
chequeo_electricidad();
tant_tarea3=millis();
}

Bueno, es una idea de como podrías enfocarlo. En este tipo de programas, no hagas un while, o cosas de estas que puedan bloquear tu programa.
Al final, el tiempo de ciclo que le cuesta chequear todo el código, es mucho menor de 4 minutos o tiempos así que estamos hablando.

En caso de que estemos hablando de tiempos de orden de milisegundos o menor, entonces la cosa cambia....

¿qué te parece?

:wink:

Muchar Gracias IgorR y LuisAntonio

LuisAntonio: Si, lo del bit a bit es lo que hace Bitread y Bitwrite, lo estoy usando en ese bucle, no ibas desencaminado, miratelo porque es muy util, y repito gracias por las ideas, todas son bienvenidas.

IgorR: Gracias de nuevo, voy a ver el codigo a ver si le saco punta.

Estaba derivandome a bucles while, en los cuales conteo el tiempo del RTC y salgo de ellos en base a break pero no me gusta no me gusta y es codigo "farragoso"

Voy a seguir y ver tu codigo a ver si se adapta bien a lo que quiero.

PD: No queria emplear el RTC para bucles porque si un dia se queda sin pila... se joroba y bloqueara (por eso en terminar esta parte voy a ver los watchdog por hardware.

Un saludo compañeros.

PD2: IgorR eres un maquina de cuidado (en el sentido bueno) mira que busco soluciones en la web y por H o por B me lleva google a un articulo tuyo en el que ya te lo has currado. (Yo de mayor quiero ser como tu).

No es para tanto... :wink:

Lo único que tienes que mirar es cual es la frecuencia máxima de todos tus procesos (tiempo mínimo que tienes que atender el proceso).
Si quieres un buen libro, y encima es gratis, aunque en inglés: "Patterns for Time-Triggered Embedded Systems" (http://www.tte-systems.com/books/pttes). Usan un 8051, pero los programas están escritos en C, por lo que es inmediato portarlo a Arduino. En la propia web han portado su TTC scheduler para Atmel.

Hacerte un diagrama de flujo y tiempos de tu programa, para tener claro los procesos, tiempos , etc seguro que te ayuda antes de ponerte a picar código....

:wink:

Ese libro tiene muy buena pinta, ya lo tengo guardado en mi biblioteca virtual.

La frecuencia de estos procesos es larga, luego, tengo unos procesos que son mas criticos pero estan controlados.

Solo me queda una duda:
¿Que pasaria si precisamente un proceso se produce en el dia 50 desde que arranque el arduino?

Porque tengo una funcion muy parecida:
while (Tiempo < (Cronometro + 10000)){
CheckCrono();
CheckDatos();

Y acabo de caer en el detalle de que el millis() se resetea al dia 50, y si resulta que he cargado "Cronometro" con el valor actual de millis() y lo comparo con "Tiempo" que es el valor de millis actualizado, con lo cual y antes de que se cumpla se resetea el contador del arduino?

"cuestion critica"

Gracias IgorR

PD: Estoy intentando todo esto en diagramas de flujo antes de picarlo, porque poner un dato en el LCD, p.ej. lo puedo hacer sin un diagrama, pero esto esta de pensar bastante...

No hay problema.... te haces tu millis().....je,je,je

Te he puesto millis para que se entienda.... Te puedes hacer con un timer tu propio reloj... o usar un RTC.... era para ver el concepto....
En vez que mida milisegundos, que mida minutos, horas,.... a tu antojo!!

:wink: