Compare commits

..

10 Commits

Author SHA1 Message Date
foley@ru.is
6fcde3bb4b Set the synchronizer to run the full time. Added documentation indicating that artists must add blank time at the end to eliminate the need to chop time off. 2014-01-24 12:36:41 +00:00
foley@ru.is
f7d8c07bad System seems OK, changed choptime to 4 seconds to keep running time to 14:41 out of 14:44 2014-01-24 12:20:34 +00:00
foley@ru.is
4d77eff73d Changed sending command to send the command 5 time with 10ms spacing, now much more robust. Playtime now adds in the "delay" from resetting. Some weirdness with EOL, setting to CRLF for now. 2014-01-24 11:26:26 +00:00
foley@ru.is
7a55e0c71f The play time got left at the 5 minute test time for the trajectories installation. Corrected, in testing. 2014-01-24 09:09:38 +00:00
foley@ru.is
e3daa0cee0 Windows Arduino 1.0.X does not like to import zip files. Unzipped to make installation easier. 2014-01-15 17:18:08 +00:00
foley@ru.is
0ff28de55a New libraries needed for the synchronizers 2014-01-15 16:19:46 +00:00
foley@ru.is
86004ff9c1 Finished new synchronizer and decoder label. Filled the rest of the sheet. 2014-01-15 16:17:43 +00:00
foley@ru.is
ffc3610c00 unified the code to use the Time and TimeAlarm libraries. This simplifies the code greatly and should improve the accuracy. 2014-01-15 02:33:44 +00:00
foley@ru.is
75bd4dcb42 minor updates to the instructions about how to program a new synchronizer 2014-01-15 02:32:39 +00:00
foley@ru.is
bb36a16f30 completed and tested Sony BDP-5790 synchronizer, need to sanitize and push the code to the other versions 2014-01-15 01:40:28 +00:00
36 changed files with 3130 additions and 412 deletions

View File

@@ -8,39 +8,41 @@ const String SVN_ID="$Id$";
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
*
* Useful information at http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
* More codes at http://www.lirc.org/
* This uses remote Sony RMT-B122P
* This uses remote Sony RMT-B122P
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*
*
*/
#include <IRremote.h>
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
int pinGND=4; // Longer leg on the IR LED
// IR LED pin 3 should be the longer leg
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int secs;
int heartbeat_state=0;
String INST_NAME="Trajectories";
String ARTIST="Sigurdur Gudjonsson (video) & Anna Thorvaldsdottir (sound)";
String YEAR="2014";
int videotime = 14*60+44; // set here your DVD title playtime in sec
// Fill this information in so that it will be easy to identify later
String INST_NAME="<TITLE>";
String ARTIST="<ARTIST>";
String YEAR="<YEAR>";
int videotime = 1*60+1; // set here your DVD title playtime in seconds
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 3; // seconds from reset to playing from beginning
IRsend irsend;
int alarm_bell = false;
int heartbeat_state=0;
void showtime() {
Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl;
}
void showtime(int secs) { Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl; }
void trigger_sync() { alarm_bell = true; }
void setup() {
pinMode(pinGND,OUTPUT);
@@ -53,14 +55,17 @@ void setup() {
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
secs=playtime;
showtime();
sync();
Alarm.timerRepeat(playtime, sync);
Alarm.timerRepeat(playtime, trigger_sync);
}
/********************************************************************/
void loop() {
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
@@ -78,19 +83,10 @@ void heartbeat() {
void sync() {
Serial << "Sync" << endl;
send_pause();
waitsec(resetdelay);
//send_pause();
//waitsec(resetdelay);
send_previous();
/* for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
showtime();
}
*/
showtime(playtime);
}
/**************************************************************/
@@ -104,14 +100,14 @@ void waitsec(int sec) {
// NEC data format: first comes the pre-data bits, then the command code
void send_stop() {
Serial << " stop" << endl;
irsend.sendNEC(0xA25D28D7,32);
irsend.sendSony(0x18B47,20);
}
/********************************************************************/
void send_play() {
// Note that play and pause are a toggle for the same command
Serial << " play" << endl;
irsend.sendNEC(0xA25DA857, 32);
irsend.sendSony(0x58B47,20);
}
@@ -120,13 +116,13 @@ void send_pause() {
// On this model, pause and play are the same button so it toggles
// We use the "step" command which will always pause, no matter
// how many times we press it.
Serial << " step/pause" << endl;
irsend.sendNEC(0xA25D00FF,32);
Serial << " step/pause" << endl;
irsend.sendSony(0x98B47,20);
}
/********************************************************************/
void send_previous() {
// First comes the pre-data bits, then the command code
Serial.println(" previous");
irsend.sendNEC(0xA25DC43B, 32);
Serial << " previous" << endl;
irsend.sendSony(0xEAB47,20);
}

View File

@@ -62,11 +62,18 @@ The zip file/CD should contain this structure:
\texttt{libraries/} &required libraries and sample code for them\\
\texttt{prior-art/} &other existing synchronizer code that this system was inspired by\\
\texttt{tests/} &code for initial testing of the IR libraries\\
\texttt{util/} &useful utilities including a brute-force search routine for Philips remotes\\
\texttt{util/} &useful utilities including a general IR decoder\\
\end{tabular}
\section{Video preparation}
If you can get the artist to put at least 10 seconds of black at the end of the video, then you can use the full duration.
Otherwise, we will always cut off a few seconds of the video at the end to sure that all players stay synchronized.
See the {\tt choptime} and {\tt resetdelay} timing parameters in the code for how to adjust how much is cut.
In addition, the DVD or BD should have the entire content in one chapter and set to autoplay.
\section{How to operate}
To setup a freshly programmed synchronizer, the procedure is straightforward.
To setup a freshly programmed synchronizer, the procedure is straightforward.\\
\begin{enumerate}
\item Unpack the synchronizer and verify all of the parts are present.
\item {\em Make sure that the installation, play time, and player model on the label match the configuration you are setting up.}
@@ -79,14 +86,18 @@ To setup a freshly programmed synchronizer, the procedure is straightforward.
If the player fails to synchronize, consult Section~\ref{faq} for hints on how to diagnose.
\section{How to reconfigure}
If you need to change something, you will need to setup the Arduino IDE to change the program and upload it to the synchronizer.
\subsection{Arduino IDE and libraries}
You will first need to install the Arduino programming software from \url{http://arduino.cc}.
At the time of writing, the suggested version is 1.0.5.
If you are on a windows computer, it is very important to pick the right version (32bit vs. 64bit).
We do not include a copy of the Arduino software because it is constantly changing and improving.
Then install the IRRemote library from Ken Shirriff\cite{shirriff2009multiproto}.
Install the IRremote library from libraries. \footnote{The latest version can be acquired from \url{https://github.com/shirriff/Arduino-IRremote}} This usually consists of copying the \texttt{IRRemote} folder into \url{Documents/Arduino/libraries}. The newest 1.0+ series of Arduino software has an automated tool for this under ``Sketch'' then ``Import libraries''. More details on installing libraries at \cite{arduino:libraries}.
Install the all of the libraries in the {\tt libraries} folder. This usually consists of copying the \texttt{IRRemote} folder into \url{Documents/Arduino/libraries}.
The newest 1.0+ series of Arduino software has an automated tool for this under ``Sketch'' then ``Import libraries''.
More details on installing libraries at \cite{arduino:libraries}.
You may need to install other libraries; consult the top of the arduino code you are using for where to download the latest version.
Generally, the files in {\tt libraries} are sufficient.
\subsection{Setting up code}
Either copy the installation code\footnote{from \texttt{installations/}} or fresh synchronizer code\footnote{from \texttt{dvd/}} into a new \texttt{installations/} folder with the name and model number. For example, the installation ``dawn'' on a ``Toshiba SD590EKE'' would have the folder name \begin{verbatim}installations/dawn_toshiba_sd590eke/\end{verbatim}.
@@ -166,13 +177,20 @@ The simplest way to correct this is to reduce the playtime in the code by a few
\caption{Hardware setup for IR decoder on Arduino. \cite{shirriff2009multiproto}\label{fig:ir-schematic}}
\end{figure}
You will first need to construct the circuit shown in the left side of Figure~\ref{fig:ir-schematic}. You can get a 38Khz IR receiver from Íhlutir or Miðbær Radio.
You will first need to construct the circuit shown in the left side of
Figure~\ref{fig:ir-schematic}. You can get a 38Khz IR receiver from
Íhlutir or Miðbær Radio. {\em Note! This is different than an IR
phototransistor!} We like the TSOP38238 you can buy from Adafruit
at \url{www.adafruit.com/products/157}. If you use the modified
IRrecvDump.ino included, you can simply put the left pin (with
the bump facing you) into pin 10. Some synchronizers may include the
chip. If so, it will have two holes in the left side of the box.
\begin{enumerate}
\item Copy an existing synchronizer into a new folder in \texttt{dvd/} which indicates the model of the player.
\item Run the Arduino Program
\item Install the IRremote library from \texttt{libraries/}\footnote{The latest version can be acquired from \url{https://github.com/shirriff/Arduino-IRremote}}.
\item Run the IRRecvDump example program.
\item Go to \texttt{util} and run the \texttt{IRrecvDump.ino} program.
\item Open the ``Serial Monitor'' at 9600 baud.
\item Push the appropriate buttons on the remote: stop, pause, play, previous
\item Make note of the codes and encoding format

View File

@@ -1,13 +1,17 @@
/* DVD IR Synchronizer for Philips DVP3142/12
* Code written by Joe Foley <foley@ru.is>
* on 2013-09-08
*
const String DESCRIPTION="IR Synchronizer for Philips DVP3142/12";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2013-09-08
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
*
* IR Remote codes from IRrecvDemo
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Details on the Philips RC6 coding
* http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/
@@ -16,47 +20,74 @@
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*/
#include <IRremote.h>
int pinGND=4; // Longer leg on the IR LED
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
// IR LED pin 3 should be the longer leg
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int heartbeat=0;
int secs;
int playtime=1*60+1; // Play time in seconds, you usually leave off a second or two
// Fill this information in so that it will be easy to identify later
String INST_NAME="<TITLE>";
String ARTIST="<ARTIST>";
String YEAR="<YEAR>";
int videotime = 1*60+1; // set here your DVD title playtime in seconds
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 3; // seconds from reset to playing from beginning
IRsend irsend;
int alarm_bell = false;
int heartbeat_state=0;
void showtime(int secs) { Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl;}
void trigger_sync() { alarm_bell = true; }
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial.println("Panasonic DVD DVP-3142/12 Synchronizer $Rev$");
Serial.println("For \"$INSTALLATION NAME$\" by $ARTIST$ ($YEAR$)");
Serial.println("Code by Joe Foley <foley@ru.is>");
Serial.println("$URL$");
Serial.println("$Id$");
Serial.print("Playtime: ");
secs=playtime;
Serial.print("sec:");
Serial.print(secs);
Serial.print(" / mm:ss ");
Serial.print(secs/60);
Serial.print(":");
Serial.print(secs % 60);
Serial.println("");
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
sync();
showtime(playtime);
secs=playtime;
Alarm.timerRepeat(playtime, trigger_sync);
send_play();
}
/********************************************************************/
void loop() {
Serial.println("Sync");
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat_state = 1;
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
//send_pause();
//waitsec(2);
//waitsec(resetdelay);
// The three players don't always see the "previous command" so we send it multiple times
send_previous();
@@ -66,58 +97,34 @@ void loop() {
// Don't send play because previous automatically starts it
// If we hit play it will merely pause it.
//send_play();
for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
Serial.print("sec:");
Serial.print(playtime);
Serial.print(" / mm:ss ");
Serial.print(t/60);
Serial.print(":");
Serial.print(t % 60);
Serial.println("");
if (heartbeat == 1) {
digitalWrite(pinLED, HIGH);
heartbeat = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat = 1;
}
delay(1000);
}
}
/**************************************************************/
void waitsec(int sec) {
Serial.print("Wait ");
Serial.print(sec);
Serial.println(" seconds");
delay(sec*1000);
}
/**************************************************************/
void waitsec(int sec) {
Serial << "Wait " << sec << " seconds" << endl;
Alarm.delay(sec*1000);
}
/********************************************************************/
void send_stop() {
// First comes the pre-data bits, then the command code
Serial.println(" stop");
Serial << " stop" << endl;
irsend.sendRC6(0x10431,20);
}
/********************************************************************/
void send_play() {
// First comes the pre-data bits, then the command code
Serial.println(" play");
Serial << " play" << endl;
irsend.sendRC6(0x1042C,20);
}
/********************************************************************/
void send_pause() {
// First comes the pre-data bits, then the command code
Serial << " step/pause" << endl;
Serial.println(" pause");
irsend.sendRC6(0x1042C,20);
}

View File

@@ -1,60 +1,97 @@
/* DVD IR Synchronizer for Philips DVP3142/12
* Code written by Joe Foley <foley@ru.is>
* on 2013-09-08
*
const String DESCRIPTION="IR Synchronizer for Scott DVX605 HD(Rev2)";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2013-09-08
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
*
* IR Remote codes from IRrecvDemo
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Details on the Philips RC6 coding
* http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*/
#include <IRremote.h>
int pinGND=4; // Longer leg on the IR LED
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
// IR LED pin 3 should be the longer leg
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int heartbeat=0;
int secs;
int playtime= 1*60+1; // Play time in seconds, you usually leave off a second or two
// Fill this information in so that it will be easy to identify later
String INST_NAME="<TITLE>";
String ARTIST="<ARTIST>";
String YEAR="<YEAR>";
int videotime = 1*60+1; // set here your DVD title playtime in seconds
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 3; // seconds from reset to playing from beginning
IRsend irsend;
int alarm_bell = false;
int heartbeat_state=0;
void showtime(int secs) {
Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl;
}
void trigger_sync() { alarm_bell = true; }
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial.println("Scott DVX605 HD(Rev2) Synchronizer $Rev$");
Serial.println("For \"$INSTALLATION NAME$\" by $ARTIST$ ($YEAR$)");
Serial.println("Code by Joe Foley <foley@ru.is>");
Serial.println("$URL$");
Serial.println("$Id$");
Serial.print("Playtime: ");
secs=playtime;
Serial.print("sec:");
Serial.print(secs);
Serial.print(" / mm:ss ");
Serial.print(secs/60);
Serial.print(":");
Serial.print(secs % 60);
Serial.println("");
secs=playtime;
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
sync();
showtime(playtime);
Alarm.timerRepeat(playtime, trigger_sync);
send_play();
}
/********************************************************************/
void loop() {
Serial.println("Sync");
//send_pause();
//waitsec(2);
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat_state = 1;
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
//send_pause();
//waitsec(resetdelay);
// The three players don't always see the "previous command" so we send it multiple times
send_previous();
send_previous();
send_previous();
@@ -62,40 +99,15 @@ void loop() {
// Don't send play because previous automatically starts it
// If we hit play it will merely pause it.
//send_play();
for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
Serial.print("sec:");
Serial.print(playtime);
Serial.print(" / mm:ss ");
Serial.print(t/60);
Serial.print(":");
Serial.print(t % 60);
Serial.println("");
if (heartbeat == 1) {
digitalWrite(pinLED, HIGH);
heartbeat = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat = 1;
}
delay(1000);
}
}
/**************************************************************/
void waitsec(int sec) {
Serial.print("Wait ");
Serial.print(sec);
Serial.println(" seconds");
delay(sec*1000);
}
/**************************************************************/
void waitsec(int sec) {
Serial << "Wait " << sec << " seconds" << endl;
Alarm.delay(sec*1000);
}
/********************************************************************/
void send_stop() {

View File

@@ -1,102 +1,111 @@
/* DVD IR Synchronizer for Toshiba SD1091EKE
* Code written by Joe Foley <foley@ru.is>
* on 2013-09-08
const String DESCRIPTION="IR Synchronizer for Philips Toshiba SD1091EKE";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2013-09-08
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
*
* More codes at http://www.lirc.org/
* The compatible remote is SE-R0301
* We use the codes for the SE-R0031
* http://lirc.sourceforge.net/remotes/toshiba/SE-R0031
* Note that this has some similar codes
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Details on the Philips RC6 coding
* http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*
*
*/
#include <IRremote.h>
int pinGND=4; // Longer leg on the IR LED
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
// IR LED pin 3 should be the longer leg
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int secs;
int heartbeat=0;
int playtime= 1*60+1; // set here your DVD title playtime in sec leave a little extra
// Fill this information in so that it will be easy to identify later
String INST_NAME="<TITLE>";
String ARTIST="<ARTIST>";
String YEAR="<YEAR>";
int videotime = 1*60+1; // set here your DVD title playtime in seconds
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 3; // seconds from reset to playing from beginning
IRsend irsend;
int alarm_bell = false;
int heartbeat_state=0;
void showtime(int secs) { Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl; }
void trigger_sync() { alarm_bell = true; }
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
sync();
showtime(playtime);
Serial.println("Toshiba DVD SD1091EKE Synchronizer $Rev$");
Serial.println("For \"$INSTALLATION NAME$\" by $ARTIST$ ($YEAR$)");
Serial.println("Code by Joe Foley <foley@ru.is>");
Serial.println("$URL$");
Serial.println("$Id$");
Serial.print("Playtime: ");
secs=playtime;
Serial.print("sec:");
Serial.print(secs);
Serial.print(" / mm:ss ");
Serial.print(secs/60);
Serial.print(":");
Serial.print(secs % 60);
Serial.println("");
secs=playtime;
Alarm.timerRepeat(playtime, trigger_sync);
send_play();
}
/********************************************************************/
void loop() {
Serial.println("Sync");
// The DVD player starts playing automatically, so we should pause it
send_pause();
waitsec(2);
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
send_previous();
// on this model, previous immediately starts playing
for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
Serial.print("sec:");
Serial.print(playtime);
Serial.print(" / mm:ss ");
Serial.print(t/60);
Serial.print(":");
Serial.print(t % 60);
Serial.println("");
if (heartbeat == 1) {
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat = 0;
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat = 1;
heartbeat_state = 1;
}
delay(1000);
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
//send_pause();
//waitsec(resetdelay);
// The three players don't always see the "previous command" so we send it multiple times
send_previous();
send_previous();
send_previous();
//waitsec(2);
// Don't send play because previous automatically starts it
// If we hit play it will merely pause it.
//send_play();
}
/**************************************************************/
void waitsec(int sec) {
Serial.print("Wait ");
Serial.print(sec);
Serial.println(" seconds");
delay(sec*1000);
}
/**************************************************************/
void waitsec(int sec) {
Serial << "Wait " << sec << " seconds" << endl;
Alarm.delay(sec*1000);
}
/********************************************************************/
// NEC data format: first comes the pre-data bits, then the command code

View File

@@ -1,89 +1,99 @@
/* DVD IR Synchronizer for Toshiba SD590EKE
* Code written by Joe Foley <foley@ru.is>
* on 2013-09-08
const String DESCRIPTION="IR Synchronizer for Philips DVP3142/12";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2013-09-08
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
*
* IR Remote codes from SE-R0313
* http://lirc.sourceforge.net/remotes/toshiba/SE-R0313
* Instructions http://www.righto.com/2009/08/multi-protocol-infrared-remote-library.html
*
* Details on the Philips RC6 coding
* http://www.pcbheaven.com/userpages/The_Philips_RC6_Protocol/
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*/
#include <IRremote.h>
int pinGND=4; // Longer leg on the IR LED
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
// IR LED pin 3 should be the longer leg
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int heartbeat=0;
int secs;
int playtime= 1*60+1; // set here your DVD title playtime in sec leave a little extra
// Fill this information in so that it will be easy to identify later
String INST_NAME="<TITLE>";
String ARTIST="<ARTIST>";
String YEAR="<YEAR>";
int videotime = 1*60+1; // set here your DVD title playtime in seconds
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 2; // seconds from reset to playing from beginning
IRsend irsend;
int alarm_bell = false;
int heartbeat_state=0;
void showtime(int secs) { Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl; }
void trigger_sync() { alarm_bell = true; }
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial.println("Toshiba DVD SD590EKE Synchronizer $Rev$");
Serial.println("For \"$INSTALLATION NAME$\" by $ARTIST$ ($YEAR$)");
Serial.println("Code by Joe Foley <foley@ru.is>");
Serial.println("$URL$");
Serial.println("$Id$");
Serial.print("Playtime: ");
secs=playtime;
Serial.print("sec:");
Serial.print(secs);
Serial.print(" / mm:ss ");
Serial.print(secs/60);
Serial.print(":");
Serial.print(secs % 60);
Serial.println("");
// The DVD player starts playing automatically, so maybe we should pause it
//send_pause();
//waitsec(2);
secs=playtime;
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
sync();
showtime(playtime);
Alarm.timerRepeat(playtime, trigger_sync);
send_play();
}
/********************************************************************/
void loop() {
Serial.println("Sync");
send_pause();
waitsec(2);
send_previous();
//waitsec(2);
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
//send_play(); // this should not be necessary, but just in case
for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
Serial.print("sec:");
Serial.print(playtime);
Serial.print(" / mm:ss ");
Serial.print(t/60);
Serial.print(":");
Serial.print(t % 60);
Serial.println("");
if (heartbeat == 1) {
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat = 0;
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat = 1;
heartbeat_state = 1;
}
delay(1000);
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
send_pause();
waitsec(resetdelay);
send_previous();
//waitsec(2);
// Don't send play because previous automatically starts it
// If we hit play it will merely pause it.
//send_play();
}
/**************************************************************/

View File

@@ -66,10 +66,17 @@
%\lab{}{}{}{}
\newcommand{\syncdesigner}{Synchronizer\\by Joe Foley $<$foley@ru.is$>$ +354-661-7658}
\newcommand{\syncdecdesigner}{Synchronizer \& Decoder\\by Joe Foley $<$foley@ru.is$>$ +354-661-7658}
%\labnoru{Dawn (6:09)}{By Sigrún Harðar}{Toshiba SD590EKE \syncdesigner}{1986}
%\labnoru{Sarcity (20:58)}{By Þor Elís}{Philips DVP3142 \syncdesigner}{1981}
%\labnoru{West (25:42)}{By Steina Vasulka}{Toshiba SD1091EKE \syncdesigner}{1983}
\labnoru{Trajectories (14:44)}{By Sigurður Guðjónsson (video) \& Anna Thorvaldsdóttir (sound)}{Sony BDP-S790 \syncdesigner}{2014}
\labnoru{Trajectories (14:44)}{By Sigurður Guðjónsson (video) \& Anna Thorvaldsdóttir (sound)}{Sony BDP-S790 \syncdecdesigner}{2014}
\labnoru{\hspace*{50mm} (\quad{}:\quad{})}{\quad}{\quad\\\\\syncdesigner}{\quad}
\labnoru{\hspace*{50mm} (\quad{}:\quad{})}{\quad}{\quad\\\\\syncdesigner}{\quad}
\labnoru{\hspace*{50mm} (\quad{}:\quad{})}{\quad}{\quad\\\\\syncdesigner}{\quad}
\labnoru{\hspace*{50mm} (\quad{}:\quad{})}{\quad}{\quad\\\\\syncdesigner}{\quad}
\labnoru{\hspace*{50mm} (\quad{}:\quad{})}{\quad}{\quad\\\\\syncdecdesigner}{\quad}
%\input{label-input.tex}
\end{document}

View File

@@ -1,132 +1,140 @@
const String DESCRIPTION="IR Synchronizer for Sony Blu-ray player BDP-S790";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2014-01-14
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Streaming http://arduiniana.org/libraries/streaming/
* More codes at http://www.lirc.org/
* This uses remote Sony RMT-B122P
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*
*
*/
#include <IRremote.h>
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
int pinGND=4; // Longer leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int secs;
int heartbeat_state=0;
String INST_NAME="Trajectories";
String ARTIST="Sigurdur Gudjonsson (video) & Anna Thorvaldsdottir (sound)";
String YEAR="2014";
int videotime = 14*60+44; // set here your DVD title playtime in sec
int choptime = 3; // how much to chop at the end if the videos are
// not exactly the same length
int playtime = videotime - choptime;
int resetdelay = 3; // seconds from reset to playing from beginning
IRsend irsend;
void showtime() {
Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl;
}
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
secs=playtime;
showtime();
Alarm.timerRepeat(playtime, sync);
}
/********************************************************************/
void loop() {
heartbeat();
}
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat_state = 1;
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
send_pause();
waitsec(resetdelay);
send_previous();
/* for(int t = 0; t < playtime; t++) {
// This will not give us perfect 1 second timing
// but it is good enough for most video applications
// The most critical is having everything start at the
// same time.
showtime();
}
*/
}
/**************************************************************/
void waitsec(int sec) {
Serial << "Wait " << sec << " seconds" << endl;
Alarm.delay(sec*1000);
}
/********************************************************************/
// NEC data format: first comes the pre-data bits, then the command code
void send_stop() {
Serial << " stop" << endl;
irsend.sendNEC(0xA25D28D7,32);
}
/********************************************************************/
void send_play() {
// Note that play and pause are a toggle for the same command
Serial << " play" << endl;
irsend.sendNEC(0xA25DA857, 32);
}
/********************************************************************/
void send_pause() {
// On this model, pause and play are the same button so it toggles
// We use the "step" command which will always pause, no matter
// how many times we press it.
Serial << " step/pause" << endl;
irsend.sendNEC(0xA25D00FF,32);
}
/********************************************************************/
void send_previous() {
// First comes the pre-data bits, then the command code
Serial.println(" previous");
irsend.sendNEC(0xA25DC43B, 32);
}
const String DESCRIPTION="IR Synchronizer for Sony Blu-ray player BDP-S790";
const String AUTHOR="Joe Foley <foley@ru.is>";
const String SVN_REVISION="$Rev$";
const String SVN_URL="$URL$";
const String SVN_ID="$Id$";
/* Code written by Joe Foley <foley@ru.is> on 2014-01-14
*
* Requires libraries:
* Arduino-IRremote https://github.com/shirriff/Arduino-IRremote
* Streaming http://arduiniana.org/libraries/streaming/
* Time http://www.pjrc.com/teensy/td_libs_Time.html
* TimeAlarms http://www.pjrc.com/teensy/td_libs_TimeAlarms.html
* More codes at http://www.lirc.org/
* This uses remote Sony RMT-B122P
*
* The IRremote library uses Pin 3 for the Anode (longer pin)
* We have made a ground pin on Pin 4 for the Cathode (shorter pin)
*
*
*/
#include <IRremote.h>
#include <Streaming.h>
#include <Time.h>
#include <TimeAlarms.h>
// IR LED pin 3 should be longer
int pinGND=4; // Shorter leg on the IR LED
int pinLED=13; // The heartbeat LED on the board
int secs;
int heartbeat_state=0;
String INST_NAME="Trajectories";
String ARTIST="Sigurdur Gudjonsson (video) & Anna Thorvaldsdottir (sound)";
String YEAR="2014";
int videotime = 14*60+44; // set here your DVD title playtime in seconds
int choptime = 0; // how much to chop at the end
// choptime is also for tuning timing errors
// if the artists include 10 seconds of blackscreen at the end, then this can be set
// to 0
int resetdelay = 0; // seconds from reset to playing from beginning
int playtime = videotime - choptime + resetdelay;
IRsend irsend;
int alarm_bell = false;
void showtime(int secs) {
Serial << "sec:" << secs << " / mm:ss " << secs/60 << ":" << secs % 60 << endl;
}
void setup() {
pinMode(pinGND,OUTPUT);
pinMode(pinLED,OUTPUT);
Serial.begin(115200);
setTime(23,15,16,1,14,14); // set time to 23:15:16 Jan 14 2014
Serial << DESCRIPTION << " " << SVN_REVISION << endl;
Serial << "Code by " << AUTHOR << endl;
Serial << "For \""<< INST_NAME << "\" by "<< ARTIST <<"(" << YEAR << ")" << endl;
Serial << SVN_URL << endl << SVN_ID << endl;
Serial << "Playtime: " << playtime << endl;
sync();
showtime(playtime);
Alarm.timerRepeat(playtime, trigger_sync);
}
void trigger_sync() {
alarm_bell = true;
}
/********************************************************************/
void loop() {
if (alarm_bell == true) {
sync();
alarm_bell = false;
}
heartbeat();
}
void heartbeat() {
if (heartbeat_state == 1) {
digitalWrite(pinLED, HIGH);
heartbeat_state = 0;
}
else {
digitalWrite(pinLED, LOW);
heartbeat_state = 1;
}
Alarm.delay(1000);
}
void sync() {
Serial << "Sync" << endl;
//send_pause();
//waitsec(resetdelay);
for (int i=0; i<5; i++) {
send_previous();
delay(10); // need short pause between commands, 10ms is good
}
}
/**************************************************************/
void waitsec(int sec) {
Serial << "Wait " << sec << " seconds" << endl;
Alarm.delay(sec*1000);
}
/********************************************************************/
// NEC data format: first comes the pre-data bits, then the command code
void send_stop() {
Serial << " stop" << endl;
irsend.sendSony(0x18B47,20);
}
/********************************************************************/
void send_play() {
// Note that play and pause are a toggle for the same command
Serial << " play" << endl;
irsend.sendSony(0x58B47,20);
}
/********************************************************************/
void send_pause() {
// On this model, pause and play are the same button so it toggles
// We use the "step" command which will always pause, no matter
// how many times we press it.
Serial << " step/pause" << endl;
irsend.sendSony(0x98B47,20);
}
/********************************************************************/
void send_previous() {
// First comes the pre-data bits, then the command code
Serial.println(" previous");
irsend.sendSony(0xEAB47,20);
}

View File

@@ -0,0 +1,22 @@
#include <Streaming.h>
void setup()
{
Serial.begin(9600);
int lettera = 'A';
int month = 4, day = 17, year = 2009;
Serial << "This is an example of the new streaming" << endl;
Serial << "library. This allows you to print variables" << endl;
Serial << "and strings without having to type line after" << endl;
Serial << "line of Serial.print() calls. Examples: " << endl;
Serial << "A is " << lettera << "." << endl;
Serial << "The current date is " << day << "-" << month << "-" << year << "." << endl;
Serial << "You can use modifiers too, for example:" << endl;
Serial << _BYTE(lettera) << " is " << _HEX(lettera) << " in hex. " << endl;
}
void loop()
{}

View File

@@ -0,0 +1,105 @@
/*
Streaming.h - Arduino library for supporting the << streaming operator
Copyright (c) 2010-2012 Mikal Hart. All rights reserved.
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
*/
#ifndef ARDUINO_STREAMING
#define ARDUINO_STREAMING
#if defined(ARDUINO) && ARDUINO >= 100
#include "Arduino.h"
#else
#include "WProgram.h"
#endif
#define STREAMING_LIBRARY_VERSION 5
// Generic template
template<class T>
inline Print &operator <<(Print &stream, T arg)
{ stream.print(arg); return stream; }
struct _BASED
{
long val;
int base;
_BASED(long v, int b): val(v), base(b)
{}
};
#if ARDUINO >= 100
struct _BYTE_CODE
{
byte val;
_BYTE_CODE(byte v) : val(v)
{}
};
#define _BYTE(a) _BYTE_CODE(a)
inline Print &operator <<(Print &obj, const _BYTE_CODE &arg)
{ obj.write(arg.val); return obj; }
#else
#define _BYTE(a) _BASED(a, BYTE)
#endif
#define _HEX(a) _BASED(a, HEX)
#define _DEC(a) _BASED(a, DEC)
#define _OCT(a) _BASED(a, OCT)
#define _BIN(a) _BASED(a, BIN)
// Specialization for class _BASED
// Thanks to Arduino forum user Ben Combee who suggested this
// clever technique to allow for expressions like
// Serial << _HEX(a);
inline Print &operator <<(Print &obj, const _BASED &arg)
{ obj.print(arg.val, arg.base); return obj; }
#if ARDUINO >= 18
// Specialization for class _FLOAT
// Thanks to Michael Margolis for suggesting a way
// to accommodate Arduino 0018's floating point precision
// feature like this:
// Serial << _FLOAT(gps_latitude, 6); // 6 digits of precision
struct _FLOAT
{
float val;
int digits;
_FLOAT(double v, int d): val(v), digits(d)
{}
};
inline Print &operator <<(Print &obj, const _FLOAT &arg)
{ obj.print(arg.val, arg.digits); return obj; }
#endif
// Specialization for enum _EndLineCode
// Thanks to Arduino forum user Paul V. who suggested this
// clever technique to allow for expressions like
// Serial << "Hello!" << endl;
enum _EndLineCode { endl };
inline Print &operator <<(Print &obj, _EndLineCode arg)
{ obj.println(); return obj; }
#endif

View File

@@ -0,0 +1,25 @@
#######################################
# Syntax Coloring Map for Streaming
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
Streaming KEYWORD1
#######################################
# Methods and Functions (KEYWORD2)
#######################################
_HEX KEYWORD2
_DEC KEYWORD2
_OCT KEYWORD2
_BIN KEYWORD2
_BYTE KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
endl LITERAL1

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,90 @@
/* DateStrings.cpp
* Definitions for date strings for use with the Time library
*
* 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 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";
PGM_P monthNames_P[] PROGMEM =
{
"",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";
PGM_P dayNames_P[] PROGMEM = { dayStr0,dayStr1,dayStr2,dayStr3,dayStr4,dayStr5,dayStr6,dayStr7};
char dayShortNames_P[] PROGMEM = "ErrSunMonTueWedThrFriSat";
/* functions to return date strings */
char* monthStr(uint8_t month)
{
strcpy_P(buffer, (PGM_P)pgm_read_word(&(monthNames_P[month])));
return buffer;
}
char* monthShortStr(uint8_t month)
{
for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(monthShortNames_P[i+ (month*dt_SHORT_STR_LEN)]));
buffer[dt_SHORT_STR_LEN] = 0;
return buffer;
}
char* dayStr(uint8_t day)
{
strcpy_P(buffer, (PGM_P)pgm_read_word(&(dayNames_P[day])));
return buffer;
}
char* dayShortStr(uint8_t day)
{
uint8_t index = day*dt_SHORT_STR_LEN;
for (int i=0; i < dt_SHORT_STR_LEN; i++)
buffer[i] = pgm_read_byte(&(dayShortNames_P[index + i]));
buffer[dt_SHORT_STR_LEN] = 0;
return buffer;
}

View File

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

View File

@@ -0,0 +1,318 @@
/*
time.c - low level time and date functions
Copyright (c) Michael Margolis 2009
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
6 Jan 2010 - initial release
12 Feb 2010 - fixed leap year calculation error
1 Nov 2010 - fixed setTime bug (thanks to Korman for this)
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.
*/
#if ARDUINO >= 100
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include "Time.h"
static tmElements_t tm; // a cache of time elements
static time_t cacheTime; // the time the cache was updated
static uint32_t syncInterval = 300; // time sync will be attempted after this many seconds
void refreshCache(time_t t) {
if (t != cacheTime) {
breakTime(t, tm);
cacheTime = t;
}
}
int hour() { // the hour now
return hour(now());
}
int hour(time_t t) { // the hour for the given time
refreshCache(t);
return tm.Hour;
}
int hourFormat12() { // the hour now in 12 hour format
return hourFormat12(now());
}
int hourFormat12(time_t t) { // the hour for the given time in 12 hour format
refreshCache(t);
if( tm.Hour == 0 )
return 12; // 12 midnight
else if( tm.Hour > 12)
return tm.Hour - 12 ;
else
return tm.Hour ;
}
uint8_t isAM() { // returns true if time now is AM
return !isPM(now());
}
uint8_t isAM(time_t t) { // returns true if given time is AM
return !isPM(t);
}
uint8_t isPM() { // returns true if PM
return isPM(now());
}
uint8_t isPM(time_t t) { // returns true if PM
return (hour(t) >= 12);
}
int minute() {
return minute(now());
}
int minute(time_t t) { // the minute for the given time
refreshCache(t);
return tm.Minute;
}
int second() {
return second(now());
}
int second(time_t t) { // the second for the given time
refreshCache(t);
return tm.Second;
}
int day(){
return(day(now()));
}
int day(time_t t) { // the day for the given time (0-6)
refreshCache(t);
return tm.Day;
}
int weekday() { // Sunday is day 1
return weekday(now());
}
int weekday(time_t t) {
refreshCache(t);
return tm.Wday;
}
int month(){
return month(now());
}
int month(time_t t) { // the month for the given time
refreshCache(t);
return tm.Month;
}
int year() { // as in Processing, the full four digit year: (2009, 2010 etc)
return year(now());
}
int year(time_t t) { // the year for the given time
refreshCache(t);
return tmYearToCalendar(tm.Year);
}
/*============================================================================*/
/* functions to convert to and from system time */
/* These are for interfacing with time serivces and are not normally needed in a sketch */
// leap year calulator expects year argument as years offset from 1970
#define LEAP_YEAR(Y) ( ((1970+Y)>0) && !((1970+Y)%4) && ( ((1970+Y)%100) || !((1970+Y)%400) ) )
static const uint8_t monthDays[]={31,28,31,30,31,30,31,31,30,31,30,31}; // API starts months from 1, this array starts from 0
void breakTime(time_t timeInput, tmElements_t &tm){
// break the given time_t into time components
// this is a more compact version of the C library localtime function
// note that year is offset from 1970 !!!
uint8_t year;
uint8_t month, monthLength;
uint32_t time;
unsigned long days;
time = (uint32_t)timeInput;
tm.Second = time % 60;
time /= 60; // now it is minutes
tm.Minute = time % 60;
time /= 60; // now it is hours
tm.Hour = time % 24;
time /= 24; // now it is days
tm.Wday = ((time + 4) % 7) + 1; // Sunday is day 1
year = 0;
days = 0;
while((unsigned)(days += (LEAP_YEAR(year) ? 366 : 365)) <= time) {
year++;
}
tm.Year = year; // year is offset from 1970
days -= LEAP_YEAR(year) ? 366 : 365;
time -= days; // now it is days in this year, starting at 0
days=0;
month=0;
monthLength=0;
for (month=0; month<12; month++) {
if (month==1) { // february
if (LEAP_YEAR(year)) {
monthLength=29;
} else {
monthLength=28;
}
} else {
monthLength = monthDays[month];
}
if (time >= monthLength) {
time -= monthLength;
} else {
break;
}
}
tm.Month = month + 1; // jan is month 1
tm.Day = time + 1; // day of month
}
time_t makeTime(tmElements_t &tm){
// assemble time elements into time_t
// note year argument is offset from 1970 (see macros in time.h to convert to other formats)
// previous version used full four digit year (or digits since 2000),i.e. 2009 was 2009 or 9
int i;
uint32_t seconds;
// seconds from 1970 till 1 jan 00:00:00 of the given year
seconds= tm.Year*(SECS_PER_DAY * 365);
for (i = 0; i < tm.Year; i++) {
if (LEAP_YEAR(i)) {
seconds += SECS_PER_DAY; // add extra days for leap years
}
}
// add days for this year, months start from 1
for (i = 1; i < tm.Month; i++) {
if ( (i == 2) && LEAP_YEAR(tm.Year)) {
seconds += SECS_PER_DAY * 29;
} else {
seconds += SECS_PER_DAY * monthDays[i-1]; //monthDay array starts from 0
}
}
seconds+= (tm.Day-1) * SECS_PER_DAY;
seconds+= tm.Hour * SECS_PER_HOUR;
seconds+= tm.Minute * SECS_PER_MIN;
seconds+= tm.Second;
return (time_t)seconds;
}
/*=====================================================*/
/* Low level system time functions */
static uint32_t sysTime = 0;
static uint32_t prevMillis = 0;
static uint32_t nextSyncTime = 0;
static timeStatus_t Status = timeNotSet;
getExternalTime getTimePtr; // pointer to external sync function
//setExternalTime setTimePtr; // not used in this version
#ifdef TIME_DRIFT_INFO // define this to get drift data
time_t sysUnsyncedTime = 0; // the time sysTime unadjusted by sync
#endif
time_t now() {
while (millis() - prevMillis >= 1000){
sysTime++;
prevMillis += 1000;
#ifdef TIME_DRIFT_INFO
sysUnsyncedTime++; // this can be compared to the synced time to measure long term drift
#endif
}
if (nextSyncTime <= sysTime) {
if (getTimePtr != 0) {
time_t t = getTimePtr();
if (t != 0) {
setTime(t);
} else {
nextSyncTime = sysTime + syncInterval;
Status = (Status == timeNotSet) ? timeNotSet : timeNeedsSync;
}
}
}
return (time_t)sysTime;
}
void setTime(time_t t) {
#ifdef TIME_DRIFT_INFO
if(sysUnsyncedTime == 0)
sysUnsyncedTime = t; // store the time of the first call to set a valid Time
#endif
sysTime = (uint32_t)t;
nextSyncTime = (uint32_t)t + syncInterval;
Status = timeSet;
prevMillis = millis(); // restart counting from now (thanks to Korman for this fix)
}
void setTime(int hr,int min,int sec,int dy, int mnth, int yr){
// year can be given as full four digit year or two digts (2010 or 10 for 2010);
//it is converted to years since 1970
if( yr > 99)
yr = yr - 1970;
else
yr += 30;
tm.Year = yr;
tm.Month = mnth;
tm.Day = dy;
tm.Hour = hr;
tm.Minute = min;
tm.Second = sec;
setTime(makeTime(tm));
}
void adjustTime(long adjustment) {
sysTime += adjustment;
}
// indicates if time has been set and recently synchronized
timeStatus_t timeStatus() {
now(); // required to actually update the status
return Status;
}
void setSyncProvider( getExternalTime getTimeFunction){
getTimePtr = getTimeFunction;
nextSyncTime = sysTime;
now(); // this will sync the clock
}
void setSyncInterval(time_t interval){ // set the number of seconds between re-sync
syncInterval = (uint32_t)interval;
nextSyncTime = sysTime + syncInterval;
}

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,69 @@
/*
* 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__);
}
setSyncProvider(getArduinoDueTime);
if(timeStatus()!= timeSet)
Serial.println("Unable to sync with the RTC");
else
Serial.println("RTC has set the system time");
}
time_t getArduinoDueTime()
{
return rtc_clock.unixtime();
}
void loop()
{
digitalClockDisplay();
delay(1000);
}
void digitalClockDisplay(){
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.print(" ");
Serial.print(day());
Serial.print(" ");
Serial.print(month());
Serial.print(" ");
Serial.print(year());
Serial.println();
}
void printDigits(int digits){
// utility function for digital clock display: prints preceding colon and leading 0
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,110 @@
/*
* 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 > /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()) {
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("Setting long format");
}
else if( c == FORMAT_SHORT){
isLongFormat = false;
Serial.println("Setting short format");
}
}
void processSyncMessage() {
unsigned long pctime;
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013 - paul, perhaps we define in time.h?
pctime = Serial.parseInt();
if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
setTime(pctime); // Sync Arduino clock to the time received on the serial port
}
}
time_t requestSync()
{
Serial.write(TIME_REQUEST);
return 0; // the time will be sent later in response to serial mesg
}

View File

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

View File

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

Binary file not shown.

View File

@@ -0,0 +1,357 @@
/*
TimeAlarms.cpp - Arduino Time alarms for use with Time library
Copyright (c) 208-2011 Michael Margolis.
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.
*/
/*
2 July 2011 - replaced alarm types implied from alarm value with enums to make trigger logic more robust
- this fixes bug in repeating weekly alarms - thanks to Vincent Valdy and draythomp for testing
*/
extern "C" {
#include <string.h> // for memset
}
#if ARDUINO > 22
#include <Arduino.h>
#else
#include <WProgram.h>
#endif
#include "TimeAlarms.h"
#include "Time.h"
#define IS_ONESHOT true // constants used in arguments to create method
#define IS_REPEAT false
//**************************************************************
//* Alarm Class Constructor
AlarmClass::AlarmClass()
{
Mode.isEnabled = Mode.isOneShot = 0;
Mode.alarmType = dtNotAllocated;
value = nextTrigger = 0;
onTickHandler = NULL; // prevent a callback until this pointer is explicitly set
}
//**************************************************************
//* Private Methods
void AlarmClass::updateNextTrigger()
{
if( (value != 0) && Mode.isEnabled )
{
time_t time = now();
if( dtIsAlarm(Mode.alarmType) && nextTrigger <= time ) // update alarm if next trigger is not yet in the future
{
if(Mode.alarmType == dtExplicitAlarm ) // is the value a specific date and time in the future
{
nextTrigger = value; // yes, trigger on this value
}
else if(Mode.alarmType == dtDailyAlarm) //if this is a daily alarm
{
if( value + previousMidnight(now()) <= time)
{
nextTrigger = value + nextMidnight(time); // if time has passed then set for tomorrow
}
else
{
nextTrigger = value + previousMidnight(time); // set the date to today and add the time given in value
}
}
else if(Mode.alarmType == dtWeeklyAlarm) // if this is a weekly alarm
{
if( (value + previousSunday(now())) <= time)
{
nextTrigger = value + nextSunday(time); // if day has passed then set for the next week.
}
else
{
nextTrigger = value + previousSunday(time); // set the date to this week today and add the time given in value
}
}
else // its not a recognized alarm type - this should not happen
{
Mode.isEnabled = 0; // Disable the alarm
}
}
if( Mode.alarmType == dtTimer)
{
// its a timer
nextTrigger = time + value; // add the value to previous time (this ensures delay always at least Value seconds)
}
}
else
{
Mode.isEnabled = 0; // Disable if the value is 0
}
}
//**************************************************************
//* Time Alarms Public Methods
TimeAlarmsClass::TimeAlarmsClass()
{
isServicing = false;
for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
free(id); // ensure all Alarms are cleared and available for allocation
}
// this method creates a trigger at the given absolute time_t
// it replaces the call to alarmOnce with values greater than a week
AlarmID_t TimeAlarmsClass::triggerOnce(time_t value, OnTick_t onTickHandler){ // trigger once at the given time_t
if( value > 0)
return create( value, onTickHandler, IS_ONESHOT, dtExplicitAlarm );
else
return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day
}
// this method will now return an error if the value is greater than one day - use DOW methods for weekly alarms
AlarmID_t TimeAlarmsClass::alarmOnce(time_t value, OnTick_t onTickHandler){ // trigger once at the given time of day
if( value <= SECS_PER_DAY)
return create( value, onTickHandler, IS_ONESHOT, dtDailyAlarm );
else
return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day
}
AlarmID_t TimeAlarmsClass::alarmOnce(const int H, const int M, const int S,OnTick_t onTickHandler){ // as above with HMS arguments
return create( AlarmHMS(H,M,S), onTickHandler, IS_ONESHOT, dtDailyAlarm );
}
AlarmID_t TimeAlarmsClass::alarmOnce(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler){ // as above, with day of week
return create( (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S), onTickHandler, IS_ONESHOT, dtWeeklyAlarm );
}
// this method will now return an error if the value is greater than one day - use DOW methods for weekly alarms
AlarmID_t TimeAlarmsClass::alarmRepeat(time_t value, OnTick_t onTickHandler){ // trigger daily at the given time
if( value <= SECS_PER_DAY)
return create( value, onTickHandler, IS_REPEAT, dtDailyAlarm );
else
return dtINVALID_ALARM_ID; // dont't allocate if the time is greater than one day
}
AlarmID_t TimeAlarmsClass::alarmRepeat(const int H, const int M, const int S, OnTick_t onTickHandler){ // as above with HMS arguments
return create( AlarmHMS(H,M,S), onTickHandler, IS_REPEAT, dtDailyAlarm );
}
AlarmID_t TimeAlarmsClass::alarmRepeat(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler){ // as above, with day of week
return create( (DOW-1) * SECS_PER_DAY + AlarmHMS(H,M,S), onTickHandler, IS_REPEAT, dtWeeklyAlarm );
}
AlarmID_t TimeAlarmsClass::timerOnce(time_t value, OnTick_t onTickHandler){ // trigger once after the given number of seconds
return create( value, onTickHandler, IS_ONESHOT, dtTimer );
}
AlarmID_t TimeAlarmsClass::timerOnce(const int H, const int M, const int S, OnTick_t onTickHandler){ // As above with HMS arguments
return create( AlarmHMS(H,M,S), onTickHandler, IS_ONESHOT, dtTimer );
}
AlarmID_t TimeAlarmsClass::timerRepeat(time_t value, OnTick_t onTickHandler){ // trigger after the given number of seconds continuously
return create( value, onTickHandler, IS_REPEAT, dtTimer);
}
AlarmID_t TimeAlarmsClass::timerRepeat(const int H, const int M, const int S, OnTick_t onTickHandler){ // trigger after the given number of seconds continuously
return create( AlarmHMS(H,M,S), onTickHandler, IS_REPEAT, dtTimer);
}
void TimeAlarmsClass::enable(AlarmID_t ID)
{
if(isAllocated(ID)) {
Alarm[ID].Mode.isEnabled = (Alarm[ID].value != 0) && (Alarm[ID].onTickHandler != 0) ; // only enable if value is non zero and a tick handler has been set
Alarm[ID].updateNextTrigger(); // trigger is updated whenever this is called, even if already enabled
}
}
void TimeAlarmsClass::disable(AlarmID_t ID)
{
if(isAllocated(ID))
Alarm[ID].Mode.isEnabled = false;
}
// write the given value to the given alarm
void TimeAlarmsClass::write(AlarmID_t ID, time_t value)
{
if(isAllocated(ID))
{
Alarm[ID].value = value;
enable(ID); // update trigger time
}
}
// return the value for the given alarm ID
time_t TimeAlarmsClass::read(AlarmID_t ID)
{
if(isAllocated(ID))
return Alarm[ID].value ;
else
return dtINVALID_TIME;
}
// return the alarm type for the given alarm ID
dtAlarmPeriod_t TimeAlarmsClass::readType(AlarmID_t ID)
{
if(isAllocated(ID))
return (dtAlarmPeriod_t)Alarm[ID].Mode.alarmType ;
else
return dtNotAllocated;
}
void TimeAlarmsClass::free(AlarmID_t ID)
{
if(isAllocated(ID))
{
Alarm[ID].Mode.isEnabled = false;
Alarm[ID].Mode.alarmType = dtNotAllocated;
Alarm[ID].onTickHandler = 0;
Alarm[ID].value = 0;
Alarm[ID].nextTrigger = 0;
}
}
// returns the number of allocated timers
uint8_t TimeAlarmsClass::count()
{
uint8_t c = 0;
for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
{
if(isAllocated(id))
c++;
}
return c;
}
// returns true only if id is allocated and the type is a time based alarm, returns false if not allocated or if its a timer
bool TimeAlarmsClass::isAlarm(AlarmID_t ID)
{
return( isAllocated(ID) && dtIsAlarm(Alarm[ID].Mode.alarmType) );
}
// returns true if this id is allocated
bool TimeAlarmsClass::isAllocated(AlarmID_t ID)
{
return( ID < dtNBR_ALARMS && Alarm[ID].Mode.alarmType != dtNotAllocated );
}
AlarmID_t TimeAlarmsClass::getTriggeredAlarmId() //returns the currently triggered alarm id
// returns dtINVALID_ALARM_ID if not invoked from within an alarm handler
{
if(isServicing)
return servicedAlarmId; // new private data member used instead of local loop variable i in serviceAlarms();
else
return dtINVALID_ALARM_ID; // valid ids only available when servicing a callback
}
// following functions are not Alarm ID specific.
void TimeAlarmsClass::delay(unsigned long ms)
{
unsigned long start = millis();
while( millis() - start <= ms)
serviceAlarms();
}
void TimeAlarmsClass::waitForDigits( uint8_t Digits, dtUnits_t Units)
{
while(Digits != getDigitsNow(Units) )
{
serviceAlarms();
}
}
void TimeAlarmsClass::waitForRollover( dtUnits_t Units)
{
while(getDigitsNow(Units) == 0 ) // if its just rolled over than wait for another rollover
serviceAlarms();
waitForDigits(0, Units);
}
uint8_t TimeAlarmsClass::getDigitsNow( dtUnits_t Units)
{
time_t time = now();
if(Units == dtSecond) return numberOfSeconds(time);
if(Units == dtMinute) return numberOfMinutes(time);
if(Units == dtHour) return numberOfHours(time);
if(Units == dtDay) return dayOfWeek(time);
return 255; // This should never happen
}
//***********************************************************
//* Private Methods
void TimeAlarmsClass::serviceAlarms()
{
if(! isServicing)
{
isServicing = true;
for( servicedAlarmId = 0; servicedAlarmId < dtNBR_ALARMS; servicedAlarmId++)
{
if( Alarm[servicedAlarmId].Mode.isEnabled && (now() >= Alarm[servicedAlarmId].nextTrigger) )
{
OnTick_t TickHandler = Alarm[servicedAlarmId].onTickHandler;
if(Alarm[servicedAlarmId].Mode.isOneShot)
free(servicedAlarmId); // free the ID if mode is OnShot
else
Alarm[servicedAlarmId].updateNextTrigger();
if( TickHandler != NULL) {
(*TickHandler)(); // call the handler
}
}
}
isServicing = false;
}
}
// returns the absolute time of the next scheduled alarm, or 0 if none
time_t TimeAlarmsClass::getNextTrigger()
{
time_t nextTrigger = 0xffffffff; // the max time value
for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
{
if(isAllocated(id) )
{
if(Alarm[id].nextTrigger < nextTrigger)
nextTrigger = Alarm[id].nextTrigger;
}
}
return nextTrigger == 0xffffffff ? 0 : nextTrigger;
}
// attempt to create an alarm and return true if successful
AlarmID_t TimeAlarmsClass::create( time_t value, OnTick_t onTickHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType, uint8_t isEnabled)
{
if( ! (dtIsAlarm(alarmType) && now() < SECS_PER_YEAR)) // only create alarm ids if the time is at least Jan 1 1971
{
for(uint8_t id = 0; id < dtNBR_ALARMS; id++)
{
if( Alarm[id].Mode.alarmType == dtNotAllocated )
{
// here if there is an Alarm id that is not allocated
Alarm[id].onTickHandler = onTickHandler;
Alarm[id].Mode.isOneShot = isOneShot;
Alarm[id].Mode.alarmType = alarmType;
Alarm[id].value = value;
isEnabled ? enable(id) : disable(id);
return id; // alarm created ok
}
}
}
return dtINVALID_ALARM_ID; // no IDs available or time is invalid
}
// make one instance for the user to use
TimeAlarmsClass Alarm = TimeAlarmsClass() ;

View File

@@ -0,0 +1,127 @@
// TimeAlarms.h - Arduino Time alarms header for use with Time library
#ifndef TimeAlarms_h
#define TimeAlarms_h
#include <inttypes.h>
#include "Time.h"
#define dtNBR_ALARMS 6 // max is 255
#define USE_SPECIALIST_METHODS // define this for testing
typedef enum { dtMillisecond, dtSecond, dtMinute, dtHour, dtDay } dtUnits_t;
typedef struct {
uint8_t alarmType :4 ; // enumeration of daily/weekly (in future: biweekly/semimonthly/monthly/annual)
// note that the current API only supports daily or weekly alarm periods
uint8_t isEnabled :1 ; // the timer is only actioned if isEnabled is true
uint8_t isOneShot :1 ; // the timer will be de-allocated after trigger is processed
}
AlarmMode_t ;
// new time based alarms should be added just before dtLastAlarmType
typedef enum {dtNotAllocated, dtTimer, dtExplicitAlarm, dtDailyAlarm, dtWeeklyAlarm, dtLastAlarmType } dtAlarmPeriod_t ; // in future: dtBiweekly, dtMonthly, dtAnnual
// macro to return true if the given type is a time based alarm, false if timer or not allocated
#define dtIsAlarm(_type_) (_type_ >= dtExplicitAlarm && _type_ < dtLastAlarmType)
typedef uint8_t AlarmID_t;
typedef AlarmID_t AlarmId; // Arduino friendly name
#define dtINVALID_ALARM_ID 255
#define dtINVALID_TIME 0L
class AlarmClass; // forward reference
typedef void (*OnTick_t)(); // alarm callback function typedef
// class defining an alarm instance, only used by dtAlarmsClass
class AlarmClass
{
private:
public:
AlarmClass();
OnTick_t onTickHandler;
void updateNextTrigger();
time_t value;
time_t nextTrigger;
AlarmMode_t Mode;
};
// class containing the collection of alarms
class TimeAlarmsClass
{
private:
AlarmClass Alarm[dtNBR_ALARMS];
void serviceAlarms();
uint8_t isServicing;
uint8_t servicedAlarmId; // the alarm currently being serviced
AlarmID_t create( time_t value, OnTick_t onTickHandler, uint8_t isOneShot, dtAlarmPeriod_t alarmType, uint8_t isEnabled=true);
public:
TimeAlarmsClass();
// functions to create alarms and timers
AlarmID_t triggerOnce(time_t value, OnTick_t onTickHandler); // trigger once at the given time_t
AlarmID_t alarmRepeat(time_t value, OnTick_t onTickHandler); // trigger daily at given time of day
AlarmID_t alarmRepeat(const int H, const int M, const int S, OnTick_t onTickHandler); // as above, with hms arguments
AlarmID_t alarmRepeat(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler); // as above, with day of week
AlarmID_t alarmOnce(time_t value, OnTick_t onTickHandler); // trigger once at given time of day
AlarmID_t alarmOnce( const int H, const int M, const int S, OnTick_t onTickHandler); // as above, with hms arguments
AlarmID_t alarmOnce(const timeDayOfWeek_t DOW, const int H, const int M, const int S, OnTick_t onTickHandler); // as above, with day of week
AlarmID_t timerOnce(time_t value, OnTick_t onTickHandler); // trigger once after the given number of seconds
AlarmID_t timerOnce(const int H, const int M, const int S, OnTick_t onTickHandler); // As above with HMS arguments
AlarmID_t timerRepeat(time_t value, OnTick_t onTickHandler); // trigger after the given number of seconds continuously
AlarmID_t timerRepeat(const int H, const int M, const int S, OnTick_t onTickHandler); // As above with HMS arguments
void delay(unsigned long ms);
// utility methods
uint8_t getDigitsNow( dtUnits_t Units); // returns the current digit value for the given time unit
void waitForDigits( uint8_t Digits, dtUnits_t Units);
void waitForRollover(dtUnits_t Units);
// low level methods
void enable(AlarmID_t ID); // enable the alarm to trigger
void disable(AlarmID_t ID); // prevent the alarm from triggering
AlarmID_t getTriggeredAlarmId(); // returns the currently triggered alarm id
void write(AlarmID_t ID, time_t value); // write the value (and enable) the alarm with the given ID
time_t read(AlarmID_t ID); // return the value for the given timer
dtAlarmPeriod_t readType(AlarmID_t ID); // return the alarm type for the given alarm ID
#ifndef USE_SPECIALIST_METHODS
private: // the following methods are for testing and are not documented as part of the standard library
#endif
void free(AlarmID_t ID); // free the id to allow its reuse
uint8_t count(); // returns the number of allocated timers
time_t getNextTrigger(); // returns the time of the next scheduled alarm
bool isAllocated(AlarmID_t ID); // returns true if this id is allocated
bool isAlarm(AlarmID_t ID); // returns true if id is for a time based alarm, false if its a timer or not allocated
};
extern TimeAlarmsClass Alarm; // make an instance for the user
/*==============================================================================
* MACROS
*============================================================================*/
/* public */
#define waitUntilThisSecond(_val_) waitForDigits( _val_, dtSecond)
#define waitUntilThisMinute(_val_) waitForDigits( _val_, dtMinute)
#define waitUntilThisHour(_val_) waitForDigits( _val_, dtHour)
#define waitUntilThisDay(_val_) waitForDigits( _val_, dtDay)
#define waitMinuteRollover() waitForRollover(dtSecond)
#define waitHourRollover() waitForRollover(dtMinute)
#define waitDayRollover() waitForRollover(dtHour)
#define AlarmHMS(_hr_, _min_, _sec_) (_hr_ * SECS_PER_HOUR + _min_ * SECS_PER_MIN + _sec_)
#endif /* TimeAlarms_h */

View File

@@ -0,0 +1,77 @@
/*
* TimeAlarmExample.pde
*
* This example calls alarm functions at 8:30 am and at 5:45 pm (17:45)
* and simulates turning lights on at night and off in the morning
* A weekly timer is set for Saturdays at 8:30:30
*
* A timer is called every 15 seconds
* Another timer is called once only after 10 seconds
*
* At startup the time is set to Jan 1 2011 8:29 am
*/
#include <Time.h>
#include <TimeAlarms.h>
void setup()
{
Serial.begin(9600);
setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
// create the alarms
Alarm.alarmRepeat(8,30,0, MorningAlarm); // 8:30am every day
Alarm.alarmRepeat(17,45,0,EveningAlarm); // 5:45pm every day
Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm); // 8:30:30 every Saturday
Alarm.timerRepeat(15, Repeats); // timer for every 15 seconds
Alarm.timerOnce(10, OnceOnly); // called once after 10 seconds
}
void loop(){
digitalClockDisplay();
Alarm.delay(1000); // wait one second between clock display
}
// functions to be called when an alarm triggers:
void MorningAlarm(){
Serial.println("Alarm: - turn lights off");
}
void EveningAlarm(){
Serial.println("Alarm: - turn lights on");
}
void WeeklyAlarm(){
Serial.println("Alarm: - its Monday Morning");
}
void ExplicitAlarm(){
Serial.println("Alarm: - this triggers only at the given date and time");
}
void Repeats(){
Serial.println("15 second timer");
}
void OnceOnly(){
Serial.println("This timer only triggers once");
}
void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}
void printDigits(int digits)
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}

View File

@@ -0,0 +1,25 @@
#######################################
# Syntax Coloring Map For TimeAlarms
#######################################
#######################################
# Datatypes (KEYWORD1)
#######################################
#######################################
# Methods and Functions (KEYWORD2)
#######################################
alarmRepeat KEYWORD2
alarmOnce KEYWORD2
timerRepeat KEYWORD2
timerOnce KEYWORD2
delay KEYWORD2
#######################################
# Instances (KEYWORD2)
#######################################
Alarm KEYWORD2
#######################################
# Constants (LITERAL1)
#######################################
dtINVALID_ALARM_ID LITERAL1
dtINVALID_TIME LITERAL1

View File

@@ -0,0 +1,220 @@
Alarms
The Alarm library is a companion to the Time library that makes it easy to
perform tasks at specific times or after specific intervals.
Tasks scheduled at a particular time of day are called Alarms,
tasks scheduled after an interval of time has elapsed are called Timers.
These tasks can be created to continuously repeat or to occur once only.
Here is how you create an alarm to trigger a task repeatedly at a particular time of day:
Alarm.alarmRepeat(8,30,0, MorningAlarm);
This would call the function MorningAlarm() at 8:30 am every day.
If you want the alarm to trigger only once you can use the alarmOnce method:
Alarm.alarmOnce(8,30,0, MorningAlarm);
This calls a MorningAlarm() function in a sketch once only (when the time is next 8:30am)
Alarms can be specified to trigger a task repeatedly at a particular day of week and time of day:
Alarm.alarmRepeat(dowMonday, 9,15,0, MondayMorningAlarm);
This would call the function WeeklyAlarm() at 9:15am every Monday.
If you want the alarm to trigger once only on a particular day and time you can do this:
Alarm.alarmOnce(dowMonday, 9,15,0, MondayMorningAlarm);
This would call the function MondayMorning() Alarm on the next Monday at 9:15am.
Timers trigger tasks that occur after a specified interval of time has passed.
The timer interval can be specified in seconds, or in hour, minutes and seconds.
Alarm.timerRepeat(15, Repeats); // timer task every 15 seconds
This calls the Repeats() function in your sketch every 15 seconds.
If you want a timer to trigger once only, you can use the timerOnce method:
Alarm.timerOnce(10, OnceOnly); // called once after 10 seconds
This calls the onceOnly() function in a sketch 10 seconds after the timer is created.
If you want to trigger once at a specified date and time you can use the trigger Once() method:
Alarm. triggerOnce(time_t value, explicitAlarm); // value specifies a date and time
(See the makeTime() method in the Time library to convert dates and times into time_t)
Your sketch should call the Alarm.delay() function instead of the Arduino delay() function when
using the Alarms library. The timeliness of triggers depends on sketch delays using this function.
Alarm.delay( period); // Similar to Arduino delay - pauses the program for the period (in milliseconds).
Here is an example sketch:
This sketch triggers daily alarms at 8:30 am and 17:45 pm.
A Timer is triggered every 15 seconds, another timer triggers once only after 10 seconds.
A weekly alarm is triggered every Sunday at 8:30:30
#include <Time.h>
#include <TimeAlarms.h>
void setup()
{
Serial.begin(9600);
setTime(8,29,0,1,1,11); // set time to Saturday 8:29:00am Jan 1 2011
// create the alarms
Alarm.alarmRepeat(8,30,0, MorningAlarm); // 8:30am every day
Alarm.alarmRepeat(17,45,0,EveningAlarm); // 5:45pm every day
Alarm.alarmRepeat(dowSaturday,8,30,30,WeeklyAlarm); // 8:30:30 every Saturday
Alarm.timerRepeat(15, Repeats); // timer for every 15 seconds
Alarm.timerOnce(10, OnceOnly); // called once after 10 seconds
}
void loop(){
digitalClockDisplay();
Alarm.delay(1000); // wait one second between clock display
}
// functions to be called when an alarm triggers:
void MorningAlarm(){
Serial.println("Alarm: - turn lights off");
}
void EveningAlarm(){
Serial.println("Alarm: - turn lights on");
}
void WeeklyAlarm(){
Serial.println("Alarm: - its Monday Morning");
}
void ExplicitAlarm(){
Serial.println("Alarm: - this triggers only at the given date and time");
}
void Repeats(){
Serial.println("15 second timer");
}
void OnceOnly(){
Serial.println("This timer only triggers once");
}
void digitalClockDisplay()
{
// digital clock display of the time
Serial.print(hour());
printDigits(minute());
printDigits(second());
Serial.println();
}
void printDigits(int digits)
{
Serial.print(":");
if(digits < 10)
Serial.print('0');
Serial.print(digits);
}
Note that the loop code calls Alarm.delay(1000) - Alarm.delay must be used
instead of the usual arduino delay function because the alarms are serviced in the Alarm.delay method.
Failing to regularly call Alarm.delay will result in the alarms not being triggered
so always use Alarm.delay instead of delay in sketches that use the Alarms library.
Functional reference:
// functions to create alarms and timers
Alarm.triggerOnce(value, AlarmFunction);
Description: Call user provided AlarmFunction once at the date and time of the given value
See the Ttime library for more on time_t values
Alarm.alarmRepeat(Hour, Minute, Second, AlarmFunction);
Description: Calls user provided AlarmFunction every day at the given Hour, Minute and Second.
Alarm.alarmRepeat(value, AlarmFunction);
Description: Calls user provided AlarmFunction every day at the time indicated by the given value
Alarm.alarmRepeat(DayOfWeek, Hour, Minute, Second, AlarmFunction);
Description: Calls user provided AlarmFunction every week on the given DayOfWeek, Hour, Minute and Second.
Alarm.alarmOnce(Hour, Minute, Second, AlarmFunction);
Description: Calls user provided AlarmFunction once when the Arduino time next reaches the given Hour, Minute and Second.
Alarm.alarmOnce(value, AlarmFunction);
Description: Calls user provided AlarmFunction once at the next time indicated by the given value
Alarm.alarmOnce(DayOfWeek, Hour, Minute, Second, AlarmFunction);
Description: Calls user provided AlarmFunction once only on the next DayOfWeek, Hour, Minute and Second.
Alarm.timerRepeat(Period, TimerFunction);
Description: Continuously calls user provided TimerFunction after the given period in seconds has elapsed.
Alarm.timerRepeat(Hour, Minute, Second, TimerFunction);
Description: As timerRepeat above, but period is the number of seconds in the given Hour, Minute and Second parameters
Alarm.timerOnce(Period, TimerFunction);
Description: Calls user provided TimerFunction once only after the given period in seconds has elapsed.
Alarm.timerOnce(Hour, Minute, Second, TimerFunction);
Description: As timerOnce above, but period is the number of seconds in the given Hour, Minute and Second parameters
Alarm.delay( period)
Description: Similar to Arduino delay - pauses the program for the period (in miliseconds) specified.
Call this function rather than the Arduino delay function when using the Alarms library.
The timeliness of the triggers depends on sketch delays using this function.
Low level functions not usually required for typical applications:
disable( ID); - prevent the alarm associated with the given ID from triggering
enable(ID); - enable the alarm
write(ID, value); - write the value (and enable) the alarm for the given ID
read(ID); - return the value for the given ID
readType(ID); - return the alarm type for the given alarm ID
getTriggeredAlarmId(); - returns the currently triggered alarm id, only valid in an alarm callback
FAQ
Q: What hardware and software is needed to use this library?
A: This library requires the Time library. No internal or external hardware is used by the Alarm library.
Q: Why must I use Alarm.delay() instead of delay()?
A: Task scheduling is handled in the Alarm.delay function.
Tasks are monitored and triggered from within the Alarm.delay call so Alarm.delay should be called
whenever a delay is required in your sketch.
If your sketch waits on an external event (for example, a sensor change),
make sure you repeatedly call Alarm.delay while checking the sensor.
You can call Alarm.delay(0) if you need to service the scheduler without a delay.
Q: Are there any restrictions on the code in a task handler function?
A: No. The scheduler does not use interrupts so your task handling function is no
different from other functions you create in your sketch.
Q: What are the shortest and longest intervals that can be scheduled?
A: Time intervals can range from 1 second to years.
(If you need timer intervals shorter than 1 second then the TimedAction library
by Alexander Brevig may be more suitable, see: http://www.arduino.cc/playground/Code/TimedAction)
Q: How are scheduled tasks affected if the system time is changed?
A: Tasks are scheduled for specific times designated by the system clock.
If the system time is reset to a later time (for example one hour ahead) then all
alarms and timers will occur one hour later.
If the system time is set backwards (for example one hour back) then the alarms and timers will occur an hour earlier.
If the time is reset before the time a task was scheduled, then the task will be triggered on the next service (the next call to Alarm.delay).
This is the expected behaviour for Alarms <20> tasks scheduled for a specific time of day will trigger at that time, but the affect on timers may not be intuitive. If a timer is scheduled to trigger in 5 minutes time and the clock is set ahead by one hour, that timer will not trigger until one hour and 5 minutes has elapsed.
Q: What is the valid range of times supported by these libraries?
A: The time library is intended to handle times from Jan 1 1970 through Jan 19 2038.
The Alarms library expects dates to be on or after Jan1 1971 so clocks should no be set earlier than this if using Alarms.
(The functions to create alarms will return an error if an earlier date is given).
Q: How many alarms can be created?
A: Up to six alarms can be scheduled.
The number of alarms can be changed in the TimeAlarms header file (set by the constant dtNBR_ALARMS,
note that the RAM used equals dtNBR_ALARMS * 11)
onceOnly Alarms and Timers are freed when they are triggered so another onceOnly alarm can be set to trigger again.
There is no limit to the number of times a onceOnly alarm can be reset.
The following fragment gives one example of how a timerOnce task can be rescheduled:
Alarm.timerOnce(random(10), randomTimer); // trigger after random number of seconds
void randomTimer(){
int period = random(2,10); // get a new random period
Alarm.timerOnce(period, randomTimer); // trigger for another random period
}

View File

@@ -0,0 +1,88 @@
/*
* IRremote: IRrecvDump - dump details of IR codes with IRrecv
* An IR detector/demodulator must be connected to the input RECV_PIN.
* Version 0.1 July, 2009
* Copyright 2009 Ken Shirriff
* http://arcfn.com
* JVC and Panasonic protocol added by Kristian Lauszus (Thanks to zenwheel and other people at the original blog post)
* Small modifications by Joe Foley <foley@ru.is> for Reykjavik Art Museum Synchronizers
*/
#include <IRremote.h>
int IR_VCC_PIN = 12;
int IR_GND_PIN = 11;
int RECV_PIN = 10;
IRrecv irrecv(RECV_PIN);
decode_results results;
void setup()
{
pinMode(IR_VCC_PIN, OUTPUT);
digitalWrite(IR_VCC_PIN, HIGH);
pinMode(IR_GND_PIN, OUTPUT);
digitalWrite(IR_GND_PIN, LOW);
Serial.begin(9600);
irrecv.enableIRIn(); // Start the receiver
}
// Dumps out the decode_results structure.
// Call this after IRrecv::decode()
// void * to work around compiler issue
//void dump(void *v) {
// decode_results *results = (decode_results *)v
void dump(decode_results *results) {
int count = results->rawlen;
if (results->decode_type == UNKNOWN) {
Serial.print("Unknown encoding: ");
}
else if (results->decode_type == NEC) {
Serial.print("Decoded NEC: ");
}
else if (results->decode_type == SONY) {
Serial.print("Decoded SONY: ");
}
else if (results->decode_type == RC5) {
Serial.print("Decoded RC5: ");
}
else if (results->decode_type == RC6) {
Serial.print("Decoded RC6: ");
}
else if (results->decode_type == PANASONIC) {
Serial.print("Decoded PANASONIC - Address: ");
Serial.print(results->panasonicAddress,HEX);
Serial.print(" Value: ");
}
else if (results->decode_type == JVC) {
Serial.print("Decoded JVC: ");
}
Serial.print(results->value, HEX);
Serial.print(" (");
Serial.print(results->bits, DEC);
Serial.println(" bits)");
Serial.print("Raw (");
Serial.print(count, DEC);
Serial.print("): ");
for (int i = 0; i < count; i++) {
if ((i % 2) == 1) {
Serial.print(results->rawbuf[i]*USECPERTICK, DEC);
}
else {
Serial.print(-(int)results->rawbuf[i]*USECPERTICK, DEC);
}
Serial.print(" ");
}
Serial.println("");
}
void loop() {
if (irrecv.decode(&results)) {
Serial.println(results.value, HEX);
dump(&results);
irrecv.resume(); // Receive the next value
}
}