Compare commits
10 Commits
636dffc3dc
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6fcde3bb4b | ||
|
|
f7d8c07bad | ||
|
|
4d77eff73d | ||
|
|
7a55e0c71f | ||
|
|
e3daa0cee0 | ||
|
|
0ff28de55a | ||
|
|
86004ff9c1 | ||
|
|
ffc3610c00 | ||
|
|
75bd4dcb42 | ||
|
|
bb36a16f30 |
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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() {
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
/**************************************************************/
|
||||
|
||||
@@ -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}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
{}
|
||||
105
synchronizer/libraries/Streaming/Streaming.h
Normal file
105
synchronizer/libraries/Streaming/Streaming.h
Normal 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
|
||||
25
synchronizer/libraries/Streaming/keywords.txt
Normal file
25
synchronizer/libraries/Streaming/keywords.txt
Normal 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
|
||||
BIN
synchronizer/libraries/Streaming5.zip
Normal file
BIN
synchronizer/libraries/Streaming5.zip
Normal file
Binary file not shown.
BIN
synchronizer/libraries/Time.zip
Normal file
BIN
synchronizer/libraries/Time.zip
Normal file
Binary file not shown.
90
synchronizer/libraries/Time/DateStrings.cpp
Normal file
90
synchronizer/libraries/Time/DateStrings.cpp
Normal 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;
|
||||
}
|
||||
131
synchronizer/libraries/Time/Readme.txt
Normal file
131
synchronizer/libraries/Time/Readme.txt
Normal file
@@ -0,0 +1,131 @@
|
||||
Readme file for Arduino Time Library
|
||||
|
||||
Time is a library that provides timekeeping functionality for Arduino.
|
||||
|
||||
The code is derived from the Playground DateTime library but is updated
|
||||
to provide an API that is more flexable and easier to use.
|
||||
|
||||
A primary goal was to enable date and time functionality that can be used with
|
||||
a variety of external time sources with minimum differences required in sketch logic.
|
||||
|
||||
Example sketches illustrate how similar sketch code can be used with: a Real Time Clock,
|
||||
internet NTP time service, GPS time data, and Serial time messages from a computer
|
||||
for time synchronization.
|
||||
|
||||
The functions available in the library include:
|
||||
|
||||
hour(); // the hour now (0-23)
|
||||
minute(); // the minute now (0-59)
|
||||
second(); // the second now (0-59)
|
||||
day(); // the day now (1-31)
|
||||
weekday(); // day of the week, Sunday is day 0
|
||||
month(); // the month now (1-12)
|
||||
year(); // the full four digit year: (2009, 2010 etc)
|
||||
|
||||
there are also functions to return the hour in 12 hour format
|
||||
hourFormat12(); // the hour now in 12 hour format
|
||||
isAM(); // returns true if time now is AM
|
||||
isPM(); // returns true if time now is PM
|
||||
|
||||
now(); // returns the current time as seconds since Jan 1 1970
|
||||
|
||||
The time and date functions can take an optional parameter for the time. This prevents
|
||||
errors if the time rolls over between elements. For example, if a new minute begins
|
||||
between getting the minute and second, the values will be inconsistent. Using the
|
||||
following functions eliminates this probglem
|
||||
time_t t = now(); // store the current time in time variable t
|
||||
hour(t); // returns the hour for the given time t
|
||||
minute(t); // returns the minute for the given time t
|
||||
second(t); // returns the second for the given time t
|
||||
day(t); // the day for the given time t
|
||||
weekday(t); // day of the week for the given time t
|
||||
month(t); // the month for the given time t
|
||||
year(t); // the year for the given time t
|
||||
|
||||
|
||||
Functions for managing the timer services are:
|
||||
setTime(t); // set the system time to the give time t
|
||||
setTime(hr,min,sec,day,mnth,yr); // alternative to above, yr is 2 or 4 digit yr (2010 or 10 sets year to 2010)
|
||||
adjustTime(adjustment); // adjust system time by adding the adjustment value
|
||||
|
||||
timeStatus(); // indicates if time has been set and recently synchronized
|
||||
// returns one of the following enumerations:
|
||||
timeNotSet // the time has never been set, the clock started at Jan 1 1970
|
||||
timeNeedsSync // the time had been set but a sync attempt did not succeed
|
||||
timeSet // the time is set and is synced
|
||||
Time and Date values are not valid if the status is timeNotSet. Otherwise values can be used but
|
||||
the returned time may have drifted if the status is timeNeedsSync.
|
||||
|
||||
setSyncProvider(getTimeFunction); // set the external time provider
|
||||
setSyncInterval(interval); // set the number of seconds between re-sync
|
||||
|
||||
|
||||
There are many convenience macros in the time.h file for time constants and conversion of time units.
|
||||
|
||||
To use the library, copy the download to the Library directory.
|
||||
|
||||
The Time directory contains the Time library and some example sketches
|
||||
illustrating how the library can be used with various time sources:
|
||||
|
||||
- TimeSerial.pde shows Arduino as a clock without external hardware.
|
||||
It is synchronized by time messages sent over the serial port.
|
||||
A companion Processing sketch will automatically provide these messages
|
||||
if it is running and connected to the Arduino serial port.
|
||||
|
||||
- TimeSerialDateStrings.pde adds day and month name strings to the sketch above
|
||||
Short (3 character) and long strings are available to print the days of
|
||||
the week and names of the months.
|
||||
|
||||
- TimeRTC uses a DS1307 real time clock to provide time synchronization.
|
||||
A basic RTC library named DS1307RTC is included in the download.
|
||||
To run this sketch the DS1307RTC library must be installed.
|
||||
|
||||
- TimeRTCSet is similar to the above and adds the ability to set the Real Time Clock
|
||||
|
||||
- TimeRTCLog demonstrates how to calculate the difference between times.
|
||||
It is a vary simple logger application that monitors events on digtial pins
|
||||
and prints (to the serial port) the time of an event and the time period since the previous event.
|
||||
|
||||
- TimeNTP uses the Arduino Ethernet shield to access time using the internet NTP time service.
|
||||
The NTP protocol uses UDP and the UdpBytewise library is required, see:
|
||||
http://bitbucket.org/bjoern/arduino_osc/src/14667490521f/libraries/Ethernet/
|
||||
|
||||
- TimeGPS gets time from a GPS
|
||||
This requires the TinyGPS library from Mikal Hart:
|
||||
http://arduiniana.org/libraries/TinyGPS
|
||||
|
||||
Differences between this code and the playground DateTime library
|
||||
although the Time library is based on the DateTime codebase, the API has changed.
|
||||
Changes in the Time library API:
|
||||
- time elements are functions returning int (they are variables in DateTime)
|
||||
- Years start from 1970
|
||||
- days of the week and months start from 1 (they start from 0 in DateTime)
|
||||
- DateStrings do not require a seperate library
|
||||
- time elements can be accessed non-atomically (in DateTime they are always atomic)
|
||||
- function added to automatically sync time with extrnal source
|
||||
- localTime and maketime parameters changed, localTime renamed to breakTime
|
||||
|
||||
Technical notes:
|
||||
|
||||
Internal system time is based on the standard Unix time_t.
|
||||
The value is the number of seconds since Jan 1 1970.
|
||||
System time begins at zero when the sketch starts.
|
||||
|
||||
The internal time can be automatically synchronized at regular intervals to an external time source.
|
||||
This is enabled by calling the setSyncProvider(provider) function - the provider argument is
|
||||
the address of a function that returns the current time as a time_t.
|
||||
See the sketches in the examples directory for usage.
|
||||
|
||||
The default interval for re-syncing the time is 5 minutes but can be changed by calling the
|
||||
setSyncInterval( interval) method to set the number of seconds between re-sync attempts.
|
||||
|
||||
The Time library defines a structure for holding time elements that is a compact version of the C tm structure.
|
||||
All the members of the Arduino tm structure are bytes and the year is offset from 1970.
|
||||
Convenience macros provide conversion to and from the Arduino format.
|
||||
|
||||
Low level functions to convert between system time and individual time elements are provided:
|
||||
breakTime( time, &tm); // break time_t into elements stored in tm struct
|
||||
makeTime( &tm); // return time_t from elements stored in tm struct
|
||||
|
||||
The DS1307RTC library included in the download provides an example of how a time provider
|
||||
can use the low level functions to interface with the Time library.
|
||||
318
synchronizer/libraries/Time/Time.cpp
Normal file
318
synchronizer/libraries/Time/Time.cpp
Normal 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;
|
||||
}
|
||||
144
synchronizer/libraries/Time/Time.h
Normal file
144
synchronizer/libraries/Time/Time.h
Normal file
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
time.h - low level time and date functions
|
||||
*/
|
||||
|
||||
/*
|
||||
July 3 2011 - fixed elapsedSecsThisWeek macro (thanks Vincent Valdy for this)
|
||||
- fixed daysToTime_t macro (thanks maniacbug)
|
||||
*/
|
||||
|
||||
#ifndef _Time_h
|
||||
#ifdef __cplusplus
|
||||
#define _Time_h
|
||||
|
||||
#include <inttypes.h>
|
||||
#ifndef __AVR__
|
||||
#include <sys/types.h> // for __time_t_defined, but avr libc lacks sys/types.h
|
||||
#endif
|
||||
|
||||
|
||||
#if !defined(__time_t_defined) // avoid conflict with newlib or other posix libc
|
||||
typedef unsigned long time_t;
|
||||
#endif
|
||||
|
||||
|
||||
// This ugly hack allows us to define C++ overloaded functions, when included
|
||||
// from within an extern "C", as newlib's sys/stat.h does. Actually it is
|
||||
// intended to include "time.h" from the C library (on ARM, but AVR does not
|
||||
// have that file at all). On Mac and Windows, the compiler will find this
|
||||
// "Time.h" instead of the C library "time.h", so we may cause other weird
|
||||
// and unpredictable effects by conflicting with the C library header "time.h",
|
||||
// but at least this hack lets us define C++ functions as intended. Hopefully
|
||||
// nothing too terrible will result from overriding the C library header?!
|
||||
extern "C++" {
|
||||
typedef enum {timeNotSet, timeNeedsSync, timeSet
|
||||
} timeStatus_t ;
|
||||
|
||||
typedef enum {
|
||||
dowInvalid, dowSunday, dowMonday, dowTuesday, dowWednesday, dowThursday, dowFriday, dowSaturday
|
||||
} timeDayOfWeek_t;
|
||||
|
||||
typedef enum {
|
||||
tmSecond, tmMinute, tmHour, tmWday, tmDay,tmMonth, tmYear, tmNbrFields
|
||||
} tmByteFields;
|
||||
|
||||
typedef struct {
|
||||
uint8_t Second;
|
||||
uint8_t Minute;
|
||||
uint8_t Hour;
|
||||
uint8_t Wday; // day of week, sunday is day 1
|
||||
uint8_t Day;
|
||||
uint8_t Month;
|
||||
uint8_t Year; // offset from 1970;
|
||||
} tmElements_t, TimeElements, *tmElementsPtr_t;
|
||||
|
||||
//convenience macros to convert to and from tm years
|
||||
#define tmYearToCalendar(Y) ((Y) + 1970) // full four digit year
|
||||
#define CalendarYrToTm(Y) ((Y) - 1970)
|
||||
#define tmYearToY2k(Y) ((Y) - 30) // offset is from 2000
|
||||
#define y2kYearToTm(Y) ((Y) + 30)
|
||||
|
||||
typedef time_t(*getExternalTime)();
|
||||
//typedef void (*setExternalTime)(const time_t); // not used in this version
|
||||
|
||||
|
||||
/*==============================================================================*/
|
||||
/* Useful Constants */
|
||||
#define SECS_PER_MIN (60UL)
|
||||
#define SECS_PER_HOUR (3600UL)
|
||||
#define SECS_PER_DAY (SECS_PER_HOUR * 24UL)
|
||||
#define DAYS_PER_WEEK (7UL)
|
||||
#define SECS_PER_WEEK (SECS_PER_DAY * DAYS_PER_WEEK)
|
||||
#define SECS_PER_YEAR (SECS_PER_WEEK * 52UL)
|
||||
#define SECS_YR_2000 (946684800UL) // the time at the start of y2k
|
||||
|
||||
/* Useful Macros for getting elapsed time */
|
||||
#define numberOfSeconds(_time_) (_time_ % SECS_PER_MIN)
|
||||
#define numberOfMinutes(_time_) ((_time_ / SECS_PER_MIN) % SECS_PER_MIN)
|
||||
#define numberOfHours(_time_) (( _time_% SECS_PER_DAY) / SECS_PER_HOUR)
|
||||
#define dayOfWeek(_time_) ((( _time_ / SECS_PER_DAY + 4) % DAYS_PER_WEEK)+1) // 1 = Sunday
|
||||
#define elapsedDays(_time_) ( _time_ / SECS_PER_DAY) // this is number of days since Jan 1 1970
|
||||
#define elapsedSecsToday(_time_) (_time_ % SECS_PER_DAY) // the number of seconds since last midnight
|
||||
// The following macros are used in calculating alarms and assume the clock is set to a date later than Jan 1 1971
|
||||
// Always set the correct time before settting alarms
|
||||
#define previousMidnight(_time_) (( _time_ / SECS_PER_DAY) * SECS_PER_DAY) // time at the start of the given day
|
||||
#define nextMidnight(_time_) ( previousMidnight(_time_) + SECS_PER_DAY ) // time at the end of the given day
|
||||
#define elapsedSecsThisWeek(_time_) (elapsedSecsToday(_time_) + ((dayOfWeek(_time_)-1) * SECS_PER_DAY) ) // note that week starts on day 1
|
||||
#define previousSunday(_time_) (_time_ - elapsedSecsThisWeek(_time_)) // time at the start of the week for the given time
|
||||
#define nextSunday(_time_) ( previousSunday(_time_)+SECS_PER_WEEK) // time at the end of the week for the given time
|
||||
|
||||
|
||||
/* Useful Macros for converting elapsed time to a time_t */
|
||||
#define minutesToTime_t ((M)) ( (M) * SECS_PER_MIN)
|
||||
#define hoursToTime_t ((H)) ( (H) * SECS_PER_HOUR)
|
||||
#define daysToTime_t ((D)) ( (D) * SECS_PER_DAY) // fixed on Jul 22 2011
|
||||
#define weeksToTime_t ((W)) ( (W) * SECS_PER_WEEK)
|
||||
|
||||
/*============================================================================*/
|
||||
/* time and date functions */
|
||||
int hour(); // the hour now
|
||||
int hour(time_t t); // the hour for the given time
|
||||
int hourFormat12(); // the hour now in 12 hour format
|
||||
int hourFormat12(time_t t); // the hour for the given time in 12 hour format
|
||||
uint8_t isAM(); // returns true if time now is AM
|
||||
uint8_t isAM(time_t t); // returns true the given time is AM
|
||||
uint8_t isPM(); // returns true if time now is PM
|
||||
uint8_t isPM(time_t t); // returns true the given time is PM
|
||||
int minute(); // the minute now
|
||||
int minute(time_t t); // the minute for the given time
|
||||
int second(); // the second now
|
||||
int second(time_t t); // the second for the given time
|
||||
int day(); // the day now
|
||||
int day(time_t t); // the day for the given time
|
||||
int weekday(); // the weekday now (Sunday is day 1)
|
||||
int weekday(time_t t); // the weekday for the given time
|
||||
int month(); // the month now (Jan is month 1)
|
||||
int month(time_t t); // the month for the given time
|
||||
int year(); // the full four digit year: (2009, 2010 etc)
|
||||
int year(time_t t); // the year for the given time
|
||||
|
||||
time_t now(); // return the current time as seconds since Jan 1 1970
|
||||
void setTime(time_t t);
|
||||
void setTime(int hr,int min,int sec,int day, int month, int yr);
|
||||
void adjustTime(long adjustment);
|
||||
|
||||
/* date strings */
|
||||
#define dt_MAX_STRING_LEN 9 // length of longest date string (excluding terminating null)
|
||||
char* monthStr(uint8_t month);
|
||||
char* dayStr(uint8_t day);
|
||||
char* monthShortStr(uint8_t month);
|
||||
char* dayShortStr(uint8_t day);
|
||||
|
||||
/* time sync functions */
|
||||
timeStatus_t timeStatus(); // indicates if time has been set and recently synchronized
|
||||
void setSyncProvider( getExternalTime getTimeFunction); // identify the external time provider
|
||||
void setSyncInterval(time_t interval); // set the number of seconds between re-sync
|
||||
|
||||
/* low level functions to convert to and from system time */
|
||||
void breakTime(time_t time, tmElements_t &tm); // break time_t into elements
|
||||
time_t makeTime(tmElements_t &tm); // convert time elements into time_t
|
||||
|
||||
} // extern "C++"
|
||||
#endif // __cplusplus
|
||||
#endif /* _Time_h */
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/**
|
||||
* SyncArduinoClock.
|
||||
*
|
||||
* portIndex must be set to the port connected to the Arduino
|
||||
*
|
||||
* The current time is sent in response to request message from Arduino
|
||||
* or by clicking the display window
|
||||
*
|
||||
* The time message is 11 ASCII text characters; a header (the letter 'T')
|
||||
* followed by the ten digit system time (unix time)
|
||||
*/
|
||||
|
||||
|
||||
import processing.serial.*;
|
||||
import java.util.Date;
|
||||
import java.util.Calendar;
|
||||
import java.util.GregorianCalendar;
|
||||
|
||||
public static final short portIndex = 0; // select the com port, 0 is the first port
|
||||
public static final String TIME_HEADER = "T"; //header for arduino serial time message
|
||||
public static final char TIME_REQUEST = 7; // ASCII bell character
|
||||
public static final char LF = 10; // ASCII linefeed
|
||||
public static final char CR = 13; // ASCII linefeed
|
||||
Serial myPort; // Create object from Serial class
|
||||
|
||||
void setup() {
|
||||
size(200, 200);
|
||||
println(Serial.list());
|
||||
println(" Connecting to -> " + Serial.list()[portIndex]);
|
||||
myPort = new Serial(this,Serial.list()[portIndex], 9600);
|
||||
println(getTimeNow());
|
||||
}
|
||||
|
||||
void draw()
|
||||
{
|
||||
textSize(20);
|
||||
textAlign(CENTER);
|
||||
fill(0);
|
||||
text("Click to send\nTime Sync", 0, 75, 200, 175);
|
||||
if ( myPort.available() > 0) { // If data is available,
|
||||
char val = char(myPort.read()); // read it and store it in val
|
||||
if(val == TIME_REQUEST){
|
||||
long t = getTimeNow();
|
||||
sendTimeMessage(TIME_HEADER, t);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(val == LF)
|
||||
; //igonore
|
||||
else if(val == CR)
|
||||
println();
|
||||
else
|
||||
print(val); // echo everying but time request
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void mousePressed() {
|
||||
sendTimeMessage( TIME_HEADER, getTimeNow());
|
||||
}
|
||||
|
||||
|
||||
void sendTimeMessage(String header, long time) {
|
||||
String timeStr = String.valueOf(time);
|
||||
myPort.write(header); // send header and time to arduino
|
||||
myPort.write(timeStr);
|
||||
myPort.write('\n');
|
||||
}
|
||||
|
||||
long getTimeNow(){
|
||||
// java time is in ms, we want secs
|
||||
Date d = new Date();
|
||||
Calendar cal = new GregorianCalendar();
|
||||
long current = d.getTime()/1000;
|
||||
long timezone = cal.get(cal.ZONE_OFFSET)/1000;
|
||||
long daylight = cal.get(cal.DST_OFFSET)/1000;
|
||||
return current + timezone + daylight;
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
SyncArduinoClock is a Processing sketch that responds to Arduino requests for
|
||||
time synchronization messages.
|
||||
|
||||
The portIndex must be set the Serial port connected to Arduino.
|
||||
|
||||
Download TimeSerial.pde onto Arduino and you should see the time
|
||||
message displayed when you run SyncArduinoClock in Processing.
|
||||
The Arduino time is set from the time on your computer through the
|
||||
Processing sketch.
|
||||
@@ -0,0 +1,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);
|
||||
}
|
||||
|
||||
87
synchronizer/libraries/Time/examples/TimeGPS/TimeGPS.ino
Normal file
87
synchronizer/libraries/Time/examples/TimeGPS/TimeGPS.ino
Normal file
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* TimeGPS.pde
|
||||
* example code illustrating time synced from a GPS
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
#include <TinyGPS.h> // http://arduiniana.org/libraries/TinyGPS/
|
||||
#include <SoftwareSerial.h>
|
||||
// TinyGPS and SoftwareSerial libraries are the work of Mikal Hart
|
||||
|
||||
SoftwareSerial SerialGPS = SoftwareSerial(10, 11); // receive on pin 10
|
||||
TinyGPS gps;
|
||||
|
||||
// To use a hardware serial port, which is far more efficient than
|
||||
// SoftwareSerial, uncomment this line and remove SoftwareSerial
|
||||
//#define SerialGPS Serial1
|
||||
|
||||
// Offset hours from gps time (UTC)
|
||||
const int offset = 1; // Central European Time
|
||||
//const int offset = -5; // Eastern Standard Time (USA)
|
||||
//const int offset = -4; // Eastern Daylight Time (USA)
|
||||
//const int offset = -8; // Pacific Standard Time (USA)
|
||||
//const int offset = -7; // Pacific Daylight Time (USA)
|
||||
|
||||
// Ideally, it should be possible to learn the time zone
|
||||
// based on the GPS position data. However, that would
|
||||
// require a complex library, probably incorporating some
|
||||
// sort of database using Eric Muller's time zone shape
|
||||
// maps, at http://efele.net/maps/tz/
|
||||
|
||||
time_t prevDisplay = 0; // when the digital clock was displayed
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
while (!Serial) ; // Needed for Leonardo only
|
||||
SerialGPS.begin(4800);
|
||||
Serial.println("Waiting for GPS time ... ");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
while (SerialGPS.available()) {
|
||||
if (gps.encode(SerialGPS.read())) { // process gps messages
|
||||
// when TinyGPS reports new data...
|
||||
unsigned long age;
|
||||
int Year;
|
||||
byte Month, Day, Hour, Minute, Second;
|
||||
gps.crack_datetime(&Year, &Month, &Day, &Hour, &Minute, &Second, NULL, &age);
|
||||
if (age < 500) {
|
||||
// set the Time to the latest GPS reading
|
||||
setTime(Hour, Minute, Second, Day, Month, Year);
|
||||
adjustTime(offset * SECS_PER_HOUR);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (timeStatus()!= timeNotSet) {
|
||||
if (now() != prevDisplay) { //update the display only if the time has changed
|
||||
prevDisplay = now();
|
||||
digitalClockDisplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digitalClockDisplay(){
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printDigits(int digits) {
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
135
synchronizer/libraries/Time/examples/TimeNTP/TimeNTP.ino
Normal file
135
synchronizer/libraries/Time/examples/TimeNTP/TimeNTP.ino
Normal file
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* Time_NTP.pde
|
||||
* Example showing time sync to NTP time source
|
||||
*
|
||||
* This sketch uses the Ethernet library
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
#include <Ethernet.h>
|
||||
#include <EthernetUdp.h>
|
||||
#include <SPI.h>
|
||||
|
||||
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
|
||||
// NTP Servers:
|
||||
IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov
|
||||
// IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov
|
||||
// IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov
|
||||
|
||||
|
||||
const int timeZone = 1; // Central European Time
|
||||
//const int timeZone = -5; // Eastern Standard Time (USA)
|
||||
//const int timeZone = -4; // Eastern Daylight Time (USA)
|
||||
//const int timeZone = -8; // Pacific Standard Time (USA)
|
||||
//const int timeZone = -7; // Pacific Daylight Time (USA)
|
||||
|
||||
|
||||
EthernetUDP Udp;
|
||||
unsigned int localPort = 8888; // local port to listen for UDP packets
|
||||
|
||||
void setup()
|
||||
{
|
||||
Serial.begin(9600);
|
||||
while (!Serial) ; // Needed for Leonardo only
|
||||
delay(250);
|
||||
Serial.println("TimeNTP Example");
|
||||
if (Ethernet.begin(mac) == 0) {
|
||||
// no point in carrying on, so do nothing forevermore:
|
||||
while (1) {
|
||||
Serial.println("Failed to configure Ethernet using DHCP");
|
||||
delay(10000);
|
||||
}
|
||||
}
|
||||
Serial.print("IP number assigned by DHCP is ");
|
||||
Serial.println(Ethernet.localIP());
|
||||
Udp.begin(localPort);
|
||||
Serial.println("waiting for sync");
|
||||
setSyncProvider(getNtpTime);
|
||||
}
|
||||
|
||||
time_t prevDisplay = 0; // when the digital clock was displayed
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (timeStatus() != timeNotSet) {
|
||||
if (now() != prevDisplay) { //update the display only if time has changed
|
||||
prevDisplay = now();
|
||||
digitalClockDisplay();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void digitalClockDisplay(){
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
/*-------- NTP code ----------*/
|
||||
|
||||
const int NTP_PACKET_SIZE = 48; // NTP time is in the first 48 bytes of message
|
||||
byte packetBuffer[NTP_PACKET_SIZE]; //buffer to hold incoming & outgoing packets
|
||||
|
||||
time_t getNtpTime()
|
||||
{
|
||||
while (Udp.parsePacket() > 0) ; // discard any previously received packets
|
||||
Serial.println("Transmit NTP Request");
|
||||
sendNTPpacket(timeServer);
|
||||
uint32_t beginWait = millis();
|
||||
while (millis() - beginWait < 1500) {
|
||||
int size = Udp.parsePacket();
|
||||
if (size >= NTP_PACKET_SIZE) {
|
||||
Serial.println("Receive NTP Response");
|
||||
Udp.read(packetBuffer, NTP_PACKET_SIZE); // read packet into the buffer
|
||||
unsigned long secsSince1900;
|
||||
// convert four bytes starting at location 40 to a long integer
|
||||
secsSince1900 = (unsigned long)packetBuffer[40] << 24;
|
||||
secsSince1900 |= (unsigned long)packetBuffer[41] << 16;
|
||||
secsSince1900 |= (unsigned long)packetBuffer[42] << 8;
|
||||
secsSince1900 |= (unsigned long)packetBuffer[43];
|
||||
return secsSince1900 - 2208988800UL + timeZone * SECS_PER_HOUR;
|
||||
}
|
||||
}
|
||||
Serial.println("No NTP Response :-(");
|
||||
return 0; // return 0 if unable to get the time
|
||||
}
|
||||
|
||||
// send an NTP request to the time server at the given address
|
||||
void sendNTPpacket(IPAddress &address)
|
||||
{
|
||||
// set all bytes in the buffer to 0
|
||||
memset(packetBuffer, 0, NTP_PACKET_SIZE);
|
||||
// Initialize values needed to form NTP request
|
||||
// (see URL above for details on the packets)
|
||||
packetBuffer[0] = 0b11100011; // LI, Version, Mode
|
||||
packetBuffer[1] = 0; // Stratum, or type of clock
|
||||
packetBuffer[2] = 6; // Polling Interval
|
||||
packetBuffer[3] = 0xEC; // Peer Clock Precision
|
||||
// 8 bytes of zero for Root Delay & Root Dispersion
|
||||
packetBuffer[12] = 49;
|
||||
packetBuffer[13] = 0x4E;
|
||||
packetBuffer[14] = 49;
|
||||
packetBuffer[15] = 52;
|
||||
// all NTP fields have been given values, now
|
||||
// you can send a packet requesting a timestamp:
|
||||
Udp.beginPacket(address, 123); //NTP requests are to port 123
|
||||
Udp.write(packetBuffer, NTP_PACKET_SIZE);
|
||||
Udp.endPacket();
|
||||
}
|
||||
|
||||
55
synchronizer/libraries/Time/examples/TimeRTC/TimeRTC.pde
Normal file
55
synchronizer/libraries/Time/examples/TimeRTC/TimeRTC.pde
Normal file
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* TimeRTC.pde
|
||||
* example code illustrating Time library with Real Time Clock.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
#include <Wire.h>
|
||||
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) ; // wait until Arduino Serial Monitor opens
|
||||
setSyncProvider(RTC.get); // the function to get the time from the RTC
|
||||
if(timeStatus()!= timeSet)
|
||||
Serial.println("Unable to sync with the RTC");
|
||||
else
|
||||
Serial.println("RTC has set the system time");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (timeStatus() == timeSet) {
|
||||
digitalClockDisplay();
|
||||
} else {
|
||||
Serial.println("The time has not been set. Please run the Time");
|
||||
Serial.println("TimeRTCSet example, or DS1307RTC SetTime example.");
|
||||
Serial.println();
|
||||
delay(4000);
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void digitalClockDisplay(){
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
107
synchronizer/libraries/Time/examples/TimeRTCLog/TimeRTCLog.pde
Normal file
107
synchronizer/libraries/Time/examples/TimeRTCLog/TimeRTCLog.pde
Normal file
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* TimeRTCLogger.pde
|
||||
* example code illustrating adding and subtracting Time.
|
||||
*
|
||||
* this sketch logs pin state change events
|
||||
* the time of the event and time since the previous event is calculated and sent to the serial port.
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
#include <Wire.h>
|
||||
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
|
||||
|
||||
const int nbrInputPins = 6; // monitor 6 digital pins
|
||||
const int inputPins[nbrInputPins] = {2,3,4,5,6,7}; // pins to monitor
|
||||
boolean state[nbrInputPins] ; // the state of the monitored pins
|
||||
time_t prevEventTime[nbrInputPins] ; // the time of the previous event
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
setSyncProvider(RTC.get); // the function to sync the time from the RTC
|
||||
for(int i=0; i < nbrInputPins; i++){
|
||||
pinMode( inputPins[i], INPUT);
|
||||
// uncomment these lines if pull-up resistors are wanted
|
||||
// pinMode( inputPins[i], INPUT_PULLUP);
|
||||
// state[i] = HIGH;
|
||||
}
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
for(int i=0; i < nbrInputPins; i++)
|
||||
{
|
||||
boolean val = digitalRead(inputPins[i]);
|
||||
if(val != state[i])
|
||||
{
|
||||
time_t duration = 0; // the time since the previous event
|
||||
state[i] = val;
|
||||
time_t timeNow = now();
|
||||
if(prevEventTime[i] > 0)
|
||||
// if this was not the first state change, calculate the time from the previous change
|
||||
duration = duration = timeNow - prevEventTime[i];
|
||||
logEvent(inputPins[i], val, timeNow, duration ); // log the event
|
||||
prevEventTime[i] = timeNow; // store the time for this event
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void logEvent( int pin, boolean state, time_t timeNow, time_t duration)
|
||||
{
|
||||
Serial.print("Pin ");
|
||||
Serial.print(pin);
|
||||
if( state == HIGH)
|
||||
Serial.print(" went High at ");
|
||||
else
|
||||
Serial.print(" went Low at ");
|
||||
showTime(timeNow);
|
||||
if(duration > 0){
|
||||
// only display duration if greater than 0
|
||||
Serial.print(", Duration was ");
|
||||
showDuration(duration);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
|
||||
void showTime(time_t t){
|
||||
// display the given time
|
||||
Serial.print(hour(t));
|
||||
printDigits(minute(t));
|
||||
printDigits(second(t));
|
||||
Serial.print(" ");
|
||||
Serial.print(day(t));
|
||||
Serial.print(" ");
|
||||
Serial.print(month(t));
|
||||
Serial.print(" ");
|
||||
Serial.print(year(t));
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
void showDuration(time_t duration){
|
||||
// prints the duration in days, hours, minutes and seconds
|
||||
if(duration >= SECS_PER_DAY){
|
||||
Serial.print(duration / SECS_PER_DAY);
|
||||
Serial.print(" day(s) ");
|
||||
duration = duration % SECS_PER_DAY;
|
||||
}
|
||||
if(duration >= SECS_PER_HOUR){
|
||||
Serial.print(duration / SECS_PER_HOUR);
|
||||
Serial.print(" hour(s) ");
|
||||
duration = duration % SECS_PER_HOUR;
|
||||
}
|
||||
if(duration >= SECS_PER_MIN){
|
||||
Serial.print(duration / SECS_PER_MIN);
|
||||
Serial.print(" minute(s) ");
|
||||
duration = duration % SECS_PER_MIN;
|
||||
}
|
||||
Serial.print(duration);
|
||||
Serial.print(" second(s) ");
|
||||
}
|
||||
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* TimeRTCSet.pde
|
||||
* example code illustrating Time library with Real Time Clock.
|
||||
*
|
||||
* RTC clock is set in response to serial port time message
|
||||
* A Processing example sketch to set the time is included in the download
|
||||
* On Linux, you can use "date +T%s > /dev/ttyACM0" (UTC time zone)
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
#include <Wire.h>
|
||||
#include <DS1307RTC.h> // a basic DS1307 library that returns time as a time_t
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) ; // Needed for Leonardo only
|
||||
setSyncProvider(RTC.get); // the function to get the time from the RTC
|
||||
if (timeStatus() != timeSet)
|
||||
Serial.println("Unable to sync with the RTC");
|
||||
else
|
||||
Serial.println("RTC has set the system time");
|
||||
}
|
||||
|
||||
void loop()
|
||||
{
|
||||
if (Serial.available()) {
|
||||
time_t t = processSyncMessage();
|
||||
if (t != 0) {
|
||||
RTC.set(t); // set the RTC and the system time to the received value
|
||||
setTime(t);
|
||||
}
|
||||
}
|
||||
digitalClockDisplay();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void digitalClockDisplay(){
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
/* code to process time sync messages from the serial port */
|
||||
#define TIME_HEADER "T" // Header tag for serial time sync message
|
||||
|
||||
unsigned long processSyncMessage() {
|
||||
unsigned long pctime = 0L;
|
||||
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
|
||||
|
||||
if(Serial.find(TIME_HEADER)) {
|
||||
pctime = Serial.parseInt();
|
||||
return pctime;
|
||||
if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
|
||||
pctime = 0L; // return 0 to indicate that the time is not valid
|
||||
}
|
||||
}
|
||||
return pctime;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* TimeSerial.pde
|
||||
* example code illustrating Time library set through serial port messages.
|
||||
*
|
||||
* Messages consist of the letter T followed by ten digit time (as seconds since Jan 1 1970)
|
||||
* you can send the text on the next line using Serial Monitor to set the clock to noon Jan 1 2013
|
||||
T1357041600
|
||||
*
|
||||
* A Processing example sketch to automatically send the messages is inclided in the download
|
||||
* On Linux, you can use "date +T%s > /dev/ttyACM0" (UTC time zone)
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
|
||||
#define TIME_HEADER "T" // Header tag for serial time sync message
|
||||
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
while (!Serial) ; // Needed for Leonardo only
|
||||
pinMode(13, OUTPUT);
|
||||
setSyncProvider( requestSync); //set function to call when sync required
|
||||
Serial.println("Waiting for sync message");
|
||||
}
|
||||
|
||||
void loop(){
|
||||
if (Serial.available()) {
|
||||
processSyncMessage();
|
||||
}
|
||||
if (timeStatus()!= timeNotSet) {
|
||||
digitalClockDisplay();
|
||||
}
|
||||
if (timeStatus() == timeSet) {
|
||||
digitalWrite(13, HIGH); // LED on if synced
|
||||
} else {
|
||||
digitalWrite(13, LOW); // LED off if needs refresh
|
||||
}
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void digitalClockDisplay(){
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
|
||||
void processSyncMessage() {
|
||||
unsigned long pctime;
|
||||
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
|
||||
|
||||
if(Serial.find(TIME_HEADER)) {
|
||||
pctime = Serial.parseInt();
|
||||
if( pctime >= DEFAULT_TIME) { // check the integer is a valid time (greater than Jan 1 2013)
|
||||
setTime(pctime); // Sync Arduino clock to the time received on the serial port
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
time_t requestSync()
|
||||
{
|
||||
Serial.write(TIME_REQUEST);
|
||||
return 0; // the time will be sent later in response to serial mesg
|
||||
}
|
||||
|
||||
@@ -0,0 +1,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
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* TimeRTC.pde
|
||||
* example code illustrating Time library with Real Time Clock.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <Time.h>
|
||||
|
||||
void setup() {
|
||||
// set the Time library to use Teensy 3.0's RTC to keep time
|
||||
setSyncProvider(getTeensy3Time);
|
||||
|
||||
Serial.begin(115200);
|
||||
while (!Serial); // Wait for Arduino Serial Monitor to open
|
||||
delay(100);
|
||||
if (timeStatus()!= timeSet) {
|
||||
Serial.println("Unable to sync with the RTC");
|
||||
} else {
|
||||
Serial.println("RTC has set the system time");
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if (Serial.available()) {
|
||||
time_t t = processSyncMessage();
|
||||
if (t != 0) {
|
||||
Teensy3Clock.set(t); // set the RTC
|
||||
setTime(t);
|
||||
}
|
||||
}
|
||||
digitalClockDisplay();
|
||||
delay(1000);
|
||||
}
|
||||
|
||||
void digitalClockDisplay() {
|
||||
// digital clock display of the time
|
||||
Serial.print(hour());
|
||||
printDigits(minute());
|
||||
printDigits(second());
|
||||
Serial.print(" ");
|
||||
Serial.print(day());
|
||||
Serial.print(" ");
|
||||
Serial.print(month());
|
||||
Serial.print(" ");
|
||||
Serial.print(year());
|
||||
Serial.println();
|
||||
}
|
||||
|
||||
time_t getTeensy3Time()
|
||||
{
|
||||
return Teensy3Clock.get();
|
||||
}
|
||||
|
||||
/* code to process time sync messages from the serial port */
|
||||
#define TIME_HEADER "T" // Header tag for serial time sync message
|
||||
|
||||
unsigned long processSyncMessage() {
|
||||
unsigned long pctime = 0L;
|
||||
const unsigned long DEFAULT_TIME = 1357041600; // Jan 1 2013
|
||||
|
||||
if(Serial.find(TIME_HEADER)) {
|
||||
pctime = Serial.parseInt();
|
||||
return pctime;
|
||||
if( pctime < DEFAULT_TIME) { // check the value is a valid time (greater than Jan 1 2013)
|
||||
pctime = 0L; // return 0 to indicate that the time is not valid
|
||||
}
|
||||
}
|
||||
return pctime;
|
||||
}
|
||||
|
||||
void printDigits(int digits){
|
||||
// utility function for digital clock display: prints preceding colon and leading 0
|
||||
Serial.print(":");
|
||||
if(digits < 10)
|
||||
Serial.print('0');
|
||||
Serial.print(digits);
|
||||
}
|
||||
|
||||
33
synchronizer/libraries/Time/keywords.txt
Normal file
33
synchronizer/libraries/Time/keywords.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Time
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Datatypes (KEYWORD1)
|
||||
#######################################
|
||||
time_t KEYWORD1
|
||||
#######################################
|
||||
# Methods and Functions (KEYWORD2)
|
||||
#######################################
|
||||
now KEYWORD2
|
||||
second KEYWORD2
|
||||
minute KEYWORD2
|
||||
hour KEYWORD2
|
||||
day KEYWORD2
|
||||
month KEYWORD2
|
||||
year KEYWORD2
|
||||
isAM KEYWORD2
|
||||
isPM KEYWORD2
|
||||
weekday KEYWORD2
|
||||
setTime KEYWORD2
|
||||
adjustTime KEYWORD2
|
||||
setSyncProvider KEYWORD2
|
||||
setSyncInterval KEYWORD2
|
||||
timeStatus KEYWORD2
|
||||
#######################################
|
||||
# Instances (KEYWORD2)
|
||||
#######################################
|
||||
|
||||
#######################################
|
||||
# Constants (LITERAL1)
|
||||
#######################################
|
||||
BIN
synchronizer/libraries/TimeAlarms.zip
Normal file
BIN
synchronizer/libraries/TimeAlarms.zip
Normal file
Binary file not shown.
357
synchronizer/libraries/TimeAlarms/TimeAlarms.cpp
Normal file
357
synchronizer/libraries/TimeAlarms/TimeAlarms.cpp
Normal 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() ;
|
||||
|
||||
127
synchronizer/libraries/TimeAlarms/TimeAlarms.h
Normal file
127
synchronizer/libraries/TimeAlarms/TimeAlarms.h
Normal 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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
25
synchronizer/libraries/TimeAlarms/keywords.txt
Normal file
25
synchronizer/libraries/TimeAlarms/keywords.txt
Normal 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
|
||||
220
synchronizer/libraries/TimeAlarms/readme.txt
Normal file
220
synchronizer/libraries/TimeAlarms/readme.txt
Normal 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
|
||||
}
|
||||
|
||||
88
synchronizer/util/IRrecvDump/IRrecvDump.ino
Executable file
88
synchronizer/util/IRrecvDump/IRrecvDump.ino
Executable 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
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user