Buenas tengo un problema, tengo que hacer un programa que tenga una interrupcion interna con un timer, para que cada 30 segundos se muestre un mensaje en la pantalla lcd, pero no esta funcionando, lo hace cada 4, 6, 5 segundos, es lo unico y lo ultimo que me esta fallando, por favor si alguien me puede decir como se puede se puede hacer lo agradeceria mucho.
El programa principal debe de imprimir los numeros del 1 al 99 cada numero en un intervalo de 500 mS y hay 3 interrupciones, 2 externas (ya funcionan) y una interna (el timer que nomas no funciona).
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Inicializa la pantalla LCD 16x2 con el modulo I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Variables globales
volatile unsigned long tiempo_transcurrido = 0;
volatile bool interrupt1_triggered = false;
volatile bool interrupt2_triggered = false;
volatile bool flagInterrupcion = false;
// Función para manejar la interrupción 1
void interrupt1() {
interrupt1_triggered = true;
}
// Función para manejar la interrupción 2
void interrupt2() {
interrupt2_triggered = true;
}
// Función para manejar la interrupción 2
ISR(TIMER3_COMPA_vect) {
tiempo_transcurrido++; // Incrementar el tiempo transcurrido en 1 segundo
}
void setup() {
Serial.begin(9600);
// Configurar el timer1 para interrupción cada 30 segundos
cli(); // Deshabilitar interrupciones
TCCR3A = 0; // Configurar el Timer3 en modo normal
TCCR3B = (1 << CS32) | (1 << CS30); // Configurar el Timer3 con preescaler de 1024
TCNT3 = 0; // Reiniciar el contador del Timer3
OCR3A = 500000; // Valor de comparación para interrupción cada 30 segundos
TIMSK3 |= (1 << OCIE3A); // Habilitar interrupción del Timer3 por comparación con OCR3A
sei(); // Habilitar interrupciones
// Inicializa la pantalla LCD
lcd.init();
lcd.backlight();
// Configura los pines de las interrupciones externas
attachInterrupt(digitalPinToInterrupt(2), interrupt1, FALLING);
attachInterrupt(digitalPinToInterrupt(3), interrupt2, FALLING);
}
void loop() {
// Cuenta del 1 al 99 y muestra cada número en la pantalla
for (int i = 1; i <= 99; i++) {
if (tiempo_transcurrido >= 30) {
lcd.clear();
lcd.setCursor(0, 0); // Posicionar el cursor en la primera columna de la segunda fila
lcd.print("PASARON 30 SEG"); // Mostrar el mensaje "pasaron 30 seg" en la pantalla LCD
tiempo_transcurrido = 0; // Reiniciar el tiempo transcurrido
}
// Verifica si se ha activado la interrupción 1
if (interrupt1_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("interrupción 1");
// Reinicia la variable de interrupción
interrupt1_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
// Verifica si se ha activado la interrupción 2
if (interrupt2_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("interrupción 2");
// Reinicia la variable de interrupción
interrupt2_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(i);
// Espera medio segundo antes de mostrar el siguiente número
delay(500);
}
}
Por el timer3 asumo que estas utilizando un arduino Mega cierto?
El usuario Thomasx en su publicación del foro ejecuta satisfactoriamente interrupciones con el arduino mega en el timer 4 timer setup for timer4 For arduino Mega
A su vez me queda claro que estas haciendo mal la interrupción 3 ya que estableces el timer 3 con un prescaler de 1024 a 16 bits , lo que significa que puede almacenar un valor de contador máximo de 65535 y tu le asignas 500000
OCR3A = 500000; // Valor de comparación para interrupción cada 30 segundos
para finalizar cuentas con la variable tiempo transcurrido para crear un contador de 30 segundos cada que se interrumpe el timer3, pero esta declarado para incrementar la misma cada 1 segundo segun esta funcion
ISR(TIMER3_COMPA_vect) {
tiempo_transcurrido++; // Incrementar el tiempo transcurrido en 1 segundo
}
En conclusión recomiendo hacer el timer3 a frecuencia de 1Hz lo que te dara una interrupción cada 1 segundo, así podrias usar tu variable tiempo_transcurrido hasta que llegue a 30 y presentar el mensaje en tu LCD, leyendo el código de thomasx las correcciones en el setup quedarian de la siguiente forma
void setup() {
Serial.begin(9600);
// Configurar el timer1 para interrupción cada 30 segundos
cli(); // Deshabilitar interrupciones
TCCR3A = 0; // Configurar el Timer3 en modo normal
TCCR3B = 0 // same for TCCR1B
TCNT3 = 0; // Reiniciar el contador del Timer3
// set compare match register for 1hz increments
OCR3A = 15624 / 1; // = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR3B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR3B |= (1 << CS12) | (1 << CS10);
TIMSK3 |= (1 << OCIE3A); // Habilitar interrupción del Timer3 por comparación con OCR3A
sei(); // Habilitar interrupciones
// Inicializa la pantalla LCD
lcd.init();
lcd.backlight();
// Configura los pines de las interrupciones externas
attachInterrupt(digitalPinToInterrupt(2), interrupt1, FALLING);
attachInterrupt(digitalPinToInterrupt(3), interrupt2, FALLING);
}
Ya hice los cambios que me comentaste y sigue sin funcionar, me di cuenta que al imprimir la variable tiempo_transcurrido en cada ciclo en vez del mensaje "PASARON 30 SEG", me estaba imprimiendo 891, como si en una vuelta del ciclo for la variable se incrementara 891 veces, no se si sea la condicion o algo en el programa principal que no permite que funcione correctamente aqui esta el codigo actualizado. Ah en mi desesperacion por querer hacerlo funcionar cambie el timer 3 por el timer 2 y efectivamente tengo arduino mega
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Inicializa la pantalla LCD 16x2 con el modulo I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Variables globales
volatile unsigned long tiempo_transcurrido = 0;
volatile bool interrupt1_triggered = false;
volatile bool interrupt2_triggered = false;
volatile bool flagInterrupcion = false;
// Función para manejar la interrupción 1
void interrupt1() {
interrupt1_triggered = true;
}
// Función para manejar la interrupción 2
void interrupt2() {
interrupt2_triggered = true;
}
// Función para manejar la interrupción 2
ISR(TIMER2_COMPA_vect) {
tiempo_transcurrido++; // Incrementar el tiempo transcurrido en 1 segundo
}
void setup() {
Serial.begin(9600);
// Configurar el timer2 para interrupción cada 30 segundos
cli(); // Deshabilitar interrupciones
TCCR2A = 0; // Configurar el Timer2 en modo normal
TCCR2B = 0; // Configurar el Timer2 en modo normal
TCNT2 = 0; // Reiniciar el contador del Timer2
// set compare match register for 1hz increments
OCR2A = 15624 / 1; // = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR2A |= (1 << WGM21);
// Set CS22 and CS21 and CS20 bits for 1024 prescaler
TCCR2B |= (1 << CS22) | (1 << CS21) | (1 << CS20);
TIMSK2 |= (1 << OCIE2A); // Habilitar interrupción del Timer2 por comparación con OCR2A
sei(); // Habilitar interrupciones
// Inicializa la pantalla LCD
lcd.init();
lcd.backlight();
// Configura los pines de las interrupciones externas
attachInterrupt(digitalPinToInterrupt(2), interrupt1, FALLING);
attachInterrupt(digitalPinToInterrupt(3), interrupt2, FALLING);
}
void loop() {
// Cuenta del 1 al 99 y muestra cada número en la pantalla
for (int i = 1; i <= 99; i++) {
if (tiempo_transcurrido >= 30) {
lcd.clear();
lcd.setCursor(0, 0); // Posicionar el cursor en la primera columna de la segunda fila
lcd.print(tiempo_transcurrido); // Mostrar el mensaje "pasaron 30 seg" en la pantalla LCD
delay(500);
tiempo_transcurrido = 0; // Reiniciar el tiempo transcurrido
}
// Verifica si se ha activado la interrupción 2
if (interrupt1_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("FRANCISCO CETI");
// Reinicia la variable de interrupción
interrupt1_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
// Verifica si se ha activado la interrupción 2
if (interrupt2_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("DON CHUY FILEMON");
// Reinicia la variable de interrupción
interrupt2_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(i);
// Espera medio segundo antes de mostrar el siguiente número
delay(500);
}
}
Probado y funciona bien (corregido seteo del timer)
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Inicializa la pantalla LCD 16x2 con el modulo I2C
LiquidCrystal_I2C lcd(0x27, 16, 2);
// Variables globales
volatile unsigned long tiempo_transcurrido = 0;
volatile bool interrupt1_triggered = false;
volatile bool interrupt2_triggered = false;
volatile bool flagInterrupcion = false;
// Función para manejar la interrupción 1
void interrupt1() {
interrupt1_triggered = true;
}
// Función para manejar la interrupción 2
void interrupt2() {
interrupt2_triggered = true;
}
// Función para manejar la interrupción timer3
ISR(TIMER3_COMPA_vect) {
tiempo_transcurrido++; // Incrementar el tiempo transcurrido en 1 segundo
}
void setup() {
Serial.begin(9600);
// Configurar el timer1 para interrupción cada 1 segundo
noInterrupts();
// Clear registers
TCCR3A = 0;
TCCR3B = 0;
TCNT3 = 0;
// 1 Hz (16000000/((15624+1)*1024))
OCR3A = 15624;
// CTC
TCCR3B |= (1 << WGM32);
// Prescaler 1024
TCCR3B |= (1 << CS32) | (1 << CS30);
// Output Compare Match A Interrupt Enable
TIMSK3 |= (1 << OCIE3A);
interrupts();
// Inicializa la pantalla LCD
lcd.init();
lcd.backlight();
// Configura los pines de las interrupciones externas
attachInterrupt(digitalPinToInterrupt(2), interrupt1, FALLING);
attachInterrupt(digitalPinToInterrupt(3), interrupt2, FALLING);
}
void loop() {
// Cuenta del 1 al 99 y muestra cada número en la pantalla
for (int i = 1; i <= 99; i++) {
if (tiempo_transcurrido >= 30) {
lcd.clear();
lcd.setCursor(0, 0); // Posicionar el cursor en la primera columna de la segunda fila
lcd.print("PASARON 30 SEG"); // Mostrar el mensaje "pasaron 30 seg" en la pantalla LCD
tiempo_transcurrido = 0; // Reiniciar el tiempo transcurrido
delay(2000); // agregue este delay para que se vea el mensaje
}
// Verifica si se ha activado la interrupción 1
if (interrupt1_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("interrupción 1");
// Reinicia la variable de interrupción
interrupt1_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
// Verifica si se ha activado la interrupción 2
if (interrupt2_triggered) {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("interrupción 2");
// Reinicia la variable de interrupción
interrupt2_triggered = false;
// Espera un segundo antes de continuar con la cuenta
delay(1000);
}
lcd.clear();
lcd.setCursor(0, 0);
lcd.print(i);
// Espera medio segundo antes de mostrar el siguiente número
delay(500);
}
}
Ya funciono!, muchas gracias amigo, de verdad. Note que tiene un ligero desfase, supongo que sera por el delay de 500mS para mostrar el iterator del ciclo. Muchas gracias otra vez!.