Am reprodus si eu experimentul pentru a intelege modul de schimbare al orei si datei, mai putin releul...
Daca se apasa pentru scurt timp se afiseaza orele de rasarit si de apus ale soarelui.
iar la o noua apasare, se alege modul de actionare la unui releu: AUTO (pe durata zilei, mereu actionat contact sau permanent decuplat contact), asta deoarece se folosea pentru alimentarea pe timpul zilei a unei fantani arteziene.
Daca se apasa lung (mai mult de 3 secunde) se intra in modul de reglaj:
- an:
- luna:
- zi:
- ora:
- minute:
Pentru a putea calcula perioada cat soarele este pe cer se foloseste o librarie speciala, TimeLord.h (se poate descarca si de la aici), care necesita introducerea in sketch a coordonatelor GPS alel localitatii si a orei locale fata cea de baza:
Pentru verificarea datelor, am cautat si, evident, gasit orele de rasarit si apus ale soarelui pentru ziua respectiva:
si se observa ca eroare este doar de cateva minute, rasaritul de soare este calculat de Arduino ca fiind la 7:59, iar pe site am gasit ca a fost 8:00, respectiv apusul soarelui a fost calculat ca fiind la 17:02, iar pe site este 17:04.
Am facut un film, numit ceas cu DS1307 reglat cu encoder rotativ si date despre soare (rasarit si apus) pentru a se vedea mai usor modul de "actiune":
Revenind la partea care m-a interesat in mod deosebit, am adaugat si un modul cu senzor DHT11 pentru a pune si umiditatea si temperatura, conectand pinul de date la A1:
Sketch-ul folosit de mine este:
// Dawn & Dusk controller. http://andydoz.blogspot.ro/2014_08_01_archive.html
// 16th August 2014.
// (C) A.G.Doswell 2014
// adapted sketch by niq_ro from http://nicuflorica.blogspot.ro & http://arduinotehniq.blogspot.com/
// Date and time functions using a DS1307 RTC connected via I2C and Wire lib
//
// Designed to control a relay connected to pin A3. Pin goes low during daylight hours and high during night. Relay uses active low, so is
// "On" during the day. This is connected to the fountain pump in my garden.
//
// Time is set using a rotary encoder with integral push button. The Encoder is connected to interrupt pins D2 & D3 (and GND),
// and the push button to pin analogue 0 (and GND)
// The RTC is connections are: Analogue pin 4 to SDA. Connect analogue pin 5 to SCL.
// A 2 x 16 LCD display is connected as follows (NOTE. This is NOT conventional, as interrupt pins are required for the encoder)
// Arduino LCD
// D4 DB7
// D5 DB6
// D6 DB5
// D7 DB4
// D12 RS
// D13 E
//
// Use: Pressing and holding the button will enter the clock set mode (on release of the button). Clock is set using the rotary encoder.
// The clock must be set to UTC.
// Pressing and releasing the button quickly will display the current sun rise and sun set times. Pressing the button again will enter the mode select menu.
// Modes are AUTO: On when the sun rises, off when it sets.
// ON: Permanently ON
// OFF: Permanently OFF (Who'd have guessed it?)
//
// Change the LATTITUDE and LONGITUDE constant to your location.
#include <Wire.h>
#include "RTClib.h" // from https://github.com/adafruit/RTClib
#include <LiquidCrystal.h>
#include <Encoder.h> // from http://www.pjrc.com/teensy/td_libs_Encoder.html
#include <TimeLord.h> // from http://swfltek.com/arduino/timelord.html. When adding it to your IDE, rename the file, removing the "-depreciated"
// http://www.timeanddate.com/sun/romania/craiova - for control sun time
RTC_DS1307 RTC; // Tells the RTC library that we're using a DS1307 RTC
Encoder knob(2, 3); //encoder connected to pins 2 and 3 (and ground)
LiquidCrystal lcd(12, 13, 7, 6, 5, 4); // I used an odd pin combination because I need pin 2 and 3 for the interrupts.
//the variables provide the holding values for the set clock routine
int setyeartemp;
int setmonthtemp;
int setdaytemp;
int sethourstemp;
int setminstemp;
int setsecs = 0;
int maxday; // maximum number of days in the given month
int TimeMins; // number of seconds since midnight
int TimerMode = 2; //mode 0=Off 1=On 2=Auto
int TimeOut = 10;
int TimeOutCounter;
// These variables are for the push button routine
int buttonstate = 0; //flag to see if the button has been pressed, used internal on the subroutine only
int pushlengthset = 3000; // value for a long push in mS
int pushlength = pushlengthset; // set default pushlength
int pushstart = 0;// sets default push value for the button going low
int pushstop = 0;// sets the default value for when the button goes back high
int knobval; // value for the rotation of the knob
boolean buttonflag = false; // default value for the button flag
//const int TIMEZONE = 0; //UTC
const int TIMEZONE = 2; //UTC Craiova (Romania) - http://www.worldtimebuddy.com/utc-to-romania-craiova
//const float LATITUDE = 51.89, LONGITUDE = -2.04; // set YOUR position here
const float LATITUDE = 44.3167, LONGITUDE = 23.8; // Craiova GPS position
int Sunrise, Sunset; //sunrise and sunset expressed as minute of day (0-1439)
TimeLord myLord; // TimeLord Object, Global variable
byte sunTime[] = {0, 0, 0, 1, 1, 13}; // 17 Oct 2013
int SunriseHour, SunriseMin, SunsetHour, SunsetMin; //Variables used to make a decent display of our sunset and sunrise time.
// http://arduino.cc/en/Reference/LiquidCrystalCreateChar
byte grad[8] = {
B01100,
B10010,
B10010,
B01100,
B00000,
B00000,
B00000,
};
#include <DHT.h>
#define DHTPIN A1 // what pin we're connected DHT11/22
#define DHTTYPE DHT11 // DHT 11
//#define DHTTYPE DHT22 // DHT 22
DHT dht(DHTPIN, DHTTYPE);
float t1;
void setup () {
//Serial.begin(57600); //start debug serial interface
Wire.begin(); //start I2C interface
RTC.begin(); //start RTC interface
dht.begin(); // DHT init
lcd.createChar(0, grad); // create custom symbol
lcd.begin(16,2); //Start LCD (defined as 16 x 2 characters)
lcd.clear();
pinMode(A0,INPUT);//push button on encoder connected to A0 (and GND)
digitalWrite(A0,HIGH); //Pull A0 high
pinMode(A3,OUTPUT); //Relay connected to A3
digitalWrite (A3, HIGH); //sets relay off (default condition)
//Checks to see if the RTC is runnning, and if not, sets the time to the time this sketch was compiled.
if (! RTC.isrunning()) {
RTC.adjust(DateTime(__DATE__, __TIME__));
}
//Timelord initialisation
myLord.TimeZone(TIMEZONE * 60);
myLord.Position(LATITUDE, LONGITUDE);
CalcSun ();
}
void loop () {
int h = dht.readHumidity();
float t = dht.readTemperature();
lcd.setCursor(11, 1);
// lcd.print("t=");
if (t < 0)
{t1=-t;}
else t1=t;
if ( t1 < 10)
{
lcd.print(" ");
}
if (t>0) lcd.print("+");
if (t==0) lcd.print(" ");
if (t<0) lcd.print("-");
lcd.print(t1,0);
//lcd.print(",0");
// lcd.write(0b11011111);
lcd.write(byte(0));
lcd.print("C");
lcd.setCursor(11, 0);
// lcd.print("H=");
lcd.print(h);
lcd.print("%RH");
DateTime now = RTC.now(); //get time from RTC
//Display current time
lcd.setCursor (0,0);
lcd.print(now.day(), DEC);
lcd.print('/');
lcd.print(now.month());
lcd.print('/');
lcd.print(now.year(), DEC);
lcd.print(" ");
lcd.setCursor (0,1);
lcd.print(now.hour(), DEC);
lcd.print(':');
if (now.minute() <10)
{
lcd.print("0");
}
lcd.print(now.minute(), DEC);
lcd.print(':');
if (now.second() <10)
{
lcd.print("0");
}
lcd.print(now.second());
// lcd.print(" ");
//current time in minutes since midnight (used to check against sunrise/sunset easily)
TimeMins = (now.hour() * 60) + now.minute();
// Calculate sun times once a day at a minute past midnight
if (TimeMins == 1) {
CalcSun ();
}
if (TimerMode ==2) {
if (TimeMins >= Sunrise && TimeMins <=Sunset-1) { //If it's after sunrise and before sunset, switch our relay on
digitalWrite (A3, LOW);
lcd.setCursor (9,1);
lcd.print ("*");
}
else { //otherwise switch it off
digitalWrite (A3, HIGH);
lcd.setCursor (9,1);
lcd.print ("!");
}
}
if (TimerMode ==0) {
digitalWrite (A3, HIGH);
lcd.setCursor (9,1);
lcd.print ("!");
}
if (TimerMode ==1) {
digitalWrite (A3, LOW);
lcd.setCursor (9,1);
lcd.print ("*");
}
pushlength = pushlengthset;
pushlength = getpushlength ();
delay (10);
if (pushlength <pushlengthset) {
ShortPush ();
}
//This runs the setclock routine if the knob is pushed for a long time
if (pushlength >pushlengthset) {
lcd.clear();
DateTime now = RTC.now();
setyeartemp=now.year(),DEC;
setmonthtemp=now.month(),DEC;
setdaytemp=now.day(),DEC;
sethourstemp=now.hour(),DEC;
setminstemp=now.minute(),DEC;
setclock();
pushlength = pushlengthset;
};
}
//sets the clock
void setclock (){
setyear ();
lcd.clear ();
setmonth ();
lcd.clear ();
setday ();
lcd.clear ();
sethours ();
lcd.clear ();
setmins ();
lcd.clear();
RTC.adjust(DateTime(setyeartemp,setmonthtemp,setdaytemp,sethourstemp,setminstemp,setsecs));
CalcSun ();
delay (1000);
}
// subroutine to return the length of the button push.
int getpushlength () {
buttonstate = digitalRead(A0);
if(buttonstate == LOW && buttonflag==false) {
pushstart = millis();
buttonflag = true;
};
if (buttonstate == HIGH && buttonflag==true) {
pushstop = millis ();
pushlength = pushstop - pushstart;
buttonflag = false;
};
return pushlength;
}
// The following subroutines set the individual clock parameters
int setyear () {
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Year");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return setyeartemp;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) { //bit of software de-bounce
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
setyeartemp=setyeartemp + knobval;
if (setyeartemp < 2014) { //Year can't be older than currently, it's not a time machine.
setyeartemp = 2014;
}
lcd.print (setyeartemp);
lcd.print(" ");
setyear();
}
int setmonth () {
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Month");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return setmonthtemp;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) {
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
setmonthtemp=setmonthtemp + knobval;
if (setmonthtemp < 1) {// month must be between 1 and 12
setmonthtemp = 1;
}
if (setmonthtemp > 12) {
setmonthtemp=12;
}
lcd.print (setmonthtemp);
lcd.print(" ");
setmonth();
}
int setday () {
if (setmonthtemp == 4 || setmonthtemp == 5 || setmonthtemp == 9 || setmonthtemp == 11) { //30 days hath September, April June and November
maxday = 30;
}
else {
maxday = 31; //... all the others have 31
}
if (setmonthtemp ==2 && setyeartemp % 4 ==0) { //... Except February alone, and that has 28 days clear, and 29 in a leap year.
maxday = 29;
}
if (setmonthtemp ==2 && setyeartemp % 4 !=0) {
maxday = 28;
}
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Day");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return setdaytemp;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) {
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
setdaytemp=setdaytemp+ knobval;
if (setdaytemp < 1) {
setdaytemp = 1;
}
if (setdaytemp > maxday) {
setdaytemp = maxday;
}
lcd.print (setdaytemp);
lcd.print(" ");
setday();
}
int sethours () {
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Hours");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return sethourstemp;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) {
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
sethourstemp=sethourstemp + knobval;
if (sethourstemp < 1) {
sethourstemp = 1;
}
if (sethourstemp > 23) {
sethourstemp=23;
}
lcd.print (sethourstemp);
lcd.print(" ");
sethours();
}
int setmins () {
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Mins");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return setminstemp;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) {
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
setminstemp=setminstemp + knobval;
if (setminstemp < 0) {
setminstemp = 0;
}
if (setminstemp > 59) {
setminstemp=59;
}
lcd.print (setminstemp);
lcd.print(" ");
setmins();
}
int setmode () { //Sets the mode of the timer. Auto, On or Off
//lcd.clear();
lcd.setCursor (0,0);
lcd.print ("Set Mode");
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
return TimerMode;
}
lcd.setCursor (0,1);
knob.write(0);
delay (50);
knobval=knob.read();
if (knobval < -1) {
knobval = -1;
}
if (knobval > 1) {
knobval = 1;
}
TimerMode=TimerMode + knobval;
if (TimerMode < 0) {
TimerMode = 0;
}
if (TimerMode > 2) {
TimerMode=2;
}
if (TimerMode == 0) {
lcd.print("Off (!)");
lcd.print(" ");
}
if (TimerMode == 1) {
lcd.print("On (*)");
lcd.print(" ");
}
if (TimerMode == 2) {
lcd.print("Auto");
lcd.print(" ");
}
setmode ();
}
int CalcSun () { //Calculates the Sunrise and Sunset times
DateTime now = RTC.now();
sunTime[3] = now.day(); // Give Timelord the current date
sunTime[4] = now.month();
sunTime[5] = now.year();
myLord.SunRise(sunTime); // Computes Sun Rise.
Sunrise = sunTime[2] * 60 + sunTime[1]; // Sunrise returned in minutes past midnight
SunriseHour = sunTime[2];
SunriseMin = sunTime [1];
sunTime[3] = now.day(); // Uses the Time library to give Timelord the current date
sunTime[4] = now.month();
sunTime[5] = now.year();
myLord.SunSet(sunTime); // Computes Sun Set.
Sunset = sunTime[2] * 60 + sunTime[1]; // Sunset returned in minutes past midnight
SunsetHour = sunTime[2];
SunsetMin = sunTime [1];
}
void ShortPush () {
//This displays the calculated sunrise and sunset times when the knob is pushed for a short time.
lcd.clear();
for (long Counter = 0; Counter < 604 ; Counter ++) { //returns to the main loop if it's been run 604 times
//(don't ask me why I've set 604,it seemed like a good number)
lcd.setCursor (0,0);
lcd.print ("Sunrise ");
lcd.print (SunriseHour);
lcd.print (":");
if (SunriseMin <10)
{
lcd.print("0");
}
lcd.print (SunriseMin);
lcd.setCursor (0,1);
lcd.print ("Sunset ");
lcd.print (SunsetHour);
lcd.print (":");
if (SunsetMin <10)
{
lcd.print("0");
}
lcd.print (SunsetMin);
//If the knob is pushed again, enter the mode set menu
pushlength = pushlengthset;
pushlength = getpushlength ();
if (pushlength != pushlengthset) {
lcd.clear ();
TimerMode = setmode ();
}
}
lcd.clear();
}
Am facut inca 2 filmulete cu noua varianta:- statie meteo cu DHT11 si ceas cu DS1307 reglat cu encoder rotativ si date despre soare
Nice work! Glad you liked it!
RăspundețiȘtergereI was inspired by your blog.. :)
Ștergereimi place , super tare.
RăspundețiȘtergerepuneti DHT22 in loc de DHT11, e net superior
Ștergere