Hola.
He conseguido poner en marcha el proyecto. He usado las librerías "Sodaq_DS3231.h" para configurar la alarma del DS3231 y la librería "Sleep_n0m1.h" para configurar el modo Sleep (además de "SD.h", "DHT.h" y "Wire.h" para el resto de funciones en el proyecto).
Me ha pasado una cosa. Tenía configurada una interrupción mediante attachInterrupt(0, INT0_ISR, FALLING) que se ejecutaba cuando saltaba la alarma; entraba en INT0_ISR y seguía las rutinas que tengo programadas. Después he añadido al programa el paso a modo Sleep con sleep.pwrDownMode() y sleep.sleepInterrupt(0,FALLING).
El caso es que después de haber añadido la entrada en modo Sleep el programa deja de entrar en INT_ISR. ¿Se debe esto a que después de la interrupción el micro tiene que hacer dos cosas, despertar y entrar en INT_ISR, y al final sólo hace una?
Por otro lado, estoy casi seguro que el micro entra en modo Sleep, ya que impirmí un carácter por el puerto serie después de activar el PowerDown y se ejecuta sólo una vez cada 10 minutos, pero...¿de qué modo puedo comprobar con seguridad que he entrado en el modo Sleep y estoy ahorrando energía?
Os pego el código por si os puede servir:
/*Guarda en una tarjeta micro SD la humedad y temperatura de dos sensores cada 10 minutos y mientras está en modo Power Down*/
#include <SPI.h>
#include <SD.h>
#include <DHT.h>
#include <Wire.h>
#include "Sodaq_DS3231.h"
#include <Sleep_n0m1.h>
File archivo;
char weekDay[][4] = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
DateTime dt(2015, 12, 1, 18, 39, 55, 2); //year, month, date, hour, min, sec and week-day(starts from 0 (domingo) and goes to 6 (sábado))
Sleep sleep;
#define DHT1PIN 7 //Seleccionamos el pin en el que se conectará el sensor 1
#define DHT2PIN 8 //Seleccionamos el pin en el que se conectará el sensor 2
#define DHT1TYPE DHT22 //Se selecciona el DHT22 (hay otros DHT)
#define DHT2TYPE DHT22 //Se selecciona el DHT22 (hay otros DHT)
#define DS3231_I2C_ADDRESS 0x68
/*
DHT 1 INTERIOR
DHT 2 EXTERIOR*/
DHT dht1(DHT1PIN, DHT1TYPE); //Se inicia una variable que será usada por Arduino para comunicarse con el sensor
DHT dht2(DHT2PIN, DHT2TYPE); //Se inicia una variable que será usada por Arduino para comunicarse con el sensor
void setup()
{
Serial.begin(9600); //Se abren las comunicaciones serie
Wire.begin();
rtc.begin();
rtc.setDateTime(dt); //Adjust date-time as defined 'dt' above
PORTD |= 0x04; /*Se configura INT0 para que acepte interrupciones*/
DDRD &=~ 0x04;
if (!SD.begin(4)) {
Serial.println("initialization failed!");
return;
} //Este trozo de código se usa si queremos comprobar que la inicialización se ha llevado a cabo*/
dht1.begin(); //Se inicia el sensor
dht2.begin(); //Se inicia el sensor
rtc.clearINTStatus(); //Antes de habilitar las interrupciones hay que poner INT0 a HIGH
}
void configurar_alarma(int minutos, int hora)
{
if (minutos < 10) { //Mediante este conjunto de if defino los minutos y la hora de la siguiente interrupción
minutos = 10;
}
else if (minutos < 20) {
minutos = 20;
}
else if (minutos < 30) {
minutos = 30;
}
else if (minutos < 40) {
minutos = 40;
}
else if (minutos < 50) {
minutos = 50;
}
else if (minutos < 60) {
minutos = 0;
if (hora == 23){
hora = 0;
}
else {
hora++;
}
}
rtc.enableInterrupts(hora,minutos,0); //Defino la interrupción cada 10 minutos
}
void loop()
{
DateTime now = rtc.now(); //get the current date-time
//float nueva_hora, minutos_en_horas;
configurar_alarma(now.minute(),now.hour());
sleep.pwrDownMode(); //set sleep mode
sleep.sleepInterrupt(0,FALLING); //(interrupt Number (en nuestro caso es INT0 y vale 0), interrupt State)
float h_int = dht1.readHumidity(); //Se lee la humedad
float t_int = dht1.readTemperature(); //Se lee la temperatura
float h_ext = dht2.readHumidity(); //Se lee la humedad
float t_ext = dht2.readTemperature(); //Se lee la temperatura
archivo = SD.open("HHVV.txt", FILE_WRITE); //Se abre el fichero de trabajo. Es importante saber que sólo puede haber un
//fichero abierto, por lo que hay que cerrar el anterior antes de abrir uno nuevo. El fichero debe tener nombre corto
now = rtc.now();
if (archivo) { //El IF se ejecuta si el fichero se ha abierto correctamente
archivo.print(now.date());
archivo.print("/");
archivo.print(now.month());
archivo.print("/");
archivo.print(now.year());
archivo.print(",");
archivo.print(now.hour());
if (now.minute() == 10) { //Este conjunto de if es un modo cutre de expresar los minutos como horas. Debería reprogramarse y que se calculara
archivo.print(".16,");
}
else if (now.minute() == 20) {
archivo.print(".33,");
}
else if (now.minute() == 30) {
archivo.print(".50,");
}
else if (now.minute() == 40) {
archivo.print(".66,");
}
else if (now.minute() == 50) {
archivo.print(".83,");
}
else if (now.minute() == 0) {
archivo.print(".00,");
}
archivo.print(h_int);
archivo.print(",");
archivo.print(t_int);
archivo.print(",");
archivo.print(h_ext);
archivo.print(",");
archivo.println(t_ext);
}
archivo.close(); //Se cierra el fichero
rtc.clearINTStatus(); //Antes de habilitar de nuevo las interrupciones hay que poner INT en HIGH
}
Un saludo y gracias.