Hello all,
First off, let me thank Geir Andersen and Oddbot for their excellent work on datalogging shields, mosfet circuitry and other answers to my silent questions, reading through the articles was great fn and a good learning experience.
Presently, I'm trying to make an Arduino datalogger based around the Arduino Pro Mini, running 8Mhz on an external crystal/resonator. This, in conjunction with an LDO regulator, SD card and RTC should allow me to build a logger and lo and behold, it works!
By putting the arduino into a deep sleep and letting it wake up by the RTC works like a charm. Right now, I have a quiescent current of 0,32mA. However, since the arduino is picking its nose for the most part of the time interval, I tried what others are already doing (looking at you Geir :) ) and looked into using the RTC INT output to operate a Mosfet which in turns switches the loads on the 3V3 bus.
So I build the schematic Oddbot describes in the low power datalogger shield of Geir with the change that the DS3231SN uses an open drain N channel mosfet internally so I use a 4K7 pull-up on the INT pin to get good results. It works in the sleeping arduino set-up.
But when I connect the INT pin to the mosfet, things don't work our as I have planned and that's why I turn to you.
The basic idea is that the RTC is pre-programmed to pull the INT pin low in order to drive the gate of the mosfet to 0, allowing the voltage on the source to get to the drain. When I plug and pull wires to simulate, the mosfet does what it is supposed to do. When plug it into the RTC, it doesn't.
After a lot of fiddling, maybe my nice plan of converting to this set-up is hitting snag in that when I program the arduino, I set the interval (in this case every minute, just for test), let the arduino do its thing and then clear the interrupt flag of the RTC, expecting the RTC to pull the pin high again and effectively killing the Arduino. Once its time register (seconds = 0) trips the alarm register, the INT pin is pulled low, mosfet kicks in and the show starts again, at least that what's it supposed to do.
I'll post my code here, I tried using tags to get a code block but couldn't get it to work..
//This sketch uses a mosfet connected to the RTC to turn the whole system on and off, no use of the sleep library necessary.
#include <avr/io.h>
#include <Wire.h>
#include <DS3231.h>
#include <Fat16.h>
#include <Fat16util.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include "Wire.h"
#include <EEPROM.h>
#include <Time.h>
#define NDevices 9 // Number of DS18B20s
#define BUS 3 // OneWire bus on pin 3
OneWire oneWire(BUS);
DallasTemperature sensors(&oneWire); // pass to the DT library
DeviceAddress TAddress; // 8-bit T-sensor address
int EAddress; // EEPROM address pointer
DS3231 RTC; //Create RTC object for DS3231 RTC come Temp Sensor
// static uint8_t prevSecond=0;
static DateTime interruptTime;
SdCard card;
Fat16 file;
//int led = 13;
// store error strings in flash to save RAM
#define error(s) error_P(PSTR(s))
void error_P(const char* str) {
PgmPrint("error: ");
SerialPrintln_P(str);
if (card.errorCode) {
PgmPrint("SD error: ");
Serial.println(card.errorCode, HEX);
}
while(1);
}
void setup ()
{
/*Initialize INT0 pin for accepting interrupts */
PORTD |= 0x04;
DDRD &=~ 0x04;
pinMode(4,INPUT); //extern power
DDRB = B00000000; // set pins 8 to 13 as inputs
PORTB |= B11111111; // enable pullups on pins 8 to 13
Wire.begin();
Serial.begin(9600);
RTC.begin();
//attachInterrupt(0, INT0_ISR, LOW); //Only LOW level interrupt can wake up from PWR_DOWN
//set_sleep_mode(SLEEP_MODE_PWR_DOWN);
//Enable Interrupt
RTC.enableInterrupts(EveryMinute); //interrupt at EverySecond, EveryMinute, EveryHour
// or this
//DateTime start = RTC.now();
//interruptTime = DateTime(start.get() + 60); //Add 1 minute in seconds to start time
sensors.begin();
//pinMode(led, OUTPUT);
}
void loop ()
{
DateTime now = RTC.now(); //get the current date-time
sensors.requestTemperatures(); // Send out a global "check temperatures" command
Serial.println("busy");
//|||||||||||||||||||Write to Disk||||||||||||||||||||||||||||||||||
// initialize the SD card
if (!card.init()) error("card.init");
// initialize a FAT16 volume
if (!Fat16::init(&card)) error("Fat16::init");
char name[] = "DATALOG.CSV";
// clear write error
file.writeError = false;
// O_CREAT - create the file if it does not exist
// O_APPEND - seek to the end of the file prior to each write
// O_WRITE - open for write
if (!file.open(name, O_CREAT | O_APPEND | O_WRITE))
error("error opening file");
if (now.date() < 10)
file.print("0");
file.print(now.date(), DEC);
file.print('/');
if (now.month() < 10)
file.print("0");
file.print(now.month(), DEC);
file.print('/');
file.print(now.year(), DEC);
file.print(';');
if (now.hour() < 10)
file.print("0");
file.print(now.hour(), DEC);
file.print(':');
if (now.minute() < 10)
file.print("0");
file.print(now.minute(), DEC);
file.print(':');
file.print(now.second(), DEC);
file.print(';');
RTC.convertTemperature(); //convert current temperature into registers
file.print(RTC.getTemperature()); //read registers and display the temperature
file.print(';');
// Now get those temperatures
EAddress = 0;
for (byte j=0;j<NDevices;j++) { // loop over devices
for (byte k=0;k<8;k++) { // loop over address bytes
TAddress[k] = EEPROM.read(EAddress);
EAddress += 1;
}
file.print(sensors.getTempC(TAddress));
file.print(";");
}
file.print("\n");
if (!file.close())
error("error closing file");
//digitalWrite(led, HIGH); // turn the LED on (HIGH is the voltage level)
//delay(1000); // wait for a second
//digitalWrite(led, LOW); // turn the LED off by making the voltage LOW
//|||||||||||||||||||Write to Disk||||||||||||||||||||||||||||||||||
Serial.println("bye!");
delay(1000);
RTC.clearINTStatus(); //This function call is a must to bring /INT pin HIGH after an interrupt.
//RTC.enableInterrupts(interruptTime.hour(),interruptTime.minute(),interruptTime.second()); // set the interrupt at (h,m,s)
//attachInterrupt(0, INT0_ISR, LOW); //Enable INT0 interrupt (as ISR disables interrupt). This strategy is required to handle LEVEL triggered interrupt
////////////////////////END : Application code ////////////////////////////////
}
//Interrupt service routine for external interrupt on INT0 pin connected to DS3231 /INT
//void INT0_ISR()
//{
//Keep this as short as possible. Possibly avoid using function calls
// detachInterrupt(0);
//interruptTime = DateTime(interruptTime.get() + 60); //decide the time for next interrupt, configure next interrupt
//}
I'll see if I can upload a schematic to make things a bit more clear. I can't shake the thought I'm missing something major or that I need to (re)program the arduino differently the moment the RTC is connected to the Mosfet.