¿Es el uso correcto del RTC RV8523 para activar un atmega328p?

Estoy usando el RV8523 para despertar cada 2 minutos un arduino atmega328p. El rtc está cableado así:

Esquema del RTC conectado al ATmega328p

Donde INT1 está conectado al pin 3 del puerto D. La resistencia de extracción interna está activada y, sin embargo, funciona correctamente. Se despierta a veces cada 2 minutos, pero a veces no.

Ahí está el código para programar el RTC:

#define I2C_ADDR (0xD0 >> 1)

#define TIMERA_CLK 0x03    
#define TIMERA_PERIOD 0x02

void Rtc_init()
{
    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x00)); //control 1 register
    Wire.write(byte(0x00)); 
    Wire.endTransmission();

    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x01)); //control 2 register
    Wire.write(byte(0x02)); 
    Wire.endTransmission();

    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x02)); //control 3 register
    Wire.write(byte(0x00)); 
    Wire.endTransmission();

    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x10));       // Timer A Clock register
    Wire.write(byte(TIMERA_CLK)); //  
    Wire.endTransmission();

    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x11));          // Timer A register
    Wire.write(byte(TIMERA_PERIOD)); //  
    Wire.endTransmission();

    Wire.beginTransmission(I2C_ADDR);
    Wire.write(byte(0x0F)); // Timer & Clkout register
    Wire.write(byte(0xBA)); //  
    Wire.endTransmission();

    pinMode(INT, INPUT_PULLUP); // <== Sleep mode from RTC

    delay(100);
}

Y está el código "principal":

#define INT 1
void setup()
{

    Serial.begin(9600);
    while (!Serial){;}

    mySerial.begin(9600);


    mySerial.println("Start ");


    // Setup RTC
    Rtc_init();
    mySerial.println("RTC Init Done");

}

void loop () 
{
    mySerial.println("\n\nWAKE UP ");
    delay(1000);
    mySerial.println("\n\nGoing to sleep");
    mySerial.flush(); 


    attachInterrupt(INT, Push, FALLING); 
    LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
    detachInterrupt(INT); 
}

void Push()
{

}

Toda la biblioteca está incluida y está la señal del pin de interrupción rtc (INT1):Señal RTC ==> INT1.  Podemos ver la interrupción pero el voltaje parece muy bajo.

Si tiene alguna pista que me guíe en la dirección correcta para la depuración, no tengo ideas :-/

EDITAR: Debo precisar que el atmega se alimenta con un voltaje de 3.3V al igual que el RTC. EDICIÓN 2: la señal visible en el alcance se repite correctamente 1 vez cada 2 minutos PERO el atmega no se activa:En una escala temporal más grande: podemos ver el patrón repitiéndose cada 2 minutos

Comenzaría verificando si ese pulso es lo suficientemente largo como para ser detectado por MCU.
Creo que sí ! De hecho, a veces el atmega se despierta y verifico que la señal va directamente a 0V. Ahí no es el caso (el mínimo es de 18mV) así que creo que está más relacionado con el nivel de voltaje que con la sincronización del pulso. Revisaré la hoja de datos de atmega solo para estar seguro.
Después de una revisión rápida, solo puedo decir que la duración del pulso es de 15 ms. No encontré ninguna información al respecto en la hoja de datos de atmega328p. Como dije, estoy bastante seguro de que no es un problema relacionado con el tiempo.
Descubrí: "los pulsos que duran más de un período de reloj generarán una interrupción". Estoy usando un oscilador externo de 8 MHz, por lo que el período del reloj es de 0,125 us (no estoy seguro) y la duración del pulso es de unos 15 ms. Realmente creo que no es el problema aquí :-/
La cita anterior es para el funcionamiento normal. Aquí está el que necesita: "Nota: si se usa una interrupción activada por nivel para activarse desde el apagado, el nivel requerido debe mantenerse el tiempo suficiente para que la MCU complete la activación para activar la interrupción de nivel".
Me pregunto, ¿por qué estás usando un reloj externo? la "P" en 328P significa "pico power", que es un amplio conjunto de funciones para ahorrar energía. De hecho, la biblioteca Arduino que usa se basa en esas características. Es decir, cuando apaga la MCU de la forma en que lo hace, entra en un estado que le permite activarse por sí sola después del tiempo preestablecido. Agregar RV8523 solo agrega consumo de energía, por pequeño que sea
Y una cosa más, según la hoja de datos, solo se puede usar la interrupción de nivel para despertar por INT0/1. Creo que está utilizando la interrupción de cambio de nivel en su código.
Pensé que sería una buena idea usar un RTC externo por 2 razones: una es porque la biblioteca de bajo consumo que estoy usando permite poner el atmega328p en suspensión profunda durante solo 8 segundos como máximo o para siempre (necesito 2 minutos). La segunda razón es asegurar que el reloj se conserve incluso si la batería se está agotando (usando la batería de respaldo del rtc). Además, leí en alguna parte que este rtc externo es más preciso que el del atmega328p (pero tal vez me equivoque).
¿Dónde encontraste la información que dice que no podemos usar el borde descendente para activar el ATmega? De todos modos, gracias por tu ayuda, ¡es muy útil!
Muchas gracias, puede que solucione mi problema! Probaré esto y volveré para confirmar.
Sigo pensando que la longitud del pulso también está contribuyendo al problema. La interrupción de activación requiere que la entrada sea baja durante todo el tiempo de activación, que puede durar hasta 258 ciclos de reloj. Es posible que la MCU aún se active, pero no se generará la interrupción y no sé cómo manejará eso su biblioteca. Reprecisión: es tan buena como la fuente del reloj. Puede conectar exactamente el mismo (o mejor) cristal de 32,768 kHz que en RV8523 a los pines MCU TOSC.
¡Intenté usar la interrupción nivelada en lugar de la pulsada y funcionó! gracias por su ayuda. Cuando dices que debería usar un cristal externo, ¿quieres decir que podría usarlo con un temporizador interno o algo así para despertar la MCU? Aquí estoy usando el RV8523 solo para generar interrupciones, no lo estoy usando como reloj para la MCU.
Me alegro de poder ayudar. Voy a hacer que sea una respuesta entonces. Lo que dije sobre el cristal es que su MCU admite 2 de ellos, uno para el reloj del procesador, uno 32.768 para el temporizador interno, lo que lo hace tan preciso como el RV8523. Por lo tanto, si alguna vez decide que puede usar el temporizador MCU interno para despertarse, no perderá precisión.
ah vale, es bueno saberlo! Entonces, mi único argumento para usar este RTC es que puedo hacer más de 8 segundos en sueño profundo.
Bueno, el esquema es simple, la corriente agregada es minúscula y la conveniencia de configurar el retraso está ahí. No veo ninguna razón para no usarlo, aparte de la mía (por lo que no se aplica a su caso) no me gusta que se agregue una sola resistencia al circuito si se puede evitar. Agregaré algunos pensamientos sobre ese límite de 8 segundos a la respuesta.
De alguna manera, la actualización resultó ser 5 veces más larga que la respuesta real... Y creo que la frase sobre 2 cristales fue engañosa. No se pueden conectar al mismo tiempo, es reloj de cristal o sistema de cristal de reloj.

Respuestas (1)

Solo se puede usar la interrupción de nivel para despertar por INT0/1. La interrupción por cambio de nivel no funciona.

Además, si es necesario procesar la interrupción (no solo la activación), debe mantenerse baja durante todo el tiempo de activación, que puede durar hasta 258 ciclos de reloj. De lo contrario, la MCU se activará pero se perderá la interrupción.

ACTUALIZAR

No está directamente relacionado con la pregunta, pero podría valer la pena considerarlo.

El límite de 8 segundos en el retraso del sueño que lo obligó a usar un temporizador externo es puramente artificial. Es el resultado directo de la biblioteca que está utilizando confiando en el temporizador de vigilancia como fuente de interrupción de activación. La razón por la que utilizan el mecanismo de vigilancia es que WDT es la única fuente de interrupción interna disponible en todos los modos de suspensión. Esto facilita la escritura de la biblioteca, pero no significa que el resultado final sea el mejor posible.

El modo de suspensión de energía más bajo es Power-down. Watchdog, interrupción externa y coincidencia TWI son las únicas posibles fuentes de interrupción disponibles. Esto lo obliga a usar una interrupción externa para retrasos de más de 8 segundos. El consumo de energía total es apagado + reloj externo, o 0.5uA + 0.13uA = 0.63uA

Echemos un vistazo al modo de ahorro de energía. La única diferencia con el apagado es que el reloj asíncrono está activo, lo que le permite usar un reloj de cristal de 32,768 kHz como fuente de reloj. Y se puede utilizar para la interrupción del despertar. El consumo total de energía es Power-save, que es Power-down + reloj interno. De acuerdo con la hoja de datos, la corriente de aproximadamente 0.95uA se puede lograr en este modo (aunque necesita hacer algunos trucos de software avanzados para esto, como deshabilitar el apagón, apagar ADC, etc.)

La diferencia entre estos modos es dos veces menor que la que consumen incluso los LDO de corriente de reposo ultrabaja (alrededor de 0,5 uA). Teniendo en cuenta que esto le permite deshacerse de todas esas partes externas, diría que es una opción bastante viable.

Hay dos inconvenientes a tener en cuenta. En primer lugar, dado que se utilizan los mismos pines para el cristal del reloj que para el oscilador de cristal normal, está limitado al oscilador RC interno como fuente de reloj del sistema. Tenga en cuenta que el RC interno puede ser calibrado por el usuario con una precisión de aproximadamente el 1%, lo que debería ser suficiente para la mayoría de las aplicaciones.

En segundo lugar, no hay copia de seguridad de celda de botón que haya mencionado antes. Sin embargo, dado que esta es una aplicación alimentada por batería (supongo que lo es, de lo contrario, controlaría el adaptador de alimentación por reloj, no por el modo de suspensión de MCU), entonces no veo la necesidad de una copia de seguridad. Una batería es una batería. Puede agregar interruptores mosfet simples para apagar el resto del circuito y conectar la batería al pin ADC. Luego, mediría el voltaje de la batería al despertar y deshabilitaría todo menos RTC si está bajando demasiado.