1
0
mirror of https://github.com/oliexdev/openScale.git synced 2025-08-13 12:14:19 +02:00

initial commit microcontroller unit (mcu) arduino sketch for the custom bluetooth scale.

This commit is contained in:
OliE
2014-12-13 16:54:05 +01:00
parent 45081b8f09
commit 9711f35e4f
36 changed files with 4875 additions and 0 deletions

View File

@@ -0,0 +1,2 @@
*.zip
*.7z

View File

@@ -0,0 +1,335 @@
/*----------------------------------------------------------------------*
* DS3232RTC.cpp - Arduino library for the Maxim Integrated DS3232 *
* Real-Time Clock. This library is intended for use with the Arduino *
* Time.h library, http://www.arduino.cc/playground/Code/Time *
* *
* This library is a drop-in replacement for the DS1307RTC.h library *
* by Michael Margolis that is supplied with the Arduino Time library *
* above. To change from using a DS1307 RTC to an DS3232 RTC, it is *
* only necessary to change the #include statement to include this *
* library instead of DS1307RTC.h. *
* *
* In addition, this library implements functions to support the *
* additional features of the DS3232. *
* *
* This library will also work with the DS3231 RTC, which has the same *
* features of the DS3232 except: (1) Battery-backed SRAM, (2) Battery- *
* backed 32kHz output (BB32kHz bit in Control/Status register 0x0F), *
* and (3) Adjustable temperature sensor sample rate (CRATE1:0 bits in *
* the Control/Status register). *
* *
* Whether used with the DS3232 or DS3231, the user is responsible for *
* ensuring reads and writes do not exceed the device's address space *
* (0x00-0x12 for DS3231, 0x00-0xFF for DS3232); no bounds checking *
* is done by this library. *
* *
* Jack Christensen 06Mar2013 *
* 28Aug2013 Changed the lower level methods to return the status of *
* the I2C communication with the RTC. Thanks to *
* Rob Tillaart for the suggestion. (Fixes issue #1.) *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 444 Castro Street, Suite 900, *
* Mountain View, CA 94041. *
*----------------------------------------------------------------------*/
#include <DS3232RTC.h>
//define release-independent I2C functions
#if defined(__AVR_ATtiny44__) || defined(__AVR_ATtiny84__) || defined(__AVR_ATtiny45__) || defined(__AVR_ATtiny85__)
#include <TinyWireM.h>
#define i2cBegin TinyWireM.begin
#define i2cBeginTransmission TinyWireM.beginTransmission
#define i2cEndTransmission TinyWireM.endTransmission
#define i2cRequestFrom TinyWireM.requestFrom
#define i2cRead TinyWireM.receive
#define i2cWrite TinyWireM.send
#elif ARDUINO >= 100
#include <Wire.h>
#define i2cBegin Wire.begin
#define i2cBeginTransmission Wire.beginTransmission
#define i2cEndTransmission Wire.endTransmission
#define i2cRequestFrom Wire.requestFrom
#define i2cRead Wire.read
#define i2cWrite Wire.write
#else
#include <Wire.h>
#define i2cBegin Wire.begin
#define i2cBeginTransmission Wire.beginTransmission
#define i2cEndTransmission Wire.endTransmission
#define i2cRequestFrom Wire.requestFrom
#define i2cRead Wire.receive
#define i2cWrite Wire.send
#endif
/*----------------------------------------------------------------------*
* Constructor. *
*----------------------------------------------------------------------*/
DS3232RTC::DS3232RTC()
{
i2cBegin();
}
/*----------------------------------------------------------------------*
* Read the current time from the RTC and return it as a time_t value. *
* Returns a zero value if an I2C error occurred (e.g. RTC *
* not present). *
*----------------------------------------------------------------------*/
time_t DS3232RTC::get()
{
tmElements_t tm;
if ( read(tm) ) return 0;
return( makeTime(tm) );
}
/*----------------------------------------------------------------------*
* Set the RTC to the given time_t value. *
* Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::set(time_t t)
{
tmElements_t tm;
breakTime(t, tm);
return ( write(tm) );
}
/*----------------------------------------------------------------------*
* Read the current time from the RTC and return it in a tmElements_t *
* structure. Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::read(tmElements_t &tm)
{
i2cBeginTransmission(RTC_ADDR);
i2cWrite((uint8_t)RTC_SECONDS);
if ( byte e = i2cEndTransmission() ) return e;
//request 7 bytes (secs, min, hr, dow, date, mth, yr)
i2cRequestFrom(RTC_ADDR, tmNbrFields);
tm.Second = bcd2dec(i2cRead() & ~_BV(DS1307_CH));
tm.Minute = bcd2dec(i2cRead());
tm.Hour = bcd2dec(i2cRead() & ~_BV(HR1224)); //assumes 24hr clock
tm.Wday = i2cRead();
tm.Day = bcd2dec(i2cRead());
tm.Month = bcd2dec(i2cRead() & ~_BV(CENTURY)); //don't use the Century bit
tm.Year = y2kYearToTm(bcd2dec(i2cRead()));
return 0;
}
/*----------------------------------------------------------------------*
* Set the RTC's time from a tmElements_t structure. *
* Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::write(tmElements_t &tm)
{
i2cBeginTransmission(RTC_ADDR);
i2cWrite((uint8_t)RTC_SECONDS);
i2cWrite(dec2bcd(tm.Second));
i2cWrite(dec2bcd(tm.Minute));
i2cWrite(dec2bcd(tm.Hour)); //sets 24 hour format (Bit 6 == 0)
i2cWrite(tm.Wday);
i2cWrite(dec2bcd(tm.Day));
i2cWrite(dec2bcd(tm.Month));
i2cWrite(dec2bcd(tmYearToY2k(tm.Year)));
return i2cEndTransmission();
}
/*----------------------------------------------------------------------*
* Write multiple bytes to RTC RAM. *
* Valid address range is 0x00 - 0xFF, no checking. *
* Number of bytes (nBytes) must be between 1 and 31 (Wire library *
* limitation). *
* Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::writeRTC(byte addr, byte *values, byte nBytes)
{
i2cBeginTransmission(RTC_ADDR);
i2cWrite(addr);
for (byte i=0; i<nBytes; i++) i2cWrite(values[i]);
return i2cEndTransmission();
}
/*----------------------------------------------------------------------*
* Write a single byte to RTC RAM. *
* Valid address range is 0x00 - 0xFF, no checking. *
* Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::writeRTC(byte addr, byte value)
{
return ( writeRTC(addr, &value, 1) );
}
/*----------------------------------------------------------------------*
* Read multiple bytes from RTC RAM. *
* Valid address range is 0x00 - 0xFF, no checking. *
* Number of bytes (nBytes) must be between 1 and 32 (Wire library *
* limitation). *
* Returns the I2C status (zero if successful). *
*----------------------------------------------------------------------*/
byte DS3232RTC::readRTC(byte addr, byte *values, byte nBytes)
{
i2cBeginTransmission(RTC_ADDR);
i2cWrite(addr);
if ( byte e = i2cEndTransmission() ) return e;
i2cRequestFrom( (uint8_t)RTC_ADDR, nBytes );
for (byte i=0; i<nBytes; i++) values[i] = i2cRead();
return 0;
}
/*----------------------------------------------------------------------*
* Read a single byte from RTC RAM. *
* Valid address range is 0x00 - 0xFF, no checking. *
*----------------------------------------------------------------------*/
byte DS3232RTC::readRTC(byte addr)
{
byte b;
readRTC(addr, &b, 1);
return b;
}
/*----------------------------------------------------------------------*
* Set an alarm time. Sets the alarm registers only. To cause the *
* INT pin to be asserted on alarm match, use alarmInterrupt(). *
* This method can set either Alarm 1 or Alarm 2, depending on the *
* value of alarmType (use a value from the ALARM_TYPES_t enumeration). *
* When setting Alarm 2, the seconds value must be supplied but is *
* ignored, recommend using zero. (Alarm 2 has no seconds register.) *
*----------------------------------------------------------------------*/
void DS3232RTC::setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate)
{
uint8_t addr;
seconds = dec2bcd(seconds);
minutes = dec2bcd(minutes);
hours = dec2bcd(hours);
daydate = dec2bcd(daydate);
if (alarmType & 0x01) seconds |= _BV(A1M1);
if (alarmType & 0x02) minutes |= _BV(A1M2);
if (alarmType & 0x04) hours |= _BV(A1M3);
if (alarmType & 0x10) hours |= _BV(DYDT);
if (alarmType & 0x08) daydate |= _BV(A1M4);
if ( !(alarmType & 0x80) ) { //alarm 1
addr = ALM1_SECONDS;
writeRTC(addr++, seconds);
}
else {
addr = ALM2_MINUTES;
}
writeRTC(addr++, minutes);
writeRTC(addr++, hours);
writeRTC(addr++, daydate);
}
/*----------------------------------------------------------------------*
* Set an alarm time. Sets the alarm registers only. To cause the *
* INT pin to be asserted on alarm match, use alarmInterrupt(). *
* This method can set either Alarm 1 or Alarm 2, depending on the *
* value of alarmType (use a value from the ALARM_TYPES_t enumeration). *
* However, when using this method to set Alarm 1, the seconds value *
* is set to zero. (Alarm 2 has no seconds register.) *
*----------------------------------------------------------------------*/
void DS3232RTC::setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate)
{
setAlarm(alarmType, 0, minutes, hours, daydate);
}
/*----------------------------------------------------------------------*
* Enable or disable an alarm "interrupt" which asserts the INT pin *
* on the RTC. *
*----------------------------------------------------------------------*/
void DS3232RTC::alarmInterrupt(byte alarmNumber, boolean interruptEnabled)
{
uint8_t controlReg, mask;
controlReg = readRTC(RTC_CONTROL);
mask = _BV(A1IE) << (alarmNumber - 1);
if (interruptEnabled)
controlReg |= mask;
else
controlReg &= ~mask;
writeRTC(RTC_CONTROL, controlReg);
}
/*----------------------------------------------------------------------*
* Returns true or false depending on whether the given alarm has been *
* triggered, and resets the alarm flag bit. *
*----------------------------------------------------------------------*/
boolean DS3232RTC::alarm(byte alarmNumber)
{
uint8_t statusReg, mask;
statusReg = readRTC(RTC_STATUS);
mask = _BV(A1F) << (alarmNumber - 1);
if (statusReg & mask) {
statusReg &= ~mask;
writeRTC(RTC_STATUS, statusReg);
return true;
}
else {
return false;
}
}
/*----------------------------------------------------------------------*
* Enable or disable the square wave output. *
* Use a value from the SQWAVE_FREQS_t enumeration for the parameter. *
*----------------------------------------------------------------------*/
void DS3232RTC::squareWave(SQWAVE_FREQS_t freq)
{
uint8_t controlReg;
controlReg = readRTC(RTC_CONTROL);
if (freq >= SQWAVE_NONE) {
controlReg |= _BV(INTCN);
}
else {
controlReg = (controlReg & 0xE3) | (freq << RS1);
}
writeRTC(RTC_CONTROL, controlReg);
}
/*----------------------------------------------------------------------*
* Checks the OSF bit in the status register which indicates that the *
* oscillator is or was stopped. *
*----------------------------------------------------------------------*/
boolean DS3232RTC::oscStopped(void)
{
return ( readRTC(RTC_STATUS) & _BV(OSF) );
}
/*----------------------------------------------------------------------*
* Returns the temperature in Celsius times four. *
*----------------------------------------------------------------------*/
int DS3232RTC::temperature(void)
{
union int16_byte {
int i;
byte b[2];
} rtcTemp;
rtcTemp.b[0] = readRTC(TEMP_LSB);
rtcTemp.b[1] = readRTC(TEMP_MSB);
return rtcTemp.i >> 6;
}
/*----------------------------------------------------------------------*
* Decimal-to-BCD conversion *
*----------------------------------------------------------------------*/
uint8_t DS3232RTC::dec2bcd(uint8_t n)
{
return n + 6 * (n / 10);
}
/*----------------------------------------------------------------------*
* BCD-to-Decimal conversion *
*----------------------------------------------------------------------*/
uint8_t __attribute__ ((noinline)) DS3232RTC::bcd2dec(uint8_t n)
{
return n - 6 * (n >> 4);
}
DS3232RTC RTC = DS3232RTC(); //instantiate an RTC object

View File

@@ -0,0 +1,157 @@
/*----------------------------------------------------------------------*
* DS3232RTC.h - Arduino library for the Maxim Integrated DS3232 *
* Real-Time Clock. This library is intended for use with the Arduino *
* Time.h library, http://www.arduino.cc/playground/Code/Time *
* *
* This library is a drop-in replacement for the DS1307RTC.h library *
* by Michael Margolis that is supplied with the Arduino Time library *
* above. To change from using a DS1307 RTC to an DS3232 RTC, it is *
* only necessary to change the #include statement to include this *
* library instead of DS1307RTC.h. *
* *
* In addition, this library implements functions to support the *
* additional features of the DS3232. *
* *
* This library will also work with the DS3231 RTC, which has the same *
* features of the DS3232 except: (1) Battery-backed SRAM, (2) Battery- *
* backed 32kHz output (BB32kHz bit in Control/Status register 0x0F), *
* and (3) Adjustable temperature sensor sample rate (CRATE1:0 bits in *
* the Control/Status register). *
* *
* Whether used with the DS3232 or DS3231, the user is responsible for *
* ensuring reads and writes do not exceed the device's address space *
* (0x00-0x12 for DS3231, 0x00-0xFF for DS3232); no bounds checking *
* is done by this library. *
* *
* Jack Christensen 06Mar2013 *
* 28Aug2013 Changed the lower level methods to return the status of *
* the I2C communication with the RTC. Thanks to *
* Rob Tillaart for the suggestion. (Fixes issue #1.) *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 444 Castro Street, Suite 900, *
* Mountain View, CA 94041. *
*----------------------------------------------------------------------*/
#ifndef DS3232RTC_h
#define DS3232RTC_h
#include <Time.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
//DS3232 I2C Address
#define RTC_ADDR 0x68
//DS3232 Register Addresses
#define RTC_SECONDS 0x00
#define RTC_MINUTES 0x01
#define RTC_HOURS 0x02
#define RTC_DAY 0x03
#define RTC_DATE 0x04
#define RTC_MONTH 0x05
#define RTC_YEAR 0x06
#define ALM1_SECONDS 0x07
#define ALM1_MINUTES 0x08
#define ALM1_HOURS 0x09
#define ALM1_DAYDATE 0x0A
#define ALM2_MINUTES 0x0B
#define ALM2_HOURS 0x0C
#define ALM2_DAYDATE 0x0D
#define RTC_CONTROL 0x0E
#define RTC_STATUS 0x0F
#define RTC_AGING 0x10
#define TEMP_MSB 0x11
#define TEMP_LSB 0x12
#define SRAM_START_ADDR 0x14 //first SRAM address
#define SRAM_SIZE 236 //number of bytes of SRAM
//Alarm mask bits
#define A1M1 7
#define A1M2 7
#define A1M3 7
#define A1M4 7
#define A2M2 7
#define A2M3 7
#define A2M4 7
//Control register bits
#define EOSC 7
#define BBSQW 6
#define CONV 5
#define RS2 4
#define RS1 3
#define INTCN 2
#define A2IE 1
#define A1IE 0
//Status register bits
#define OSF 7
#define BB32KHZ 6
#define CRATE1 5
#define CRATE0 4
#define EN32KHZ 3
#define BSY 2
#define A2F 1
#define A1F 0
//Square-wave output frequency (TS2, RS1 bits)
enum SQWAVE_FREQS_t {SQWAVE_1_HZ, SQWAVE_1024_HZ, SQWAVE_4096_HZ, SQWAVE_8192_HZ, SQWAVE_NONE};
//Alarm masks
enum ALARM_TYPES_t {
ALM1_EVERY_SECOND = 0x0F,
ALM1_MATCH_SECONDS = 0x0E,
ALM1_MATCH_MINUTES = 0x0C, //match minutes *and* seconds
ALM1_MATCH_HOURS = 0x08, //match hours *and* minutes, seconds
ALM1_MATCH_DATE = 0x00, //match date *and* hours, minutes, seconds
ALM1_MATCH_DAY = 0x10, //match day *and* hours, minutes, seconds
ALM2_EVERY_MINUTE = 0x8E,
ALM2_MATCH_MINUTES = 0x8C, //match minutes
ALM2_MATCH_HOURS = 0x88, //match hours *and* minutes
ALM2_MATCH_DATE = 0x80, //match date *and* hours, minutes
ALM2_MATCH_DAY = 0x90, //match day *and* hours, minutes
};
#define ALARM_1 1 //constants for calling functions
#define ALARM_2 2
//Other
#define DS1307_CH 7 //for DS1307 compatibility, Clock Halt bit in Seconds register
#define HR1224 6 //Hours register 12 or 24 hour mode (24 hour mode==0)
#define CENTURY 7 //Century bit in Month register
#define DYDT 6 //Day/Date flag bit in alarm Day/Date registers
class DS3232RTC
{
public:
DS3232RTC();
static time_t get(void);
static byte set(time_t t);
static byte read(tmElements_t &tm);
static byte write(tmElements_t &tm);
byte writeRTC(byte addr, byte *values, byte nBytes);
byte writeRTC(byte addr, byte value);
byte readRTC(byte addr, byte *values, byte nBytes);
byte readRTC(byte addr);
void setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate);
void setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate);
void alarmInterrupt(byte alarmNumber, boolean alarmEnabled);
boolean alarm(byte alarmNumber);
void squareWave(SQWAVE_FREQS_t freq);
boolean oscStopped(void);
int temperature(void);
private:
static uint8_t dec2bcd(uint8_t n);
static uint8_t bcd2dec(uint8_t n);
};
extern DS3232RTC RTC;
#endif

View File

@@ -0,0 +1,8 @@
# Arduino DS3232RTC Library v1.0 #
https://github.com/JChristensen/DS3232RTC
LICENSE file
Jack Christensen Mar 2013
![CC BY-SA](http://mirrors.creativecommons.org/presskit/buttons/88x31/png/by-sa.png)
## CC BY-SA ##
"Arduino DS3232RTC Library" by Jack Christensen is licensed under [CC BY-SA 4.0](http://creativecommons.org/licenses/by-sa/4.0/).

View File

@@ -0,0 +1,345 @@
# Arduino DS3232RTC Library v1.0 #
https://github.com/JChristensen/DS3232RTC
ReadMe file
Jack Christensen Mar 2013
![CC BY-SA](http://mirrors.creativecommons.org/presskit/buttons/80x15/png/by-sa.png)
## Introduction ##
**DS3232RTC** is an Arduino library that supports the Maxim Integrated DS3232 and DS3231 Real-Time Clocks. This library is intended to be used with the [Arduino Time library](http://www.arduino.cc/playground/Code/Time).
The **DS3232RTC** library is a drop-in replacement for the DS1307RTC.h library by Michael Margolis that is supplied with the Arduino Time library above. To change from using a DS1307 RTC to an DS323x RTC, it is only necessary to use `#include <DS3232RTC.h>` instead of `#include <DS1307RTC.h>`.
**DS3232RTC** also implements functions to support the additional features of the DS3232 and DS3231. The DS3231 has the same features as the DS3232 except: (1) Battery-backed SRAM, (2) Battery-backed 32kHz output (BB32kHz bit in Control/Status register 0x0F), and (3) Adjustable temperature sensor sample rate (CRATE1:0 bits in the Control/Status register).
"Arduino DS3232RTC Library" by Jack Christensen is licensed under CC BY-SA 4.0.
## Installation ##
To use the **DS3232RTC** library:
- Go to https://github.com/JChristensen/DS3232RTC, click the **Download ZIP** button and save the ZIP file to a convenient location on your PC.
- Uncompress the downloaded file. This will result in a folder containing all the files for the library, that has a name that includes the branch name, usually **DS3232RTC-master**.
- Rename the folder to just **DS3232RTC**.
- Copy the renamed folder to the Arduino sketchbook\libraries folder.
## Examples ##
The following example sketches are included with the **DS3232RTC** library:
- **SetSerial:** Set the RTC's date and time from the Arduino serial monitor. Displays date, time and temperature.
- **TimeRTC:** Same as the example of the same name provided with the **Time** library, demonstrating the interchangeability of the **DS3232RTC** library with the **DS1307RTC** library.
- **tiny3232_KnockBang:** Demonstrates interfacing an ATtiny45/85 to a DS3231 or DS3232 RTC.
## Usage notes ##
When using the **DS3232RTC** library, the user is responsible for ensuring that reads and writes do not exceed the device's address space (0x00-0x12 for DS3231, 0x00-0xFF for DS3232); no bounds checking is done by the library.
Similar to the **DS1307RTC** library, the **DS3232RTC** library instantiates an RTC object; the user does not need to do this.
To use the **DS3232RTC** library, the Time and Wire libraries must also be included. For brevity, these includes are not repeated in the examples below:
```c++
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://www.arduino.cc/playground/Code/Time
#include <Wire.h> //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
```
## Enumerations ##
### SQWAVE_FREQS_t
##### Description
Symbolic names used with the squareWave() method (described below).
##### Values
- SQWAVE_NONE
- SQWAVE_1_HZ
- SQWAVE_1024_HZ
- SQWAVE_4096_HZ
- SQWAVE_8192_HZ
### ALARM_TYPES_t
##### Description
Symbolic names used with the setAlarm() method (described below).
##### Values for Alarm 1
- ALM1_EVERY_SECOND -- causes an alarm once per second.
- ALM1_MATCH_SECONDS -- causes an alarm when the seconds match (i.e. once per minute).
- ALM1_MATCH_MINUTES -- causes an alarm when the minutes *and* seconds match.
- ALM1_MATCH_HOURS -- causes an alarm when the hours *and* minutes *and* seconds match.
- ALM1_MATCH_DATE -- causes an alarm when the date of the month *and* hours *and* minutes *and* seconds match.
- ALM1_MATCH_DAY -- causes an alarm when the day of the week *and* hours *and* minutes *and* seconds match.
##### Values for Alarm 2
- ALM2_EVERY_MINUTE -- causes an alarm once per minute.
- ALM2_MATCH_MINUTES -- causes an alarm when the minutes match (i.e. once per hour).
- ALM2_MATCH_HOURS -- causes an alarm when the hours *and* minutes match.
- ALM2_MATCH_DATE -- causes an alarm when the date of the month *and* hours *and* minutes match.
- ALM2_MATCH_DAY -- causes an alarm when the day of the week *and* hours *and* minutes match.
## Methods for setting and reading the time ##
###get(void)
#####Description
Reads the current date and time from the RTC and returns it as a *time_t* value. Returns zero if an I2C error occurs (RTC not present, etc.).
#####Syntax
`RTC.get();`
#####Parameters
None.
#####Returns
Current date and time *(time_t)*
#####Example
```c++
time_t myTime;
myTime = RTC.get();
```
###set(time_t t)
#####Description
Sets the RTC date and time to the given *time_t* value.
#####Syntax
`RTC.set(t);`
#####Parameters
**t:** The date and time to set the RTC to *(time_t)*
#####Returns
I2C status *(byte)*. Returns zero if successful.
#####Example
```c++
//this example first sets the system time (maintained by the Time library) to
//a hard-coded date and time, and then sets the RTC from the system time.
//the setTime() function is part of the Time library.
setTime(23, 31, 30, 13, 2, 2009); //set the system time to 23h31m30s on 13Feb2009
RTC.set(now()); //set the RTC from the system time
```
###read(tmElements_t &tm)
#####Description
Reads the current date and time from the RTC and returns it as a *tmElements_t* structure. See the [Arduino Time library](http://www.arduino.cc/playground/Code/Time) for details on the *tmElements_t* structure.
#####Syntax
`RTC.read(tm);`
#####Parameters
**tm:** Address of a *tmElements_t* structure to which the date and time are returned.
#####Returns
I2C status *(byte)*. Returns zero if successful. The date and time read from the RTC are returned to the **tm** parameter.
#####Example
```c++
tmElements_t tm;
RTC.read(tm);
Serial.print(tm.Hour, DEC);
Serial.print(':');
Serial.print(tm.Minute,DEC);
Serial.print(':');
Serial.println(tm.Second,DEC);
```
###write(tmElements_t &tm)
#####Description
Sets the RTC to the date and time given by a *tmElements_t* structure.
#####Syntax
`RTC.write(tm);`
#####Parameters
**tm:** Address of a *tmElements_t* structure used to set the date and time.
#####Returns
I2C status *(byte)*. Returns zero if successful.
#####Example
```c++
tmElements_t tm;
tm.Hour = 23; //set the tm structure to 23h31m30s on 13Feb2009
tm.Minute = 31;
tm.Minute = 30;
tm.Day = 13;
tm.Month = 2;
tm.Year = 2009 - 1970; //tmElements_t.Year is the offset from 1970
RTC.write(tm); //set the RTC from the tm structure
```
## Methods for reading and writing RTC registers or static RAM (SRAM) for the DS3232 ##
The DS3232RTC.h file defines symbolic names for the timekeeping, alarm, status and control registers. These can be used for the addr argument in the functions below.
###writeRTC(byte addr, byte *values, byte nBytes)
#####Description
Write one or more bytes to RTC memory.
#####Syntax
`RTC.writeRTC(addr, values, nbytes);`
#####Parameters
**addr:** First SRAM address to write *(byte)*. The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
**values:** An array of values to write _(*byte)_
**nBytes:** Number of bytes to write *(byte)*. Must be between 1 and 31 (Wire library limitation) but is not checked by the library.
#####Returns
I2C status *(byte)*. Returns zero if successful.
#####Example
```c++
//write 1, 2, ..., 8 to the first eight DS3232 SRAM locations
byte buf[8] = {1, 2, 3, 4, 5, 6, 7, 8};
RTC.sramWrite(0x14, buf, 8);
```
###writeRTC(byte addr, byte value)
#####Description
Write a single byte to RTC memory.
#####Syntax
`RTC.writeRTC(addr, value);`
#####Parameters
**addr:** SRAM address to write *(byte)*. The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
**value:** Value to write _(byte)_
#####Returns
I2C status *(byte)*. Returns zero if successful.
#####Example
```c++
RTC.writeRTC(3, 14); //write the value 14 to SRAM address 3
```
###readRTC(byte addr, byte *values, byte nBytes)
#####Description
Read one or more bytes from RTC RAM.
#####Syntax
`RTC.readRTC(addr, values, nbytes);`
#####Parameters
**addr:** First SRAM address to read *(byte)*. The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
**values:** An array to receive the values read _(*byte)_
**nBytes:** Number of bytes to read *(byte)*. Must be between 1 and 32 (Wire library limitation) but is not checked by the library.
#####Returns
I2C status *(byte)*. Returns zero if successful.
#####Example
```c++
//read the last eight locations of SRAM into buf
byte buf[8];
RTC.sramRead(248, buf, 8);
```
###readRTC(byte addr)
#####Description
Reads a single byte from RTC RAM.
#####Syntax
`RTC.readRTC(addr);`
#####Parameters
**addr:** SRAM address to read *(byte)*. The valid address range is 0x00-0x12 for DS3231, 0x00-0xFF for DS3232. The general-purpose SRAM for the DS3232 begins at address 0x14. Address is not checked for validity by the library.
#####Returns
Value read from the RTC *(byte)*
#####Example
```c++
byte val;
val = RTC.readRTC(3); //read the value from SRAM location 3
```
## Alarm methods ##
The DS3232 and DS3231 have two alarms. Alarm1 can be set to seconds precision; Alarm2 can only be set to minutes precision.
###setAlarm(ALARM_TYPES_t alarmType, byte seconds, byte minutes, byte hours, byte daydate)
#####Description
Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This method can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). When setting Alarm 2, the seconds value must be supplied but is ignored, recommend using zero. (Alarm 2 has no seconds register.)
#####Syntax
`RTC.setAlarm(alarmType, seconds, minutes, hours, dayOrDate);`
#####Parameters
**alarmType:** A value from the ALARM_TYPES_t enumeration, above. *(ALARM_TYPES_t)*
**seconds:** The seconds value to set the alarm to. *(byte)*
**minutes:** The minutes value to set the alarm to. *(byte)*
**hours:** The hours value to set the alarm to. *(byte)*
**dayOrDate:** The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. *(byte)*
#####Returns
None.
#####Example
```c++
//Set Alarm1 for 12:34:56 on Sunday
RTC.setAlarm(ALM1_MATCH_DAY, 56, 34, 12, dowSunday);
```
###setAlarm(ALARM_TYPES_t alarmType, byte minutes, byte hours, byte daydate)
#####Description
Set an alarm time. Sets the alarm registers only. To cause the INT pin to be asserted on alarm match, use alarmInterrupt(). This method can set either Alarm 1 or Alarm 2, depending on the value of alarmType (use the ALARM_TYPES_t enumeration above). However, when using this method to set Alarm 1, the seconds value is set to zero. (Alarm 2 has no seconds register.)
#####Syntax
`RTC.setAlarm(alarmType, minutes, hours, dayOrDate);`
#####Parameters
**alarmType:** A value from the ALARM_TYPES_t enumeration, above. *(ALARM_TYPES_t)*
**minutes:** The minutes value to set the alarm to. *(byte)*
**hours:** The hours value to set the alarm to. *(byte)*
**dayOrDate:** The day of the week or the date of the month. For day of the week, use a value from the Time library timeDayOfWeek_t enumeration, i.e. dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday. *(byte)*
#####Returns
None.
#####Example
```c++
//Set Alarm2 for 12:34 on the 4th day of the month
RTC.setAlarm(ALM1_MATCH_DATE, 34, 12, 4);
```
###alarmInterrupt(byte alarmNumber, boolean alarmEnabled)
#####Description
Enable or disable an alarm "interrupt". Note that this "interrupt" causes the RTC's INT pin to be asserted. To use this signal as an actual interrupt to a microcontroller, it will need to be connected properly and programmed in the application firmware.
on the RTC.
#####Syntax
`RTC.alarmInterrupt(alarmNumber, enable);`
#####Parameters
**alarmNumber:** The number of the alarm to enable or disable, ALARM_1 or ALARM_2 *(byte)*
**alarmEnabled:** true or false *(boolean)*
#####Returns
None.
#####Example
```c++
RTC.alarmInterrupt(ALARM_1, true); //assert the INT pin when Alarm1 occurs.
RTC.alarmInterrupt(ALARM_2, false); //disable Alarm2
```
###alarm(byte alarmNumber)
#####Description
Tests whether an alarm has been triggered. If the alarm was triggered, returns true and resets the alarm flag in the RTC, else returns false.
#####Syntax
`RTC.alarm(alarmNumber);`
#####Parameters
**alarmNumber:** The number of the alarm to test, ALARM_1 or ALARM_2 *(byte)*
#####Returns
Description *(type)*
#####Example
```c++
if ( RTC.alarm(ALARM_1) ) { //has Alarm1 triggered?
//yes, act on the alarm
}
else {
//no alarm
}
```
## Other methods ##
###temperature(void)
#####Description
Returns the RTC temperature.
#####Syntax
`RTC.temperature();`
#####Parameters
None.
#####Returns
RTC temperature as degrees Celsius times four. *(int)*
#####Example
```c++
int t = RTC.temperature();
float celsius = t / 4.0;
float fahrenheit = celsius * 9.0 / 5.0 + 32.0;
```
###squareWave(SQWAVE_FREQS_t freq)
#####Description
Enables or disables the square wave output.
#####Syntax
`RTC.squareWave(freq);`
#####Parameters
**freq:** a value from the SQWAVE_FREQS_t enumeration above. *(SQWAVE_FREQS_t)*
#####Returns
None.
#####Example
```c++
RTC.squareWave(SQWAVE_1_HZ); //1 Hz square wave
RTC.squareWave(SQWAVE_NONE); //no square wave
```
###oscStopped(void)
#####Description
Check whether the RTC oscillator is or was stopped. This may indicate that the RTC's time is not accurate.
#####Syntax
`RTC.oscStopped();`
#####Parameters
None.
#####Returns
True or false *(boolean)*
#####Example
```c++
if ( RTC.oscStopped() ) { //check the oscillator
//may be trouble
}
else {
//all is well
}
```

View File

@@ -0,0 +1,132 @@
/*----------------------------------------------------------------------*
* Display the date and time from a DS3231 or DS3232 RTC every second. *
* Display the temperature once per minute. (The DS3231 does a *
* temperature conversion once every 64 seconds. This is also the *
* default for the DS3232.) *
* *
* Set the date and time by entering the following on the Arduino *
* serial monitor: *
* year,month,day,hour,minute,second, *
* *
* Where *
* year can be two or four digits, *
* month is 1-12, *
* day is 1-31, *
* hour is 0-23, and *
* minute and second are 0-59. *
* *
* Entering the final comma delimiter (after "second") will avoid a *
* one-second timeout and will allow the RTC to be set more accurately. *
* *
* No validity checking is done, invalid values or incomplete syntax *
* in the input will result in an incorrect RTC setting. *
* *
* Jack Christensen 08Aug2013 *
* *
* Tested with Arduino 1.0.5, Arduino Uno, DS3231/Chronodot, DS3232. *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Streaming.h> //http://arduiniana.org/libraries/streaming/
#include <Time.h> //http://playground.arduino.cc/Code/Time
#include <Wire.h> //http://arduino.cc/en/Reference/Wire
void setup(void)
{
Serial.begin(115200);
//setSyncProvider() causes the Time library to synchronize with the
//external RTC by calling RTC.get() every five minutes by default.
setSyncProvider(RTC.get);
Serial << F("RTC Sync");
if (timeStatus() != timeSet) Serial << F(" FAIL!");
Serial << endl;
}
void loop(void)
{
static time_t tLast;
time_t t;
tmElements_t tm;
//check for input to set the RTC, minimum length is 12, i.e. yy,m,d,h,m,s
if (Serial.available() >= 12) {
//note that the tmElements_t Year member is an offset from 1970,
//but the RTC wants the last two digits of the calendar year.
//use the convenience macros from Time.h to do the conversions.
int y = Serial.parseInt();
if (y >= 100 && y < 1000)
Serial << F("Error: Year must be two digits or four digits!") << endl;
else {
if (y >= 1000)
tm.Year = CalendarYrToTm(y);
else //(y < 100)
tm.Year = y2kYearToTm(y);
tm.Month = Serial.parseInt();
tm.Day = Serial.parseInt();
tm.Hour = Serial.parseInt();
tm.Minute = Serial.parseInt();
tm.Second = Serial.parseInt();
t = makeTime(tm);
RTC.set(t); //use the time_t value to ensure correct weekday is set
setTime(t);
Serial << F("RTC set to: ");
printDateTime(t);
Serial << endl;
//dump any extraneous input
while (Serial.available() > 0) Serial.read();
}
}
t = now();
if (t != tLast) {
tLast = t;
printDateTime(t);
if (second(t) == 0) {
float c = RTC.temperature() / 4.;
float f = c * 9. / 5. + 32.;
Serial << F(" ") << c << F(" C ") << f << F(" F");
}
Serial << endl;
}
}
//print date and time to Serial
void printDateTime(time_t t)
{
printDate(t);
Serial << ' ';
printTime(t);
}
//print time to Serial
void printTime(time_t t)
{
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');
}
//print date to Serial
void printDate(time_t t)
{
printI00(day(t), 0);
Serial << monthShortStr(month(t)) << _DEC(year(t));
}
//Print an integer in "00" format (with leading zero),
//followed by a delimiter character to Serial.
//Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
if (val < 10) Serial << '0';
Serial << _DEC(val);
if (delim > 0) Serial << delim;
return;
}

View File

@@ -0,0 +1,50 @@
/*
* TimeRTC.pde
* Example code illustrating Time library with Real Time Clock.
* This example is identical to the example provided with the Time Library,
* only the #include statement has been changed to include the DS3232RTC library.
*/
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://www.arduino.cc/playground/Code/Time
#include <Wire.h> //http://arduino.cc/en/Reference/Wire (included with Arduino IDE)
void setup(void)
{
Serial.begin(9600);
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
void loop(void)
{
digitalClockDisplay();
delay(1000);
}
void digitalClockDisplay(void)
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(' ');
Serial.print(day());
Serial.print(' ');
Serial.print(month());
Serial.print(' ');
Serial.print(year());
Serial.println();
}
void printDigits(int digits)
{
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(':');
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,88 @@
/*----------------------------------------------------------------------*
* Digital clock display using a DS3231/32 Real-Time Clock *
* and an ATtiny45/85 with a 1MHz system clock. *
* Also seems to work with a DS1307 which is fairly similar but the *
* DS3232RTC library doesn't officially support it. *
* *
* Tested with Arduino 1.0.5. Also Arduino-Tiny Core, TinyISP, and *
* TinyDebugKnockBang from http://code.google.com/p/arduino-tiny/ *
* *
* Run TinyISP on an ATmega microcontroller that does not have an LED *
* connected to pin 13 (SCK). The LED causes problems because the SPI *
* pins are also the I2C pins on the ATtiny. Connect MISO, MOSI, SCK *
* on the ATmega to the corresponding pins on the ATtiny through 220Ω *
* resistors for safety. Use 4.7K pullup resistors on the ATtiny *
* I2C bus. *
* *
* Jack Christensen 21Aug2013 *
* *
* This work is licensed under the Creative Commons Attribution- *
* ShareAlike 3.0 Unported License. To view a copy of this license, *
* visit http://creativecommons.org/licenses/by-sa/3.0/ or send a *
* letter to Creative Commons, 171 Second Street, Suite 300, *
* San Francisco, California, 94105, USA. *
*----------------------------------------------------------------------*/
#include <DS3232RTC.h> //http://github.com/JChristensen/DS3232RTC
#include <Time.h> //http://playground.arduino.cc/Code/Time
#include <TinyDebugKnockBang.h> //http://code.google.com/p/arduino-tiny/
#include <TinyWireM.h> //http://playground.arduino.cc/Code/USIi2c
void setup(void)
{
Debug.begin(250000);
//setSyncProvider() causes the Time library to synchronize with the
//external RTC by calling RTC.get() every five minutes by default.
setSyncProvider(RTC.get);
Debug.print(F("RTC Sync"));
if (timeStatus() != timeSet) Debug.print(F(" FAIL!"));
Debug.println();
}
void loop(void)
{
static time_t tLast;
time_t t = now();
if (t != tLast) {
tLast = t;
printDateTime(t);
Debug.println();
}
}
//print date and time to Serial
void printDateTime(time_t t)
{
printDate(t);
Debug.print(' ');
printTime(t);
}
//print time to Serial
void printTime(time_t t)
{
printI00(hour(t), ':');
printI00(minute(t), ':');
printI00(second(t), ' ');
}
//print date to Serial
void printDate(time_t t)
{
printI00(day(t), 0);
Debug.print(monthShortStr(month(t)));
Debug.print(year(t), DEC);
}
//Print an integer in "00" format (with leading zero),
//followed by a delimiter character to Serial.
//Input value assumed to be between 0 and 99.
void printI00(int val, char delim)
{
if (val < 10) Debug.print('0');
Debug.print(val, DEC);;
if (delim > 0) Debug.print(delim);
return;
}

View File

@@ -0,0 +1,13 @@
DS3232RTC KEYWORD1
get KEYWORD2
set KEYWORD2
read KEYWORD2
write KEYWORD2
writeRTC KEYWORD2
readRTC KEYWORD2
setAlarm KEYWORD2
alarmInterrupt KEYWORD2
alarm KEYWORD2
squareWave KEYWORD2
oscStopped KEYWORD2
temperature KEYWORD2

View File

@@ -0,0 +1,212 @@
//
// FILE: I2C_eeprom.cpp
// AUTHOR: Rob Tillaart
// VERSION: 1.0.05
// PURPOSE: Simple I2C_eeprom library for Arduino with EEPROM 24LC256 et al.
//
// HISTORY:
// 0.1.00 - 2011-01-21 initial version
// 0.1.01 - 2011-02-07 added setBlock function
// 0.2.00 - 2011-02-11 fixed 64 bit boundary bug
// 0.2.01 - 2011-08-13 _readBlock made more robust + return value
// 1.0.00 - 2013-06-09 support for Arduino 1.0.x
// 1.0.01 - 2013-11-01 fixed writeBlock bug, refactor
// 1.0.02 - 2013-11-03 optimize internal buffers, refactor
// 1.0.03 - 2013-11-03 refactor 5 millis() write-latency
// 1.0.04 - 2013-11-03 fix bug in readBlock, moved waitEEReady() -> more efficient.
// 1.0.05 - 2013-11-06 improved waitEEReady(), added determineSize()
//
// Released to the public domain
//
#include <I2C_eeprom.h>
I2C_eeprom::I2C_eeprom(uint8_t device)
{
_deviceAddress = device;
Wire.begin();
_lastWrite = 0;
TWBR = 12; // 12=400Khz 32=200 72=100 152=50 F_CPU/16+(2*TWBR)
}
int I2C_eeprom::writeByte(uint16_t address, uint8_t data)
{
int rv = _WriteBlock(address, &data, 1);
return rv;
}
int I2C_eeprom::setBlock(uint16_t address, uint8_t data, uint16_t length)
{
uint8_t buffer[I2C_TWIBUFFERSIZE];
for (uint8_t i =0; i< I2C_TWIBUFFERSIZE; i++) buffer[i] = data;
int rv = _pageBlock(address, buffer, length, false); // todo check return value..
return rv;
}
int I2C_eeprom::writeBlock(uint16_t address, uint8_t* buffer, uint16_t length)
{
int rv = _pageBlock(address, buffer, length, true); // todo check return value..
return rv;
}
uint8_t I2C_eeprom::readByte(uint16_t address)
{
uint8_t rdata;
_ReadBlock(address, &rdata, 1);
return rdata;
}
uint16_t I2C_eeprom::readBlock(uint16_t address, uint8_t* buffer, uint16_t length)
{
uint16_t rv = 0;
while (length > 0)
{
uint8_t cnt = min(length, I2C_TWIBUFFERSIZE);
rv += _ReadBlock(address, buffer, cnt);
address += cnt;
buffer += cnt;
length -= cnt;
}
return rv;
}
#ifdef I2C_EEPROM_EXTENDED
// returns 64, 32, 16, 8, 4, 2, 1, 0
// 0 is smaller than 1K
uint8_t I2C_eeprom::determineSize()
{
uint8_t rv = 0; // unknown
uint8_t orgValues[8];
uint16_t addr;
// remember old values, non destructive
for (uint8_t i=0; i<8; i++)
{
addr = (512 << i) + 1;
orgValues[i] = readByte(addr);
}
// scan page folding
for (uint8_t i=0; i<8; i++)
{
rv = i;
uint16_t addr1 = (512 << i) + 1;
uint16_t addr2 = (512 << (i+1)) + 1;
writeByte(addr1, 0xAA);
writeByte(addr2, 0x55);
if (readByte(addr1) == 0x55) // folded!
{
break;
}
}
// restore original values
for (uint8_t i=0; i<8; i++)
{
uint16_t addr = (512 << i) + 1;
writeByte(addr, orgValues[i]);
}
return 0x01 << (rv-1);
}
#endif
////////////////////////////////////////////////////////////////////
//
// PRIVATE
//
// _pageBlock aligns buffer to page boundaries for writing.
// and to TWI buffer size
// returns 0 = OK otherwise error
int I2C_eeprom::_pageBlock(uint16_t address, uint8_t* buffer, uint16_t length, bool incrBuffer)
{
int rv = 0;
while (length > 0)
{
uint8_t bytesUntilPageBoundary = I2C_EEPROM_PAGESIZE - address%I2C_EEPROM_PAGESIZE;
uint8_t cnt = min(length, bytesUntilPageBoundary);
cnt = min(cnt, I2C_TWIBUFFERSIZE);
int rv = _WriteBlock(address, buffer, cnt); // todo check return value..
if (rv != 0) return rv;
address += cnt;
if (incrBuffer) buffer += cnt;
length -= cnt;
}
return rv;
}
// pre: length <= I2C_EEPROM_PAGESIZE && length <= I2C_TWIBUFFERSIZE;
// returns 0 = OK otherwise error
int I2C_eeprom::_WriteBlock(uint16_t address, uint8_t* buffer, uint8_t length)
{
waitEEReady();
Wire.beginTransmission(_deviceAddress);
#if defined(ARDUINO) && ARDUINO >= 100
Wire.write((int)(address >> 8));
Wire.write((int)(address & 0xFF));
for (uint8_t cnt = 0; cnt < length; cnt++)
Wire.write(buffer[cnt]);
#else
Wire.send((int)(address >> 8));
Wire.send((int)(address & 0xFF));
for (uint8_t cnt = 0; cnt < length; cnt++)
Wire.send(buffer[cnt]);
#endif
int rv = Wire.endTransmission();
_lastWrite = micros();
return rv;
}
// pre: buffer is large enough to hold length bytes
// returns bytes written
uint8_t I2C_eeprom::_ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length)
{
waitEEReady();
Wire.beginTransmission(_deviceAddress);
#if defined(ARDUINO) && ARDUINO >= 100
Wire.write((int)(address >> 8));
Wire.write((int)(address & 0xFF));
#else
Wire.send((int)(address >> 8));
Wire.send((int)(address & 0xFF));
#endif
int rv = Wire.endTransmission();
if (rv != 0) return 0; // error
Wire.requestFrom(_deviceAddress, length);
uint8_t cnt = 0;
uint32_t before = millis();
while ((cnt < length) && ((millis() - before) < I2C_EEPROM_TIMEOUT))
{
#if defined(ARDUINO) && ARDUINO >= 100
if (Wire.available()) buffer[cnt++] = Wire.read();
#else
if (Wire.available()) buffer[cnt++] = Wire.receive();
#endif
}
return cnt;
}
void I2C_eeprom::waitEEReady()
{
#define I2C_WRITEDELAY 5000
// Wait until EEPROM gives ACK again.
// this is a bit faster than the hardcoded 5 milli
while ((micros() - _lastWrite) <= I2C_WRITEDELAY)
{
Wire.beginTransmission(_deviceAddress);
int x = Wire.endTransmission();
if (x == 0) break;
}
}
//
// END OF FILE
//

View File

@@ -0,0 +1,67 @@
#ifndef I2C_EEPROM_H
#define I2C_EEPROM_H
//
// FILE: I2C_eeprom.h
// AUTHOR: Rob Tillaart
// PURPOSE: Simple I2C_eeprom library for Arduino with EEPROM 24LC256 et al.
// VERSION: 1.0.05
// HISTORY: See I2C_eeprom.cpp
// URL: http://arduino.cc/playground/Main/LibraryForI2CEEPROM
//
// Released to the public domain
//
#include <Wire.h>
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#include "Wstring.h"
#include "Wiring.h"
#endif
#define I2C_EEPROM_VERSION "1.0.05"
// I2C_EEPROM_PAGESIZE must be multiple of 2 e.g. 16, 32 or 64
// 24LC256 -> 64 bytes
#define I2C_EEPROM_PAGESIZE 64
// TWI buffer needs max 2 bytes for address
#define I2C_TWIBUFFERSIZE 30
// to break blocking read/write
#define I2C_EEPROM_TIMEOUT 1000
// comment next line to keep lib small
#define I2C_EEPROM_EXTENDED
class I2C_eeprom
{
public:
I2C_eeprom(uint8_t deviceAddress);
int writeByte(uint16_t address, uint8_t value);
int writeBlock(uint16_t address, uint8_t* buffer, uint16_t length);
int setBlock(uint16_t address, uint8_t value, uint16_t length);
uint8_t readByte(uint16_t address);
uint16_t readBlock(uint16_t address, uint8_t* buffer, uint16_t length);
#ifdef I2C_EEPROM_EXTENDED
uint8_t determineSize();
#endif
private:
uint8_t _deviceAddress;
uint32_t _lastWrite; // for waitEEReady
int _pageBlock(uint16_t address, uint8_t* buffer, uint16_t length, bool incrBuffer);
int _WriteBlock(uint16_t address, uint8_t* buffer, uint8_t length);
uint8_t _ReadBlock(uint16_t address, uint8_t* buffer, uint8_t length);
void waitEEReady();
};
#endif
// END OF FILE

View File

@@ -0,0 +1,31 @@
// **** INCLUDES *****
#include "LowPower.h"
void setup()
{
// No setup is required for this library
}
void loop()
{
// Enter idle state for 8 s with the rest of peripherals turned off
// Each microcontroller comes with different number of peripherals
// Comment off line of code where necessary
// ATmega328P, ATmega168
LowPower.idle(SLEEP_8S, ADC_OFF, TIMER2_OFF, TIMER1_OFF, TIMER0_OFF,
SPI_OFF, USART0_OFF, TWI_OFF);
// ATmega32U4
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER4_OFF, TIMER3_OFF, TIMER1_OFF,
// TIMER0_OFF, SPI_OFF, USART1_OFF, TWI_OFF, USB_OFF);
// ATmega2560
//LowPower.idle(SLEEP_8S, ADC_OFF, TIMER5_OFF, TIMER4_OFF, TIMER3_OFF,
// TIMER2_OFF, TIMER1_OFF, TIMER0_OFF, SPI_OFF, USART3_OFF,
// USART2_OFF, USART1_OFF, USART0_OFF, TWI_OFF);
// Do something here
// Example: Read sensor, data logging, data transmission.
}

View File

@@ -0,0 +1,33 @@
// **** INCLUDES *****
#include "LowPower.h"
// Use pin 2 as wake up pin
const int wakeUpPin = 2;
void wakeUp()
{
// Just a handler for the pin interrupt.
}
void setup()
{
// Configure wake up pin as input.
// This will consumes few uA of current.
pinMode(wakeUpPin, INPUT);
}
void loop()
{
// Allow wake up pin to trigger interrupt on low.
attachInterrupt(0, wakeUp, LOW);
// Enter power down state with ADC and BOD module disabled.
// Wake up when wake up pin is low.
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// Disable external pin interrupt on wake up pin.
detachInterrupt(0);
// Do something here
// Example: Read sensor, data logging, data transmission.
}

View File

@@ -0,0 +1,16 @@
// **** INCLUDES *****
#include "LowPower.h"
void setup()
{
// No setup is required for this library
}
void loop()
{
// Enter power down state for 8 s with ADC and BOD module disabled
LowPower.powerDown(SLEEP_8S, ADC_OFF, BOD_OFF);
// Do something here
// Example: Read sensor, data logging, data transmission.
}

View File

@@ -0,0 +1,856 @@
/*******************************************************************************
* LowPower Library
* Version: 1.30
* Date: 22-05-2013
* Company: Rocket Scream Electronics
* Website: www.rocketscream.com
*
* This is a lightweight low power library for Arduino. Please check our wiki
* (www.rocketscream.com/wiki) for more information on using this piece of
* library.
*
* This library is licensed under Creative Commons Attribution-ShareAlike 3.0
* Unported License.
*
* Revision Description
* ======== ===========
* 1.30 Added support for ATMega168, ATMega2560, ATMega1280 & ATMega32U4.
* Tested to work with Arduino IDE 1.0.1 - 1.0.4.
* 1.20 Remove typo error in idle method for checking whether Timer 0 was
* turned off.
* Remove dependecy on WProgram.h which is not required.
* Tested to work with Arduino IDE 1.0.
* 1.10 Added #ifndef for sleep_bod_disable() for compatibility with future
* Arduino IDE release.
* 1.00 Initial public release.
*******************************************************************************/
#include <avr/sleep.h>
#include <avr/wdt.h>
#include <avr/power.h>
#include <avr/interrupt.h>
#include "LowPower.h"
// Only Pico Power devices can change BOD settings through software
#if defined __AVR_ATmega328P__
#ifndef sleep_bod_disable
#define sleep_bod_disable() \
do { \
unsigned char tempreg; \
__asm__ __volatile__("in %[tempreg], %[mcucr]" "\n\t" \
"ori %[tempreg], %[bods_bodse]" "\n\t" \
"out %[mcucr], %[tempreg]" "\n\t" \
"andi %[tempreg], %[not_bodse]" "\n\t" \
"out %[mcucr], %[tempreg]" \
: [tempreg] "=&d" (tempreg) \
: [mcucr] "I" _SFR_IO_ADDR(MCUCR), \
[bods_bodse] "i" (_BV(BODS) | _BV(BODSE)), \
[not_bodse] "i" (~_BV(BODSE))); \
} while (0)
#endif
#endif
#define lowPowerBodOn(mode) \
do { \
set_sleep_mode(mode); \
cli(); \
sleep_enable(); \
sei(); \
sleep_cpu(); \
sleep_disable(); \
sei(); \
} while (0);
// Only Pico Power devices can change BOD settings through software
#if defined __AVR_ATmega328P__
#define lowPowerBodOff(mode)\
do { \
set_sleep_mode(mode); \
cli(); \
sleep_enable(); \
sleep_bod_disable(); \
sei(); \
sleep_cpu(); \
sleep_disable(); \
sei(); \
} while (0);
#endif
// Some macros is still missing from AVR GCC distribution for ATmega32U4
#if defined __AVR_ATmega32U4__
// Timer 4 PRR bit is currently not defined in iom32u4.h
#ifndef PRTIM4
#define PRTIM4 4
#endif
// Timer 4 power reduction macro is not defined currently in power.h
#ifndef power_timer4_disable
#define power_timer4_disable() (PRR1 |= (uint8_t)(1 << PRTIM4))
#endif
#ifndef power_timer4_enable
#define power_timer4_enable() (PRR1 &= (uint8_t)~(1 << PRTIM4))
#endif
#endif
/*******************************************************************************
* Name: idle
* Description: Putting ATmega328P/168 into idle state. Please make sure you
* understand the implication and result of disabling module.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control:
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. timer2 Timer 2 module disable control:
* (a) TIMER2_OFF - Turn off Timer 2 module
* (b) TIMER2_ON - Leave Timer 2 module in its default state
*
* 4. timer1 Timer 1 module disable control:
* (a) TIMER1_OFF - Turn off Timer 1 module
* (b) TIMER1_ON - Leave Timer 1 module in its default state
*
* 5. timer0 Timer 0 module disable control:
* (a) TIMER0_OFF - Turn off Timer 0 module
* (b) TIMER0_ON - Leave Timer 0 module in its default state
*
* 6. spi SPI module disable control:
* (a) SPI_OFF - Turn off SPI module
* (b) SPI_ON - Leave SPI module in its default state
*
* 7. usart0 USART0 module disable control:
* (a) USART0_OFF - Turn off USART0 module
* (b) USART0_ON - Leave USART0 module in its default state
*
* 8. twi TWI module disable control:
* (a) TWI_OFF - Turn off TWI module
* (b) TWI_ON - Leave TWI module in its default state
*
*******************************************************************************/
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168__)
void LowPowerClass::idle(period_t period, adc_t adc, timer2_t timer2,
timer1_t timer1, timer0_t timer0,
spi_t spi, usart0_t usart0, twi_t twi)
{
// Temporary clock source variable
unsigned char clockSource = 0;
if (timer2 == TIMER2_OFF)
{
if (TCCR2B & CS22) clockSource |= (1 << CS22);
if (TCCR2B & CS21) clockSource |= (1 << CS21);
if (TCCR2B & CS20) clockSource |= (1 << CS20);
// Remove the clock source to shutdown Timer2
TCCR2B &= ~(1 << CS22);
TCCR2B &= ~(1 << CS21);
TCCR2B &= ~(1 << CS20);
power_timer2_disable();
}
if (adc == ADC_OFF)
{
ADCSRA &= ~(1 << ADEN);
power_adc_disable();
}
if (timer1 == TIMER1_OFF) power_timer1_disable();
if (timer0 == TIMER0_OFF) power_timer0_disable();
if (spi == SPI_OFF) power_spi_disable();
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
lowPowerBodOn(SLEEP_MODE_IDLE);
if (adc == ADC_OFF)
{
power_adc_enable();
ADCSRA |= (1 << ADEN);
}
if (timer2 == TIMER2_OFF)
{
if (clockSource & CS22) TCCR2B |= (1 << CS22);
if (clockSource & CS21) TCCR2B |= (1 << CS21);
if (clockSource & CS20) TCCR2B |= (1 << CS20);
power_timer2_enable();
}
if (timer1 == TIMER1_OFF) power_timer1_enable();
if (timer0 == TIMER0_OFF) power_timer0_enable();
if (spi == SPI_OFF) power_spi_enable();
if (usart0 == USART0_OFF) power_usart0_enable();
if (twi == TWI_OFF) power_twi_enable();
}
#endif
/*******************************************************************************
* Name: idle
* Description: Putting ATmega32U4 into idle state. Please make sure you
* understand the implication and result of disabling module.
* Take note that Timer 2 is not available and USART0
* is replaced with USART1 on ATmega32U4.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control:
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. timer4 Timer 4 module disable control:
* (a) TIMER4_OFF - Turn off Timer 4 module
* (b) TIMER4_ON - Leave Timer 4 module in its default state
*
* 4. timer3 Timer 3 module disable control:
* (a) TIMER3_OFF - Turn off Timer 3 module
* (b) TIMER3_ON - Leave Timer 3 module in its default state
*
* 5. timer1 Timer 1 module disable control:
* (a) TIMER1_OFF - Turn off Timer 1 module
* (b) TIMER1_ON - Leave Timer 1 module in its default state
*
* 6. timer0 Timer 0 module disable control:
* (a) TIMER0_OFF - Turn off Timer 0 module
* (b) TIMER0_ON - Leave Timer 0 module in its default state
*
* 7. spi SPI module disable control:
* (a) SPI_OFF - Turn off SPI module
* (b) SPI_ON - Leave SPI module in its default state
*
* 8. usart1 USART1 module disable control:
* (a) USART1_OFF - Turn off USART1 module
* (b) USART1_ON - Leave USART1 module in its default state
*
* 9. twi TWI module disable control:
* (a) TWI_OFF - Turn off TWI module
* (b) TWI_ON - Leave TWI module in its default state
*
* 10.usb USB module disable control:
* (a) USB_OFF - Turn off USB module
* (b) USB_ON - Leave USB module in its default state
*******************************************************************************/
#if defined __AVR_ATmega32U4__
void LowPowerClass::idle(period_t period, adc_t adc,
timer4_t timer4, timer3_t timer3,
timer1_t timer1, timer0_t timer0,
spi_t spi, usart1_t usart1, twi_t twi, usb_t usb)
{
if (adc == ADC_OFF)
{
ADCSRA &= ~(1 << ADEN);
power_adc_disable();
}
if (timer4 == TIMER4_OFF) power_timer4_disable();
if (timer3 == TIMER3_OFF) power_timer3_disable();
if (timer1 == TIMER1_OFF) power_timer1_disable();
if (timer0 == TIMER0_OFF) power_timer0_disable();
if (spi == SPI_OFF) power_spi_disable();
if (usart1 == USART1_OFF) power_usart1_disable();
if (twi == TWI_OFF) power_twi_disable();
if (usb == USB_OFF) power_usb_disable();
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
lowPowerBodOn(SLEEP_MODE_IDLE);
if (adc == ADC_OFF)
{
power_adc_enable();
ADCSRA |= (1 << ADEN);
}
if (timer4 == TIMER4_OFF) power_timer4_enable();
if (timer3 == TIMER3_OFF) power_timer3_enable();
if (timer1 == TIMER1_OFF) power_timer1_enable();
if (timer0 == TIMER0_OFF) power_timer0_enable();
if (spi == SPI_OFF) power_spi_enable();
if (usart1 == USART1_OFF) power_usart1_enable();
if (twi == TWI_OFF) power_twi_enable();
if (usb == USB_OFF) power_usb_enable();
}
#endif
/*******************************************************************************
* Name: idle
* Description: Putting ATmega2560 & ATmega1280 into idle state. Please make sure
* you understand the implication and result of disabling module.
* Take note that extra Timer 5, 4, 3 compared to an ATmega328P/168.
* Also take note that extra USART 3, 2, 1 compared to an
* ATmega328P/168.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control:
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. timer5 Timer 5 module disable control:
* (a) TIMER5_OFF - Turn off Timer 5 module
* (b) TIMER5_ON - Leave Timer 5 module in its default state
*
* 4. timer4 Timer 4 module disable control:
* (a) TIMER4_OFF - Turn off Timer 4 module
* (b) TIMER4_ON - Leave Timer 4 module in its default state
*
* 5. timer3 Timer 3 module disable control:
* (a) TIMER3_OFF - Turn off Timer 3 module
* (b) TIMER3_ON - Leave Timer 3 module in its default state
*
* 6. timer2 Timer 2 module disable control:
* (a) TIMER2_OFF - Turn off Timer 2 module
* (b) TIMER2_ON - Leave Timer 2 module in its default state
*
* 7. timer1 Timer 1 module disable control:
* (a) TIMER1_OFF - Turn off Timer 1 module
* (b) TIMER1_ON - Leave Timer 1 module in its default state
*
* 8. timer0 Timer 0 module disable control:
* (a) TIMER0_OFF - Turn off Timer 0 module
* (b) TIMER0_ON - Leave Timer 0 module in its default state
*
* 9. spi SPI module disable control:
* (a) SPI_OFF - Turn off SPI module
* (b) SPI_ON - Leave SPI module in its default state
*
* 10.usart3 USART3 module disable control:
* (a) USART3_OFF - Turn off USART3 module
* (b) USART3_ON - Leave USART3 module in its default state
*
* 11.usart2 USART2 module disable control:
* (a) USART2_OFF - Turn off USART2 module
* (b) USART2_ON - Leave USART2 module in its default state
*
* 12.usart1 USART1 module disable control:
* (a) USART1_OFF - Turn off USART1 module
* (b) USART1_ON - Leave USART1 module in its default state
*
* 13.usart0 USART0 module disable control:
* (a) USART0_OFF - Turn off USART0 module
* (b) USART0_ON - Leave USART0 module in its default state
*
* 14.twi TWI module disable control:
* (a) TWI_OFF - Turn off TWI module
* (b) TWI_ON - Leave TWI module in its default state
*
*******************************************************************************/
#if defined (__AVR_ATmega2560__) || defined (__AVR_ATmega1280__)
void LowPowerClass::idle(period_t period, adc_t adc, timer5_t timer5,
timer4_t timer4, timer3_t timer3, timer2_t timer2,
timer1_t timer1, timer0_t timer0, spi_t spi,
usart3_t usart3, usart2_t usart2, usart1_t usart1,
usart0_t usart0, twi_t twi)
{
// Temporary clock source variable
unsigned char clockSource = 0;
if (timer2 == TIMER2_OFF)
{
if (TCCR2B & CS22) clockSource |= (1 << CS22);
if (TCCR2B & CS21) clockSource |= (1 << CS21);
if (TCCR2B & CS20) clockSource |= (1 << CS20);
// Remove the clock source to shutdown Timer2
TCCR2B &= ~(1 << CS22);
TCCR2B &= ~(1 << CS21);
TCCR2B &= ~(1 << CS20);
power_timer2_disable();
}
if (adc == ADC_OFF)
{
ADCSRA &= ~(1 << ADEN);
power_adc_disable();
}
if (timer5 == TIMER5_OFF) power_timer5_disable();
if (timer4 == TIMER4_OFF) power_timer4_disable();
if (timer3 == TIMER3_OFF) power_timer3_disable();
if (timer1 == TIMER1_OFF) power_timer1_disable();
if (timer0 == TIMER0_OFF) power_timer0_disable();
if (spi == SPI_OFF) power_spi_disable();
if (usart3 == USART3_OFF) power_usart3_disable();
if (usart2 == USART2_OFF) power_usart2_disable();
if (usart1 == USART1_OFF) power_usart1_disable();
if (usart0 == USART0_OFF) power_usart0_disable();
if (twi == TWI_OFF) power_twi_disable();
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
lowPowerBodOn(SLEEP_MODE_IDLE);
if (adc == ADC_OFF)
{
power_adc_enable();
ADCSRA |= (1 << ADEN);
}
if (timer2 == TIMER2_OFF)
{
if (clockSource & CS22) TCCR2B |= (1 << CS22);
if (clockSource & CS21) TCCR2B |= (1 << CS21);
if (clockSource & CS20) TCCR2B |= (1 << CS20);
power_timer2_enable();
}
if (timer5 == TIMER5_OFF) power_timer5_enable();
if (timer4 == TIMER4_OFF) power_timer4_enable();
if (timer3 == TIMER3_OFF) power_timer3_enable();
if (timer1 == TIMER1_OFF) power_timer1_enable();
if (timer0 == TIMER0_OFF) power_timer0_enable();
if (spi == SPI_OFF) power_spi_enable();
if (usart3 == USART3_OFF) power_usart3_enable();
if (usart2 == USART2_OFF) power_usart2_enable();
if (usart1 == USART1_OFF) power_usart1_enable();
if (usart0 == USART0_OFF) power_usart0_enable();
if (twi == TWI_OFF) power_twi_enable();
}
#endif
/*******************************************************************************
* Name: adcNoiseReduction
* Description: Putting microcontroller into ADC noise reduction state. This is
* a very useful state when using the ADC to achieve best and low
* noise signal.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control. Turning off the ADC module is
* basically removing the purpose of this low power mode.
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. timer2 Timer 2 module disable control:
* (a) TIMER2_OFF - Turn off Timer 2 module
* (b) TIMER2_ON - Leave Timer 2 module in its default state
*
*******************************************************************************/
void LowPowerClass::adcNoiseReduction(period_t period, adc_t adc,
timer2_t timer2)
{
// Temporary clock source variable
unsigned char clockSource = 0;
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (TCCR2B & CS22) clockSource |= (1 << CS22);
if (TCCR2B & CS21) clockSource |= (1 << CS21);
if (TCCR2B & CS20) clockSource |= (1 << CS20);
// Remove the clock source to shutdown Timer2
TCCR2B &= ~(1 << CS22);
TCCR2B &= ~(1 << CS21);
TCCR2B &= ~(1 << CS20);
}
#endif
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
lowPowerBodOn(SLEEP_MODE_ADC);
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (clockSource & CS22) TCCR2B |= (1 << CS22);
if (clockSource & CS21) TCCR2B |= (1 << CS21);
if (clockSource & CS20) TCCR2B |= (1 << CS20);
}
#endif
}
/*******************************************************************************
* Name: powerDown
* Description: Putting microcontroller into power down state. This is
* the lowest current consumption state. Use this together with
* external pin interrupt to wake up through external event
* triggering (example: RTC clockout pin, SD card detect pin).
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control. Turning off the ADC module is
* basically removing the purpose of this low power mode.
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. bod Brown Out Detector (BOD) module disable control:
* (a) BOD_OFF - Turn off BOD module
* (b) BOD_ON - Leave BOD module in its default state
*
*******************************************************************************/
void LowPowerClass::powerDown(period_t period, adc_t adc, bod_t bod)
{
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
if (bod == BOD_OFF)
{
#if defined __AVR_ATmega328P__
lowPowerBodOff(SLEEP_MODE_PWR_DOWN);
#else
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_DOWN);
}
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}
/*******************************************************************************
* Name: powerSave
* Description: Putting microcontroller into power save state. This is
* the lowest current consumption state after power down.
* Use this state together with an external 32.768 kHz crystal (but
* 8/16 MHz crystal/resonator need to be removed) to provide an
* asynchronous clock source to Timer 2. Please take note that
* Timer 2 is also used by the Arduino core for PWM operation.
* Please refer to wiring.c for explanation. Removal of the external
* 8/16 MHz crystal/resonator requires the microcontroller to run
* on its internal RC oscillator which is not so accurate for time
* critical operation.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control. Turning off the ADC module is
* basically removing the purpose of this low power mode.
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. bod Brown Out Detector (BOD) module disable control:
* (a) BOD_OFF - Turn off BOD module
* (b) BOD_ON - Leave BOD module in its default state
*
* 4. timer2 Timer 2 module disable control:
* (a) TIMER2_OFF - Turn off Timer 2 module
* (b) TIMER2_ON - Leave Timer 2 module in its default state
*
*******************************************************************************/
void LowPowerClass::powerSave(period_t period, adc_t adc, bod_t bod,
timer2_t timer2)
{
// Temporary clock source variable
unsigned char clockSource = 0;
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (TCCR2B & CS22) clockSource |= (1 << CS22);
if (TCCR2B & CS21) clockSource |= (1 << CS21);
if (TCCR2B & CS20) clockSource |= (1 << CS20);
// Remove the clock source to shutdown Timer2
TCCR2B &= ~(1 << CS22);
TCCR2B &= ~(1 << CS21);
TCCR2B &= ~(1 << CS20);
}
#endif
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
if (bod == BOD_OFF)
{
#if defined __AVR_ATmega328P__
lowPowerBodOff(SLEEP_MODE_PWR_SAVE);
#else
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_PWR_SAVE);
}
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (clockSource & CS22) TCCR2B |= (1 << CS22);
if (clockSource & CS21) TCCR2B |= (1 << CS21);
if (clockSource & CS20) TCCR2B |= (1 << CS20);
}
#endif
}
/*******************************************************************************
* Name: powerStandby
* Description: Putting microcontroller into power standby state.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control. Turning off the ADC module is
* basically removing the purpose of this low power mode.
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. bod Brown Out Detector (BOD) module disable control:
* (a) BOD_OFF - Turn off BOD module
* (b) BOD_ON - Leave BOD module in its default state
*
*******************************************************************************/
void LowPowerClass::powerStandby(period_t period, adc_t adc, bod_t bod)
{
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
if (bod == BOD_OFF)
{
#if defined __AVR_ATmega328P__
lowPowerBodOff(SLEEP_MODE_STANDBY);
#else
lowPowerBodOn(SLEEP_MODE_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_STANDBY);
}
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
}
/*******************************************************************************
* Name: powerExtStandby
* Description: Putting microcontroller into power extended standby state. This
* is different from the power standby state as it has the
* capability to run Timer 2 asynchronously.
*
* Argument Description
* ========= ===========
* 1. period Duration of low power mode. Use SLEEP_FOREVER to use other wake
* up resource:
* (a) SLEEP_15MS - 15 ms sleep
* (b) SLEEP_30MS - 30 ms sleep
* (c) SLEEP_60MS - 60 ms sleep
* (d) SLEEP_120MS - 120 ms sleep
* (e) SLEEP_250MS - 250 ms sleep
* (f) SLEEP_500MS - 500 ms sleep
* (g) SLEEP_1S - 1 s sleep
* (h) SLEEP_2S - 2 s sleep
* (i) SLEEP_4S - 4 s sleep
* (j) SLEEP_8S - 8 s sleep
* (k) SLEEP_FOREVER - Sleep without waking up through WDT
*
* 2. adc ADC module disable control.
* (a) ADC_OFF - Turn off ADC module
* (b) ADC_ON - Leave ADC module in its default state
*
* 3. bod Brown Out Detector (BOD) module disable control:
* (a) BOD_OFF - Turn off BOD module
* (b) BOD_ON - Leave BOD module in its default state
*
* 4. timer2 Timer 2 module disable control:
* (a) TIMER2_OFF - Turn off Timer 2 module
* (b) TIMER2_ON - Leave Timer 2 module in its default state
*
*******************************************************************************/
void LowPowerClass::powerExtStandby(period_t period, adc_t adc, bod_t bod,
timer2_t timer2)
{
// Temporary clock source variable
unsigned char clockSource = 0;
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (TCCR2B & CS22) clockSource |= (1 << CS22);
if (TCCR2B & CS21) clockSource |= (1 << CS21);
if (TCCR2B & CS20) clockSource |= (1 << CS20);
// Remove the clock source to shutdown Timer2
TCCR2B &= ~(1 << CS22);
TCCR2B &= ~(1 << CS21);
TCCR2B &= ~(1 << CS20);
}
#endif
if (adc == ADC_OFF) ADCSRA &= ~(1 << ADEN);
if (period != SLEEP_FOREVER)
{
wdt_enable(period);
WDTCSR |= (1 << WDIE);
}
if (bod == BOD_OFF)
{
#if defined __AVR_ATmega328P__
lowPowerBodOff(SLEEP_MODE_EXT_STANDBY);
#else
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
#endif
}
else
{
lowPowerBodOn(SLEEP_MODE_EXT_STANDBY);
}
if (adc == ADC_OFF) ADCSRA |= (1 << ADEN);
#if !defined(__AVR_ATmega32U4__)
if (timer2 == TIMER2_OFF)
{
if (clockSource & CS22) TCCR2B |= (1 << CS22);
if (clockSource & CS21) TCCR2B |= (1 << CS21);
if (clockSource & CS20) TCCR2B |= (1 << CS20);
}
#endif
}
/*******************************************************************************
* Name: ISR (WDT_vect)
* Description: Watchdog Timer interrupt service routine. This routine is
* required to allow automatic WDIF and WDIE bit clearance in
* hardware.
*
*******************************************************************************/
ISR (WDT_vect)
{
// WDIE & WDIF is cleared in hardware upon entering this ISR
wdt_disable();
}
LowPowerClass LowPower;

View File

@@ -0,0 +1,137 @@
#ifndef LowPower_h
#define LowPower_h
enum period_t
{
SLEEP_15Ms,
SLEEP_30MS,
SLEEP_60MS,
SLEEP_120MS,
SLEEP_250MS,
SLEEP_500MS,
SLEEP_1S,
SLEEP_2S,
SLEEP_4S,
SLEEP_8S,
SLEEP_FOREVER
};
enum bod_t
{
BOD_OFF,
BOD_ON
};
enum adc_t
{
ADC_OFF,
ADC_ON
};
enum timer5_t
{
TIMER5_OFF,
TIMER5_ON
};
enum timer4_t
{
TIMER4_OFF,
TIMER4_ON
};
enum timer3_t
{
TIMER3_OFF,
TIMER3_ON
};
enum timer2_t
{
TIMER2_OFF,
TIMER2_ON
};
enum timer1_t
{
TIMER1_OFF,
TIMER1_ON
};
enum timer0_t
{
TIMER0_OFF,
TIMER0_ON
};
enum spi_t
{
SPI_OFF,
SPI_ON
};
enum usart0_t
{
USART0_OFF,
USART0_ON
};
enum usart1_t
{
USART1_OFF,
USART1_ON
};
enum usart2_t
{
USART2_OFF,
USART2_ON
};
enum usart3_t
{
USART3_OFF,
USART3_ON
};
enum twi_t
{
TWI_OFF,
TWI_ON
};
enum usb_t
{
USB_OFF,
USB_ON
};
class LowPowerClass
{
public:
#if defined (__AVR_ATmega328P__) || defined (__AVR_ATmega168__)
void idle(period_t period, adc_t adc, timer2_t timer2,
timer1_t timer1, timer0_t timer0, spi_t spi,
usart0_t usart0, twi_t twi);
#elif defined __AVR_ATmega2560__
void idle(period_t period, adc_t adc, timer5_t timer5,
timer4_t timer4, timer3_t timer3, timer2_t timer2,
timer1_t timer1, timer0_t timer0, spi_t spi,
usart3_t usart3, usart2_t usart2, usart1_t usart1,
usart0_t usart0, twi_t twi);
#elif defined __AVR_ATmega32U4__
void idle(period_t period, adc_t adc, timer4_t timer4, timer3_t timer3,
timer1_t timer1, timer0_t timer0, spi_t spi,
usart1_t usart1, twi_t twi, usb_t usb);
#else
#error "Please ensure chosen MCU is either 328P, 32U4 or 2560."
#endif
void adcNoiseReduction(period_t period, adc_t adc, timer2_t timer2);
void powerDown(period_t period, adc_t adc, bod_t bod);
void powerSave(period_t period, adc_t adc, bod_t bod, timer2_t timer2);
void powerStandby(period_t period, adc_t adc, bod_t bod);
void powerExtStandby(period_t period, adc_t adc, bod_t bod, timer2_t timer2);
};
extern LowPowerClass LowPower;
#endif

View File

@@ -0,0 +1,68 @@
#######################################
# Syntax Coloring Map LowPower
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
idle KEYWORD2
adcNoiseReduction KEYWORD2
powerDown KEYWORD2
powerSave KEYWORD2
powerStandby KEYWORD2
powerExtStandby KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
LowPower KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
SLEEP_15MS LITERAL1
SLEEP_30MS LITERAL1
SLEEP_60MS LITERAL1
SLEEP_120MS LITERAL1
SLEEP_250MS LITERAL1
SLEEP_500MS LITERAL1
SLEEP_1S LITERAL1
SLEEP_2S LITERAL1
SLEEP_4S LITERAL1
SLEEP_8S LITERAL1
SLEEP_FOREVER LITERAL1
ADC_OFF LITERAL1
ADC_ON LITERAL1
BOD_OFF LITERAL1
BOD_ON LITERAL1
TIMER4_OFF LITERAL1
TIMER4_ON LITERAL1
TIMER3_OFF LITERAL1
TIMER3_ON LITERAL1
TIMER2_OFF LITERAL1
TIMER2_ON LITERAL1
TIMER1_OFF LITERAL1
TIMER1_ON LITERAL1
TIMER0_OFF LITERAL1
TIMER0_ON LITERAL1
USART3_OFF LITERAL1
USART3_ON LITERAL1
USART2_OFF LITERAL1
USART2_ON LITERAL1
USART1_OFF LITERAL1
USART1_ON LITERAL1
USART0_OFF LITERAL1
USART0_ON LITERAL1
SPI_OFF LITERAL1
SPI_ON LITERAL1
TWI_OFF LITERAL1
TWI_ON LITERAL1
USB_OFF LITERAL1
USB_ON LITERAL1

View File

@@ -0,0 +1,129 @@
#ifndef RunningMedian_h
#define RunningMedian_h
//
// FILE: RunningMedian.h
// AUTHOR: Rob dot Tillaart at gmail dot com
// PURPOSE: RunningMedian library for Arduino
// VERSION: 0.2.00 - template edition
// URL: http://arduino.cc/playground/Main/RunningMedian
// HISTORY: 0.2.00 first template version by Ronny
// 0.2.01 added getAverage(uint8_t nMedians, float val)
//
// Released to the public domain
//
#include <inttypes.h>
template <typename T, int N> class RunningMedian {
public:
enum STATUS {OK = 0, NOK = 1};
RunningMedian() {
_size = N;
clear();
};
void clear() {
_cnt = 0;
_idx = 0;
};
void add(T value) {
_ar[_idx++] = value;
if (_idx >= _size) _idx = 0; // wrap around
if (_cnt < _size) _cnt++;
};
STATUS getMedian(T& value) {
if (_cnt > 0) {
sort();
value = _as[_cnt/2];
return OK;
}
return NOK;
};
STATUS getAverage(float &value) {
if (_cnt > 0) {
float sum = 0;
for (uint8_t i=0; i< _cnt; i++) sum += _ar[i];
value = sum / _cnt;
return OK;
}
return NOK;
};
STATUS getAverage(uint8_t nMedians, float &value) {
if ((_cnt > 0) && (nMedians > 0))
{
if (_cnt < nMedians) nMedians = _cnt; // when filling the array for first time
uint8_t start = ((_cnt - nMedians)/2);
uint8_t stop = start + nMedians;
sort();
float sum = 0;
for (uint8_t i = start; i < stop; i++) sum += _as[i];
value = sum / nMedians;
return OK;
}
return NOK;
}
STATUS getHighest(T& value) {
if (_cnt > 0) {
sort();
value = _as[_cnt-1];
return OK;
}
return NOK;
};
STATUS getLowest(T& value) {
if (_cnt > 0) {
sort();
value = _as[0];
return OK;
}
return NOK;
};
unsigned getSize() {
return _size;
};
unsigned getCount() {
return _cnt;
}
STATUS getStatus() {
return (_cnt > 0 ? OK : NOK);
};
private:
uint8_t _size;
uint8_t _cnt;
uint8_t _idx;
T _ar[N];
T _as[N];
void sort() {
// copy
for (uint8_t i=0; i< _cnt; i++) _as[i] = _ar[i];
// sort all
for (uint8_t i=0; i< _cnt-1; i++) {
uint8_t m = i;
for (uint8_t j=i+1; j< _cnt; j++) {
if (_as[j] < _as[m]) m = j;
}
if (m != i) {
T t = _as[m];
_as[m] = _as[i];
_as[i] = t;
}
}
};
};
#endif
// --- END OF FILE ---

View File

@@ -0,0 +1,97 @@
/* DateStrings.cpp
* Definitions for date strings for use with the Time library
*
* Updated for Arduino 1.5.7 18 July 2014
*
* No memory is consumed in the sketch if your code does not call any of the string methods
* You can change the text of the strings, make sure the short strings are each exactly 3 characters
* the long strings can be any length up to the constant dt_MAX_STRING_LEN defined in Time.h
*
*/
#if defined(__AVR__)
#include <avr/pgmspace.h>
#else
// for compatiblity with Arduino Due and Teensy 3.0 and maybe others?
#define PROGMEM
#define PGM_P const char *
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define pgm_read_word(addr) (*(const unsigned char **)(addr))
#define strcpy_P(dest, src) strcpy((dest), (src))
#endif
#include <string.h> // for strcpy_P or strcpy
#include "Time.h"
// the short strings for each day or month must be exactly dt_SHORT_STR_LEN
#define dt_SHORT_STR_LEN 3 // the length of short strings
static char buffer[dt_MAX_STRING_LEN+1]; // must be big enough for longest string and the terminating null
const char monthStr0[] PROGMEM = "";
const char monthStr1[] PROGMEM = "January";
const char monthStr2[] PROGMEM = "February";
const char monthStr3[] PROGMEM = "March";
const char monthStr4[] PROGMEM = "April";
const char monthStr5[] PROGMEM = "May";
const char monthStr6[] PROGMEM = "June";
const char monthStr7[] PROGMEM = "July";
const char monthStr8[] PROGMEM = "August";
const char monthStr9[] PROGMEM = "September";
const char monthStr10[] PROGMEM = "October";
const char monthStr11[] PROGMEM = "November";
const char monthStr12[] PROGMEM = "December";
const PROGMEM char * const PROGMEM monthNames_P[] =
{
monthStr0,monthStr1,monthStr2,monthStr3,monthStr4,monthStr5,monthStr6,
monthStr7,monthStr8,monthStr9,monthStr10,monthStr11,monthStr12
};
const char monthShortNames_P[] PROGMEM = "ErrJanFebMarAprMayJunJulAugSepOctNovDec";
const char dayStr0[] PROGMEM = "Err";
const char dayStr1[] PROGMEM = "Sunday";
const char dayStr2[] PROGMEM = "Monday";
const char dayStr3[] PROGMEM = "Tuesday";
const char dayStr4[] PROGMEM = "Wednesday";
const char dayStr5[] PROGMEM = "Thursday";
const char dayStr6[] PROGMEM = "Friday";
const char dayStr7[] PROGMEM = "Saturday";
const PROGMEM char * const PROGMEM dayNames_P[] =
{
dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7
};
const char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat";
/* functions to return date strings */
char* monthStr(uint8_t month)
{
strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month])));
return buffer;
}
char* monthShortStr(uint8_t month)
{
for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)]));
buffer[dt_SHORT_STR_LEN] = 0;
return buffer;
}
char* dayStr(uint8_t day)
{
strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day])));
return buffer;
}
char* dayShortStr(uint8_t day)
{
uint8_t index = day*dt_SHORT_STR_LEN;
for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i]));
buffer[dt_SHORT_STR_LEN] = 0;
return buffer;
}

View File

@@ -0,0 +1,131 @@
Readme file for Arduino Time Library
Time is a library that provides timekeeping functionality for Arduino.
The code is derived from the Playground DateTime library but is updated
to provide an API that is more flexable and easier to use.
A primary goal was to enable date and time functionality that can be used with
a variety of external time sources with minimum differences required in sketch logic.
Example sketches illustrate how similar sketch code can be used with: a Real Time Clock,
internet NTP time service, GPS time data, and Serial time messages from a computer
for time synchronization.
The functions available in the library include:
hour(); // the hour now (0-23)
minute(); // the minute now (0-59)
second(); // the second now (0-59)
day(); // the day now (1-31)
weekday(); // day of the week, Sunday is day 0
month(); // the month now (1-12)
year(); // the full four digit year: (2009, 2010 etc)
there are also functions to return the hour in 12 hour format
hourFormat12(); // the hour now in 12 hour format
isAM(); // returns true if time now is AM
isPM(); // returns true if time now is PM
now(); // returns the current time as seconds since Jan 1 1970
The time and date functions can take an optional parameter for the time. This prevents
errors if the time rolls over between elements. For example, if a new minute begins
between getting the minute and second, the values will be inconsistent. Using the
following functions eliminates this probglem
time_t t = now(); // store the current time in time variable t
hour(t); // returns the hour for the given time t
minute(t); // returns the minute for the given time t
second(t); // returns the second for the given time t
day(t); // the day for the given time t
weekday(t); // day of the week for the given time t
month(t); // the month for the given time t
year(t); // the year for the given time t
Functions for managing the timer services are:
setTime(t); // set the system time to the give time t
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr (2010 or 10 sets year to 2010)
adjustTime(adjustment); // adjust system time by adding the adjustment value
timeStatus(); // indicates if time has been set and recently synchronized
// returns one of the following enumerations:
timeNotSet // the time has never been set, the clock started at Jan 1 1970
timeNeedsSync // the time had been set but a sync attempt did not succeed
timeSet // the time is set and is synced
Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but
the returned time may have drifted if the status is timeNeedsSync.
setSyncProvider(getTimeFunction); // set the external time provider
setSyncInterval(interval); // set the number of seconds between re-sync
There are many convenience macros in the time.h file for time constants and conversion of time units.
To use the library, copy the download to the Library directory.
The Time directory contains the Time library and some example sketches
illustrating how the library can be used with various time sources:
- TimeSerial.pde shows Arduino as a clock without external hardware.
It is synchronized by time messages sent over the serial port.
A companion Processing sketch will automatically provide these messages
if it is running and connected to the Arduino serial port.
- TimeSerialDateStrings.pde adds day and month name strings to the sketch above
Short (3 character) and long strings are available to print the days of
the week and names of the months.
- TimeRTC uses a DS1307 real time clock to provide time synchronization.
A basic RTC library named DS1307RTC is included in the download.
To run this sketch the DS1307RTC library must be installed.
- TimeRTCSet is similar to the above and adds the ability to set the Real Time Clock
- TimeRTCLog demonstrates how to calculate the difference between times.
It is a vary simple logger application that monitors events on digtial pins
and prints (to the serial port) the time of an event and the time period since the previous event.
- TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service.
The NTP protocol uses UDP and the UdpBytewise library is required, see:
http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/
- TimeGPS gets time from a GPS
This requires the TinyGPS library from Mikal Hart:
http://arduiniana.org/libraries/TinyGPS
Differences between this code and the playground DateTime library
although the Time library is based on the DateTime codebase, the API has changed.
Changes in the Time library API:
- time elements are functions returning int (they are variables in DateTime)
- Years start from 1970
- days of the week and months start from 1 (they start from 0 in DateTime)
- DateStrings do not require a seperate library
- time elements can be accessed non-atomically (in DateTime they are always atomic)
- function added to automatically sync time with extrnal source
- localTime and maketime parameters changed, localTime renamed to breakTime
Technical notes:
Internal system time is based on the standard Unix time_t.
The value is the number of seconds since Jan 1 1970.
System time begins at zero when the sketch starts.
The internal time can be automatically synchronized at regular intervals to an external time source.
This is enabled by calling the setSyncProvider(provider) function - the provider argument is
the address of a function that returns the current time as a time_t.
See the sketches in the examples directory for usage.
The default interval for re-syncing the time is 5 minutes but can be changed by calling the
setSyncInterval( interval) method to set the number of seconds between re-sync attempts.
The Time library defines a structure for holding time elements that is a compact version of the C tm structure.
All the members of the Arduino tm structure are bytes and the year is offset from 1970.
Convenience macros provide conversion to and from the Arduino format.
Low level functions to convert between system time and individual time elements are provided:
breakTime( time, &tm); // break time_t into elements stored in tm struct
makeTime( &tm); // return time_t from elements stored in tm struct
The DS1307RTC library included in the download provides an example of how a time provider
can use the low level functions to interface with the Time library.

View File

@@ -0,0 +1,319 @@
/*
time.c - low level time and date functions
Copyright (c) Michael Margolis 2009-2014
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
1.0 6 Jan 2010 - initial release
1.1 12 Feb 2010 - fixed leap year calculation error
1.2 1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
1.3 24 Mar 2012 - many edits by Paul Stoffregen: fixed timeStatus() to update
status, updated examples for Arduino 1.0, fixed ARM
compatibility issues, added TimeArduinoDue and TimeTeensy3
examples, add error checking and messages to RTC examples,
add examples to DS1307RTC library.
1.4 5 Sep 2014 - compatibility with Arduino 1.5.7
*/
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include "Time.h"
static tmElements_t tm; // a cache of time elements
static time_t cacheTime; // the time the cache was updated
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
void refreshCache(time_t t) {
if (t != cacheTime) {
breakTime(t, tm);
cacheTime = t;
}
}
int hour() { // the hour now
return hour(now());
}
int hour(time_t t) { // the hour for the given time
refreshCache(t);
return tm.Hour;
}
int hourFormat12() { // the hour now in 12 hour format
return hourFormat12(now());
}
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
refreshCache(t);
if( tm.Hour == 0 )
return 12; // 12 midnight
else if( tm.Hour > 12)
return tm.Hour - 12 ;
else
return tm.Hour ;
}
uint8_t isAM() { // returns true if time now is AM
return !isPM(now());
}
uint8_t isAM(time_t t) { // returns true if given time is AM
return !isPM(t);
}
uint8_t isPM() { // returns true if PM
return isPM(now());
}
uint8_t isPM(time_t t) { // returns true if PM
return (hour(t) >= 12);
}
int minute() {
return minute(now());
}
int minute(time_t t) { // the minute for the given time
refreshCache(t);
return tm.Minute;
}
int second() {
return second(now());
}
int second(time_t t) { // the second for the given time
refreshCache(t);
return tm.Second;
}
int day(){
return(day(now()));
}
int day(time_t t) { // the day for the given time (0-6)
refreshCache(t);
return tm.Day;
}
int weekday() { // Sunday is day 1
return weekday(now());
}
int weekday(time_t t) {
refreshCache(t);
return tm.Wday;
}
int month(){
return month(now());
}
int month(time_t t) { // the month for the given time
refreshCache(t);
return tm.Month;
}
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
return year(now());
}
int year(time_t t) { // the year for the given time
refreshCache(t);
return tmYearToCalendar(tm.Year);
}
/*============================================================================*/
/* functions to convert to and from system time */
/* These are for interfacing with time serivces and are not normally needed in a sketch */
// leap year calulator expects year argument as years offset from 1970
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
void breakTime(time_t timeInput, tmElements_t &tm){
// break the given time_t into time components
// this is a more compact version of the C library localtime function
// note that year is offset from 1970 !!!
uint8_t year;
uint8_t month, monthLength;
uint32_t time;
unsigned long days;
time = (uint32_t)timeInput;
tm.Second = time % 60;
time /= 60; // now it is minutes
tm.Minute = time % 60;
time /= 60; // now it is hours
tm.Hour = time % 24;
time /= 24; // now it is days
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
year = 0;
days = 0;
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
year++;
}
tm.Year = year; // year is offset from 1970
days -= LEAP_YEAR(year) ? 366 : 365;
time -= days; // now it is days in this year, starting at 0
days=0;
month=0;
monthLength=0;
for (month=0; month<12; month++) {
if (month==1) { // february
if (LEAP_YEAR(year)) {
monthLength=29;
} else {
monthLength=28;
}
} else {
monthLength = monthDays[month];
}
if (time >= monthLength) {
time -= monthLength;
} else {
break;
}
}
tm.Month = month + 1; // jan is month 1
tm.Day = time + 1; // day of month
}
time_t makeTime(tmElements_t &tm){
// assemble time elements into time_t
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
int i;
uint32_t seconds;
// seconds from 1970 till 1 jan 00:00:00 of the given year
seconds= tm.Year*(SECS_PER_DAY * 365);
for (i = 0; i < tm.Year; i++) {
if (LEAP_YEAR(i)) {
seconds += SECS_PER_DAY; // add extra days for leap years
}
}
// add days for this year, months start from 1
for (i = 1; i < tm.Month; i++) {
if ( (i == 2) && LEAP_YEAR(tm.Year)) {
seconds += SECS_PER_DAY * 29;
} else {
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
}
}
seconds+= (tm.Day-1) * SECS_PER_DAY;
seconds+= tm.Hour * SECS_PER_HOUR;
seconds+= tm.Minute * SECS_PER_MIN;
seconds+= tm.Second;
return (time_t)seconds;
}
/*=====================================================*/
/* Low level system time functions */
static uint32_t sysTime = 0;
static uint32_t prevMillis = 0;
static uint32_t nextSyncTime = 0;
static timeStatus_t Status = timeNotSet;
getExternalTime getTimePtr; // pointer to external sync function
//setExternalTime setTimePtr; // not used in this version
#ifdef TIME_DRIFT_INFO // define this to get drift data
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
#endif
time_t now() {
while (millis() - prevMillis >= 1000){
sysTime++;
prevMillis += 1000;
#ifdef TIME_DRIFT_INFO
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
#endif
}
if (nextSyncTime <= sysTime) {
if (getTimePtr != 0) {
time_t t = getTimePtr();
if (t != 0) {
setTime(t);
} else {
nextSyncTime = sysTime + syncInterval;
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
}
}
}
return (time_t)sysTime;
}
void setTime(time_t t) {
#ifdef TIME_DRIFT_INFO
if(sysUnsyncedTime == 0)
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
#endif
sysTime = (uint32_t)t;
nextSyncTime = (uint32_t)t + syncInterval;
Status = timeSet;
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
}
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
//it is converted to years since 1970
if( yr > 99)
yr = yr - 1970;
else
yr += 30;
tm.Year = yr;
tm.Month = mnth;
tm.Day = dy;
tm.Hour = hr;
tm.Minute = min;
tm.Second = sec;
setTime(makeTime(tm));
}
void adjustTime(long adjustment) {
sysTime += adjustment;
}
// indicates if time has been set and recently synchronized
timeStatus_t timeStatus() {
now(); // required to actually update the status
return Status;
}
void setSyncProvider( getExternalTime getTimeFunction){
getTimePtr = getTimeFunction;
nextSyncTime = sysTime;
now(); // this will sync the clock
}
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
syncInterval = (uint32_t)interval;
nextSyncTime = sysTime + syncInterval;
}

View File

@@ -0,0 +1,144 @@
/*
time.h - low level time and date functions
*/
/*
July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this)
- fixed daysToTime_t macro (thanks maniacbug)
*/
#ifndef _Time_h
#ifdef __cplusplus
#define _Time_h
#include <inttypes.h>
#ifndef __AVR__
#include <sys/types.h> // for __time_t_defined, but avr libc lacks sys/types.h
#endif
#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc
typedef unsigned long time_t;
#endif
// This ugly hack allows us to define C++ overloaded functions, when included
// from within an extern "C", as newlib's sys/stat.h does. Actually it is
// intended to include "time.h" from the C library (on ARM, but AVR does not
// have that file at all). On Mac and Windows, the compiler will find this
// "Time.h" instead of the C library "time.h", so we may cause other weird
// and unpredictable effects by conflicting with the C library header "time.h",
// but at least this hack lets us define C++ functions as intended. Hopefully
// nothing too terrible will result from overriding the C library header?!
extern "C++" {
typedef enum {timeNotSet, timeNeedsSync, timeSet
} timeStatus_t ;
typedef enum {
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
} timeDayOfWeek_t;
typedef enum {
tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields
} tmByteFields;
typedef struct {
uint8_t Second;
uint8_t Minute;
uint8_t Hour;
uint8_t Wday; // day of week, sunday is day 1
uint8_t Day;
uint8_t Month;
uint8_t Year; // offset from 1970;
} tmElements_t, TimeElements, *tmElementsPtr_t;
//convenience macros to convert to and from tm years
#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
#define CalendarYrToTm(Y) ((Y) - 1970)
#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000
#define y2kYearToTm(Y) ((Y) + 30)
typedef time_t(*getExternalTime)();
//typedef void (*setExternalTime)(const time_t); // not used in this version
/*==============================================================================*/
/* Useful Constants */
#define SECS_PER_MIN (60UL)
#define SECS_PER_HOUR (3600UL)
#define SECS_PER_DAY (SECS_PER_HOUR * 24UL)
#define DAYS_PER_WEEK (7UL)
#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK)
#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL)
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
/* Useful Macros for getting elapsed time */
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
#define dayOfWeek(_time_) ((( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970
#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight
// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
// Always set the correct time before settting alarms
#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY) ) // note that week starts on day 1
#define previousSunday(_time_) (_time_ - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time
#define nextSunday(_time_) ( previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time
/* Useful Macros for converting elapsed time to a time_t */
#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN)
#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR)
#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
/*============================================================================*/
/* time and date functions */
int hour(); // the hour now
int hour(time_t t); // the hour for the given time
int hourFormat12(); // the hour now in 12 hour format
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
uint8_t isAM(); // returns true if time now is AM
uint8_t isAM(time_t t); // returns true the given time is AM
uint8_t isPM(); // returns true if time now is PM
uint8_t isPM(time_t t); // returns true the given time is PM
int minute(); // the minute now
int minute(time_t t); // the minute for the given time
int second(); // the second now
int second(time_t t); // the second for the given time
int day(); // the day now
int day(time_t t); // the day for the given time
int weekday(); // the weekday now (Sunday is day 1)
int weekday(time_t t); // the weekday for the given time
int month(); // the month now (Jan is month 1)
int month(time_t t); // the month for the given time
int year(); // the full four digit year: (2009, 2010 etc)
int year(time_t t); // the year for the given time
time_t now(); // return the current time as seconds since Jan 1 1970
void setTime(time_t t);
void setTime(int hr,int min,int sec,int day, int month, int yr);
void adjustTime(long adjustment);
/* date strings */
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
char* monthStr(uint8_t month);
char* dayStr(uint8_t day);
char* monthShortStr(uint8_t month);
char* dayShortStr(uint8_t day);
/* time sync functions */
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
/* low level functions to convert to and from system time */
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
} // extern "C++"
#endif // __cplusplus
#endif /* _Time_h */

View File

@@ -0,0 +1,78 @@
/**
* SyncArduinoClock.
*
* portIndex must be set to the port connected to the Arduino
*
* The current time is sent in response to request message from Arduino
* or by clicking the display window
*
* The time message is 11 ASCII text characters; a header (the letter 'T')
* followed by the ten digit system time (unix time)
*/
import processing.serial.*;
import java.util.Date;
import java.util.Calendar;
import java.util.GregorianCalendar;
public static final short portIndex = 0; // select the com port, 0 is the first port
public static final String TIME_HEADER = "T"; //header for arduino serial time message
public static final char TIME_REQUEST = 7; // ASCII bell character
public static final char LF = 10; // ASCII linefeed
public static final char CR = 13; // ASCII linefeed
Serial myPort; // Create object from Serial class
void setup() {
size(200, 200);
println(Serial.list());
println(" Connecting to -> " + Serial.list()[portIndex]);
myPort = new Serial(this,Serial.list()[portIndex], 9600);
println(getTimeNow());
}
void draw()
{
textSize(20);
textAlign(CENTER);
fill(0);
text("Click to send\nTime Sync", 0, 75, 200, 175);
if ( myPort.available() > 0) { // If data is available,
char val = char(myPort.read()); // read it and store it in val
if(val == TIME_REQUEST){
long t = getTimeNow();
sendTimeMessage(TIME_HEADER, t);
}
else
{
if(val == LF)
; //igonore
else if(val == CR)
println();
else
print(val); // echo everying but time request
}
}
}
void mousePressed() {
sendTimeMessage( TIME_HEADER, getTimeNow());
}
void sendTimeMessage(String header, long time) {
String timeStr = String.valueOf(time);
myPort.write(header); // send header and time to arduino
myPort.write(timeStr);
myPort.write('\n');
}
long getTimeNow(){
// java time is in ms, we want secs
Date d = new Date();
Calendar cal = new GregorianCalendar();
long current = d.getTime()/1000;
long timezone = cal.get(cal.ZONE_OFFSET)/1000;
long daylight = cal.get(cal.DST_OFFSET)/1000;
return current + timezone + daylight;
}

View File

@@ -0,0 +1,9 @@
SyncArduinoClock is a Processing sketch that responds to Arduino requests for
time synchronization messages.
The portIndex must be set the Serial port connected to Arduino.
Download TimeSerial.pde onto Arduino and you should see the time
message displayed when you run SyncArduinoClock in Processing.
The Arduino time is set from the time on your computer through the
Processing sketch.

View File

@@ -0,0 +1,71 @@
/*
* TimeRTC.pde
* example code illustrating Time library with Real Time Clock.
*
* This example requires Markus Lange's Arduino Due RTC Library
* https://github.com/MarkusLange/Arduino-Due-RTC-Library
*/
#include <Time.h>
#include <rtc_clock.h>
// Select the Slowclock source
//RTC_clock rtc_clock(RC);
RTC_clock rtc_clock(XTAL);
void setup() {
Serial.begin(9600);
rtc_clock.init();
if (rtc_clock.date_already_set() == 0) {
// Unfortunately, the Arduino Due hardware does not seem to
// be designed to maintain the RTC clock state when the
// board resets. Markus described it thusly: "Uhh the Due
// does reset with the NRSTB pin. This resets the full chip
// with all backup regions including RTC, RTT and SC. Only
// if the reset is done with the NRST pin will these regions
// stay with their old values."
rtc_clock.set_time(__TIME__);
rtc_clock.set_date(__DATE__);
// However, this might work on other unofficial SAM3X boards
// with different reset circuitry than Arduino Due?
}
setSyncProvider(getArduinoDueTime);
if(timeStatus()!= timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
time_t getArduinoDueTime()
{
return rtc_clock.unixtime();
}
void loop()
{
digitalClockDisplay();
delay(1000);
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,87 @@
/*
* TimeGPS.pde
* example code illustrating time synced from a GPS
*
*/
#include <Time.h>
#include <TinyGPS.h> // http://arduiniana.org/libraries/TinyGPS/
#include <SoftwareSerial.h>
// TinyGPS and SoftwareSerial libraries are the work of Mikal Hart
SoftwareSerial SerialGPS = SoftwareSerial(10, 11); // receive on pin 10
TinyGPS gps;
// To use a hardware serial port, which is far more efficient than
// SoftwareSerial, uncomment this line and remove SoftwareSerial
//#define SerialGPS Serial1
// Offset hours from gps time (UTC)
const int offset = 1; // Central European Time
//const int offset = -5; // Eastern Standard Time (USA)
//const int offset = -4; // Eastern Daylight Time (USA)
//const int offset = -8; // Pacific Standard Time (USA)
//const int offset = -7; // Pacific Daylight Time (USA)
// Ideally, it should be possible to learn the time zone
// based on the GPS position data. However, that would
// require a complex library, probably incorporating some
// sort of database using Eric Muller's time zone shape
// maps, at http://efele.net/maps/tz/
time_t prevDisplay = 0; // when the digital clock was displayed
void setup()
{
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
SerialGPS.begin(4800);
Serial.println("Waiting for GPS time ... ");
}
void loop()
{
while (SerialGPS.available()) {
if (gps.encode(SerialGPS.read())) { // process gps messages
// when TinyGPS reports new data...
unsigned long age;
int Year;
byte Month, Day, Hour, Minute, Second;
gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age);
if (age < 500) {
// set the Time to the latest GPS reading
setTime(Hour, Minute, Second, Day, Month, Year);
adjustTime(offset * SECS_PER_HOUR);
}
}
}
if (timeStatus()!= timeNotSet) {
if (now() != prevDisplay) { //update the display only if the time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits) {
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,135 @@
/*
* Time_NTP.pde
* Example showing time sync to NTP time source
*
* This sketch uses the Ethernet library
*/
#include <Time.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include <SPI.h>
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// NTP Servers:
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
const int timeZone = 1; // Central European Time
//const int timeZone = -5; // Eastern Standard Time (USA)
//const int timeZone = -4; // Eastern Daylight Time (USA)
//const int timeZone = -8; // Pacific Standard Time (USA)
//const int timeZone = -7; // Pacific Daylight Time (USA)
EthernetUDP Udp;
unsigned int localPort = 8888; // local port to listen for UDP packets
void setup()
{
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
delay(250);
Serial.println("TimeNTP Example");
if (Ethernet.begin(mac) == 0) {
// no point in carrying on, so do nothing forevermore:
while (1) {
Serial.println("Failed to configure Ethernet using DHCP");
delay(10000);
}
}
Serial.print("IP number assigned by DHCP is ");
Serial.println(Ethernet.localIP());
Udp.begin(localPort);
Serial.println("waiting for sync");
setSyncProvider(getNtpTime);
}
time_t prevDisplay = 0; // when the digital clock was displayed
void loop()
{
if (timeStatus() != timeNotSet) {
if (now() != prevDisplay) { //update the display only if time has changed
prevDisplay = now();
digitalClockDisplay();
}
}
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
/*-------- NTP code ----------*/
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
time_t getNtpTime()
{
while (Udp.parsePacket() > 0) ; // discard any previously received packets
Serial.println("Transmit NTP Request");
sendNTPpacket(timeServer);
uint32_t beginWait = millis();
while (millis() - beginWait < 1500) {
int size = Udp.parsePacket();
if (size >= NTP_PACKET_SIZE) {
Serial.println("Receive NTP Response");
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
unsigned long secsSince1900;
// convert four bytes starting at location 40 to a long integer
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
secsSince1900 |= (unsigned long)packetBuffer[43];
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
}
}
Serial.println("No NTP Response :-(");
return 0; // return 0 if unable to get the time
}
// send an NTP request to the time server at the given address
void sendNTPpacket(IPAddress &address)
{
// set all bytes in the buffer to 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// Initialize values needed to form NTP request
// (see URL above for details on the packets)
packetBuffer[0] = 0b11100011; // LI, Version, Mode
packetBuffer[1] = 0; // Stratum, or type of clock
packetBuffer[2] = 6; // Polling Interval
packetBuffer[3] = 0xEC; // Peer Clock Precision
// 8 bytes of zero for Root Delay & Root Dispersion
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
// all NTP fields have been given values, now
// you can send a packet requesting a timestamp:
Udp.beginPacket(address, 123); //NTP requests are to port 123
Udp.write(packetBuffer, NTP_PACKET_SIZE);
Udp.endPacket();
}

View File

@@ -0,0 +1,55 @@
/*
* TimeRTC.pde
* example code illustrating Time library with Real Time Clock.
*
*/
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
void setup() {
Serial.begin(9600);
while (!Serial) ; // wait until Arduino Serial Monitor opens
setSyncProvider(RTC.get); // the function to get the time from the RTC
if(timeStatus()!= timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
void loop()
{
if (timeStatus() == timeSet) {
digitalClockDisplay();
} else {
Serial.println("The time has not been set. Please run the Time");
Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
Serial.println();
delay(4000);
}
delay(1000);
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,107 @@
/*
* TimeRTCLogger.pde
* example code illustrating adding and subtracting Time.
*
* this sketch logs pin state change events
* the time of the event and time since the previous event is calculated and sent to the serial port.
*/
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
const int nbrInputPins = 6; // monitor 6 digital pins
const int inputPins[nbrInputPins] = {2,3,4,5,6,7}; // pins to monitor
boolean state[nbrInputPins] ; // the state of the monitored pins
time_t prevEventTime[nbrInputPins] ; // the time of the previous event
void setup() {
Serial.begin(9600);
setSyncProvider(RTC.get); // the function to sync the time from the RTC
for(int i=0; i < nbrInputPins; i++){
pinMode( inputPins[i], INPUT);
// uncomment these lines if pull-up resistors are wanted
// pinMode( inputPins[i], INPUT_PULLUP);
// state[i] = HIGH;
}
}
void loop()
{
for(int i=0; i < nbrInputPins; i++)
{
boolean val = digitalRead(inputPins[i]);
if(val != state[i])
{
time_t duration = 0; // the time since the previous event
state[i] = val;
time_t timeNow = now();
if(prevEventTime[i] > 0)
// if this was not the first state change, calculate the time from the previous change
duration = duration = timeNow - prevEventTime[i];
logEvent(inputPins[i], val, timeNow, duration ); // log the event
prevEventTime[i] = timeNow; // store the time for this event
}
}
}
void logEvent( int pin, boolean state, time_t timeNow, time_t duration)
{
Serial.print("Pin ");
Serial.print(pin);
if( state == HIGH)
Serial.print(" went High at ");
else
Serial.print(" went Low at ");
showTime(timeNow);
if(duration > 0){
// only display duration if greater than 0
Serial.print(", Duration was ");
showDuration(duration);
}
Serial.println();
}
void showTime(time_t t){
// display the given time
Serial.print(hour(t));
printDigits(minute(t));
printDigits(second(t));
Serial.print(" ");
Serial.print(day(t));
Serial.print(" ");
Serial.print(month(t));
Serial.print(" ");
Serial.print(year(t));
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void showDuration(time_t duration){
// prints the duration in days, hours, minutes and seconds
if(duration >= SECS_PER_DAY){
Serial.print(duration / SECS_PER_DAY);
Serial.print(" day(s) ");
duration = duration % SECS_PER_DAY;
}
if(duration >= SECS_PER_HOUR){
Serial.print(duration / SECS_PER_HOUR);
Serial.print(" hour(s) ");
duration = duration % SECS_PER_HOUR;
}
if(duration >= SECS_PER_MIN){
Serial.print(duration / SECS_PER_MIN);
Serial.print(" minute(s) ");
duration = duration % SECS_PER_MIN;
}
Serial.print(duration);
Serial.print(" second(s) ");
}

View File

@@ -0,0 +1,80 @@
/*
* TimeRTCSet.pde
* example code illustrating Time library with Real Time Clock.
*
* RTC clock is set in response to serial port time message
* A Processing example sketch to set the time is included in the download
* On Linux, you can use "date +T%s > /dev/ttyACM0" (UTC time zone)
*/
#include <Time.h>
#include <Wire.h>
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
void setup() {
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
setSyncProvider(RTC.get); // the function to get the time from the RTC
if (timeStatus() != timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
void loop()
{
if (Serial.available()) {
time_t t = processSyncMessage();
if (t != 0) {
RTC.set(t); // set the RTC and the system time to the received value
setTime(t);
}
}
digitalClockDisplay();
delay(1000);
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
/* code to process time sync messages from the serial port */
#define TIME_HEADER "T" // Header tag for serial time sync message
unsigned long processSyncMessage() {
unsigned long pctime = 0L;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER)) {
pctime = Serial.parseInt();
return pctime;
if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
pctime = 0L; // return 0 to indicate that the time is not valid
}
}
return pctime;
}

View File

@@ -0,0 +1,81 @@
/*
* TimeSerial.pde
* example code illustrating Time library set through serial port messages.
*
* Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970)
* you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2013
T1357041600
*
* A Processing example sketch to automatically send the messages is inclided in the download
* On Linux, you can use "date +T%s\n > /dev/ttyACM0" (UTC time zone)
*/
#include <Time.h>
#define TIME_HEADER "T" // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
void setup() {
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
pinMode(13, OUTPUT);
setSyncProvider( requestSync); //set function to call when sync required
Serial.println("Waiting for sync message");
}
void loop(){
if (Serial.available()) {
processSyncMessage();
}
if (timeStatus()!= timeNotSet) {
digitalClockDisplay();
}
if (timeStatus() == timeSet) {
digitalWrite(13, HIGH); // LED on if synced
} else {
digitalWrite(13, LOW); // LED off if needs refresh
}
delay(1000);
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void processSyncMessage() {
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER)) {
pctime = Serial.parseInt();
if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
}
}
}
time_t requestSync()
{
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to serial mesg
}

View File

@@ -0,0 +1,108 @@
/*
* TimeSerialDateStrings.pde
* example code illustrating Time library date strings
*
* This sketch adds date string functionality to TimeSerial sketch
* Also shows how to handle different messages
*
* A message starting with a time header sets the time
* A Processing example sketch to automatically send the messages is inclided in the download
* On Linux, you can use "date +T%s\n > /dev/ttyACM0" (UTC time zone)
*
* A message starting with a format header sets the date format
* send: Fs\n for short date format
* send: Fl\n for long date format
*/
#include <Time.h>
// single character message tags
#define TIME_HEADER 'T' // Header tag for serial time sync message
#define FORMAT_HEADER 'F' // Header tag indicating a date format message
#define FORMAT_SHORT 's' // short month and day strings
#define FORMAT_LONG 'l' // (lower case l) long month and day strings
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
static boolean isLongFormat = true;
void setup() {
Serial.begin(9600);
while (!Serial) ; // Needed for Leonardo only
setSyncProvider( requestSync); //set function to call when sync required
Serial.println("Waiting for sync message");
}
void loop(){
if (Serial.available() > 1) { // wait for at least two characters
char c = Serial.read();
if( c == TIME_HEADER) {
processSyncMessage();
}
else if( c== FORMAT_HEADER) {
processFormatMessage();
}
}
if (timeStatus()!= timeNotSet) {
digitalClockDisplay();
}
delay(1000);
}
void digitalClockDisplay() {
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
if(isLongFormat)
Serial.print(dayStr(weekday()));
else
Serial.print(dayShortStr(weekday()));
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
if(isLongFormat)
Serial.print(monthStr(month()));
else
Serial.print(monthShortStr(month()));
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits) {
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
void processFormatMessage() {
char c = Serial.read();
if( c == FORMAT_LONG){
isLongFormat = true;
Serial.println(F("Setting long format"));
}
else if( c == FORMAT_SHORT) {
isLongFormat = false;
Serial.println(F("Setting short format"));
}
}
void processSyncMessage() {
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 - paul, perhaps we define in time.h?
pctime = Serial.parseInt();
if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
}
}
time_t requestSync() {
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to serial mesg
}

View File

@@ -0,0 +1,78 @@
/*
* TimeRTC.pde
* example code illustrating Time library with Real Time Clock.
*
*/
#include <Time.h>
void setup() {
// set the Time library to use Teensy 3.0's RTC to keep time
setSyncProvider(getTeensy3Time);
Serial.begin(115200);
while (!Serial); // Wait for Arduino Serial Monitor to open
delay(100);
if (timeStatus()!= timeSet) {
Serial.println("Unable to sync with the RTC");
} else {
Serial.println("RTC has set the system time");
}
}
void loop() {
if (Serial.available()) {
time_t t = processSyncMessage();
if (t != 0) {
Teensy3Clock.set(t); // set the RTC
setTime(t);
}
}
digitalClockDisplay();
delay(1000);
}
void digitalClockDisplay() {
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
time_t getTeensy3Time()
{
return Teensy3Clock.get();
}
/* code to process time sync messages from the serial port */
#define TIME_HEADER "T" // Header tag for serial time sync message
unsigned long processSyncMessage() {
unsigned long pctime = 0L;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
if(Serial.find(TIME_HEADER)) {
pctime = Serial.parseInt();
return pctime;
if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
pctime = 0L; // return 0 to indicate that the time is not valid
}
}
return pctime;
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,33 @@
#######################################
# Syntax Coloring Map For Time
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
time_t KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
now KEYWORD2
second KEYWORD2
minute KEYWORD2
hour KEYWORD2
day KEYWORD2
month KEYWORD2
year KEYWORD2
isAM KEYWORD2
isPM KEYWORD2
weekday KEYWORD2
setTime KEYWORD2
adjustTime KEYWORD2
setSyncProvider KEYWORD2
setSyncInterval KEYWORD2
timeStatus KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
#######################################
# Constants (LITERAL1)
#######################################

View File

@@ -0,0 +1,22 @@
{
"name": "Time",
"frameworks": "Arduino",
"keywords": "Time, date, hour, minute, second, day, week, month, year, RTC",
"description": "Time keeping library",
"url": "http://playground.arduino.cc/Code/Time",
"authors":
[
{
"name": "Michael Margolis"
},
{
"name": "Paul Stoffregen"
}
],
"repository":
{
"type": "git",
"url": "https://github.com/PaulStoffregen/Time"
}
}

View File

@@ -0,0 +1,561 @@
/* Copyright (C) 2014 olie.xdev <olie.xdev@googlemail.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
*/
#include <LowPower.h>
#include <RunningMedian.h>
#include <Wire.h>
#include <Time.h>
#include <DS3232RTC.h>
#include <I2C_eeprom.h>
#define SEG_1_1 4
#define SEG_1_2 5
#define SEG_2_1 6
#define SEG_2_2 7
#define SEG_3_1 8
#define SEG_3_2 9
#define SEG_4_1 10
#define SEG_4_2 11
#define UP 12
#define C0 A0
#define C1 A1
#define C2 A2
#define C3 A3
#define WAKEUP_PIN 3
#define EXT_SWITCH_PIN 13
#define MAX_SAMPLE_SIZE 6
#define MAX_NO_ACTIVITY_CYCLES 32
I2C_eeprom eeprom(0x50);
char port_control;
char port_digital_pinA;
char port_digital_pinB;
int control_bit[4];
int seg_raw_1_1[4];
int seg_raw_1_2[4];
int seg_raw_2_1[4];
int seg_raw_2_2[4];
int seg_raw_3_1[4];
int seg_raw_3_2[4];
int seg_raw_4_1[4];
int seg_raw_4_2[4];
char seg_value_1;
char seg_value_2;
char seg_value_3;
char seg_value_4;
RunningMedian<char, MAX_SAMPLE_SIZE> seg_samples_1;
RunningMedian<char, MAX_SAMPLE_SIZE> seg_samples_2;
RunningMedian<char, MAX_SAMPLE_SIZE> seg_samples_3;
RunningMedian<char, MAX_SAMPLE_SIZE> seg_samples_4;
int sample_count = 0;
int no_activity_cycles = 0;
volatile boolean sleep_state = true;
volatile boolean repeat_state = false;
int measured_weight = -1;
int measured_fat = -1;
int measured_water = -1;
int measured_muscle = -1;
typedef struct scale_data{
int year;
byte month;
byte day;
byte hour;
byte minute;
int weight;
int fat;
int water;
int muscle;
int checksum;
} __attribute__ ((packed)); // avoiding byte padding in this struct. Important for continuous writing/reading to/from eeprom!
void interrupt_handler()
{
sleep_state = false;
}
void setup() {
Serial.begin(9600);
pinMode(SEG_1_1, INPUT);
pinMode(SEG_1_2, INPUT);
pinMode(SEG_2_1, INPUT);
pinMode(SEG_2_2, INPUT);
pinMode(SEG_3_1, INPUT);
pinMode(SEG_3_2, INPUT);
pinMode(SEG_4_1, INPUT);
pinMode(SEG_4_2, INPUT);
pinMode(UP, OUTPUT);
pinMode(C0, INPUT);
pinMode(C1, INPUT);
pinMode(C2, INPUT);
pinMode(C3, INPUT);
pinMode(WAKEUP_PIN, INPUT);
pinMode(EXT_SWITCH_PIN, OUTPUT);
digitalWrite(EXT_SWITCH_PIN, HIGH);
}
void set_seg_raw(int cycle_n)
{
seg_raw_1_1[cycle_n] = (port_digital_pinA & (1 << 4)) ? 1 : 0;
seg_raw_1_2[cycle_n] = (port_digital_pinA & (1 << 5)) ? 1 : 0;
seg_raw_2_1[cycle_n] = (port_digital_pinA & (1 << 6)) ? 1 : 0;
seg_raw_2_2[cycle_n] = (port_digital_pinA & (1 << 7)) ? 1 : 0;
seg_raw_3_1[cycle_n] = (port_digital_pinB & (1 << 0)) ? 1 : 0;
seg_raw_3_2[cycle_n] = (port_digital_pinB & (1 << 1)) ? 1 : 0;
seg_raw_4_1[cycle_n] = (port_digital_pinB & (1 << 2)) ? 1 : 0;
seg_raw_4_2[cycle_n] = (port_digital_pinB & (1 << 3)) ? 1 : 0;
}
char decode_seg(int seg_x[4], int seg_y[4])
{
boolean b = seg_x[0];
boolean c = seg_x[1];
boolean e = seg_x[2];
boolean f = seg_x[3];
boolean a = seg_y[0];
boolean d = seg_y[1];
boolean g = seg_y[2];
boolean x = seg_y[3];
if (!e && !c && !b && !f &&
!g && !d && !a)
return ' ';
if (e && !c && b && f &&
g && d && a)
return '0';
if (e && !c && b && !f &&
!g && !d && !a)
return '1';
if (!e && c && b && f &&
g && !d && a)
return '2';
if (e && c && b && f &&
!g && !d && a)
return '3';
if (e && c && b && !f &&
!g && d && !a)
return '4';
if (e && c && !b && f &&
!g && d && a)
return '5';
if (e && c && !b && f &&
g && d && a)
return '6';
if (e && !c && b && !f &&
!g && !d && a)
return '7';
if (e && c && b && f &&
g && d && a)
return '8';
if (e && c && b && f &&
!g && d && a)
return '9';
if (!e && c && !b && !f &&
!g && !d && !a)
return '-';
if (!e && c && b && !f &&
g && d && a)
return 'P';
if (e && !c && b && !f &&
g && d && a)
return 'M';
if (!e && c && !b && f &&
g && d && a)
return 'E';
if (!e && c && !b && !f &&
g && d && a)
return 'F';
if (e && c && b && !f &&
g && d && !a)
return 'H';
return -1;
}
void before_sleep_event()
{
Serial.println("$I$ going to sleep in 3 seconds!");
if (measured_weight != -1 && measured_fat != -1 && measured_water != -1 && measured_muscle != -1) {
write_scale_data(measured_weight, measured_fat, measured_water, measured_muscle);
delay(100);
}
send_scale_data();
delay(3000);
digitalWrite(EXT_SWITCH_PIN, LOW);
}
void after_sleep_event()
{
digitalWrite(EXT_SWITCH_PIN, HIGH);
measured_weight = -1;
measured_fat = -1;
measured_water = -1;
measured_muscle = -1;
delay(4000);
digitalWrite(UP, HIGH);
delay(500);
digitalWrite(UP, LOW);
setSyncProvider(RTC.get);
if (timeStatus() != timeSet) {
Serial.println("$E$ Can't sync to RTC clock!");
} else {
Serial.println("$I$ Successful sync to RTC clock");
}
Serial.print("$I$ Time: ");
Serial.print(hour());
Serial.write(':');
Serial.print(minute());
Serial.write(':');
Serial.print(second());
Serial.print(" Date: ");
Serial.print(day());
Serial.write('/');
Serial.print(month());
Serial.write('/');
Serial.print(year());
Serial.println();
Serial.println("$I$ openScale MCU ready!");
}
void check_display_activity()
{
if (no_activity_cycles > MAX_NO_ACTIVITY_CYCLES)
{
sleep_state = true;
no_activity_cycles = 0;
}
if (sleep_state == true)
{
before_sleep_event();
// Allow wake up pin to trigger interrupt on rising edge.
attachInterrupt(1, interrupt_handler, RISING);
// Enter power down state with ADC and BOD module disabled.
// Wake up when wake up pin is rising.
LowPower.powerDown(SLEEP_FOREVER, ADC_OFF, BOD_OFF);
// Disable external pin interrupt on wake up pin.
detachInterrupt(1);
after_sleep_event();
}
}
int calc_checksum(struct scale_data* wdata)
{
int checksum = 0;
checksum ^= wdata->year;
checksum ^= wdata->month;
checksum ^= wdata->day;
checksum ^= wdata->hour;
checksum ^= wdata->minute;
checksum ^= (int)((float)wdata->weight / 10.0f);
checksum ^= (int)((float)wdata->fat / 10.0f);
checksum ^= (int)((float)wdata->water / 10.0f);
checksum ^= (int)((float)wdata->muscle / 10.0f);
return checksum;
}
void write_scale_data(int weight, int fat, int water, int muscle)
{
int data_size = 0;
struct scale_data wdata;
eeprom.readBlock(0, (uint8_t*)&data_size, sizeof(data_size));
wdata.year = year();
wdata.month = month();
wdata.day = day();
wdata.hour = hour();
wdata.minute = minute();
wdata.weight = weight;
wdata.fat = fat;
wdata.water = water;
wdata.muscle = muscle;
wdata.checksum = calc_checksum(&wdata);
if (eeprom.writeBlock(sizeof(data_size)+data_size*sizeof(wdata), (uint8_t*)&wdata, sizeof(wdata)) != 0) {
Serial.println("$E$ Error writing data to eeprom");
}
delay(100);
data_size++;
if (eeprom.writeBlock(0, (uint8_t*)&data_size, sizeof(data_size)) != 0) {
Serial.println("$E$ Error writing data to eeprom");
}
}
void send_scale_data()
{
int data_size = 0;
struct scale_data wdata;
eeprom.readBlock(0, (uint8_t*)&data_size, sizeof(data_size));
Serial.print("$S$");
Serial.println(data_size);
for (int i=0; i < data_size; i++)
{
eeprom.readBlock(sizeof(data_size)+i*sizeof(wdata), (uint8_t*)&wdata, sizeof(wdata));
if (wdata.checksum != calc_checksum(&wdata)) {
Serial.print("$E$ Wrong Checksum for data ");
Serial.print(i);
Serial.println();
}
Serial.print("$D$");
Serial.print(i);
Serial.print(',');
Serial.print(wdata.year);
Serial.print(',');
Serial.print(wdata.month);
Serial.print(',');
Serial.print(wdata.day);
Serial.print(',');
Serial.print(wdata.hour);
Serial.print(',');
Serial.print(wdata.minute);
Serial.print(',');
Serial.print((float)wdata.weight / 10.0f);
Serial.print(',');
Serial.print((float)wdata.fat / 10.0f);
Serial.print(',');
Serial.print((float)wdata.water / 10.0f);
Serial.print(',');
Serial.print((float)wdata.muscle / 10.0f);
Serial.print(',');
Serial.print(wdata.checksum);
Serial.print('\n');
}
}
void clear_scale_data()
{
int data_size = 0;
eeprom.writeBlock(0, (uint8_t*)&data_size, sizeof(data_size));
}
void loop()
{
check_display_activity();
port_control = PINC;
port_digital_pinA = PIND;
port_digital_pinB = PINB;
control_bit[0] = (port_control & (1 << 0)) ? 1 : 0;
control_bit[1] = (port_control & (1 << 1)) ? 1 : 0;
control_bit[2] = (port_control & (1 << 2)) ? 1 : 0;
control_bit[3] = (port_control & (1 << 3)) ? 1 : 0;
if (control_bit[0] == LOW && control_bit[1] == HIGH && control_bit[2] == HIGH && control_bit[3] == HIGH)
{
set_seg_raw(0);
}
else if (control_bit[0] == HIGH && control_bit[1] == LOW && control_bit[2] == HIGH && control_bit[3] == HIGH)
{
set_seg_raw(1);
}
else if (control_bit[0] == HIGH && control_bit[1] == HIGH && control_bit[2] == LOW && control_bit[3] == HIGH)
{
set_seg_raw(2);
}
else if (control_bit[0] == HIGH && control_bit[1] == HIGH && control_bit[2] == HIGH && control_bit[3] == LOW)
{
set_seg_raw(3);
}
else if (control_bit[0] == HIGH && control_bit[1] == HIGH && control_bit[2] == HIGH && control_bit[3] == HIGH)
{
no_activity_cycles++;
}
seg_value_1 = decode_seg(seg_raw_1_1, seg_raw_1_2);
seg_value_2 = decode_seg(seg_raw_2_1, seg_raw_2_2);
seg_value_3 = decode_seg(seg_raw_3_1, seg_raw_3_2);
seg_value_4 = decode_seg(seg_raw_4_1, seg_raw_4_2);
if (seg_value_1 != -1 && seg_value_2 != -1 && seg_value_3 != -1 && seg_value_4 != -1)
{
seg_samples_1.add(seg_value_1);
seg_samples_2.add(seg_value_2);
seg_samples_3.add(seg_value_3);
seg_samples_4.add(seg_value_4);
sample_count++;
}
if (sample_count > MAX_SAMPLE_SIZE)
{
seg_samples_1.getMedian(seg_value_1);
seg_samples_2.getMedian(seg_value_2);
seg_samples_3.getMedian(seg_value_3);
seg_samples_4.getMedian(seg_value_4);
if (seg_value_4 == ' ') {
measured_weight = char_to_int(seg_value_1) + char_to_int(seg_value_2)*10 + char_to_int(seg_value_3)*100;
}
if (seg_value_4 == 'F') {
measured_fat = char_to_int(seg_value_1) + char_to_int(seg_value_2)*10 + char_to_int(seg_value_3)*100;
}
if (seg_value_4 == 'H') {
measured_water = char_to_int(seg_value_1) + char_to_int(seg_value_2)*10 + char_to_int(seg_value_3)*100;
}
if (seg_value_4 == 'M') {
measured_muscle = char_to_int(seg_value_1) + char_to_int(seg_value_2)*10 + char_to_int(seg_value_3)*100;
}
sample_count = 0;
}
delay(10);
if (Serial.available() > 0)
{
char command = Serial.read();
switch(command)
{
case '0':
Serial.println("$I$ openScale MCU Version 1.0");
break;
case '1':
Serial.println("$I$ Sending scale data!");
send_scale_data();
break;
case '9':
clear_scale_data();
Serial.println("$I$ Scale data cleared!");
break;
}
}
}
int char_to_int(char c)
{
if (c == ' ')
return 0;
return (c - '0');
}
void print_debug_output()
{
Serial.print("Debug Ausgabe\n");
Serial.print("-----------------------------------\n");
Serial.print("\nSeg 1\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_1_1[i]);
}
Serial.print("\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_1_2[i]);
}
Serial.print("\nSeg 2\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_2_1[i]);
}
Serial.print("\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_2_2[i]);
}
Serial.print("\nSeg 3\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_3_1[i]);
}
Serial.print("\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_3_2[i]);
}
Serial.print("\nSeg 4\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_4_1[i]);
}
Serial.print("\n");
for (int i=0; i<4; i++)
{
Serial.print(seg_raw_4_2[i]);
}
Serial.print("\n-----------------------------------\n");
}