Hi,
If there is an arduino/AVR code person out there who has experience with using sleep modes on a 'bare bones' arduino then a bit of help would be great.
I am trying to build a data logger which wakes up every so often and takes a few analog readings and then goes back to sleep. I want it to run from batteries for a long time.
I am using a 'bare bones' arduino (ie with no power regulator). I am using a real time clock to give me a 1Hz (once per second) interrupt onto pin D3/Interrupt 1.
I want to save as much power as possible by putting the device to sleep for most fo the time. Thsi interrupt sets a flag high which tells the main loop to take a reading and then go back to sleep again. The sleep functions seem to work OK, except when I try and add an analogRead() to my code.
I am finding that I can put the unit to sleep (just waking up to flash an LED 1 per second) and the unit consumes around 2mA on average.
When I wake up and then do an analogRead() I find that the device consumes 13mA constanly - as if it is never sleeping or doing something that consumes power.
Has anyone else had similar issues? Do I need to set other pins to switch off the ADC?
My code is below. The RTC functions work well. The ONLY change I make is to comment out the analogRead() line in the main loop. This gives the difference between 2mA consumption and 13mA consumption....
Any help apreciated,
Cheers,
Matt
<code>
/********************************************************
/****** Testing sleep modes******************************
/****** by Matt Little **********************************
/****** Date: 3/2/2014 **********************************
/******
in...@re-innovation.co.uk ************************
/******
www.re-innovation.co.uk *************************
/********************************************************
See
www.re-innovation.co.uk for information and construction details
This is sample code for the DataDuino.
/*************Details of Code*****************************
This is test code to investigate power used when in sleep modes.
A Real Time Clock is used on pin D3 (Interrupt 1) to wake the unit
every second (on the falling edge).
I want to wake up, read the ADC (temperature reading) then go back to sleep.
This should happen every 'X' seconds.
//************ Real Time Clock code*******************
A PCF8563 RTC is attached to pins:
** A4 - SDA (serial data)
** A5 - SDC (serial clock)
** D2 - Clock out - This gives a 1 second pulse to record the data
RTC PCF8563 code details:
By Joe Robertson, jmr
orbit...@bellsouth.net **********************************************************************************************************/
/************ External Libraries*****************************/
#include <Wire.h> // Required for RTC
#include <Rtc_Pcf8563.h> // RTC library
#include <avr/sleep.h>
#include <avr/power.h>
/************User variables and hardware allocation**********************************************/
/*************Real Time Clock*******/
Rtc_Pcf8563 rtc;
#define I2C_RTC 0x51 // 7 bit address (without last bit - look at the datasheet)
#define RTCinterrupt 0 // RTC interrupt - This is pin 2 of ardunio - which is INT0
/********* I/O Pins *************/
#define LEDred 5 // The output led is on pin 5
#define thermistor A3 // This is the pin for the thermistor
/********** Analogue Data Storage ************/
int analog0 = 0; // Analog input
///********* Thermistor Temperature sensor****************/
float temp; // Temporary store for float
long sampleTime = 2; // This is the time between samples for the DAQ
long dataCounter = 0; // This holds the number of seconds since the last data store
volatile int writedataflag = HIGH; // A flag to tell the code when to write data
// These next ints are for the filename conversion
int day_int =0; // To find the day from the Date for the filename
int day_int1 =0;
int day_int2 =0;
int month_int = 0;
int month_int1 = 0;
int month_int2 = 0;
int year_int = 0; // Year
int hour_int = 0;
int min_int = 0;
int sec_int = 0;
// These are Char Strings - they are stored in program memory to save space in data memory
// These are a mixutre of error messages and serial printed information
const char initialisesd[] PROGMEM = "Initialising SD card...";
#define MAX_STRING 80 // Sets the maximum length of string probably could be lower
char stringBuffer[MAX_STRING]; // A buffer to hold the string when pulled from program memory
/***************************************************
* Name: RTC
*
* Returns: Nothing.
*
* Parameters: None.
*
* Description: I use the CLK_OUT from the RTC to give me exact 1Hz signal
* To do this I changed the initialise the RTC with the CLKOUT at 1Hz
*
***************************************************/
void RTC()
{
detachInterrupt(RTCinterrupt);
dataCounter++;
if(writedataflag==LOW&&dataCounter>=sampleTime) // This stops us loosing data if a second is missed
{
// Reset the DataCounter
dataCounter = 0;
// Set the writedataflag HIGH
writedataflag=HIGH;
}
}
/***************************************************
* Name: enterSleep
*
* Returns: Nothing.
*
* Parameters: None.
*
* Description: Enters the arduino into sleep mode.
*
***************************************************/
void enterSleep(void)
{
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
attachInterrupt(RTCinterrupt, RTC, FALLING);
sleep_cpu();
/* The program will continue from here. */
/* First thing to do is disable sleep. */
sleep_disable();
}
/***************************************************
* Name: setup
*
* Returns: Nothing.
*
* Parameters: None.
*
* Description: Setup for the Arduino.
*
***************************************************/
void setup()
{
Serial.begin(9600);
//******Real Time Clock Set - up********
// A4 and A5 are used as I2C interface.
// D2 is connected to CLK OUT from RTC. This triggers an interrupt to take data
// We need to enable pull up resistors
pinMode(A4, INPUT); // set pin to input
digitalWrite(A4, HIGH); // turn on pullup resistors
pinMode(A5, INPUT); // set pin to input
digitalWrite(A5, HIGH); // turn on pullup resistors
pinMode(2,INPUT); // Set D2 to be an input for the RTC CLK-OUT
//initialise the real time clock
Rtc_Pcf8563 rtc;
setupRTC(); // Initialise the real time clock
pinMode(LEDred,OUTPUT); // Set D5 to be an output LED
Serial.println("Initialisation complete.");
attachInterrupt(RTCinterrupt, RTC, FALLING);
}
/***************************************************
* Name: main loop
*
* Returns: Nothing.
*
* Parameters: None.
*
* Description: Main application loop.
*
***************************************************/
void loop()
{
if(writedataflag==HIGH)
{
digitalWrite(LEDred, HIGH); // set the LED ON
// *********** TEMPERATURE *****************************************
// Two versions of this - either with thermistor or I2C sensor
// Thermistor version
// Reading from
// Get the temperature readings and store to variables
//analog0 = analogRead(A0);
Serial.print("Temperature: ");
Serial.println(analog0);
delay(50);
digitalWrite(LEDred, LOW); // set the LED ON
}
enterSleep();
}
// Set Up RTC routine
void setupRTC()
{
// This section configures the RTC to have a 1Hz output.
// Its a bit strange as first we read the data from the RTC
// Then we load it back again but including the correct second flag
rtc.formatDate(RTCC_DATE_WORLD);
rtc.formatTime();
year_int = rtc.getYear();
day_int = rtc.getDay();
month_int = rtc.getMonth();
hour_int = rtc.getHour();
min_int = rtc.getMinute();
sec_int = rtc.getSecond();
Wire.begin(); // Initiate the Wire library and join the I2C bus as a master
Wire.beginTransmission(I2C_RTC); // Select RTC
Wire.write(0); // Start address
Wire.write(0); // Control and status 1
Wire.write(0); // Control and status 2
Wire.write(DecToBcd(sec_int)); // Second
Wire.write(DecToBcd(min_int)); // Minute
Wire.write(DecToBcd(hour_int)); // Hour
Wire.write(DecToBcd(day_int)); // Day
Wire.write(DecToBcd(2)); // Weekday
Wire.write(DecToBcd(month_int)); // Month (with century bit = 0)
Wire.write(DecToBcd(year_int)); // Year
Wire.write(0b10000000); // Minute alarm (and alarm disabled)
Wire.write(0b10000000); // Hour alarm (and alarm disabled)
Wire.write(0b10000000); // Day alarm (and alarm disabled)
Wire.write(0b10000000); // Weekday alarm (and alarm disabled)
Wire.write(0b10000011); // Output clock frequency enabled (1 Hz) ***THIS IS THE IMPORTANT LINE**
Wire.write(0); // Timer (countdown) disabled
Wire.write(0); // Timer value
Wire.endTransmission();
}
// Converts a decimal to BCD (binary coded decimal)
byte DecToBcd(byte value){
return (value / 10 * 16 + value % 10);
}
</code>