Esp32&millis()

Con esta entrada quiero grabar en mi entendimiento como se puede trabajar con las “pausas” y sus posibilidades utilizando las funciones “millis()” y “for”.

No voy a explicar algunas cosas básicas que en en muchos tutoriales y en varios idiomas se pueden encontrar en la red acerca de estas funciones, simplemente voy a exponer mi experiencia personal práctica y siempre intentando dar un toque de diferencia.

Para ello voy a utilizar mi pantalla tft que vengo usando en los diferentes ejemplos de “Esp32”,y el uso de una GPIO táctil para que me sirva de botón.

Lo primero que haremos es familiarizarnos con la función “millis()” que nos devuelve un número de tipo long igual al numero de milisegundos transcurridos desde que se alimenta la placa.

En este primer ejemplo,hemos establecido la variable t1 igual a 0 como valor inicial y la constante “pausa” con un valor de 500 msg. En setup, t1 esta comentado para que no intervenga ahora. La función millis() es llamada en el “loop” en la variable “diff” que define constantemente la diferencia entre millis() y t1. Así mismo, despues de la condicional,t1 aparece comentado y el resultado de ello se muestra en la imagen donde millis() -desde el inicio-empieza a correr milisegundos hasta que la placa sea descondectada o reseteada. Igualmente diff tambien va sumando porque t1=0

#include "SPI.h"
#include "TFT_eSPI.h"
#define TFT_GREY 0x7BEF
TFT_eSPI tft = TFT_eSPI();
unsigned long t1 = 0;
unsigned long pausa = 500;

void setup() {
  //t1 = millis();
  tft.begin();        // inicializa pantalla
  tft.setRotation(3);     // establece posicion horizontal con pines derecha
  tft.fillScreen(TFT_BLACK);

}

void loop() {
  unsigned long diff = millis() - t1;


  if (diff >= pausa) {
    //t1=millis();
    tft.fillScreen(TFT_BLACK);//refresco de pantalla
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(0, 10);
    tft.setTextSize(3);
    tft.print("valor t1=");
    tft.setTextSize(3);
    tft.setCursor(200, 10);
    tft.print(t1);
    tft.setCursor(20, 100);
    tft.print("millis()");
    tft.setCursor(200, 100);
    tft.print(millis());
    delay(100);


  }






}

En este segundo ejemplo ya se integra t1=millis() en el “setup”, y t1=26, que se interpreta como 26 msg trascurridos hasta el fin del setup

#include "SPI.h"
#include "TFT_eSPI.h"
#define TFT_GREY 0x7BEF
TFT_eSPI tft = TFT_eSPI();
unsigned long t1 = 0;
unsigned long pausa = 500;

void setup() {
  t1 = millis();
  tft.begin();        // inicializa pantalla
  tft.setRotation(3);     // establece posicion horizontal con pines derecha
  tft.fillScreen(TFT_BLACK);

}

void loop() {
  unsigned long diff = millis() - t1;


  if (diff >= pausa) {
    //t1=millis();
    tft.fillScreen(TFT_BLACK);//refresco de pantalla
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(0, 10);
    tft.setTextSize(3);
    tft.print("valor t1=");
    tft.setTextSize(3);
    tft.setCursor(200, 10);
    tft.print(t1);
    tft.setCursor(20, 100);
    tft.print("millis()");
    tft.setCursor(200, 100);
    tft.print(millis());
    delay(100);


  }






}

En este tercer ejemplo volvemos a omitir t1 en el void setup y la integramos despues de la condicional con una pausa=1 segundo, ademas de imprimir tambien diff que como cabe esperar nos va a dar un resultado constante de 1000. la primera pausa desde que se alimenta la placa parte de un valor t1=0 y millis empieza a correr hasta que diff>=1000, a continuación t1 tomara este valor y el ciclo continuara hasta que se quite la alimentación (maximo 50 dias)

#include "SPI.h"
#include "TFT_eSPI.h"
#define TFT_GREY 0x7BEF
TFT_eSPI tft = TFT_eSPI();
unsigned long t1 = 0;
unsigned long pausa = 1000;

void setup() {
  //t1 = millis();
  tft.begin();        // inicializa pantalla
  tft.setRotation(3);     // establece posicion horizontal con pines derecha
  tft.fillScreen(TFT_BLACK);

}

void loop() {
  unsigned long diff = millis() - t1;


  if (diff >= pausa) {
    t1=millis();
    tft.fillScreen(TFT_BLACK);//refresco de pantalla
    tft.setTextColor(ILI9341_YELLOW);
    tft.setCursor(0, 10);
    tft.setTextSize(3);
    tft.print("valor t1=");
    tft.setTextSize(3);
    tft.setCursor(200, 10);
    tft.print(t1);
    tft.setCursor(20, 100);
    tft.print("millis()");
    tft.setCursor(200, 100);
    tft.print(millis());
    tft.setCursor(50, 170);
    tft.print("diff=");
    tft.setCursor(200, 170);
    tft.print(diff);


  }






}

En resumen,, que si queremos establecer una sola pausa de un valor temporal determinado , la variable t1=millis(),no debe aparecer despues de la condiciona l” if diff>=pausa“. Esto es por haber establecido t1=0.

En el setup tampoco lo pondremos evitando contabilizar esos 26 msg,que en realidad son despreciables.

Control manual de un disparo con botón tactil.

En este último ejemplo , para entenderlo todo mejor, vamos a complicarlo un poco para lograr algo interesante como generar solo una pausa cada vez que pulsemos un boton tactil, y será gracias a introducir una variable booleana que he llamado ctrol. El botón será el pin tactil 4 (touchRead(4)). He utilizado la función for para generar un contador de 5 segundos, tiempo que debe ser igual o mayor a la pausa establecida. SI al terminar la cuenta de la función for la diff se hace mayor a la pausa,se visualizará en pantalla el texto “touch” durante 1 segundo (delay(1000)) al mismo tiempo que vemos el valor diff en pantalla. De lo contrario si se establecer una pausa lo suficientemente mayor para que cada vez que termine el contador el valor de diff fuese menor que pausa, ya no se disparará el suceso., que en nuestro caso es la visualización del texto “touch”

El efecto botón,como ya sabemos, se logra tocando el pin gpio4. touch se hará menor que 20 y t1 tomará el valor instantáneo de millis(), y poniendose el contador en marcha,, y cuando la diferencia millis()-t1 se haga mayor a la pausa establecida siempre que el contador nos lo permita, se visualizará el texto elegido. Al poner un delay de 1000 msg podremos leer la información con mejor calidad. Se puede sustituir el efecto de imprimir en la pantalla tft por cualquier otro acontecimiento como activar un rele, encender un led o activar un motor. Si dejamos pulsado el botón ,el ciclo seguirá repitiendose hasta que lo soltemos. También podriamos invertir el contaje desde 5 a 1 para generar una cuenta atrás.

const int threshold = 20;//se utilizará como umbral cuando se necesite
#include "SPI.h"
#include "TFT_eSPI.h"
#define TFT_GREY 0x7BEF
TFT_eSPI tft = TFT_eSPI();
unsigned long t1 = 0;
unsigned long pausa = 5000;
bool ctrol =1;

double touch;
void setup() {
 
  tft.begin();        // inicializa pantalla
  tft.setRotation(3);     // establece posicion horizontal con pines derecha
  tft.fillScreen(TFT_BLACK);

}

void loop() {
  touch = touchRead(4);
  unsigned long diff = millis() - t1;
  
  if (touch < threshold) {
    t1=millis();
    ctrol = 1;
    for (int x = 1; x <= 5; x++) {// el contador debe ser siempre mayor que la pausa para que de tiempo a que la                                                    diff se haga mayor 
 tft.setTextSize(5);
      tft.setCursor(90, 100);
      tft.setTextColor(ILI9341_YELLOW);
      tft.print(x);
      delay(1000);
      tft.fillScreen(TFT_BLACK);
      
      }
if (diff >= pausa && ctrol) {
               !ctrol;
        tft.fillScreen(TFT_BLACK);//refresco de pantalla
        tft.setTextSize(5);
        tft.setCursor(90, 10);
        tft.setTextColor(ILI9341_YELLOW);
        tft.print("touch");
tft.print(diff);// se visualiza en pantalla el valor de la difrencia para mejor comprensión
        tft.fillScreen(TFT_BLACK);

}



     
  }
   
  
}

EFECTUAR UNA TAREA EN UN TIEMPO DETERMINADO:

Suponemos un pulsador en pullup por software de forma que en reposo esta a nivel alto y al pulsar pasa a nivel bajo. declaramos la variable boton=digitalRead(pin); y para que no empiece a ejecutarse la tarea nada mas dar alimentación a la placa, declaramos una variable de inicio ini=0 de forma que con la condicion establecida en el void loop()



if (ini==0){
 t1=millis();
   } 

nos aseguramos que t1 sea igual a millis(), y la diff sera cero.

Cuando pulsemos el botón,lo primero es hacer ini=1, deshaciendo la condición inicial y estableciendo la del botón de forma que en su cambio de H-L-H, t1 dejara de ser igual a millis() y comenzará el contador ejecuntandose en el tiempo establecido la tarea requerida. AL finalizar la restricción,finalizara la tarea.



 if (diff>=1&&diff<=20){
//tarea requerida
}

long t1;
long diff;
#define pin 10
int boton=digitalRead(pin);
int ini=0;

void setup(){
pinMode(pin,INPUT_PULLUP);
}
void loop(){
  diff=(millis()-t1)/1000;
if (ini==0){
 t1=millis();
   } 
if (!boton){
  ini=1;
}
     if (diff>=1&&diff<=20){
//tarea requerida
}

}

Otro ejemplo;

Recordemos que uint_8 tiene un recorrido de 0 a 255, con lo que su uso nos restringe su aplicación.

La variable newmillis alcanzará valores desde 0 a 255.

En este ejemplo tomamos como ejemplo la comparación de dos entradas nominadas “input1” e “input2” asociadas a dos pines ADC- La variable newmillis estará en valor 0 miestras no se alcance la condición, al mismo tiempo que la variable “t1 = millis(). Cuando se satisfaga la condición, t1 habrá alcanzado un valor determinado de millis() que habrá dejado de sumar, y newmillis será ahora la diferencia entre millis y el antiguo valor de millis que era t1. Como definimos el valor de newmillis =(millis()-t1)/10, la numeracion sera en centesimas de segundo, en decimas de segundo /100 o en segundos /1000.

uint_8 newmillis=0;
long t1;

if (input1>input2){newmillis=(millis()-t1)/10;}else{t1=millis();}
if (newmillis>100){accion a desarrollar}// transcurridos 1 segundo (100 centesimas)
//nos sirve tambien para calcular el tiempo en que input1 es mayor que input 2, limitado a 255

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Translate »