Hi,
I'm trying to use a minimalist set-up with an ATMega328P-PU loaded with a Lilypad bootloader to monitor and record Vcc using a DS1307 RTC and a CAT24C32 EEPROM.
My code is shown below, I am most interested in where I am going wrong when storing and displaying the data from the external EEPROM.
Any pointers would be appreciated.
/***************************************************
* Tutorial found here -
* http://www.gammon.com.au/forum/?id=12821
***************************************************/
#include <Wire.h>
#include <Time.h>
#include <DS1307RTC.h>
#include <extEEPROM.h>
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
#define nEEPROMs 1
#define PAGE_SIZE 32
#define nBYTES 4096
#define LOG_DUMP 7
extEEPROM eeprom(kbits_32, nEEPROMs, PAGE_SIZE);
// Utility Macros for ADC
#define adc_disable() (ADCSRA &= ~(1<<ADEN)) // disable ADC (before sleep)
#define adc_enable() (ADCSRA |= (1<<ADEN)) // re-enable ADC
// watchdog interrupt
ISR (WDT_vect)
{
wdt_disable(); // disable watchdog
} // end of WDT_vect
float logData[3];
unsigned int writeAddress = 0;
unsigned int readAddress = 0;
boolean dumped = false;
void setup() {
Serial.begin(9600);
// initialise EEPROM
eeprom.begin(twiClock400kHz);
// slow clock down to 4 Mhz
clock_prescale_set (clock_div_2);
pinMode(LOG_DUMP, INPUT);
// set pins to OUTPUT and LOW
for (byte i = 0; i <= A5; i++)
{
if (i == 7)
{
continue;
}
pinMode(i, OUTPUT);
digitalWrite(i, LOW);
}
adc_disable(); // disable ADC
power_all_disable(); // turn off all modules
}
unsigned int counter;
void loop() {
// every 64 seconds send a reading
if ((++counter & 7) == 0)
{
if (digitalRead(LOG_DUMP) == LOW) {
recordLog();
}
if ((digitalRead(LOG_DUMP) == HIGH) && (dumped == false)) {
displayLog();
}
} // end of 64 seconds being up
// clear various "reset" flags
MCUSR = 0;
// allow changes, disble reset
WDTCSR = bit (WDCE) | bit (WDE);
// set interrupt mode and an interval
WDTCSR = bit (WDIE) | bit (WDP3) | bit (WDP0); // set WDIE, and 8 seconds delay
wdt_reset(); // pat the dog
set_sleep_mode (SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_cpu();
sleep_disable();
}
void recordLog()
{
power_all_enable();
adc_enable();
float millivoltage = readVcc();
logData[0] = hour();
logData[1] = minute();
logData[2] = second();
logData[3] = millivoltage / 1000;
for (int i = 0; i < 4; i++)
{
eeprom.write(writeAddress, logData[i]);
writeAddress += 4;
}
dumped = false;
adc_disable();
power_all_disable();
}
void displayLog()
{
adc_enable();
power_all_enable();
for (int k = 0; k < 1023; k++) {
float dumpData[3];
for (int i = 0; i < 4; i++)
{
dumpData[i] = eeprom.read(readAddress);
Serial.print(dumpData[i]);
Serial.print(" ");
readAddress += 4;
}
Serial.println();
}
dumped = true;
adc_disable();
power_all_disable();
}
long readVcc() {
// Read 1.1V reference against AVcc
// set the reference to Vcc and the measurement to the internal 1.1V reference
#if defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
ADMUX = _BV(REFS0) | _BV(MUX4) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#elif defined (__AVR_ATtiny24__) || defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__)
ADMUX = _BV(MUX5) | _BV(MUX0);
#elif defined (__AVR_ATtiny25__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
ADMUX = _BV(MUX3) | _BV(MUX2);
#else
ADMUX = _BV(REFS0) | _BV(MUX3) | _BV(MUX2) | _BV(MUX1);
#endif
delay(2); // Wait for Vref to settle
ADCSRA |= _BV(ADSC); // Start conversion
while (bit_is_set(ADCSRA, ADSC)); // measuring
uint8_t low = ADCL; // must read ADCL first - it then locks ADCH
uint8_t high = ADCH; // unlocks both
long result = (high << 8) | low;
result = 1125300L / result; // Calculate Vcc (in mV); 1125300 = 1.1*1023*1000
return result; // Vcc in millivolts
}