I'm making my [second] attempt to create a useful library using the Arduino IDE (0021), and I've run into a weird issue, and I'm wondering if anyone can give me any insight. Compilation seems to go OK, but depending on where I create my library object's instance, the ATmega328 I'm uploading to will crash - code in the setup() function does not run, but the chip can be reprogrammed.
Here's the code I'm using:
DS1307.h
#ifndef DS1307_H_
#define DS1307_H_
#include "WProgram.h"
// DS1307 I2C slave address
#define DS1307_I2C_ADDRESS B1101000
// DS1307 register addresses
#define DS1307_REG_SEC 0
#define DS1307_REG_MIN 1
#define DS1307_REG_HR 2
#define DS1307_REG_DOW 3 // day of week
#define DS1307_REG_DATE 4 // day of month
#define DS1307_REG_MONTH 5
#define DS1307_REG_YEAR 6
#define DS1307_REG_CTL 7
class DS1307 {
public:
// storage for date and time
byte second, minute, hour, dayOfWeek, dayOfMonth, month, year;
// methods for accessing the chip
DS1307(void);
void getDateTime(void);
private:
byte decToBcd(byte);
byte bcdToDec(byte);
};
#endif // DS1307_H_
DS1307.cpp
#include "WProgram.h"
#include <Wire.h>
#include "DS1307.h"
// constructor
DS1307::DS1307(void) {
Wire.begin();
getDateTime();
} // DS1307()
// Convert normal decimal numbers to binary coded decimal
byte DS1307::decToBcd(byte val) {
return ( (val/10*16) + (val%10) );
} // decToBcd()
// Convert binary coded decimal to normal decimal numbers
byte DS1307::bcdToDec(byte val) {
return ( (val/16*10) + (val%16) );
} // bcdToDec()
// Gets the date and time from the ds1307 and
// stores it into the class' public variables.
void DS1307::getDateTime(void) {
// Reset the register pointer
Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.send(DS1307_REG_SEC);
Wire.endTransmission();
// now retrieve the DT
Wire.requestFrom(DS1307_I2C_ADDRESS, 7);
// A few of these need masks because certain bits are control bits
second = bcdToDec(Wire.receive() & 0x7f);
minute = bcdToDec(Wire.receive());
hour = bcdToDec(Wire.receive() & 0x3f); // Need to change this if 12 hour am/pm
dayOfWeek = bcdToDec(Wire.receive());
dayOfMonth = bcdToDec(Wire.receive());
month = bcdToDec(Wire.receive());
year = bcdToDec(Wire.receive());
Wire.endTransmission();
} // getDateTime()
Demo_DS1307.pde
#include <Wire.h>
#include <DS1307.h>
#define VERSTR "Demo_DS1307 v0.02 by Emo Mosley on 1-6-2011"
#define PIN_HB 8
// VT100 escape sequences
#define ESCAPE 27
#define VT_CLEAR "\e[2J"
#define VT_RIGHT "\e[1C"
#define VT_ROW2 "\e[2H"
#define VT_EEOL "\e[K"
// instance of DS1307 RTC
// declaring the instance here causes the ATmega to lock up:
//DS1307 rtc;
// display refresh timing
#define DISP_POLL 250
unsigned long display_poll_dt;
char str[20];
void setup(void) {
pinMode(PIN_HB, OUTPUT);
Serial.begin(19200);
Serial.print(VT_CLEAR);
Serial.print(VERSTR);
digitalWrite(PIN_HB, HIGH); // turn on the heartbeat LED on
//rtc.getDateTime();
} // setup()
void loop(void) {
// instance of DS1307 RTC
// when the instance is declared here, the program works as expected,
// but isn't this a BAD place for it?
DS1307 rtc;
// check display refresh timer
if(millis() >= display_poll_dt) {
// update the display timer
display_poll_dt += DISP_POLL;
// grab the current time
rtc.getDateTime();
// format the time into a readable format
sprintf(str, "%2d:%02d:%02d\r\n", rtc.hour, rtc.minute, rtc.second);
// display the time out to the serial port
Serial.print(VT_ROW2);
Serial.print(VT_EEOL);
Serial.print(str);
} // if
} // loop()
In most code I see using a library, the object is instantiated globally in the pde file shortly after its #include statement. In some cases, this happens within the include file (but I can't get it to compile that way for some reason). The only way I could get it to run is by declaring the instance at the top of the loop() function! I must be doing something wrong, but I lack the experience with OOP to troubleshoot what should be a simple thing to do.
Does anyone have any ideas?
Many thanks.
-Emo