HI
Could please help with the programming question. I dont know how to solve this issue. I got 2 Ethernetclients which both want access to one definition of the ethernet library.
Im using a RTC-Chip, NTP-Timeserver and FTP-Client over Ethernetshield on an arduino due.
The NTP itself works fine, but as soon as i add the FTP code it breaks.
Any idea or tips how to solve this is welcome, thank you.
#include <SPI.h>
#include "NTP.h"
#include <SPI.h>
#include <Ethernet2.h>
#include <Dns.h>
const int chipSelect = 4;
//##LOCAL DEBUG FTP SERVER ADDRESS
const char* dns_name_of_server="172.16.3.194"; //type in the address of ftp server for debug upload
const String ftp_user="USER any";
const String ftp_pw="PASS any";
char g_outBuf[128];
uint16_t cnt =0;
// Enter a MAC address for your controller below.
// Newer Ethernet shields have a MAC address printed on a sticker on the shield
byte mac[] = {
0xA8, 0x61, 0x0A, 0xAE, 0x70, 0x34
};
//EthernetUDP Udp;
NTP n;
EthernetClient EtherClient;
EthernetClient PASVClient;
IPAddress ServerByAddress(0, 0, 0, 0);
void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);
while (!Serial) {
; // wait for serial port to connect. Needed for native USB port only
}
// start Ethernet and UDP
if (Ethernet.begin(mac) == 0) {
Serial.println("Failed to configure Ethernet using DHCP");
// Check for Ethernet hardware present
// no point in carrying on, so do nothing forevermore:
n._ethernet=false;
}
n.Setup();
//Udp.begin(8888);
}
/*
* Ethernet Recieve, looks for answer from FTP server
*/
byte eRcv()
{
byte respCode;
byte thisByte;
char outCount; //was global in example
while (!EtherClient.available()) delay(1);
respCode = EtherClient.peek();
outCount = 0;
while (EtherClient.available())
{
thisByte = EtherClient.read();
Serial.write(thisByte);
if (outCount < 127)
{
g_outBuf[outCount] = thisByte;
outCount++;
g_outBuf[outCount] = 0;
}
}
if (respCode >= '4')
{
//efail();
return 0;
}
return 1;
}
byte ftp(){
DNSClient dns;
dns.begin(Ethernet.dnsServerIP()); //Domain Name System
dns.getHostByName(dns_name_of_server,ServerByAddress); //solves hoste name to a IP-address
EtherClient.connect(ServerByAddress,21); //connects to ftp-server
if(EtherClient.connected()){
if (!eRcv()) return 0;
EtherClient.println(ftp_user);//writes login user
if (!eRcv()) return 0;
EtherClient.println(ftp_pw);//writes login password
if (!eRcv()) return 0;
EtherClient.println(F("SYST"));//sending FTP-COMMAND
if (!eRcv()) return 0;
EtherClient.println(F("Type I"));//sending FTP-COMMAND
if (!eRcv()) return 0;
EtherClient.println(F("PASV"));//sending FTP-COMMAND, changing to Passive-Upload
if (!eRcv())return 0 ;//
char *tStr = strtok(g_outBuf, "(,");//handling passive mode answer with the ports
int array_pasv[6];
for ( int i = 0; i < 6; i++) { //reading up to 6 answers
tStr = strtok(NULL, "(,");
array_pasv[i] = atoi(tStr);
if (tStr == NULL)
{;
}
}
unsigned int hiPort, loPort;
hiPort = array_pasv[4] << 8; //shifting answer, editing
loPort = array_pasv[5] & 255; //masking answer, editing
hiPort = hiPort | loPort; //making 2 to 1
PASVClient.connect(ServerByAddress, hiPort);//connecting another client to passive port
PASVClient.print(char(cnt)); //todo
EtherClient.print(F("STOR "));//command ftp-server storing
EtherClient.println(cnt); //give the name of the file to ftp-server
PASVClient.stop();//stopping passive connection
EtherClient.println(F("QUIT"));//command ftp-server to leave
EtherClient.stop(); //stopping ethernet connection
}
cnt++;
}
void loop() {
DateTime ntp(n.now());
String a="NTP.now(): "+n.DateTime2String(ntp);
Serial.println(a);
Serial.println();
ftp();
delay(1000);
}
#include "RTClib.h"
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include "NTP.h"
#include <time.h>
void NTP::begin(){Setup();}
void NTP::Setup()
{
_refreshRTC=false;
_rtc.begin();
autoSommerzeit(ntp_now());
delay(200);
_refreshRTC=true;
ntp_now();
}
void NTP::Setup(int16_t zeitzone, bool sommerzeit)
{
_zeitzone=zeitzone;
_sommerzeit=sommerzeit;
_rtc.begin();
delay(200);
ntp_now();
}
DateTime NTP::now()
{
uint32_t delta=(millis()-_last_millis)/1000;
if(delta<30)
{
DateTime d(_last_jjjj, _last_mo, _last_dd, _last_hh, _last_mi, _last_ss );
TimeSpan t(delta);
d=d+t;
//Serial.print("A ");
return d;
}
else
{
DateTime n(ntp_now());
if(NtpIsValid(n)){return n;}
else
{
DateTime r(rtc_now());
if(RtcIsValid(r)){return r;}
else
{
DateTime d(_last_jjjj, _last_mo, _last_dd, _last_hh, _last_mi, _last_ss );
TimeSpan t(delta);
d=d+t;
Serial.print("A ");
return d;
}
}
}
}
DateTime NTP::ntp_now()
{
if(_ethernet){
DateTime n(unix2date(getTime()));
if(_sommerzeit){TimeSpan t(3600);n=n+t;} //Eine Stunde dazuzählen (60*60sec =3600sec)
if(_zeitzone==1){TimeSpan t(3600);n=n+t;} //Korrektur auf MEZ
if(NtpIsValid(n)){
_last_millis=millis();
_last_jjjj=n.year();
_last_mo=n.month();
_last_dd=n.day();
_last_hh=n.hour();
_last_mi=n.minute();
_last_ss=n.second();
if(_refreshRTC)
{
_rtc.adjust(n);
//überprüfen ob RTC den Wert übernommen hat. Wenn ja refresh-Flag löschen
DateTime r(rtc_now());
if(r.year()==n.year() && r.month()==n.month() && r.day()==n.day() && r.hour()==n.hour() && r.minute()==n.minute()){_refreshRTC=false;}
}
}
if(_debug){Serial.print(n.hour());Serial.print(":");Serial.print(n.minute());Serial.print(":");Serial.println(n.second());}
return n;
}
else
{
DateTime n(0,0,0,0,0,0);
return n;
}
}
DateTime NTP::rtc_now()
{
DateTime r(_rtc.now());
if(RtcIsValid(r)){
_last_millis=millis();
_last_jjjj=r.year();
_last_mo=r.month();
_last_dd=r.day();
_last_hh=r.hour();
_last_mi=r.minute();
_last_ss=r.second();
}
return r;
}
DateTime NTP::ard_now()
{
uint32_t delta=(millis()-_last_millis)/1000;
DateTime d(_last_jjjj, _last_mo, _last_dd, _last_hh, _last_mi, _last_ss );
TimeSpan t(delta);
d=d+t;
return d;
}
DateTime NTP::unix2date(uint32_t unix)
{
//Serial.println(unix);
// Number of days in month
// in normal year
int daysOfMonth[] = { 31, 28, 31, 30, 31, 30,
31, 31, 30, 31, 30, 31 };
long int currYear, daysTillNow, extraTime,
extraDays, index, date, month, hours,
minutes, secondss, flag = 0;
// Calculate total days unix time T
daysTillNow = unix / (24 * 60 * 60);
extraTime = unix % (24 * 60 * 60);
currYear = 1970;
// Calculating current year
while (daysTillNow >= 365) {
if (currYear % 400 == 0
|| (currYear % 4 == 0
&& currYear % 100 != 0)) {
daysTillNow -= 366;
}
else {
daysTillNow -= 365;
}
currYear += 1;
}
// Updating extradays because it
// will give days till previous day
// and we have include current day
extraDays = daysTillNow + 1;
if (currYear % 400 == 0
|| (currYear % 4 == 0
&& currYear % 100 != 0))
flag = 1;
// Calculating MONTH and DATE
month = 0, index = 0;
if (flag == 1) {
while (true) {
if (index == 1) {
if (extraDays - 29 < 0)
break;
month += 1;
extraDays -= 29;
}
else {
if (extraDays
- daysOfMonth[index]
< 0) {
break;
}
month += 1;
extraDays -= daysOfMonth[index];
}
index += 1;
}
}
else {
while (true) {
if (extraDays
- daysOfMonth[index]
< 0) {
break;
}
month += 1;
extraDays -= daysOfMonth[index];
index += 1;
}
}
// Current Month
if (extraDays > 0) {
month += 1;
date = extraDays;
}
else {
if (month == 2 && flag == 1)
date = 29;
else {
date = daysOfMonth[month - 1];
}
}
// Calculating HH:MM:YYYY
hours = extraTime / 3600;
minutes = (extraTime % 3600) / 60;
secondss = (extraTime % 3600) % 60;
DateTime d(currYear,month,date,hours,minutes,secondss);
//Serial.print(hours);Serial.print(":");Serial.print(minutes);Serial.print(":");Serial.println(secondss);
//Serial.print(d.hour());Serial.print(":");Serial.print(d.minute());Serial.print(":");Serial.println(d.second());
return d;
}
uint32_t NTP::getTime()
{
//if(_debug){Serial.println("get Time");}
EthernetUDP Udp;
Udp.begin(8888);
if(_debug){Serial.println("UDP begin");}
//
byte packetBuffer[48]; //buffer to hold incoming and outgoing packets
// set all bytes in the buffer to 0
memset(packetBuffer, 0, 48);
// 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:
if(_debug){Serial.println("UDP Packet begin");}
Udp.beginPacket("172.16.1.19", 123); // NTP requests are to port 123
Udp.write(packetBuffer, 48);
Udp.endPacket();
if(_debug){Serial.println("Send UDP");}
delay(200);
/*
bool run=true;
int i=0;
while(run)
{
delay(10);
i++;
if(i>200){run=false;}
if (Udp.available()>0){run=false;}
}//*/
//Serial.println(Udp.available());
if (Udp.parsePacket()) {
// We've received a packet, read the data from it
Udp.read(packetBuffer, 48); // read the packet into the buffer
// the timestamp starts at byte 40 of the received packet and is four bytes,
// or two words, long. First, extract the two words:
uint32_t highWord = word(packetBuffer[40], packetBuffer[41]);
uint32_t lowWord = word(packetBuffer[42], packetBuffer[43]);
// combine the four bytes (two words) into a long integer
// this is NTP time (seconds since Jan 1 1900):
uint32_t secsSince1900 = highWord << 16 | lowWord;
//Serial.print("Seconds since Jan 1 1900 = ");
//Serial.println(secsSince1900);
// now convert NTP time into everyday time:
//Serial.print("Unix time = ");
// Unix time starts on Jan 1 1970. In seconds, that's 2208988800:
const uint32_t seventyYears = 2208988800UL;
// subtract seventy years:
uint32_t epoch = secsSince1900 - seventyYears;
// print Unix time:
//Serial.println(epoch);
Udp.stop();
return epoch;
}
}
bool NTP::NtpIsValid(DateTime t)
{
bool valid=true;
//Wenn keine Verbindung zum NTP besteht sind alle einträge im DateTime = 0 --> invalid
if(t.year()==0 && t.month()==0 && t.day()==0 && t.hour()==0 && t.minute()==0 && t.second()==0 ){valid=false;}
return valid;
}
bool NTP::RtcIsValid(DateTime n)
{
bool valid=true;
if(n.month()>12){valid=false;}
if(n.day()>31){valid=false;}
if(n.hour()>24){valid=false;}
if(n.minute()>60){valid=false;}
if(n.second()>60){valid=false;}
return valid;
}
void NTP::Sommerzeit(bool istSommer){_sommerzeit=istSommer;}
DateTime NTP::getSommerzeitBegin(uint16_t jahr)
{
//Ein Tag in Sekunden 60*60*24= 86400
TimeSpan einTag(86400);
//Die Sommerzeit beginnt am letzten Sonntag im März um 2Uhr
DateTime beginnSommerzeit(jahr, 3, 31, 2,0,0); // Startbedingung 31. März
//überprüfen ob Datum ein Sonntag ist.
//Wenn nein: Datum minus ein Tag und neu Prüfen
//Wenn ja: Datum gefunden!!! Ausgeben und fertig :-)
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
beginnSommerzeit=beginnSommerzeit-einTag;
if(beginnSommerzeit.dayOfTheWeek()==0){return beginnSommerzeit;}
}
DateTime NTP::getWinterzeitBegin(uint16_t jahr)
{
//Ein Tag in Sekunden 60*60*24= 86400
TimeSpan einTag(86400);
//Die Sommerzeit beginnt am letzten Sonntag im Oktober um 2Uhr
DateTime beginnWinterzeit(jahr, 10, 31, 2,0,0); // Startbedingung 31. März
//überprüfen ob Datum ein Sonntag ist.
//Wenn nein: Datum minus ein Tag und neu Prüfen
//Wenn ja: Datum gefunden!!! Ausgeben und fertig :-)
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
beginnWinterzeit=beginnWinterzeit-einTag;
if(beginnWinterzeit.dayOfTheWeek()==0){return beginnWinterzeit;}
}
void NTP::autoSommerzeit(DateTime n)
{
DateTime s(getSommerzeitBegin(n.year()));
DateTime w(getWinterzeitBegin(n.year()));
TimeSpan t1= n-s;
TimeSpan t2= w-n;
if(t1.totalseconds()<0){_sommerzeit=false;}
if(t1.totalseconds()>=0)
{
if(t2.totalseconds()<0){_sommerzeit=false;}
else{_sommerzeit=true;}
}
}
String NTP::DateTime2String(DateTime d)
{
String dat="";
dat=dat+d.year();
dat=dat+"/";
dat=dat+d.month();
dat=dat+"/";
dat=dat+d.day();
dat=dat+" ";
dat=dat+d.hour();
dat=dat+":";
dat=dat+d.minute();
dat=dat+":";
dat=dat+d.second();
return dat;
}
void NTP::adjust(const DateTime& dt)
{
}
#ifndef _NTP_H_
#define _NTP_H_
#include <Arduino.h>
#include <SPI.h>
#include <Ethernet.h>
#include <EthernetUdp.h>
#include "RTClib.h"
#include <time.h>
class NTP {
public:
bool _ethernet=true;
void begin();
void Setup();
void autoSommerzeit(DateTime n); //noch nicht implementiert
void Sommerzeit(bool istSommer);
DateTime getSommerzeitBegin(uint16_t jahr);
DateTime getWinterzeitBegin(uint16_t jahr);
DateTime now();
DateTime ntp_now();
DateTime rtc_now();
DateTime ard_now();
void adjust(const DateTime& dt);
String DateTime2String(DateTime d); //Gibt einen String im Format "yy/mm/dd hh:mm:ss" zurück
void adjust(DateTime n); //Ignoriert das übergebene Datum. Setzt dafür das _refreshRTC Flag --> bei der nächsten erfolgreichen NTP abfrage wird die RTC auf die Netzwerkzeit aktualisiert.
protected:
//EthernetUDP Udp;
RTC_PCF8523 _rtc;
int16_t _zeitzone=1;
bool _sommerzeit=false;
bool _refreshRTC=true;
uint16_t _last_jjjj;
uint16_t _last_mo;
uint16_t _last_dd;
uint16_t _last_hh;
uint16_t _last_mi;
uint16_t _last_ss;
uint32_t _last_millis=0;
bool _debug=false;
uint32_t _secsSince1900;
DateTime unix2date(uint32_t unix);
uint32_t getTime();
bool NtpIsValid(DateTime t);
bool RtcIsValid(DateTime n);
void Setup(int16_t zeitzone, bool sommerzeit);
};
#endif
// Code by JeeLabs http://news.jeelabs.org/code/
// Released to the public domain! Enjoy!
#include <Wire.h>
#include "RTClib.h"
#ifdef __AVR__
#include <avr/pgmspace.h>
#elif defined(ESP8266)
#include <pgmspace.h>
#elif defined(ARDUINO_ARCH_SAMD)
// nothing special needed
#elif defined(ARDUINO_SAM_DUE)
#define PROGMEM
#define pgm_read_byte(addr) (*(const unsigned char *)(addr))
#define Wire Wire1
#endif
#if (ARDUINO >= 100)
#include <Arduino.h> // capital A so it is error prone on case-sensitive filesystems
// Macro to deal with the difference in I2C write functions from old and new Arduino versions.
#define _I2C_WRITE write
#define _I2C_READ read
#else
#include <WProgram.h>
#define _I2C_WRITE send
#define _I2C_READ receive
#endif
static uint8_t read_i2c_register(uint8_t addr, uint8_t reg) {
Wire.beginTransmission(addr);
Wire._I2C_WRITE((byte)reg);
Wire.endTransmission();
Wire.requestFrom(addr, (byte)1);
return Wire._I2C_READ();
}
static void write_i2c_register(uint8_t addr, uint8_t reg, uint8_t val) {
Wire.beginTransmission(addr);
Wire._I2C_WRITE((byte)reg);
Wire._I2C_WRITE((byte)val);
Wire.endTransmission();
}
////////////////////////////////////////////////////////////////////////////////
// utility code, some of this could be exposed in the DateTime API if needed
const uint8_t daysInMonth [] PROGMEM = { 31,28,31,30,31,30,31,31,30,31,30,31 };
// number of days since 2000/01/01, valid for 2001..2099
static uint16_t date2days(uint16_t y, uint8_t m, uint8_t d) {
if (y >= 2000)
y -= 2000;
uint16_t days = d;
for (uint8_t i = 1; i < m; ++i)
days += pgm_read_byte(daysInMonth + i - 1);
if (m > 2 && y % 4 == 0)
++days;
return days + 365 * y + (y + 3) / 4 - 1;
}
static long time2long(uint16_t days, uint8_t h, uint8_t m, uint8_t s) {
return ((days * 24L + h) * 60 + m) * 60 + s;
}
////////////////////////////////////////////////////////////////////////////////
// DateTime implementation - ignores time zones and DST changes
// NOTE: also ignores leap seconds, see http://en.wikipedia.org/wiki/Leap_second
DateTime::DateTime (uint32_t t) {
t -= SECONDS_FROM_1970_TO_2000; // bring to 2000 timestamp from 1970
ss = t % 60;
t /= 60;
mm = t % 60;
t /= 60;
hh = t % 24;
uint16_t days = t / 24;
uint8_t leap;
for (yOff = 0; ; ++yOff) {
leap = yOff % 4 == 0;
if (days < 365 + leap)
break;
days -= 365 + leap;
}
for (m = 1; ; ++m) {
uint8_t daysPerMonth = pgm_read_byte(daysInMonth + m - 1);
if (leap && m == 2)
++daysPerMonth;
if (days < daysPerMonth)
break;
days -= daysPerMonth;
}
d = days + 1;
}
DateTime::DateTime (uint16_t year, uint8_t month, uint8_t day, uint8_t hour, uint8_t min, uint8_t sec) {
if (year >= 2000)
year -= 2000;
yOff = year;
m = month;
d = day;
hh = hour;
mm = min;
ss = sec;
}
DateTime::DateTime (const DateTime& copy):
yOff(copy.yOff),
m(copy.m),
d(copy.d),
hh(copy.hh),
mm(copy.mm),
ss(copy.ss)
{}
static uint8_t conv2d(const char* p) {
uint8_t v = 0;
if ('0' <= *p && *p <= '9')
v = *p - '0';
return 10 * v + *++p - '0';
}
// A convenient constructor for using "the compiler's time":
// DateTime now (__DATE__, __TIME__);
// NOTE: using F() would further reduce the RAM footprint, see below.
DateTime::DateTime (const char* date, const char* time) {
// sample input: date = "Dec 26 2009", time = "12:34:56"
yOff = conv2d(date + 9);
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
switch (date[0]) {
case 'J': m = date[1] == 'a' ? 1 : m = date[2] == 'n' ? 6 : 7; break;
case 'F': m = 2; break;
case 'A': m = date[2] == 'r' ? 4 : 8; break;
case 'M': m = date[2] == 'r' ? 3 : 5; break;
case 'S': m = 9; break;
case 'O': m = 10; break;
case 'N': m = 11; break;
case 'D': m = 12; break;
}
d = conv2d(date + 4);
hh = conv2d(time);
mm = conv2d(time + 3);
ss = conv2d(time + 6);
}
// A convenient constructor for using "the compiler's time":
// This version will save RAM by using PROGMEM to store it by using the F macro.
// DateTime now (F(__DATE__), F(__TIME__));
DateTime::DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time) {
// sample input: date = "Dec 26 2009", time = "12:34:56"
char buff[11];
memcpy_P(buff, date, 11);
yOff = conv2d(buff + 9);
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
switch (buff[0]) {
case 'J': m = buff[1] == 'a' ? 1 : m = buff[2] == 'n' ? 6 : 7; break;
case 'F': m = 2; break;
case 'A': m = buff[2] == 'r' ? 4 : 8; break;
case 'M': m = buff[2] == 'r' ? 3 : 5; break;
case 'S': m = 9; break;
case 'O': m = 10; break;
case 'N': m = 11; break;
case 'D': m = 12; break;
}
d = conv2d(buff + 4);
memcpy_P(buff, time, 8);
hh = conv2d(buff);
mm = conv2d(buff + 3);
ss = conv2d(buff + 6);
}
uint8_t DateTime::dayOfTheWeek() const {
uint16_t day = date2days(yOff, m, d);
return (day + 6) % 7; // Jan 1, 2000 is a Saturday, i.e. returns 6
}
uint32_t DateTime::unixtime(void) const {
uint32_t t;
uint16_t days = date2days(yOff, m, d);
t = time2long(days, hh, mm, ss);
t += SECONDS_FROM_1970_TO_2000; // seconds from 1970 to 2000
return t;
}
long DateTime::secondstime(void) const {
long t;
uint16_t days = date2days(yOff, m, d);
t = time2long(days, hh, mm, ss);
return t;
}
DateTime DateTime::operator+(const TimeSpan& span) {
return DateTime(unixtime()+span.totalseconds());
}
DateTime DateTime::operator-(const TimeSpan& span) {
return DateTime(unixtime()-span.totalseconds());
}
TimeSpan DateTime::operator-(const DateTime& right) {
return TimeSpan(unixtime()-right.unixtime());
}
////////////////////////////////////////////////////////////////////////////////
// TimeSpan implementation
TimeSpan::TimeSpan (int32_t seconds):
_seconds(seconds)
{}
TimeSpan::TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds):
_seconds((int32_t)days*86400L + (int32_t)hours*3600 + (int32_t)minutes*60 + seconds)
{}
TimeSpan::TimeSpan (const TimeSpan& copy):
_seconds(copy._seconds)
{}
TimeSpan TimeSpan::operator+(const TimeSpan& right) {
return TimeSpan(_seconds+right._seconds);
}
TimeSpan TimeSpan::operator-(const TimeSpan& right) {
return TimeSpan(_seconds-right._seconds);
}
////////////////////////////////////////////////////////////////////////////////
// RTC_DS1307 implementation
static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
boolean RTC_DS1307::begin(void) {
Wire.begin();
return true;
}
uint8_t RTC_DS1307::isrunning(void) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE((byte)0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 1);
uint8_t ss = Wire._I2C_READ();
return !(ss>>7);
}
void RTC_DS1307::adjust(const DateTime& dt) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE((byte)0); // start at location 0
Wire._I2C_WRITE(bin2bcd(dt.second()));
Wire._I2C_WRITE(bin2bcd(dt.minute()));
Wire._I2C_WRITE(bin2bcd(dt.hour()));
Wire._I2C_WRITE(bin2bcd(0));
Wire._I2C_WRITE(bin2bcd(dt.day()));
Wire._I2C_WRITE(bin2bcd(dt.month()));
Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
Wire.endTransmission();
}
DateTime RTC_DS1307::now() {
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE((byte)0);
Wire.endTransmission();
Wire.requestFrom(DS1307_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
uint8_t mm = bcd2bin(Wire._I2C_READ());
uint8_t hh = bcd2bin(Wire._I2C_READ());
Wire._I2C_READ();
uint8_t d = bcd2bin(Wire._I2C_READ());
uint8_t m = bcd2bin(Wire._I2C_READ());
uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
Ds1307SqwPinMode RTC_DS1307::readSqwPinMode() {
int mode;
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE(DS1307_CONTROL);
Wire.endTransmission();
Wire.requestFrom((uint8_t)DS1307_ADDRESS, (uint8_t)1);
mode = Wire._I2C_READ();
mode &= 0x93;
return static_cast<Ds1307SqwPinMode>(mode);
}
void RTC_DS1307::writeSqwPinMode(Ds1307SqwPinMode mode) {
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE(DS1307_CONTROL);
Wire._I2C_WRITE(mode);
Wire.endTransmission();
}
void RTC_DS1307::readnvram(uint8_t* buf, uint8_t size, uint8_t address) {
int addrByte = DS1307_NVRAM + address;
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE(addrByte);
Wire.endTransmission();
Wire.requestFrom((uint8_t) DS1307_ADDRESS, size);
for (uint8_t pos = 0; pos < size; ++pos) {
buf[pos] = Wire._I2C_READ();
}
}
void RTC_DS1307::writenvram(uint8_t address, uint8_t* buf, uint8_t size) {
int addrByte = DS1307_NVRAM + address;
Wire.beginTransmission(DS1307_ADDRESS);
Wire._I2C_WRITE(addrByte);
for (uint8_t pos = 0; pos < size; ++pos) {
Wire._I2C_WRITE(buf[pos]);
}
Wire.endTransmission();
}
uint8_t RTC_DS1307::readnvram(uint8_t address) {
uint8_t data;
readnvram(&data, 1, address);
return data;
}
void RTC_DS1307::writenvram(uint8_t address, uint8_t data) {
writenvram(address, &data, 1);
}
////////////////////////////////////////////////////////////////////////////////
// RTC_Millis implementation
long RTC_Millis::offset = 0;
void RTC_Millis::adjust(const DateTime& dt) {
offset = dt.unixtime() - millis() / 1000;
}
DateTime RTC_Millis::now() {
return (uint32_t)(offset + millis() / 1000);
}
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
// RTC_PCF8563 implementation
boolean RTC_PCF8523::begin(void) {
Wire.begin();
return true;
}
boolean RTC_PCF8523::initialized(void) {
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE((byte)PCF8523_CONTROL_3);
Wire.endTransmission();
Wire.requestFrom(PCF8523_ADDRESS, 1);
uint8_t ss = Wire._I2C_READ();
return ((ss & 0xE0) != 0xE0);
}
void RTC_PCF8523::adjust(const DateTime& dt) {
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE((byte)3); // start at location 3
Wire._I2C_WRITE(bin2bcd(dt.second()));
Wire._I2C_WRITE(bin2bcd(dt.minute()));
Wire._I2C_WRITE(bin2bcd(dt.hour()));
Wire._I2C_WRITE(bin2bcd(dt.day()));
Wire._I2C_WRITE(bin2bcd(0)); // skip weekdays
Wire._I2C_WRITE(bin2bcd(dt.month()));
Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
Wire.endTransmission();
// set to battery switchover mode
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE((byte)PCF8523_CONTROL_3);
Wire._I2C_WRITE((byte)0x00);
Wire.endTransmission();
}
DateTime RTC_PCF8523::now() {
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE((byte)3);
Wire.endTransmission();
Wire.requestFrom(PCF8523_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
uint8_t mm = bcd2bin(Wire._I2C_READ());
uint8_t hh = bcd2bin(Wire._I2C_READ());
uint8_t d = bcd2bin(Wire._I2C_READ());
Wire._I2C_READ(); // skip 'weekdays'
uint8_t m = bcd2bin(Wire._I2C_READ());
uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
Pcf8523SqwPinMode RTC_PCF8523::readSqwPinMode() {
int mode;
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL);
Wire.endTransmission();
Wire.requestFrom((uint8_t)PCF8523_ADDRESS, (uint8_t)1);
mode = Wire._I2C_READ();
mode >>= 3;
mode &= 0x7;
return static_cast<Pcf8523SqwPinMode>(mode);
}
void RTC_PCF8523::writeSqwPinMode(Pcf8523SqwPinMode mode) {
Wire.beginTransmission(PCF8523_ADDRESS);
Wire._I2C_WRITE(PCF8523_CLKOUTCONTROL);
Wire._I2C_WRITE(mode << 3);
Wire.endTransmission();
}
////////////////////////////////////////////////////////////////////////////////
// RTC_DS3231 implementation
boolean RTC_DS3231::begin(void) {
Wire.begin();
return true;
}
bool RTC_DS3231::lostPower(void) {
return (read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG) >> 7);
}
void RTC_DS3231::adjust(const DateTime& dt) {
Wire.beginTransmission(DS3231_ADDRESS);
Wire._I2C_WRITE((byte)0); // start at location 0
Wire._I2C_WRITE(bin2bcd(dt.second()));
Wire._I2C_WRITE(bin2bcd(dt.minute()));
Wire._I2C_WRITE(bin2bcd(dt.hour()));
Wire._I2C_WRITE(bin2bcd(0));
Wire._I2C_WRITE(bin2bcd(dt.day()));
Wire._I2C_WRITE(bin2bcd(dt.month()));
Wire._I2C_WRITE(bin2bcd(dt.year() - 2000));
Wire.endTransmission();
uint8_t statreg = read_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG);
statreg &= ~0x80; // flip OSF bit
write_i2c_register(DS3231_ADDRESS, DS3231_STATUSREG, statreg);
}
DateTime RTC_DS3231::now() {
Wire.beginTransmission(DS3231_ADDRESS);
Wire._I2C_WRITE((byte)0);
Wire.endTransmission();
Wire.requestFrom(DS3231_ADDRESS, 7);
uint8_t ss = bcd2bin(Wire._I2C_READ() & 0x7F);
uint8_t mm = bcd2bin(Wire._I2C_READ());
uint8_t hh = bcd2bin(Wire._I2C_READ());
Wire._I2C_READ();
uint8_t d = bcd2bin(Wire._I2C_READ());
uint8_t m = bcd2bin(Wire._I2C_READ());
uint16_t y = bcd2bin(Wire._I2C_READ()) + 2000;
return DateTime (y, m, d, hh, mm, ss);
}
Ds3231SqwPinMode RTC_DS3231::readSqwPinMode() {
int mode;
Wire.beginTransmission(DS3231_ADDRESS);
Wire._I2C_WRITE(DS3231_CONTROL);
Wire.endTransmission();
Wire.requestFrom((uint8_t)DS3231_ADDRESS, (uint8_t)1);
mode = Wire._I2C_READ();
mode &= 0x93;
return static_cast<Ds3231SqwPinMode>(mode);
}
void RTC_DS3231::writeSqwPinMode(Ds3231SqwPinMode mode) {
uint8_t ctrl;
ctrl = read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL);
ctrl &= ~0x04; // turn off INTCON
ctrl &= ~0x18; // set freq bits to 0
if (mode == DS3231_OFF) {
ctrl |= 0x04; // turn on INTCN
} else {
ctrl |= mode;
}
write_i2c_register(DS3231_ADDRESS, DS3231_CONTROL, ctrl);
//Serial.println( read_i2c_register(DS3231_ADDRESS, DS3231_CONTROL), HEX);
}
// Code by JeeLabs http://news.jeelabs.org/code/
// Released to the public domain! Enjoy!
#ifndef _RTCLIB_H_
#define _RTCLIB_H_
#include <Arduino.h>
class TimeSpan;
#define PCF8523_ADDRESS 0x68
#define PCF8523_CLKOUTCONTROL 0x0F
#define PCF8523_CONTROL_3 0x02
#define DS1307_ADDRESS 0x68
#define DS1307_CONTROL 0x07
#define DS1307_NVRAM 0x08
#define DS3231_ADDRESS 0x68
#define DS3231_CONTROL 0x0E
#define DS3231_STATUSREG 0x0F
#define SECONDS_PER_DAY 86400L
#define SECONDS_FROM_1970_TO_2000 946684800
#ifdef ARDUINO_SAM_DUE
#define Wire Wire1
#endif
// Simple general-purpose date/time class (no TZ / DST / leap second handling!)
class DateTime {
public:
DateTime (uint32_t t =0);
DateTime (uint16_t year, uint8_t month, uint8_t day,
uint8_t hour =0, uint8_t min =0, uint8_t sec =0);
DateTime (const DateTime& copy);
DateTime (const char* date, const char* time);
DateTime (const __FlashStringHelper* date, const __FlashStringHelper* time);
uint16_t year() const { return 2000 + yOff; }
uint8_t month() const { return m; }
uint8_t day() const { return d; }
uint8_t hour() const { return hh; }
uint8_t minute() const { return mm; }
uint8_t second() const { return ss; }
uint8_t dayOfTheWeek() const;
// 32-bit times as seconds since 1/1/2000
long secondstime() const;
// 32-bit times as seconds since 1/1/1970
uint32_t unixtime(void) const;
DateTime operator+(const TimeSpan& span);
DateTime operator-(const TimeSpan& span);
TimeSpan operator-(const DateTime& right);
protected:
uint8_t yOff, m, d, hh, mm, ss;
};
// Timespan which can represent changes in time with seconds accuracy.
class TimeSpan {
public:
TimeSpan (int32_t seconds = 0);
TimeSpan (int16_t days, int8_t hours, int8_t minutes, int8_t seconds);
TimeSpan (const TimeSpan& copy);
int16_t days() const { return _seconds / 86400L; }
int8_t hours() const { return _seconds / 3600 % 24; }
int8_t minutes() const { return _seconds / 60 % 60; }
int8_t seconds() const { return _seconds % 60; }
int32_t totalseconds() const { return _seconds; }
TimeSpan operator+(const TimeSpan& right);
TimeSpan operator-(const TimeSpan& right);
protected:
int32_t _seconds;
};
// RTC based on the DS1307 chip connected via I2C and the Wire library
enum Ds1307SqwPinMode { OFF = 0x00, ON = 0x80, SquareWave1HZ = 0x10, SquareWave4kHz = 0x11, SquareWave8kHz = 0x12, SquareWave32kHz = 0x13 };
class RTC_DS1307 {
public:
boolean begin(void);
static void adjust(const DateTime& dt);
uint8_t isrunning(void);
static DateTime now();
static Ds1307SqwPinMode readSqwPinMode();
static void writeSqwPinMode(Ds1307SqwPinMode mode);
uint8_t readnvram(uint8_t address);
void readnvram(uint8_t* buf, uint8_t size, uint8_t address);
void writenvram(uint8_t address, uint8_t data);
void writenvram(uint8_t address, uint8_t* buf, uint8_t size);
};
// RTC based on the DS3231 chip connected via I2C and the Wire library
enum Ds3231SqwPinMode { DS3231_OFF = 0x01, DS3231_SquareWave1Hz = 0x00, DS3231_SquareWave1kHz = 0x08, DS3231_SquareWave4kHz = 0x10, DS3231_SquareWave8kHz = 0x18 };
class RTC_DS3231 {
public:
boolean begin(void);
static void adjust(const DateTime& dt);
bool lostPower(void);
static DateTime now();
static Ds3231SqwPinMode readSqwPinMode();
static void writeSqwPinMode(Ds3231SqwPinMode mode);
};
// RTC based on the PCF8523 chip connected via I2C and the Wire library
enum Pcf8523SqwPinMode { PCF8523_OFF = 7, PCF8523_SquareWave1HZ = 6, PCF8523_SquareWave32HZ = 5, PCF8523_SquareWave1kHz = 4, PCF8523_SquareWave4kHz = 3, PCF8523_SquareWave8kHz = 2, PCF8523_SquareWave16kHz = 1, PCF8523_SquareWave32kHz = 0 };
class RTC_PCF8523 {
public:
boolean begin(void);
void adjust(const DateTime& dt);
boolean initialized(void);
static DateTime now();
Pcf8523SqwPinMode readSqwPinMode();
void writeSqwPinMode(Pcf8523SqwPinMode mode);
};
// RTC using the internal millis() clock, has to be initialized before use
// NOTE: this clock won't be correct once the millis() timer rolls over (>49d?)
class RTC_Millis {
public:
static void begin(const DateTime& dt) { adjust(dt); }
static void adjust(const DateTime& dt);
static DateTime now();
protected:
static long offset;
};
#endif // _RTCLIB_H_
Compiler Error log:
In file included from C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Ethernet2.h:16:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:7:
C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/EthernetClient.h:8:7: error: redefinition of 'class EthernetClient'
class EthernetClient : public Client {
^
In file included from C:\Users\dasc\Desktop\ntp\NTP.h:6:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:3:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src/Ethernet.h:214:7: error: previous definition of 'class EthernetClient'
class EthernetClient : public Client {
^
In file included from C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Ethernet2.h:17:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:7:
C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/EthernetServer.h:8:7: error: redefinition of 'class EthernetServer'
class EthernetServer :
^
In file included from C:\Users\dasc\Desktop\ntp\NTP.h:6:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:3:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src/Ethernet.h:253:7: error: previous definition of 'class EthernetServer'
class EthernetServer : public Server {
^
In file included from C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Dhcp.h:7:0,
from C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Ethernet2.h:18,
from C:\Users\dasc\Desktop\ntp\ntp.ino:7:
C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/EthernetUdp2.h:50:7: error: redefinition of 'class EthernetUDP'
class EthernetUDP : public UDP {
^
In file included from C:\Users\dasc\Desktop\ntp\NTP.h:6:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:3:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src/Ethernet.h:152:7: error: previous definition of 'class EthernetUDP'
class EthernetUDP : public UDP {
^
In file included from C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Ethernet2.h:18:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:7:
C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Dhcp.h:139:7: error: redefinition of 'class DhcpClass'
class DhcpClass {
^
In file included from C:\Users\dasc\Desktop\ntp\NTP.h:6:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:3:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src/Ethernet.h:272:7: error: previous definition of 'class DhcpClass'
class DhcpClass {
^
In file included from C:\Users\dasc\Desktop\ntp\ntp.ino:7:0:
C:\Users\dasc\Documents\Arduino\libraries\Ethernet2\src/Ethernet2.h:22:7: error: redefinition of 'class EthernetClass'
class EthernetClass {
^
In file included from C:\Users\dasc\Desktop\ntp\NTP.h:6:0,
from C:\Users\dasc\Desktop\ntp\ntp.ino:3:
C:\Program Files (x86)\Arduino\libraries\Ethernet\src/Ethernet.h:74:7: error: previous definition of 'class EthernetClass'
class EthernetClass {
^
Multiple libraries were found for "Ethernet.h"
Used: C:\Program Files (x86)\Arduino\libraries\Ethernet
Not used: C:\Users\dasc\Documents\Arduino\libraries\WIZ_Ethernet_Library-IDE1.6.x-master
exit status 1
Error compiling for board Arduino Due (Programming Port).