mirror of
https://github.com/oliexdev/openScale.git
synced 2025-08-15 05:04:22 +02:00
initial commit microcontroller unit (mcu) arduino sketch for the custom bluetooth scale.
This commit is contained in:
2
arduino_mcu/libraries/DS3232RTC/.gitignore
vendored
Normal file
2
arduino_mcu/libraries/DS3232RTC/.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
*.zip
|
||||||
|
*.7z
|
335
arduino_mcu/libraries/DS3232RTC/DS3232RTC.cpp
Normal file
335
arduino_mcu/libraries/DS3232RTC/DS3232RTC.cpp
Normal 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
|
157
arduino_mcu/libraries/DS3232RTC/DS3232RTC.h
Normal file
157
arduino_mcu/libraries/DS3232RTC/DS3232RTC.h
Normal 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
|
8
arduino_mcu/libraries/DS3232RTC/LICENSE.md
Normal file
8
arduino_mcu/libraries/DS3232RTC/LICENSE.md
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
# Arduino DS3232RTC Library v1.0 #
|
||||||
|
https://github.com/JChristensen/DS3232RTC
|
||||||
|
LICENSE file
|
||||||
|
Jack Christensen Mar 2013
|
||||||
|
|
||||||
|

|
||||||
|
## 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/).
|
345
arduino_mcu/libraries/DS3232RTC/ReadMe.md
Normal file
345
arduino_mcu/libraries/DS3232RTC/ReadMe.md
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
# Arduino DS3232RTC Library v1.0 #
|
||||||
|
https://github.com/JChristensen/DS3232RTC
|
||||||
|
ReadMe file
|
||||||
|
Jack Christensen Mar 2013
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
## 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
|
||||||
|
}
|
||||||
|
```
|
132
arduino_mcu/libraries/DS3232RTC/examples/SetSerial/SetSerial.ino
Normal file
132
arduino_mcu/libraries/DS3232RTC/examples/SetSerial/SetSerial.ino
Normal 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;
|
||||||
|
}
|
50
arduino_mcu/libraries/DS3232RTC/examples/TimeRTC/TimeRTC.ino
Normal file
50
arduino_mcu/libraries/DS3232RTC/examples/TimeRTC/TimeRTC.ino
Normal 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);
|
||||||
|
}
|
@@ -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;
|
||||||
|
}
|
13
arduino_mcu/libraries/DS3232RTC/keywords.txt
Normal file
13
arduino_mcu/libraries/DS3232RTC/keywords.txt
Normal 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
|
212
arduino_mcu/libraries/I2C_eeprom/I2C_eeprom.cpp
Normal file
212
arduino_mcu/libraries/I2C_eeprom/I2C_eeprom.cpp
Normal 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
|
||||||
|
//
|
||||||
|
|
67
arduino_mcu/libraries/I2C_eeprom/I2C_eeprom.h
Normal file
67
arduino_mcu/libraries/I2C_eeprom/I2C_eeprom.h
Normal 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
|
@@ -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.
|
||||||
|
}
|
||||||
|
|
@@ -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.
|
||||||
|
}
|
@@ -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.
|
||||||
|
}
|
856
arduino_mcu/libraries/LowPower/LowPower.cpp
Normal file
856
arduino_mcu/libraries/LowPower/LowPower.cpp
Normal 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;
|
137
arduino_mcu/libraries/LowPower/LowPower.h
Normal file
137
arduino_mcu/libraries/LowPower/LowPower.h
Normal 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
|
68
arduino_mcu/libraries/LowPower/keywords.txt
Normal file
68
arduino_mcu/libraries/LowPower/keywords.txt
Normal 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
|
129
arduino_mcu/libraries/RunningMedian/RunningMedian.h
Normal file
129
arduino_mcu/libraries/RunningMedian/RunningMedian.h
Normal 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 ---
|
97
arduino_mcu/libraries/Time/DateStrings.cpp
Normal file
97
arduino_mcu/libraries/Time/DateStrings.cpp
Normal 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;
|
||||||
|
}
|
131
arduino_mcu/libraries/Time/Readme.txt
Normal file
131
arduino_mcu/libraries/Time/Readme.txt
Normal 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.
|
319
arduino_mcu/libraries/Time/Time.cpp
Normal file
319
arduino_mcu/libraries/Time/Time.cpp
Normal 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;
|
||||||
|
}
|
144
arduino_mcu/libraries/Time/Time.h
Normal file
144
arduino_mcu/libraries/Time/Time.h
Normal 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 */
|
||||||
|
|
@@ -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;
|
||||||
|
}
|
@@ -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.
|
@@ -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);
|
||||||
|
}
|
||||||
|
|
87
arduino_mcu/libraries/Time/examples/TimeGPS/TimeGPS.ino
Normal file
87
arduino_mcu/libraries/Time/examples/TimeGPS/TimeGPS.ino
Normal 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);
|
||||||
|
}
|
||||||
|
|
135
arduino_mcu/libraries/Time/examples/TimeNTP/TimeNTP.ino
Normal file
135
arduino_mcu/libraries/Time/examples/TimeNTP/TimeNTP.ino
Normal 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();
|
||||||
|
}
|
||||||
|
|
55
arduino_mcu/libraries/Time/examples/TimeRTC/TimeRTC.pde
Normal file
55
arduino_mcu/libraries/Time/examples/TimeRTC/TimeRTC.pde
Normal 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);
|
||||||
|
}
|
||||||
|
|
107
arduino_mcu/libraries/Time/examples/TimeRTCLog/TimeRTCLog.pde
Normal file
107
arduino_mcu/libraries/Time/examples/TimeRTCLog/TimeRTCLog.pde
Normal 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) ");
|
||||||
|
}
|
||||||
|
|
@@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@@ -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
|
||||||
|
}
|
||||||
|
|
@@ -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
|
||||||
|
}
|
@@ -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);
|
||||||
|
}
|
||||||
|
|
33
arduino_mcu/libraries/Time/keywords.txt
Normal file
33
arduino_mcu/libraries/Time/keywords.txt
Normal 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)
|
||||||
|
#######################################
|
22
arduino_mcu/libraries/Time/library.json
Normal file
22
arduino_mcu/libraries/Time/library.json
Normal 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"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
561
arduino_mcu/openScale_MCU/openScale_MCU.ino
Normal file
561
arduino_mcu/openScale_MCU/openScale_MCU.ino
Normal 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");
|
||||||
|
}
|
Reference in New Issue
Block a user