Como ahora todo parece que tiene un timeline para definir que algo tiene un origen, evoluciona y muere; ya sea nuestras vidas en cualquier red social o el desarrollo de un proyecto; me he propuesto realizar un ejercicio práctico para desarrollar el concepto y aplicar el Timeline de Arduino en un programa.
La mayoría de programas no tienen una dependencia a tiempo real.
Un sistema de tiempo real es aquel que cuida minuciosamente los tiempos de ejecución de cada una de sus tareas. Por ejemplo, el sistema operativo de un ordenador gestiona y prioriza las tareas que se están desarrollando. En el caso de que un programa se quede colgado; podemos acceder al administrador de tareas con CTRL+ALT+SUPR para acceder a los servicios ejecutados y poder solucionar la incidencia. Otro ejemplo son las tarjetas gráficas que deben de realizar un gran número de operaciones por segundo para poder obtener una gran resolución en tiempo de juego y que sin esa gestión de tareas sería imposible que el flujo de juego sea natural.
Para hacerse una idea de la importancia de los sistemas de tiempo real es poco probable que el hombre hubiera llegado a la luna sin este concepto.
Es por ello, que ahora tendremos una variable temporal en nuestros programas y que podremos manipular para realizar distintos ejemplos prácticos.
KeyTime
Para comenzar utilizaremos una función muy sencilla llamada millis y poder leer el tiempo desde el que se ha comenzado a ejecutar el programa en cada ejecución del bucle loop() con Arduino.
int keyTime = 5000; void setup() { Serial.begin(9600); } void loop() { Serial.print("Actual Time: "); Serial.println(millis()); if(millis() >= keyTime){ Serial.print("Key Time Unlocked greater than "); Serial.print(keyTime); Serial.println(" milliseconds"); } }
En cada iteración del bucle leeremos el valor proporcionado por esta función millis y la pasaremos por pantalla. En el momento que se alcance un valor definido como “keyTime” o “clave de tiempo” nos aparecerá otro mensaje adicional como el que aparece en la imagen.
Un aspecto importantísimo a tener en cuenta es el tiempo que se invierte entre ejecución y ejecución. Aunque en este ejemplo sean intervalos muy pequeños, hemos de fijarnos que NO siempre es constante en función de las tareas que intervienen y cuando hay muchas instrucciones, es posible que los retrasos producidos por algunas tareas, nos pueden dar problemas de la información en tiempo real; como la lectura de un sensor o la actualización de una variable cuyo retraso produciría un valor erroneo.
En este caso crearemos un control definido en un intervalo, para poder identificar zonas de tiempo en la que ejecutar las “claves de tiempo”.
//KeyTime in milliseconds int keyTime = 5000; //Range of time (two time of this value) // KeyTime - range --> Under KeyTime // KeyTime + range --> Over KeyTime int keyRange = 300; void setup() { Serial.begin(9600); } void loop() { Serial.print("Actual Time: "); Serial.println(millis()); if((millis() >= keyTime-keyRange)&&(millis() <= keyTime+keyRange)){ Serial.print("Key Time Unlocked between "); Serial.print(keyTime-keyRange); Serial.print(" and "); Serial.print(keyTime+keyRange); Serial.println(" milliseconds"); } }
Tipo de dato para KeyTime – ¿Cuánto tiempo puede durar el control?
Si nos informamos bien dentro de la función Millis(); podremos observar que siempre obtenemos un valor entero. Y el mayor valor de tipo entero que podemo manejar es unsigned long.
Esta variable puede llegar a un valor máximo de 4.294.967.295 milisegundos.
Es decir con una precisión de milésimas de segundo y haciendo el cálculo, podemos medir:
- 4.294.967 segundos
- 71582 min (+ 46 segundos)
- 1193 horas (+ 2 minutos)
- 49 días (+17 horas)
- 1193 horas (+ 2 minutos)
- 71582 min (+ 46 segundos)
Tiempo total en una variable: 1 mes 19 días 17 horas 2 minutos 46 segundos
Aunque se pueden utilizar más variables a modo de contador. Se puede medir esa cantidad de tiempo con una sola variable. Por lo que si hemos de gestionar un funcionamiento de nuestro sistema mucho mayor a ese, deberemos crear más variables de control y no sufrir por el efecto 3000.
Array KeyTime
En este programa lo que haremos será recopilar una serie de tiempos clave dentro de un vector que estarán dispersos en el tiempo. Por lo que solo se ejecutarán en el momento que nosotros creamos conveniente. Y el modo de acceso a cada uno de ellos vendrá definido por un contador que ira sumando de uno en uno durante su ejecución.
unsigned long keyFrames[] = { 100, 500, 1000, 2000, 2500, 2700, 3000, 3500, 4450, 5200, 5500, 6200, 6500, 6800, 8000 }; int indexKeyFrame =0; int keyRange= 50; void setup() { Serial.begin(9600); } void loop() { unsigned long currentMillis = millis(); Serial.print("Actual Time: "); Serial.println(currentMillis); if((currentMillis >= keyFrames[indexKeyFrame]-keyRange)&&(currentMillis <= keyFrames[indexKeyFrame]+keyRange)){ Serial.print("Key Time: "); Serial.println(keyFrames[indexKeyFrame]); Serial.print("Value between: "); Serial.print(keyFrames[indexKeyFrame]-keyRange); Serial.print(" and "); Serial.println(keyFrames[indexKeyFrame]+keyRange); indexKeyFrame++; } }
En este programa, ya se pueden definir los tiempos como una recopilación en un vector que se va a ejecutar en los momentos predefinidos por nosotros a modo de disparador temporal. Por lo que en este momento, con este código podríamos dejar un pequeño dispositivo ejecutándose durante un mes y que ejecute en distintos instantes una acción sin necesidad de supervisión.
No quiero dar ideas, pero esto se puede utilizar tanto para el mal como para el bien. 🙂
Por ejemplo, con un zumbador ya tendríamos un despertador temporal “desechable” mensual. Y si lo queremos utilizar para el mal, con ese mismo despertador y un altavoz a todo volumen ya es suficiente para molestar al vecindario.
Si os habéis fijado en el último ejercicio, al vector lo he llamado “keyFrames“; que explicaré en el siguiente post. Así que ya is podéis hacer una idea de por dónde van los tiros.