Salve, vi scrivo per chiedervi come reperire la data corrente (giorno-mese-anno) via Ethernet attraverso un Ethernet Shield. Per quanto riguarda l’orario non sembra esserci problema ma non riesco proprio a fargli calcolare la data. Di seguito una bozza del codice che ho trovato e modificato, nel caso dovesse essere utile. Come Shield Ethernet uso questo: http://www.seeedstudio.com/wiki/Ethernet_Shield_V1.0
#include <Time.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
// configura il mac address
byte mac[] = {
0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
char isodate[25];
const long timeZoneOffset = -7200L;
time_t cur_time = 0;
unsigned int localPort = 8888; // porta in listening per i pacchetti UDP
//IPAddress timeServer(132, 163, 4, 101); // time-a.timefreq.bldrdoc.gov NTP server
//IPAddress timeServer(132, 163, 4, 102); // time-b.timefreq.bldrdoc.gov NTP server
IPAddress timeServer(132, 163, 4, 103); // time-c.timefreq.bldrdoc.gov NTP server
const int NTP_PACKET_SIZE= 48; // prende i primi 48 bytes del pacchetto
byte packetBuffer[ NTP_PACKET_SIZE]; //buffer per fermare i pacchetti in entrata e uscita
// Istanza UDP per mandare e ricevere pacchetti sul protocollo UDP
EthernetUDP Udp;
void setup()
{
Serial.begin(9600);
while (!Serial) {
;
}
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
for(;;)
;
}
Udp.begin(localPort);
}
void loop()
{
sendNTPpacket(timeServer); // manda il pacchetto NTP al time server
delay(1000);
if ( Udp.parsePacket() ) {
// Se ha ricevuto un pacchetto leggilo
Udp.read(packetBuffer,NTP_PACKET_SIZE); // leggi il pacchetto presente nel buffer
// il timestamp parte al byte 40 del pacchetto ricevuto ed è lungo 4 bytes o 2 word. Quindi estrai le due word:
unsigned long highWord = word(packetBuffer[40], packetBuffer[41]);
unsigned long lowWord = word(packetBuffer[42], packetBuffer[43]);
// unisci i 4 bytes in un long integer
// NTP time (Secondi trascorsi dal 1 Gennaio 1900):
unsigned long secsSince1900 = highWord << 16 | lowWord;
Serial.print("Secondi trascorsi dal 1 Gennaio 1900 = " );
Serial.println(secsSince1900);
// converti l'NTP time
Serial.print("Unix time = ");
// L'Unix time parte dal 1 Gennaio 1970. In secondi sono: 2208988800:
const unsigned long seventyYears = 2208988800UL;
// sottrai settanta anni:
unsigned long epoch = secsSince1900 - seventyYears;
//Serial.println(epoch);
//Serial.println(CurrentYear);
//prova giorno settimana
long day = epoch / 86400L;
Serial.println(day);
int day_of_the_week = day % 7;
switch (day_of_the_week) {
case 0:
Serial.println("Gio");
break;
case 1:
Serial.println("Ven");
break;
case 2:
Serial.println("Sab");
break;
case 3:
Serial.println("Dom");
break;
case 4:
Serial.println("Lun");
break;
case 5:
Serial.println("Mar");
break;
case 6:
Serial.println("Mer");
break;
}
//Serial.println(cur_time);
//Serial.println(now());
//Serial.println(day_of_the_week);
//cur_time = now();
// makeISOdate();
//Serial.println(isodate);
//digitalClockDisplay();
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
// Serial.println(month());
// Stampa ora, minuti e secondi
Serial.print("Sono le ore "); // UTC time: Meridiano di Greenwich
Serial.print(((epoch % 86400L) / 3600)+2); // stampa l'ora (86400 secondi al giorno)
Serial.print(':');
if ( ((epoch % 3600) / 60) < 10 ) {
// Nei primi 10 minuti di ciascuna ora abbiamo uno zero davanti
Serial.print('0');
}
Serial.print((epoch % 3600) / 60); // stampa i minuti (3600 secondi al minuto)
Serial.print(':');
if ( (epoch % 60) < 10 ) {
// Nei primi 10 secondi di ciascun minuto abbiamo uno zero davanti
Serial.print('0');
}
Serial.println(epoch %60); // stampa i secondi
}
// attendi 10 secondi prima di chiedere ancora l'orario
delay(10000);
}
/*
void digitalClockDisplay(){
// Ask only once for date and time:
time_t t = cur_time;
// digital clock display of the 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));
Serial.println();
} */
void makeISOdate(){
sprintf(isodate, "%4d-%02d-%02dT%02d:%02d:%02d%+05d\n",
year(), month(), day(), hour(), minute(), second(), timeZoneOffset/36 );
}
// manda una richiesta NTP al server
unsigned long sendNTPpacket(IPAddress& address)
{
// mette tutti i bytes nel buffer a 0
memset(packetBuffer, 0, NTP_PACKET_SIZE);
// inizializza i valori nell'NTP request
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
packetBuffer[12] = 49;
packetBuffer[13] = 0x4E;
packetBuffer[14] = 49;
packetBuffer[15] = 52;
Udp.beginPacket(address, 123); // le richieste NTP vengono fatte sulla porta 123
Udp.write(packetBuffer,NTP_PACKET_SIZE);
Udp.endPacket();
}
Puoi estrapolare la funzione dalla libreria swRTC di Leonardo --> swRTC - Megatopic - Arduino Forum
La funzione è setClockWithTimestamp e permette di ottenere dal Timestamp data e ora.
EDIT:
La funzione se non ero è anche disponibile nella libreria time. Controllala.
Provo anche io a darti una mano
se hai una connessione ad internet puoi provare in questo modo:
#include <SPI.h>
#include <Ethernet.h>
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
// if you don't want to use DNS (and reduce your sketch size)
// use the numeric IP instead of the name for the server:
//IPAddress server(74,125,232,128); // numeric IP for Google (no DNS)
char server[] = "http://www.timeapi.org/utc/now"; // name address for Google (using DNS)
// Set the static IP address to use if the DHCP fails to assign
IPAddress ip(192,168,0,177);
// Initialize the Ethernet client library
// with the IP address and port of the server
// that you want to connect to (port 80 is default for HTTP):
EthernetClient client;
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for Leonardo only
}
// start the Ethernet connection:
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// no point in carrying on, so do nothing forevermore:
// try to congifure using IP address instead of DHCP:
Ethernet.begin(mac, ip);
}
// give the Ethernet shield a second to initialize:
delay(1000);
Serial.println("connecting...");
// if you get a connection, report back via serial:
if (client.connect(server, 80)) {
Serial.println("connected");
// Make a HTTP request:
client.println("GET /utc/now HTTP/1.1");
client.println("Host: www.timeapi.org");
client.println("Connection: close");
client.println();
}
else {
// kf you didn't get a connection to the server:
Serial.println("connection failed");
}
}
Utilizzando un webservice, una volta ricevuta la stringa puoi effettuare il parser del time come meglio credi! ciaooo
Grazie innanzitutto per la risposta. Ho provato ad eseguire uno sketch di test fornito nella stessa cartella della libreria:
/* This file is part of swRTC library.
Please check the README file and the notes
inside the swRTC.h file to get more info
This example will print the time every second
to the computer through the serial port using the
format HH:MM or HH:MM:SS
Written by Leonardo Miliani <leonardo AT leonardomiliani DOT com>
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public
License as published by the Free Software Foundation; either
version 3.0 of the License, or (at your option) any later version.
*/
#include <swRTC.h>
swRTC rtc; //create a new istance of the lib
const byte WITHOUT_SECONDS = 0;
const byte WITH_SECONDS = 1;
void setup() {
rtc.stopRTC(); //stop the RTC
rtc.setTime(12,0,0); //set the time here
rtc.setDate(4,6,2012); //set the date here
rtc.startRTC(); //start the RTC
Serial.begin(19200); //choose the serial speed here
delay(2000); //delay to let the user opens the serial monitor
}
void loop() {
printTime(WITHOUT_SECONDS);
printTime(WITH_SECONDS);
Serial.println("");
delay(1000);
}
void printTime(byte withSeconds) {
sendNumber(rtc.getHours());
Serial.print(":");
sendNumber(rtc.getMinutes());
if (withSeconds) {
Serial.print(":");
sendNumber(rtc.getSeconds());
}
Serial.println("");
}
void sendNumber(byte number) {
byte temp;
if (number>9) {
temp=int(number/10);
Serial.print(char(temp+48));
number-=(temp*10);
} else {
Serial.print("0");
}
Serial.print(char(number+48));
}
e ottengo il seguente errore:
In file included from swRTCprintTime.ino:17:
C:\Documents and Settings\01stg_eta\Documenti\Arduino\libraries\swRTC/swRTC.h:39: fatal error: avr/interrupt.h: No such file or directory
compilation terminated.
Eppure il file interrupt.h è nella cartella: C:\Documents and Settings\01stg_eta\Desktop\Arduino Due\arduino-1.5.2\hardware\tools\avr\avr\include\avr
Vuol dire che quel codice non è compatibile con la DUE.
Devi eliminare tutto il superfluo e utilizzare unicamente la funzione che ti calcola data e ora partendo dal timestamp.
Perchè parlate della DUE?
C:\Documents and Settings\01stg_eta\Documenti\Arduino\libraries\swRTC/swRTC.h:39: fatal error: avr/interrupt.h: No such file or directory
compilation terminated.
sta cercando nella cartella /avr non /sam
Hai la versione aggiornata della swrtc?
da nuovo forum user secondo me è per il problema dell'incopatibilità...
Hydrarian ad ogni modo hai provato il codice che ho postato? con quello non "dovresti" avare problemi.. ]
Ciao Antroid, grazie per la dritta, non ci avevo pensato! Comunque ho appena eseguito il codice aggiungendo anche un
char c = client.read();
Serial.print(c);
per la stampa sul Serial Monitor. A parte che durante la compilazione mi da:
C:\DOCUME~1\01STG_~1\IMPOST~1\Temp\build1799273433428212384.tmp/core.a(main.cpp.o): In function main': C:\Documents and Settings\01stg_eta\Desktop\Arduino Due\arduino-1.5.2\hardware\arduino\sam\cores\arduino/main.cpp:50: warning: undefined reference to loop'
Poi quando vado a stampare su serial monitor ottengo:
connecting...
connected
ÿ
Quell'ÿ dovrebbe essere la stringa ottenuta dal server... Come renderla leggibile?
EDIT: Ho sistemato i due warning (erano dovuti all'assenza di loop())
La swRTC è stata scritta e funziona solo per gli Avr8.
Se ti servono le funzioni del timestamp puoi estrapolarle ma NON puoi includere l’intera libreria perché durante l’inizializzazione fa il setup di alcuni registri del micro che ovviamente sulla DUE non esistono.
Per la Due ho scritto una libreria apposita che si chiama adavancedFunctions che permette di accedere a delle periferiche non supportate dal core di Arduino, ad esempio l’RTC integrato. Esso è molto preciso, avendo un quarzo da 32 kHz apposito. Puoi benissimo prelevare questa libreria che ti ho detto ed aggiungerci le funzioni di timestamp. Anzi, prima o poi lo faccio anch’io che servono sempre