Cronometro pantalla oled

Hola, les consulto una duda que no puedo resolver, no puedo agregar o no se como agregar los 00:00:00 solo se visualiza 0:0:0

#include <Wire.h>      // libreria para bus I2C
#include <Adafruit_GFX.h>   // libreria para pantallas graficas
#include <Adafruit_SSD1306.h>   // libreria para controlador SSD1306
 
#define ANCHO 128     // reemplaza ocurrencia de ANCHO por 128
#define ALTO 64       // reemplaza ocurrencia de ALTO por 64

#define OLED_RESET 4      // necesario por la libreria pero no usado
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);  // crea objeto
 long t;
 int horas;
 int minutos;
 int segundos;
void setup()
{
    Wire.begin();         // inicializa bus I2C
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inicializa pantalla con direccion 0x3C 



}
void loop(){
  t=millis()/1000;
 horas =t/3600;
  minutos=(t%3600)/60;
 segundos =( t - horas*3600 - minutos *60) % 60;
  oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(0, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 1
  oled.print(horas); 
  oled.setCursor(10, 0); 
  oled.print(":");

  oled.setCursor(20, 0);
 oled.setTextSize(2);      // establece tamano de texto en 1
  oled.print(minutos);
oled.setCursor(30, 0); 
     oled.print(":");
     
   oled.setCursor(40, 0);
 oled.setTextSize(2);      // establece tamano de texto en 1
  oled.print(segundos);
  oled.display();     // muestra en pantalla todo 


}

usa sprintf y conseguirás lo que buscas sin mucho esfuerzo
creas un array

void loop(){

  char buffer[30];

  t=millis()/1000;
  horas =t/3600;
  minutos=(t%3600)/60;
  segundos =( t - horas*3600 - minutos *60) % 60;
  oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(0, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 1
  sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segundos);
  oled.print(buffer);
  oled.display();     // muestra en pantalla todo 
}

No es por nada pero esto ya te lo había aconsejado. Lo vuelves a preguntar o estoy equivocado?

1 Like

Si lo volví a preguntar porque no me funciono, lo voy a ver mejor, gracias

Añadele un "0" si son menor de 10 entes de la variable, lo mismo que le añades ":" entre variables.

FUNCIONA!!! ahora una consulta que también me esta mareando, encenderlo y pararlo con el mismo botón??? y pensaba alternarlo con 2 funciones diferentes para que se muestre en la pantalla con un swich case lo pensé selecciono una función o la otra, para detenerlo con un if como seria? todo esto es para aprender la lógica de programación, gracias por su tiempo

Usas una variable, llamémosle corriendo que cambia de estado cuando pulsas el botón.
Si corriendo es true cuentas el tiempo, si es false lo dejas de contar.

Saludos

1 Like

ahi pude mejorar bastante, ahora el delay para que se vea por unos segundo me frena el conteo, como tendria que ser pára mejorarlo

 estadoActual = digitalRead(pulsador2);
  if (estadoActual == 1 && estadoAnterior == 1){
      var++;
  }
  switch (var) 
{
    case 0:
    oled.clearDisplay(); 
       char buffer[30];
  oled.setCursor(13, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 2
  sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segundos);
  oled.print(buffer);
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
     delay(2000); 
      break;   
   case 1:
    oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(18, 20);     // ubica cursor en inicio de coordenadas 0,0
  oled.setTextSize(4);      // establece tamano de texto en 4
  oled.print(x,1);  // escribe en pantalla el texto
 oled.display(); 
 default: var = 0;
 break;
}
 estadoAnterior = estadoActual;


Pero igual no logro como lo quiero, la idea es que siempre muestre un dato en la pantalla y cuando el pulsador se oprima por 5 segundos muestre el contador por 5 segundos y vuelva a la muestra

Mi estiamod @callecuatro1976 si usas millis() no uses delay(). Si usas delay() olvidate de lograr buenos resultados con milllis().
Creo que esta clara la respuesta.
Inisistes usando delay() cuando las papas queman.
Veo un delay(2000) en el case 0.
Dime como pretendes hacer otra cosa mientras tanto?

Ve a documentación y lee sobre máquina de estados.
Busca en el foro ejemplos de máquinas de estados que hemos sugerido para muchos casos. Ahi tendras la respuesta.

Estuve buscando y probando varios ejemplos, lo mejor que pude haces fue este código, pero no logro mi cometido, por falta de experiencia, ya que quiero un dato fijo y cuando oprimo un pulsador por 10 segundos limpie la pantalla y muestre por 5 segundos el cronometro.

void loop() 
{
  
   estadoActual = digitalRead(pulsador2);
  if (estadoActual == 1 && estadoAnterior == 1){
     
      var++;
     
  }
  switch (var) 
{
    case 0:
    oled.clearDisplay(); 
       char buffer[30];
  oled.setCursor(13, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 2
  sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segundos);
  oled.print(buffer);
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
     //delay(1000); 
      break;   
   case 1:
    oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(15, 20);     // ubica cursor en inicio de coordenadas 0,0
  oled.setTextSize(4);      // establece tamano de texto en 4
  oled.print(x,1);  // escribe en pantalla el texto
 oled.display(); 
 default: var = 0;
 break;
}
 estadoAnterior = estadoActual;

este codigo hace lo que quiero pero no sostiene la muestra por 5 segundos y tampoco funciona el pulsador oprimiendo los 5 segundo, ósea muestra apreto pulsador cambia suelto pulsador vuelve valor de princio

Yo estoy a mitad de un viaje de 1600 km retornando de mis vacaciones. Si mañana no lo resolviste lo vemos.

Saludos

1 Like

Si estoy probando pero no consigo hacerlo, esta difícil el tema voy a seguir intentando, gracias por su tiempo!

¿ Como van esos estudios de las millis?... Por el tiempo veo que no muy bien, a ver si la siguiente plantilla te ayuda a entenderlas.

void loop () {

  //aqui cosas que hacer (¿mostrar el dato fijo?.)

  if (presión pulsador) {
    cuenta1 = millis() - marca1; //arrancamos la cuenta del pulsador
    if (cuenta1 >= n) { //siendo n los milisegundos mirando el pulsador sn hacer nada (nada aqui, el programa sigue)
      //se ha entrado aqui, han pasado n seg sin soltar el pulsador
      //iniciamos el cronometro
      cuenta2 = millis(); // marca de tiempo para el cronometro
      while (millis() - cuenta2 <= m) {//m milisegundos ejecutando el cronometro

        //aqui codigo del cronometro}

      }
    }
    marca1 = millis();
  }
  else {
    marca1 = millis(); //por si suelto el pulsador antes de los n seg y este tiempo no se acumule en una nueva pulsación
  }

  //aqui mas cosas que hacer ¿modificar el dato fijo por ejemplo?

}

Saludos.

1 Like

Voy a probarlo, pero una consulta se puede usar 2 veces la función millis en un programa?

Cuantas veces quieras, esa funcion solo te devuelve el valor en milisegundor desde que se enchufo el arduino.

1 Like

me aparecen los 2 valores titilando al principio y despues queda el valor fijo apretas pulsador y no vuelven aparecer hasta que lo reinicias

void loop() 
{
  oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(15, 20);     // ubica cursor en inicio de coordenadas 0,0
  oled.setTextSize(4);      // establece tamano de texto en 4
  oled.print(x,1);  // escribe en pantalla el texto
 oled.display(); 
  
 if ( pulsador) {
    cuenta1 = millis() - marca1; //arrancamos la cuenta del pulsador
    if (cuenta1 >= n) { //siendo n los milisegundos mirando el pulsador sn hacer nada (nada aqui, el programa sigue)
      //se ha entrado aqui, han pasado n seg sin soltar el pulsador
      //iniciamos el cronometro
      cuenta2 = millis(); // marca de tiempo para el cronometro
      while (millis() - cuenta2 <= m) {//m milisegundos ejecutando el cronometro
oled.clearDisplay(); 
       char buffer[30];
  oled.setCursor(13, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 2
  sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segundos);
  oled.print(buffer);
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
       

      }
    }
    marca1 = millis();
  }
  else {
    marca1 = millis(); //por si suelto el pulsador antes de los n seg y este tiempo no se acumule en una nueva pulsación
  }

  //aqui mas cosas que hacer ¿modificar el dato fijo por ejemplo?


    
    

Pero si eso ni compila!!!.. ¿donde esta el setup?... ¿donde calculas las horas minutos y segundos?....¿porque no has cambiado n y m por su valor?...???????

subo el codigo mejor ordenado


#include "avr/interrupt.h"; 
#include <EEPROM.h>
#include <stdio.h>

#include <Wire.h>      // libreria para bus I2C
#include <Adafruit_GFX.h>   // libreria para pantallas graficas
#include <Adafruit_SSD1306.h>   // libreria para controlador SSD1306
 
#define ANCHO 128     // reemplaza ocurrencia de ANCHO por 128
#define ALTO 64       // reemplaza ocurrencia de ALTO por 64

#define OLED_RESET 4      // necesario por la libreria pero no usado
Adafruit_SSD1306 oled(ANCHO, ALTO, &Wire, OLED_RESET);  // crea objeto

// variables
volatile int value;
volatile int lastEncoded = 0;
int A = 2;       //variable A a pin digital 2 (DT en modulo)
int B = 4;        //variable B a pin digital 4 (CLK en modulo)
int m =8;
int cont;
int cont1;
int volt;
float x;
const int boton=12;
const int rele=13;
int estadorele=HIGH;
int ultimoestadoboton;
int estadoactualboton;
 long t;
 int horas;
 int minutos;
 int segundos;
 const int  pulsador=7;
 int var = 0;
 unsigned long marca1;
 unsigned long cuenta1;
 unsigned long  cuenta2;


void setup()   
{  
  
    EEPROM.get(0, value); 
      Wire.begin();         // inicializa bus I2C
  oled.begin(SSD1306_SWITCHCAPVCC, 0x3C); // inicializa pantalla con direccion 0x3C 
  pinMode(9,OUTPUT);              
  pinMode(A, INPUT);   // A como entrada
  pinMode(B, INPUT);    // B como entrada
  digitalWrite(A, HIGH);
  digitalWrite(B, HIGH);
  pinMode(m,INPUT);
 pinMode(rele,OUTPUT);
 pinMode(boton,INPUT_PULLUP);
 pinMode(pulsador,INPUT_PULLUP);
 digitalWrite(rele,HIGH);
 estadoactualboton=digitalRead(boton); 

 
 //Endable Interrupts for PCIE2 arduino Pins (D0-7) 
 PCICR |= (1<<PCIE2);
 //Setup pins 2,4
 PCMSK2 |= (1<<PCINT18);  
 PCMSK2 |= (1<<PCINT20);

 TCCR1A = _BV(COM1A1) | _BV(WGM11);
  TCCR1B = _BV(CS10) | _BV(WGM12) | _BV(WGM13) ;
  ICR1 = 250; // frequency = 16000000/ = 64.000 kHz


   sei();
} 

void loop() 
{
  oled.clearDisplay();      // limpia pantalla
  oled.setTextColor(WHITE);   // establece color al unico disponible (pantalla monocromo)
  oled.setCursor(15, 20);     // ubica cursor en inicio de coordenadas 0,0
  oled.setTextSize(4);      // establece tamano de texto en 4
  oled.print(x,1);  // escribe en pantalla el texto
 oled.display(); 
  
 if ( 7 == LOW ) {
    cuenta1 = millis() - marca1; //arrancamos la cuenta del pulsador
    if (cuenta1 >= 10) { //siendo n los milisegundos mirando el pulsador sn hacer nada (nada aqui, el programa sigue)
      //se ha entrado aqui, han pasado n seg sin soltar el pulsador
      //iniciamos el cronometro
      cuenta2 = millis(); // marca de tiempo para el cronometro
      while (millis() - cuenta2 <=500) {//m milisegundos ejecutando el cronometro 
        
      oled.clearDisplay(); 
       char buffer[30];
  oled.setCursor(13, 0);     
  oled.setTextSize(2);      // establece tamano de texto en 2
  sprintf(buffer, "%02d:%02d:%02d", horas, minutos, segundos);
  oled.print(buffer);
  oled.display();     // muestra en pantalla todo lo establecido anteriormente
      }
    }
    marca1 = millis();
  }
  else {
    marca1 = millis(); //por si suelto el pulsador antes de los n seg y este tiempo no se acumule en una nueva pulsación
  }
 
   crono();
  energia();
  duty();
  voltimetro();
  pulsador1();
} 
// lectura encoder 
ISR (PCINT2_vect) {
 int MSB = digitalRead(A); 
  int LSB = digitalRead(B);
 
  int encoded = (MSB << 1) |LSB;
  int sum  = (lastEncoded << 2) | encoded; 
 
  if(sum == 0b1101 || sum == 0b0100 || sum == 0b0010 || sum == 0b1011)
    value++;
   
  if(sum == 0b1110 || sum == 0b0111 || sum == 0b0001 || sum == 0b1000)
    value--;
 
  lastEncoded = encoded; 
 
  if (value <= 0)
    value = 0;
  if (value >= 255)
    value = 255; 
  
  }
 
// funcion duty
   void duty() {
 OCR1A =  value;
 
}

// funcion memoria guarda multimo dato del encoder
void energia (){
if(digitalRead(m)==LOW){ 
cont++;
delay(3);
if (cont >5) {
 EEPROM.put(0,value);
delay(50);
cont = 0; 
}
}
} 
// genenera un falso voltimetro 
 void voltimetro(){
  volt=value;
x= map(volt, 0,255, 0,180);
  x=x/10.0;
  }
  
// funcion de boton activacion rele
  void pulsador1(){
    ultimoestadoboton=estadoactualboton; 
 estadoactualboton=digitalRead(boton);
 if (ultimoestadoboton==LOW && estadoactualboton==HIGH){
  estadorele=!estadorele;
  digitalWrite(rele,estadorele);
 }
  }

  // funcion cuenta cronometro
   void crono(){

  t=millis()/1000;
  horas =t/3600;
  minutos=(t%3600)/60;
  segundos =( t - horas*3600 - minutos *60) % 60;
 
 }

Llevas varios hilos @callecuatro1976 presentando códigos. Por favor, usa el auto format del IDE o aprende a identar correctamente.
Cada ciclo o procedimiento con las cosas alineadas.
Yo he dejado de responder porque te devuelvo un código identado y tu respondes con otro de nuevo desorganizado.
Solo es un consejo para tener mas respuestas.

1 Like

Ok, voy aver como acomodar el código mejor para que se entienda, gracias por el consejo!