Sei sulla pagina 1di 6

month(t);

Arduino Time library


The Time library adds timekeeping functionality to Arduino with or without
external timekeeping hardware. It allows a sketch to get the time and date as:
second, minute, hour, day, month and year. It also provides time as a standard
C time_t so elapsed times can be easily calculated and time values shared
across different platforms.
Update: newer versions of Time, TimeAlarms, and DS1307RTC are available,
featuring more updates for newer version of Arduino and compatibility with
Arduino Due.

The code is derived from the earlier Playground DateTime library but is
updated to provide an API that is more flexible and easier to use.
The download includes example sketches illustrating how similar sketch code can
be used with: a Real Time Clock,Internet NTP time service, GPS time
data, DCF77 radio signal, and Serial time messages from a computer. To use all
of the features in the library, you'll need the UDPbitewise library, found here.

Additional documentation is included in a readme.txt file


Functional Overview
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 1
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 problem
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

year(t);

// The month for the given time t


// The year for the given time t

Functions for printing out string descriptions for day and month
monthStr()
monthShortStr()
dayStr()
dayShortStr()

Be aware that a parameter is required for this string functions. The argument
is NOT the timestamp, e.g. time_t, but must be something like month(). So
monthStr(month()) or dayStr(weekday()) will work.
See also the TimeSerialDateString.pde in the download
Functions for managing the timer services are:
setTime(t);
// Set the system time to the
// give time t
setTime(hr,min,sec,day,month,yr); // Another way to set
// the time
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.
Using 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.
- TimeRTC uses a DS1307 Real Time Clock (or DS3231 ChronoDot RTC*)
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.
* The I2C 'DS3231' interface is very straight forward and
virtually identical to the register addresses of the
popular DS1337
and DS1307 RTCs, which means that existing code for the
Arduino,
Basic Stamp, Cubloc, and other controllers should work with
no modification.
For reference purposes see >>
https://www.adafruit.com/products/255
- 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/libra
ries/Ethernet/
Note: This is out of date. For Arduino 0022, see the built
in Udp NTP example,
and also see http://arduino.cc/en/Tutorial/UdpNtpClient.
-TimeGPS gets time from a GPS
This requires the TinyGPS and NewSoftSerial libraries from
Mikal Hart:
http://arduiniana.org/libraries/TinyGPS and
http://arduiniana.org/libraries/newsoftserial/
Example sketch:

The test sketch uses a message on the serial port to set the time. A Processing
sketch that sends these messsages is included in the download but you can
test this sketch by sending T1262347200 using the serial monitor (this sets
the time to noon on Jan 1 2010). On a unix system, you can set the time with
the shell command:
TZ_adjust=-8; echo T$(($(date +%s)+60*60*$TZ_adjust)) > /dev/tty.usbserialA8008pym
[Get Code]

-- edit: The above code did not work for me in my linux terminal, I wrote the
below script which worked. ( I was using zsh and UnoR3)
TZ_adjust=5.5;d=$(date +%s);t=$(echo "60*60*$TZ_adjust/1" | bc);echo T$(echo $d+
$t |bc ) > /dev/ttyACM0
[Get Code]

Adjust the TZ_adjust value to your timezone and the serial port to your
Arduino.
#include <Time.h>
#define TIME_MSG_LEN 11 // time sync to PC is HEADER followed by Unix time_t
as ten ASCII digits
#define TIME_HEADER 'T' // Header tag for serial time sync message
#define TIME_REQUEST 7 // ASCII bell character requests a time sync message
// T1262347200 //noon Jan 1 2010
void setup() {
Serial.begin(9600);
}
void loop(){
if(Serial.available() )
{
processSyncMessage();
}
if(timeStatus() == timeNotSet)
Serial.println("waiting for sync message");
else
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);
}
void processSyncMessage() {
// if time sync available from serial port, update time and return true
while(Serial.available() >= TIME_MSG_LEN ){ // time message consists of header &
10 ASCII digits
char c = Serial.read() ;
Serial.print(c);
if( c == TIME_HEADER ) {
time_t pctime = 0;
for(int i=0; i < TIME_MSG_LEN -1; i++){
c = Serial.read();

if( c >= '0' && c <= '9'){


pctime = (10 * pctime) + (c - '0') ; // convert digits to a number
}
}
setTime(pctime); // Sync Arduino clock to the time received on the serial port

}
}
[Get Code]

Here is a fragment from the TimeNTP.pde example sketch showing how the
syncProvider functionality simplifies the sketch code. This sketch gets time
from an Internet time provider (NTP) using the Arduino Ethernet shield. Note
that the loop code does not require any logic to maintain time sync. The Time
library will automatically monitor NTP and sync the time as necessary.
void setup()
{
Serial.begin(9600);
Ethernet.begin(mac,ip,gateway);
Serial.println("waiting for sync");
setSyncProvider(getNtpTime);
while(timeStatus()== timeNotSet)
; // wait until the time is set by the sync provider
}
void loop()
{
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);
}
/*-------- NTP code ----------*/
// ntp code not shown - see TimeNTP.pde example sketch
volatile keyword

Specifically, it directs the compiler to load the variable from RAM and not from a storage
register, which is a temporary memory location where program variables are stored and manipulated.
Under certain conditions, the value for a variable stored in registers can be inaccurate.
A variable should be declared volatile whenever its value can be changed by something beyond the
control of the code section in which it appears, such as a concurrently executing thread. In the
Arduino, the only place that this is likely to occur is in sections of code associated with
interrupts, called an interrupt service routine.
Example
// toggles LED when interrupt pin changes state
int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}
void loop()
{
digitalWrite(pin, state);
}
void blink()
{
state = !state;
}

attachInterrupt()
Description
Specifies a named Interrupt Service Routine (ISR) to call when an interrupt occurs. Replaces any
previous function that was attached to the interrupt. Most Arduino boards have two external
interrupts: numbers 0 (on digital pin 2) and 1 (on digital pin 3). The table below shows the
available interrupt pins on various boards.
Board

int.0

int.1

Uno, Ethernet

Mega2560

Leonardo

Due

int.2

int.3

int.4

int.5

21

20

19

18

(see below)

The Arduino Due board has powerful interrupt capabilities that allows you to attach an interrupt
function on all available pins. You can directly specify the pin number in attachInterrupt().
Note

Inside the attached function, delay() won't work and the value returned by millis() will not
increment. Serial data received while in the function may be lost. You should declare as volatile
any variables that you modify within the attached function. See the section on ISRs below for more
information.
Using Interrupts

volatile is a keyword known as a variable qualifier, it is usually used before the datatype of a
variable, to modify the way in which the compiler and subsequent program treats the variable.
Declaring a variable volatile is a directive to the compiler. The compiler is software which
translates your C/C++ code into the machine code, which are the real instructions for the Atmega
chip in the Arduino.

Interrupts are useful for making things happen automatically in microcontroller programs, and can
help solve timing problems. Good tasks for using an interrupt may include reading a rotary encoder,
or monitoring user input.

If you wanted to insure that a program always caught the pulses from a rotary encoder, so that it
never misses a pulse, it would make it very tricky to write a program to do anything else, because
the program would need to constantly poll the sensor lines for the encoder, in order to catch
pulses when they occurred. Other sensors have a similar interface dynamic too, such as trying to
read a sound sensor that is trying to catch a click, or an infrared slot sensor (photo-interrupter)
trying to catch a coin drop. In all of these situations, using an interrupt can free the
microcontroller to get some other work done while not missing the input.

Example
int pin = 13;
volatile int state = LOW;
void setup()
{
pinMode(pin, OUTPUT);
attachInterrupt(0, blink, CHANGE);
}

About Interrupt Service Routines


ISRs are special kinds of functions that have some unique limitations most other functions do not
have. An ISR cannot have any parameters, and they shouldn't return anything.

void loop()
{
digitalWrite(pin, state);
}

Generally, an ISR should be as short and fast as possible. If your sketch uses multiple ISRs, only
one can run at a time, other interrupts will be ignored (turned off) until the current one is
finished. as delay() and millis() both rely on interrupts, they will not work while an ISR is
running. delayMicroseconds(), which does not rely on interrupts, will work as expected.

void blink()
{
state = !state;
}

Typically global variables are used to pass data between an ISR and the main program. To make sure
variables used in an ISR are updated correctly, declare them as volatile.

detachInterrupt()

For more information on interrupts, see Nick Gammon's notes.

Description

Syntax

Turns off the given interrupt.


Syntax

attachInterrupt(interrupt, ISR, mode)


attachInterrupt(pin, ISR, mode)

(Arduino Due only)

detachInterrupt(pin)

Parameters
interrupt
:

the number of the interrupt (int)

pin:

the pin number

ISR:

the ISR to call when the interrupt occurs; this


function must take no parameters and return nothing.
This function is sometimes referred to as an interrupt
service routine.

(Arduino
Due only)

LOW to trigger the interrupt whenever the pin is low,


CHANGE to trigger the interrupt whenever the pin changes
value
RISING to trigger when the pin goes from low to high,
FALLING for when the pin goes from high to low.

none

HIGH to trigger the interrupt whenever the pin is high.

interrupt: the number of the interrupt to disable (see attachInterrupt() for more details).
pin: the pin number of the interrupt to disable ( Arduino Due only)

// read RPM
volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatileint rpm =
0;unsigned long lastmillis = 0;
void setup (){
Serial .begin(9600);
attachInterrupt(0, rpm_fan, FALLING);//interrupt cero (0) is on pin
two(2).
}
void loop (){
if (millis() - lastmillis == 1000){ /*Uptade every one second, this
will be equal to reading frecuency (Hz).*/
detachInterrupt(0); //Disable interrupt when calculating

The Due board allows also:

RPM
Code
Download RPM.ino

defines when the interrupt should be triggered. Four


contstants are predefined as valid values:

(Arduino Due only)

Parameters

mode:

Returns

detachInterrupt(interrupt)

(Arduino
Due only)

rpm = rpmcount * 60; /* Convert frecuency to RPM, note: this works


for one interruption per full rotation. For two interrups per
full rotation use rpmcount * 30.*/
Serial .print("RPM =\t"); //print the word "RPM" and tab.
Serial .print(rpm); // print the rpm value.
Serial .print("\t Hz=\t"); //print the word "Hz".
Serial .println(rpmcount); /*print revolutions per second or Hz.
And print new line or enter.*/

// Restart the RPM counter


millis(); // Uptade lasmillis
attachInterrupt
(0, rpm_fan, FALLING); //enable interrupt
}

total = total + readings[x];

rpmcount = 0;
lastmillis =
}

void rpm_fan(){ /* this code will be executed every time the


interrupt
0 (pin2) gets low.*/
rpmcount++;

average = total / numreadings;

rpm = average;

// Elimelec Lopez - April 25th 2013


Code v2 (Calculate Average)
Download RPM_V2.ino

// read RPM and calculate average every then readings.const int numreadings
10;int readings[numreadings];unsigned long average = 0;int index = 0;unsigned long
total;
volatile int rpmcount = 0;//see http://arduino.cc/en/Reference/Volatile unsigned long
0;unsigned long lastmillis = 0;

rpmcount = 0;

// Restart the RPM counter

index++;

if(index

rpm =

>= numreadings){

index=0;

void setup(){

Serial.begin(9600);
attachInterrupt(0,

rpm_fan,

FALLING);

if (millis()

> 11000){

// wait for RPMs average to get stable

void loop(){

Serial.print(" RPM = ");


Serial.println(rpm);

if (millis() - lastmillis >= 1000){ /*Uptade every one second, this will be equal
to reading frecuency (Hz).*/

lastmillis =

detachInterrupt(0);

//Disable interrupt when calculating

attachInterrupt(0,

total = 0;

rpm_fan,

FALLING); //enable interrupt

readings[index] = rpmcount * 60; /* Convert frecuency to RPM, note: this works for
one interruption per full rotation. For two interrups per full rotation use
rpmcount * 30.*/

for (int

millis(); // Uptade lasmillis

x=0; x<=9; x++){

void rpm_fan(){ /* this code will be executed every time the interrupt 0 (pin2)
gets low.*/

rpmcount++;
}
The hall effect sensor pin goes to pin 2, or interrupt 0. The LED and 10k resistor needed to be
there for this to work. If your fan takes a lot of current, you might need to use an external power
source.
Simple Circuit Option:
If the internal pull-up resistor for pin 2 (interrupt 0) is enabled by adding the line:
digitalWrite(2, HIGH);
to setup(), then the hall effect sensor can be connected directly to pin 2 without requiring an
external 10k pull-up resistor and LED. The LED is actually only serving as a visual indicator in
the original circuit and is not mandatory in for either.
Ze code:
//----------------------------------------------volatile byte half_revolutions;
unsigned int rpm;
unsigned long timeold;
void setup()
{
Serial.begin(9600);
attachInterrupt(0, rpm_fun, RISING);
half_revolutions = 0;
rpm = 0;
timeold = 0;
}
void loop()
{
if (half_revolutions >= 20) {
//Update RPM every 20 counts, increase this for better RPM resolution,
//decrease for faster update
rpm = 30*1000/(millis() - timeold)*half_revolutions;
timeold = millis();
half_revolutions = 0;
Serial.println(rpm,DEC);
}
}
void rpm_fun()
{
half_revolutions++;
//Each rotation, this interrupt function is run twice
}
//----------------------------------------------by zitron

Edited by Elimelec Lopez - April 25th 2013


// read RPM
int half_revolutions = 0;
int rpm = 0;
unsigned long lastmillis = 0;
void setup(){
Serial.begin(9600);
attachInterrupt(0, rpm_fan, FALLING);
}
void loop(){
if (millis() - lastmillis == 1000){ //Uptade every one second, this will be equal to reading
frecuency (Hz).
detachInterrupt(0);//Disable interrupt when calculating
rpm = half_revolutions * 60; // Convert frecuency to RPM, note: this works for one interruption
per full rotation. For two interrups per full rotation use half_revolutions * 30.
Serial.print("RPM =\t"); //print the word "RPM" and tab.
Serial.print(rpm); // print the rpm value.
Serial.print("\t Hz=\t"); //print the word "Hz".
Serial.println(half_revolutions); //print revolutions per second or Hz. And print new line or
enter.
half_revolutions = 0; // Restart the RPM counter

lastmillis = millis(); // Uptade lasmillis


attachInterrupt(0, rpm_fan, FALLING); //enable interrupt
}
}
// this code will be executed every time the interrupt 0 (pin2) gets low.
void rpm_fan(){
half_revolutions++;
}

Potrebbero piacerti anche